diff --git a/src/actionmanager.cpp b/src/actionmanager.cpp index 02a4b742..bf73f1b2 100644 --- a/src/actionmanager.cpp +++ b/src/actionmanager.cpp @@ -1,1720 +1,1721 @@ /* This file is part of KOrganizer. Copyright (c) 2002 Mike Pilone Copyright (c) 2002 Don Sanders Copyright (c) 2004 Cornelius Schumacher Copyright (C) 2004 Reinhold Kainhofer Copyright (c) 2005 Rafal Rzepecki Copyright (c) 2010-2019 Laurent Montel - Copyright (c) 2012 Allen Winter + Copyright (c) 2012-2019 Allen Winter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include #include "actionmanager.h" #include "akonadicollectionview.h" #include "calendaradaptor.h" #include "calendarview.h" #include "kocore.h" #include "kodialogmanager.h" #include "korganizeradaptor.h" #include "koglobals.h" #include "prefs/koprefs.h" #include "koviewmanager.h" #include "kowindowlist.h" #include "kocheckableproxymodel.h" #include #include "KdepimDBusInterfaces/ReminderClient" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "korganizer_debug.h" #include "korganizer_options.h" #include #include #include #include KOWindowList *ActionManager::mWindowList = nullptr; ActionManager::ActionManager(KXMLGUIClient *client, CalendarView *widget, QObject *parent, KOrg::MainWindow *mainWindow, bool isPart, QMenuBar *menuBar) : QObject(parent) , mCollectionViewShowAction(nullptr) , mCollectionView(nullptr) , mCollectionViewStateSaver(nullptr) , mCollectionSelectionModelStateSaver(nullptr) { new KOrgCalendarAdaptor(this); QDBusConnection::sessionBus().registerObject(QStringLiteral("/Calendar"), this); mGUIClient = client; mACollection = mGUIClient->actionCollection(); mCalendarView = widget; mIsPart = isPart; mTempFile = nullptr; mMainWindow = mainWindow; mMenuBar = menuBar; } ActionManager::~ActionManager() { // Remove Part plugins KOCore::self()->unloadParts(mMainWindow, mParts); delete mTempFile; // Take this window out of the window list. mWindowList->removeWindow(mMainWindow); delete mCollectionSelectionModelStateSaver; delete mCollectionViewStateSaver; delete mCalendarView; } void ActionManager::toggleMenubar(bool dontShowWarning) { if (mMenuBar) { if (mHideMenuBarAction->isChecked()) { mMenuBar->show(); } else { if (!dontShowWarning) { const QString accel = mHideMenuBarAction->shortcut().toString(); KMessageBox::information(mCalendarView, i18n("This will hide the menu bar completely." " You can show it again by typing %1.", accel), i18n("Hide menu bar"), QStringLiteral("HideMenuBarWarning")); } mMenuBar->hide(); } KOPrefs::instance()->setShowMenuBar(mHideMenuBarAction->isChecked()); } } // see the Note: below for why this method is necessary void ActionManager::init() { // add this instance of the window to the static list. if (!mWindowList) { mWindowList = new KOWindowList; } // Note: We need this ActionManager to be fully constructed, and // parent() to have a valid reference to it before the following // addWindow is called. mWindowList->addWindow(mMainWindow); // initialize the QAction instances initActions(); // set up autoSaving stuff mAutoArchiveTimer = new QTimer(this); mAutoArchiveTimer->setSingleShot(true); connect(mAutoArchiveTimer, &QTimer::timeout, this, &ActionManager::slotAutoArchive); // First auto-archive should be in 5 minutes (like in kmail). if (CalendarSupport::KCalPrefs::instance()->mAutoArchive) { mAutoArchiveTimer->start(5 * 60 * 1000); // singleshot } setTitle(); connect(mCalendarView, &CalendarView::modifiedChanged, this, &ActionManager::setTitle); connect(mCalendarView, &CalendarView::configChanged, this, &ActionManager::updateConfig); connect(mCalendarView, &CalendarView::incidenceSelected, this, &ActionManager::processIncidenceSelection); processIncidenceSelection(Akonadi::Item(), QDate()); // Update state of paste action mCalendarView->checkClipboard(); } Akonadi::ETMCalendar::Ptr ActionManager::calendar() const { return mCalendarView->calendar(); } void ActionManager::createCalendarAkonadi() { Q_ASSERT(calendar()); KSharedConfig::Ptr config = KSharedConfig::openConfig(); mCollectionSelectionModelStateSaver = new KViewStateMaintainer( config->group("GlobalCollectionSelection")); mCollectionSelectionModelStateSaver->setSelectionModel( calendar()->checkableProxyModel()->selectionModel()); AkonadiCollectionViewFactory factory(mCalendarView); mCalendarView->addExtension(&factory); mCollectionView = factory.collectionView(); mCollectionView->setObjectName(QStringLiteral("Resource View")); connect(mCollectionView, &AkonadiCollectionView::resourcesAddedRemoved, this, &ActionManager::slotResourcesAddedRemoved); connect(mCollectionView, &AkonadiCollectionView::defaultResourceChanged, this, &ActionManager::slotDefaultResourceChanged); connect(mCollectionView, &AkonadiCollectionView::colorsChanged, mCalendarView, qOverload<>(&CalendarView::updateConfig)); mCollectionViewStateSaver = new KViewStateMaintainer(config->group("GlobalCollectionView")); mCollectionViewStateSaver->setView(mCollectionView->view()); KCheckableProxyModel *checkableProxy = calendar()->checkableProxyModel(); QItemSelectionModel *selectionModel = checkableProxy->selectionModel(); mCollectionView->setCollectionSelectionProxyModel(checkableProxy); CalendarSupport::CollectionSelection *collectionSelection = new CalendarSupport::CollectionSelection(selectionModel); EventViews::EventView::setGlobalCollectionSelection(collectionSelection); mCalendarView->readSettings(); connect(calendar().data(), &Akonadi::ETMCalendar::calendarChanged, mCalendarView, &CalendarView::resourcesChanged); connect(mCalendarView, &CalendarView::configChanged, this, &ActionManager::updateConfig); calendar()->setOwner(KCalendarCore::Person(CalendarSupport::KCalPrefs::instance()->fullName(), CalendarSupport::KCalPrefs:: instance()->email())); } void ActionManager::initActions() { QAction *action = nullptr; /*************************** FILE MENU **********************************/ //~~~~~~~~~~~~~~~~~~~~~~~ LOADING / SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (mIsPart) { if (mMainWindow->hasDocument()) { QAction *a = mACollection->addAction(KStandardAction::Open, this, SLOT(file_open())); mACollection->addAction(QStringLiteral("korganizer_open"), a); } QAction *a = mACollection->addAction(KStandardAction::Print, mCalendarView, SLOT(print())); mACollection->addAction(QStringLiteral("korganizer_print"), a); a = mACollection->addAction(KStandardAction::PrintPreview, mCalendarView, SLOT(printPreview())); mACollection->addAction(QStringLiteral("korganizer_print_preview"), a); } else { KStandardAction::open(this, qOverload<>(&ActionManager::file_open), mACollection); KStandardAction::print(mCalendarView, &CalendarView::print, mACollection); KStandardAction::printPreview(mCalendarView, &CalendarView::printPreview, mACollection); } //~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT / EXPORT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mImportAction = new QAction(i18n("Import &Calendar..."), this); setHelpText(mImportAction, i18n("Merge the contents of another iCalendar")); mImportAction->setWhatsThis( i18n("Select this menu entry if you would like to merge the contents " "of another iCalendar into your current calendar.")); mACollection->addAction(QStringLiteral("import_icalendar"), mImportAction); connect(mImportAction, &QAction::triggered, this, &ActionManager::file_import); if (KAuthorized::authorize(QStringLiteral("ghns"))) { action = new QAction(i18n("Get &Hot New Stuff..."), this); mACollection->addAction(QStringLiteral("downloadnewstuff"), action); connect(action, &QAction::triggered, this, &ActionManager::downloadNewStuff); } action = new QAction(i18n("Export as &iCalendar..."), this); mACollection->addAction(QStringLiteral("export_icalendar"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::exportICalendar); action = new QAction(i18n("Archive O&ld Entries..."), this); mACollection->addAction(QStringLiteral("file_archive"), action); connect(action, &QAction::triggered, this, &ActionManager::file_archive); action = new QAction(i18n("Pur&ge Completed To-dos"), mACollection); mACollection->addAction(QStringLiteral("purge_completed"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::purgeCompleted); /************************** EDIT MENU *********************************/ QAction *pasteAction = nullptr; Akonadi::History *history = mCalendarView->history(); if (mIsPart) { // edit menu mCutAction = mACollection->addAction(KStandardAction::Cut, QStringLiteral("korganizer_cut"), mCalendarView, SLOT(edit_cut())); mCopyAction = mACollection->addAction(KStandardAction::Copy, QStringLiteral("korganizer_copy"), mCalendarView, SLOT(edit_copy())); pasteAction = mACollection->addAction(KStandardAction::Paste, QStringLiteral("korganizer_paste"), mCalendarView, SLOT(edit_paste())); mUndoAction = mACollection->addAction(KStandardAction::Undo, QStringLiteral("korganizer_undo"), history, SLOT(undo())); mRedoAction = mACollection->addAction(KStandardAction::Redo, QStringLiteral("korganizer_redo"), history, SLOT(redo())); } else { mCutAction = KStandardAction::cut(mCalendarView, &CalendarView::edit_cut, mACollection); mCopyAction = KStandardAction::copy(mCalendarView, &CalendarView::edit_copy, mACollection); pasteAction = KStandardAction::paste(mCalendarView, &CalendarView::edit_paste, mACollection); mUndoAction = KStandardAction::undo(history, SLOT(undo()), mACollection); mRedoAction = KStandardAction::redo(history, SLOT(redo()), mACollection); } mDeleteAction = new QAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n( "&Delete"), this); mACollection->addAction(QStringLiteral("edit_delete"), mDeleteAction); connect(mDeleteAction, &QAction::triggered, mCalendarView, &CalendarView::appointment_delete); if (mIsPart) { QAction *a = KStandardAction::find(mCalendarView->dialogManager(), SLOT(showSearchDialog()), mACollection); mACollection->addAction(QStringLiteral("korganizer_find"), a); } else { KStandardAction::find(mCalendarView->dialogManager(), SLOT(showSearchDialog()), mACollection); } pasteAction->setEnabled(false); mUndoAction->setEnabled(false); mRedoAction->setEnabled(false); connect(mCalendarView, &CalendarView::pasteEnabled, pasteAction, &QAction::setEnabled); connect(history, &Akonadi::History::changed, this, &ActionManager::updateUndoRedoActions); /************************** VIEW MENU *********************************/ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VIEWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-upcoming-events")), i18n( "What's &Next"), this); mACollection->addAction(QStringLiteral("view_whatsnext"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::showWhatsNextView); action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-month")), i18n( "&Month"), this); mACollection->addAction(QStringLiteral("view_month"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::showMonthView); action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-agenda")), i18n( "&Agenda"), this); mACollection->addAction(QStringLiteral("view_agenda"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::showAgendaView); action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-list")), i18n( "&Event List"), this); mACollection->addAction(QStringLiteral("view_list"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::showListView); action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-tasks")), i18n( "&To-do List"), this); mACollection->addAction(QStringLiteral("view_todo"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::showTodoView); action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-journal")), i18n( "&Journal"), this); mACollection->addAction(QStringLiteral("view_journal"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::showJournalView); action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-timeline")), i18n( "Time&line"), this); mACollection->addAction(QStringLiteral("view_timeline"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::showTimeLineView); //~~~~~~~~~~~~~~~~~~~~~~~~~~~ REFRESH ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ action = new QAction(i18n("&Refresh"), this); mACollection->addAction(QStringLiteral("update"), action); connect(action, &QAction::triggered, mCalendarView, qOverload<>(&CalendarView::updateView)); //~~~~~~~~~~~~~~~~~~~~~~~~~~~ FILTER ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mFilterAction = new KSelectAction(i18n("F&ilter"), this); mFilterAction->setToolBarMode(KSelectAction::MenuMode); mACollection->addAction(QStringLiteral("filter_select"), mFilterAction); mFilterAction->setEditable(false); connect(mFilterAction, qOverload(&KSelectAction::triggered), mCalendarView, &CalendarView::filterActivated); connect(mCalendarView, &CalendarView::filtersUpdated, this, &ActionManager::setItems); connect(mCalendarView, &CalendarView::filterChanged, this, &ActionManager::setTitle); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ZOOM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TODO: try to find / create better icons for the following 4 actions action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-in")), i18n("In Horizontally"), this); action->setEnabled(mCalendarView->currentView()->supportsZoom()); mACollection->addAction(QStringLiteral("zoom_in_horizontally"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::zoomInHorizontally); action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-out")), i18n( "Out Horizontally"), this); action->setEnabled(mCalendarView->currentView()->supportsZoom()); mACollection->addAction(QStringLiteral("zoom_out_horizontally"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::zoomOutHorizontally); action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-in")), i18n("In Vertically"), this); action->setEnabled(mCalendarView->currentView()->supportsZoom()); mACollection->addAction(QStringLiteral("zoom_in_vertically"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::zoomInVertically); action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-out")), i18n("Out Vertically"), this); action->setEnabled(mCalendarView->currentView()->supportsZoom()); mACollection->addAction(QStringLiteral("zoom_out_vertically"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::zoomOutVertically); /************************** Actions MENU *********************************/ bool isRTL = QApplication::isRightToLeft(); action = new QAction(QIcon::fromTheme(QStringLiteral("go-jump-today")), i18nc("@action Jump to today", "To &Today"), this); action->setIconText(i18n("Today")); setHelpText(action, i18n("Scroll to Today")); mACollection->addAction(QStringLiteral("go_today"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::goToday); action = new QAction(QIcon::fromTheme(isRTL ? QStringLiteral("go-next") : QStringLiteral( "go-previous")), i18nc("scroll backward", "&Backward"), this); action->setIconText(i18nc("scroll backward", "Back")); setHelpText(action, i18n("Scroll Backward")); mACollection->addAction(QStringLiteral("go_previous"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::goPrevious); // Changing the action text by setText makes the toolbar button disappear. // This has to be fixed first, before the connects below can be reenabled. /* connect( mCalendarView, SIGNAL(changeNavStringPrev(QString)), action, SLOT(setText(QString)) ); connect( mCalendarView, SIGNAL(changeNavStringPrev(QString)), this, SLOT(dumpText(QString)) );*/ action = new QAction(QIcon::fromTheme(isRTL ? QStringLiteral("go-previous") : QStringLiteral( "go-next")), i18nc("scroll forward", "&Forward"), this); action->setIconText(i18nc("scoll forward", "Forward")); setHelpText(action, i18n("Scroll Forward")); mACollection->addAction(QStringLiteral("go_next"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::goNext); /* connect( mCalendarView,SIGNAL(changeNavStringNext(QString)), action,SLOT(setText(QString)) ); */ action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-day")), i18n("&Day"), this); mACollection->addAction(QStringLiteral("select_day"), action); action->setEnabled(mCalendarView->currentView()->supportsDateRangeSelection()); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::selectDay); mNextXDays = new QAction(QIcon::fromTheme(QStringLiteral( "view-calendar-upcoming-days")), QString(), this); mNextXDays->setEnabled(mCalendarView->currentView()->supportsDateRangeSelection()); mACollection->addAction(QStringLiteral("select_nextx"), mNextXDays); connect(mNextXDays, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::selectNextX); mNextXDays->setText(i18np("&Next Day", "&Next %1 Days", KOPrefs::instance()->mNextXDays)); action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-workweek")), i18n( "W&ork Week"), this); action->setEnabled(mCalendarView->currentView()->supportsDateRangeSelection()); mACollection->addAction(QStringLiteral("select_workweek"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::selectWorkWeek); action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-week")), i18n("&Week"), this); action->setEnabled(mCalendarView->currentView()->supportsDateRangeSelection()); mACollection->addAction(QStringLiteral("select_week"), action); connect(action, &QAction::triggered, mCalendarView->viewManager(), &KOViewManager::selectWeek); /************************** Actions MENU *********************************/ mNewEventAction = new QAction(QIcon::fromTheme(QStringLiteral("appointment-new")), i18n( "New E&vent..."), this); //mNewEventAction->setIconText( i18nc( "@action:intoolbar create a new event", "Event" ) ); setHelpText(mNewEventAction, i18n("Create a new Event")); mACollection->addAction(QStringLiteral("new_event"), mNewEventAction); connect(mNewEventAction, &QAction::triggered, this, &ActionManager::slotNewEvent); mNewTodoAction = new QAction(QIcon::fromTheme(QStringLiteral("task-new")), i18n( "New &To-do..."), this); //mNewTodoAction->setIconText( i18n( "To-do" ) ); setHelpText(mNewTodoAction, i18n("Create a new To-do")); mACollection->addAction(QStringLiteral("new_todo"), mNewTodoAction); connect(mNewTodoAction, &QAction::triggered, this, &ActionManager::slotNewTodo); mNewSubtodoAction = new QAction(i18n("New Su&b-to-do..."), this); mACollection->addAction(QStringLiteral("new_subtodo"), mNewSubtodoAction); connect(mNewSubtodoAction, &QAction::triggered, this, &ActionManager::slotNewSubTodo); mNewSubtodoAction->setEnabled(false); connect(mCalendarView, &CalendarView::todoSelected, mNewSubtodoAction, &QAction::setEnabled); mNewJournalAction = new QAction(QIcon::fromTheme(QStringLiteral("journal-new")), i18n("New &Journal..."), this); //mNewJournalAction->setIconText( i18n( "Journal" ) ); setHelpText(mNewJournalAction, i18n("Create a new Journal")); mACollection->addAction(QStringLiteral("new_journal"), mNewJournalAction); connect(mNewJournalAction, &QAction::triggered, this, &ActionManager::slotNewJournal); mConfigureViewAction = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure View..."), this); mConfigureViewAction->setIconText(i18n("Configure")); setHelpText(mConfigureViewAction, i18n("Configure the view")); mConfigureViewAction->setEnabled(mCalendarView->currentView() && mCalendarView->currentView()->hasConfigurationDialog()); mACollection->addAction(QStringLiteral("configure_view"), mConfigureViewAction); connect(mConfigureViewAction, &QAction::triggered, mCalendarView, &CalendarView::configureCurrentView); mShowIncidenceAction = new QAction(i18n("&Show"), this); mACollection->addAction(QStringLiteral("show_incidence"), mShowIncidenceAction); connect(mShowIncidenceAction, &QAction::triggered, mCalendarView, qOverload<>(&CalendarView::showIncidence)); mEditIncidenceAction = new QAction(i18n("&Edit..."), this); mACollection->addAction(QStringLiteral("edit_incidence"), mEditIncidenceAction); connect(mEditIncidenceAction, &QAction::triggered, mCalendarView, qOverload<>(&CalendarView::editIncidence)); mDeleteIncidenceAction = new QAction(i18n("&Delete"), this); mACollection->addAction(QStringLiteral("delete_incidence"), mDeleteIncidenceAction); connect(mDeleteIncidenceAction, &QAction::triggered, mCalendarView, qOverload<>(&CalendarView::deleteIncidence)); mACollection->setDefaultShortcut(mDeleteIncidenceAction, QKeySequence(Qt::Key_Delete)); action = new QAction(i18n("&Make Sub-to-do Independent"), this); mACollection->addAction(QStringLiteral("unsub_todo"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::todo_unsub); action->setEnabled(false); connect(mCalendarView, &CalendarView::subtodoSelected, action, &QAction::setEnabled); // TODO: Add item to quickly toggle the reminder of a given incidence // mToggleAlarmAction = new KToggleAction( i18n( "&Activate Reminder" ), 0, // mCalendarView, SLOT(toggleAlarm()), // mACollection, "activate_alarm" ); /************************** SCHEDULE MENU ********************************/ mPublishEvent = new QAction(QIcon::fromTheme(QStringLiteral("mail-send")), i18n("&Publish Item Information..."), this); mACollection->addAction(QStringLiteral("schedule_publish"), mPublishEvent); connect(mPublishEvent, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_publish())); mPublishEvent->setEnabled(false); mSendInvitation = new QAction(QIcon::fromTheme(QStringLiteral("mail-send")), i18n("Send &Invitation to Attendees"), this); mACollection->addAction(QStringLiteral("schedule_request"), mSendInvitation); connect(mSendInvitation, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_request())); mSendInvitation->setEnabled(false); connect(mCalendarView, &CalendarView::organizerEventsSelected, mSendInvitation, &QAction::setEnabled); mRequestUpdate = new QAction(i18n("Re&quest Update"), this); mACollection->addAction(QStringLiteral("schedule_refresh"), mRequestUpdate); connect(mRequestUpdate, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_refresh())); mRequestUpdate->setEnabled(false); connect(mCalendarView, &CalendarView::groupEventsSelected, mRequestUpdate, &QAction::setEnabled); mSendCancel = new QAction(i18n("Send &Cancellation to Attendees"), this); mACollection->addAction(QStringLiteral("schedule_cancel"), mSendCancel); connect(mSendCancel, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_cancel())); mSendCancel->setEnabled(false); connect(mCalendarView, &CalendarView::organizerEventsSelected, mSendCancel, &QAction::setEnabled); mSendStatusUpdate = new QAction(QIcon::fromTheme(QStringLiteral("mail-reply-sender")), i18n("Send Status &Update"), this); mACollection->addAction(QStringLiteral("schedule_reply"), mSendStatusUpdate); connect(mSendStatusUpdate, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_reply())); mSendStatusUpdate->setEnabled(false); connect(mCalendarView, &CalendarView::groupEventsSelected, mSendStatusUpdate, &QAction::setEnabled); mRequestChange = new QAction(i18nc("counter proposal", "Request Chan&ge"), this); mACollection->addAction(QStringLiteral("schedule_counter"), mRequestChange); connect(mRequestChange, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_counter())); mRequestChange->setEnabled(false); connect(mCalendarView, &CalendarView::groupEventsSelected, mRequestChange, &QAction::setEnabled); action = new QAction(i18n("&Mail Free Busy Information..."), this); mACollection->addAction(QStringLiteral("mail_freebusy"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::mailFreeBusy); action->setEnabled(true); mForwardEvent = new QAction(QIcon::fromTheme(QStringLiteral("mail-forward")), i18n("&Send as iCalendar..."), this); mACollection->addAction(QStringLiteral("schedule_forward"), mForwardEvent); connect(mForwardEvent, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_forward())); mForwardEvent->setEnabled(false); action = new QAction(i18n("&Upload Free Busy Information"), this); mACollection->addAction(QStringLiteral("upload_freebusy"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::uploadFreeBusy); action->setEnabled(true); if (!mIsPart) { action = new QAction(QIcon::fromTheme(QStringLiteral("help-contents")), i18n("&Address Book"), this); mACollection->addAction(QStringLiteral("addressbook"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::openAddressbook); } /************************** SETTINGS MENU ********************************/ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mDateNavigatorShowAction = new KToggleAction(i18n("Show Date Navigator"), this); mACollection->addAction(QStringLiteral("show_datenavigator"), mDateNavigatorShowAction); connect(mDateNavigatorShowAction, &KToggleAction::triggered, this, &ActionManager::toggleDateNavigator); mTodoViewShowAction = new KToggleAction(i18n("Show To-do View"), this); mACollection->addAction(QStringLiteral("show_todoview"), mTodoViewShowAction); connect(mTodoViewShowAction, &KToggleAction::triggered, this, &ActionManager::toggleTodoView); mEventViewerShowAction = new KToggleAction(i18n("Show Item Viewer"), this); mACollection->addAction(QStringLiteral("show_eventviewer"), mEventViewerShowAction); connect(mEventViewerShowAction, &KToggleAction::triggered, this, &ActionManager::toggleEventViewer); KConfigGroup config(KSharedConfig::openConfig(), "Settings"); mDateNavigatorShowAction->setChecked(config.readEntry("DateNavigatorVisible", true)); // if we are a kpart, then let's not show the todo in the left pane by // default since there's also a Todo part and we'll assume they'll be // using that as well, so let's not duplicate it (by default) here mTodoViewShowAction->setChecked( config.readEntry("TodoViewVisible", false)); //mIsPart ? false : true ) ); mEventViewerShowAction->setChecked(config.readEntry("EventViewerVisible", true)); toggleDateNavigator(); toggleTodoView(); toggleEventViewer(); if (!mMainWindow->hasDocument()) { mCollectionViewShowAction = new KToggleAction(i18n("Show Calendar Manager"), this); mACollection->addAction(QStringLiteral("show_resourceview"), mCollectionViewShowAction); connect(mCollectionViewShowAction, &KToggleAction::triggered, this, &ActionManager::toggleResourceView); mCollectionViewShowAction->setChecked(config.readEntry("ResourceViewVisible", true)); toggleResourceView(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mHideMenuBarAction = KStandardAction::showMenubar(this, &ActionManager::toggleMenubar, mACollection); mHideMenuBarAction->setChecked(KOPrefs::instance()->showMenuBar()); toggleMenubar(true); action = new QAction(i18n("Configure &Date && Time..."), this); mACollection->addAction(QStringLiteral("conf_datetime"), action); connect(action, &QAction::triggered, this, &ActionManager::configureDateTime); action = new QAction(QIcon::fromTheme(QStringLiteral("view-filter")), i18n("Manage View &Filters..."), this); mACollection->addAction(QStringLiteral("edit_filters"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::editFilters); action = new QAction(i18n("Manage C&ategories..."), this); mACollection->addAction(QStringLiteral("edit_categories"), action); connect(action, &QAction::triggered, mCalendarView->dialogManager(), &KODialogManager::showCategoryEditDialog); if (mIsPart) { action = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("&Configure KOrganizer..."), this); mACollection->addAction(QStringLiteral("korganizer_configure"), action); connect(action, &QAction::triggered, mCalendarView, &CalendarView::edit_options); mACollection->addAction(KStandardAction::KeyBindings, QStringLiteral("korganizer_configure_shortcuts"), this, SLOT(keyBindings())); } else { KStandardAction::preferences(mCalendarView, &CalendarView::edit_options, mACollection); KStandardAction::keyBindings(this, &ActionManager::keyBindings, mACollection); } } void ActionManager::setItems(const QStringList &lst, int idx) { mFilterAction->setItems(lst); mFilterAction->setCurrentItem(idx); } void ActionManager::slotResourcesAddedRemoved() { restoreCollectionViewSetting(); } void ActionManager::slotDefaultResourceChanged(const Akonadi::Collection &collection) { mCalendarView->incidenceChanger()->setDefaultCollection(collection); } void ActionManager::slotNewEvent() { mCalendarView->newEvent(); } void ActionManager::slotNewTodo() { mCalendarView->newTodo(selectedCollection()); } void ActionManager::slotNewSubTodo() { mCalendarView->newSubTodo(selectedCollection()); } void ActionManager::slotNewJournal() { mCalendarView->newJournal(selectedCollection()); } void ActionManager::slotMergeFinished(bool success, int total) { Q_ASSERT(sender()); mImportAction->setEnabled(true); Akonadi::ICalImporter *importer = qobject_cast(sender()); if (success) { mCalendarView->showMessage(i18np("1 incidence was imported successfully.", "%1 incidences were imported successfully.", total), KMessageWidget::Information); } else { mCalendarView->showMessage(i18n("There was an error while merging the calendar: %1", importer->errorMessage()), KMessageWidget::Error); } sender()->deleteLater(); } void ActionManager::slotNewResourceFinished(bool success) { Q_ASSERT(sender()); Akonadi::ICalImporter *importer = qobject_cast(sender()); mImportAction->setEnabled(true); if (success) { mCalendarView->showMessage(i18n("New calendar added successfully"), KMessageWidget::Information); } else { mCalendarView->showMessage(i18n("Could not add a calendar. Error: %1", importer->errorMessage()), KMessageWidget::Error); } sender()->deleteLater(); } void ActionManager::readSettings() { // read settings from the KConfig, supplying reasonable // defaults where none are to be found mCalendarView->readSettings(); restoreCollectionViewSetting(); } void ActionManager::restoreCollectionViewSetting() { mCollectionSelectionModelStateSaver->restoreState(); mCollectionViewStateSaver->restoreState(); } void ActionManager::writeSettings() { KSharedConfig::Ptr config = KSharedConfig::openConfig(); KConfigGroup group = config->group("Settings"); mCalendarView->writeSettings(); if (mDateNavigatorShowAction) { group.writeEntry("DateNavigatorVisible", mDateNavigatorShowAction->isChecked()); } if (mTodoViewShowAction) { group.writeEntry("TodoViewVisible", mTodoViewShowAction->isChecked()); } if (mCollectionViewShowAction) { group.writeEntry("ResourceViewVisible", mCollectionViewShowAction->isChecked()); } if (mEventViewerShowAction) { group.writeEntry("EventViewerVisible", mEventViewerShowAction->isChecked()); } mCollectionViewStateSaver->saveState(); mCollectionSelectionModelStateSaver->saveState(); KConfigGroup selectionViewGroup = config->group("GlobalCollectionView"); KConfigGroup selectionGroup = config->group("GlobalCollectionSelection"); selectionGroup.sync(); selectionViewGroup.sync(); config->sync(); } void ActionManager::file_open() { const QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); const QUrl dir = QUrl::fromLocalFile(defaultPath + QLatin1String("/korganizer/")); const QUrl url = QFileDialog::getOpenFileUrl( dialogParent(), i18nc("@title:window", "Select Calendar File to Open"), dir, QStringLiteral("text/calendar (*.ics *.vcs)")); if (!url.isEmpty()) { // isEmpty if user canceled the dialog file_open(url); } } void ActionManager::file_open(const QUrl &url) { // is that URL already opened somewhere else? Activate that window KOrg::MainWindow *korg = ActionManager::findInstance(url); if ((nullptr != korg) && (korg != mMainWindow)) { #if KDEPIM_HAVE_X11 KWindowSystem::activateWindow(korg->topLevelWidget()->winId()); #endif return; } qCDebug(KORGANIZER_LOG) << url.toDisplayString(); importCalendar(url); } void ActionManager::file_import() { const QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); const QUrl dir = QUrl::fromLocalFile(defaultPath + QLatin1String("/korganizer/")); const QUrl url = QFileDialog::getOpenFileUrl( dialogParent(), i18nc("@title:window", "Select Calendar File to Import"), dir, QStringLiteral("text/calendar (*.ics *.vcs)")); if (!url.isEmpty()) { // isEmpty if user canceled the dialog importCalendar(url); } } void ActionManager::file_archive() { mCalendarView->archiveCalendar(); } bool ActionManager::importURL(const QUrl &url, bool merge) { Akonadi::ICalImporter *importer = new Akonadi::ICalImporter(); bool jobStarted; if (merge) { connect(importer, &Akonadi::ICalImporter::importIntoExistingFinished, this, &ActionManager::slotMergeFinished); jobStarted = importer->importIntoExistingResource(url, Akonadi::Collection()); } else { connect(importer, &Akonadi::ICalImporter::importIntoNewFinished, this, &ActionManager::slotNewResourceFinished); jobStarted = importer->importIntoNewResource(url.path()); } if (jobStarted) { mImportAction->setEnabled(false); } else { // empty error message means user canceled. if (!importer->errorMessage().isEmpty()) { mCalendarView->showMessage(i18n("An error occurred: %1", importer->errorMessage()), KMessageWidget::Error); } } return jobStarted; } bool ActionManager::saveURL() { QString ext; if (mURL.isLocalFile()) { ext = mFile.right(4); } else { ext = mURL.fileName().right(4); } if (!mCalendarView->saveCalendar(mFile)) { qCDebug(KORGANIZER_LOG) << "calendar view save failed."; return false; } if (!mURL.isLocalFile()) { auto job = KIO::file_copy(QUrl::fromLocalFile(mFile), mURL); KJobWidgets::setWindow(job, view()); if (!job->exec()) { QString msg = i18n("Cannot upload calendar to '%1'", mURL.toDisplayString()); KMessageBox::error(dialogParent(), msg); return false; } } mMainWindow->showStatusMessage(i18n("Saved calendar '%1'.", mURL.toDisplayString())); return true; } bool ActionManager::saveAsURL(const QUrl &url) { qCDebug(KORGANIZER_LOG) << url.toDisplayString(); if (url.isEmpty()) { qCDebug(KORGANIZER_LOG) << "Empty URL."; return false; } if (!url.isValid()) { qCDebug(KORGANIZER_LOG) << "Malformed URL."; return false; } QString fileOrig = mFile; QUrl URLOrig = mURL; QTemporaryFile *tempFile = nullptr; if (url.isLocalFile()) { mFile = url.toLocalFile(); } else { tempFile = new QTemporaryFile; tempFile->setAutoRemove(false); tempFile->open(); mFile = tempFile->fileName(); } mURL = url; bool success = saveURL(); // Save local file and upload local file if (success) { delete mTempFile; mTempFile = tempFile; setTitle(); } else { KMessageBox::sorry(dialogParent(), i18n("Unable to save calendar to the file %1.", mFile), i18n("Error")); qCDebug(KORGANIZER_LOG) << "failed"; mURL = URLOrig; mFile = fileOrig; delete tempFile; } return success; } void ActionManager::saveProperties(KConfigGroup &config) { config.writeEntry("UseResourceCalendar", !mMainWindow->hasDocument()); if (mMainWindow->hasDocument()) { config.writePathEntry("Calendar", mURL.url()); } } void ActionManager::readProperties(const KConfigGroup &) { mMainWindow->init(false); } // Configuration changed as a result of the options dialog. void ActionManager::updateConfig() { mNextXDays->setText(i18np("&Next Day", "&Next %1 Days", KOPrefs::instance()->mNextXDays)); KOCore::self()->reloadPlugins(); /* Hide/Show the Reminder Daemon */ if (!KOPrefs::instance()->mShowReminderDaemon) { KPIM::ReminderClient::hideDaemon(); } else { KPIM::ReminderClient::showDaemon(); } // Commented out because it crashes KOrganizer. // mParts = KOCore::self()->reloadParts( mMainWindow, mParts ); #ifdef AKONADI_PORT_DISABLED // shouldn't be required anymore if (mCollectionView) { mCollectionView->updateView(); } #endif } void ActionManager::configureDateTime() { KProcess proc; proc << QStringLiteral("kcmshell5") << QStringLiteral("formats") << QStringLiteral("translations") << QStringLiteral("clock"); if (!proc.startDetached()) { KMessageBox::sorry(dialogParent(), i18n("Could not start control module for date and time format.")); } } KOrg::MainWindow *ActionManager::findInstance(const QUrl &url) { if (mWindowList) { if (url.isEmpty()) { return mWindowList->defaultInstance(); } else { return mWindowList->findInstance(url); } } else { return nullptr; } } bool ActionManager::openURL(const QString &url) { importCalendar(QUrl::fromLocalFile(url)); return true; } void ActionManager::dumpText(const QString &str) { qCDebug(KORGANIZER_LOG) << str; } void ActionManager::toggleDateNavigator() { bool visible = mDateNavigatorShowAction->isChecked(); if (mCalendarView) { mCalendarView->showDateNavigator(visible); } } void ActionManager::toggleTodoView() { bool visible = mTodoViewShowAction->isChecked(); if (mCalendarView) { mCalendarView->showTodoView(visible); } } void ActionManager::toggleEventViewer() { bool visible = mEventViewerShowAction->isChecked(); if (mCalendarView) { mCalendarView->showEventViewer(visible); } } void ActionManager::toggleResourceView() { const bool visible = mCollectionViewShowAction->isChecked(); if (mCollectionView) { if (visible) { mCollectionView->show(); } else { mCollectionView->hide(); } } } bool ActionManager::mergeURL(const QString &url) { return importURL(QUrl::fromLocalFile(url), true); } bool ActionManager::saveAsURL(const QString &url) { return saveAsURL(QUrl::fromLocalFile(url)); } QString ActionManager::getCurrentURLasString() const { return mURL.url(); } bool ActionManager::editIncidence(Akonadi::Item::Id id) { return mCalendarView->editIncidence(id); } bool ActionManager::showIncidence(Akonadi::Item::Id id) { return mCalendarView->showIncidence(id); } bool ActionManager::showIncidenceContext(Akonadi::Item::Id id) { return mCalendarView->showIncidenceContext(id); } bool ActionManager::handleCommandLine(const QStringList &args) { QCommandLineParser parser; korganizer_options(&parser); parser.process(args); KOrg::MainWindow *mainWindow = ActionManager::findInstance(QUrl()); bool ret = true; if (!mainWindow) { qCCritical(KORGANIZER_LOG) << "Unable to find default calendar resources view."; ret = false; } else if (parser.positionalArguments().isEmpty()) { // No filenames given => all other args are meaningless, show main Window mainWindow->topLevelWidget()->show(); } else { // Import, merge, or ask => we need the resource calendar window anyway. mainWindow->topLevelWidget()->show(); // Check for import, merge or ask const QStringList argList = parser.positionalArguments(); if (parser.isSet(QStringLiteral("import"))) { for (const QString &url : argList) { importURL(QUrl::fromUserInput(url), /*merge=*/ false); } } else if (parser.isSet(QStringLiteral("merge"))) { for (const QString &url : argList) { importURL(QUrl::fromUserInput(url), /*merge=*/ true); } } else { for (const QString &url : argList) { mainWindow->actionManager()->importCalendar(QUrl::fromUserInput(url)); } } } return ret; } bool ActionManager::deleteIncidence(Akonadi::Item::Id id, bool force) { return mCalendarView->deleteIncidence(id, force); } bool ActionManager::addIncidence(const QString &ical) { return mCalendarView->addIncidence(ical); } void ActionManager::downloadNewStuff() { - QPointer dialog = new KNS3::DownloadDialog(mCalendarView); + QPointer dialog = new KNS3::DownloadDialog(QStringLiteral("korganizer.knsrc"), mCalendarView); + dialog->setTitle(i18nc("@title", "KOrganizer Calendars Add-On Installer")); dialog->exec(); const auto installedEntries = dialog->installedEntries(); for (const KNS3::Entry &e : installedEntries) { qCDebug(KORGANIZER_LOG) << " downloadNewStuff :"; const QStringList lstFile = e.installedFiles(); if (lstFile.count() != 1) { continue; } const QString file = lstFile.at(0); const QUrl filename = QUrl::fromLocalFile(file); qCDebug(KORGANIZER_LOG) << "filename :" << filename; if (!filename.isValid()) { continue; } KCalendarCore::FileStorage storage(calendar()); storage.setFileName(file); storage.setSaveFormat(new KCalendarCore::ICalFormat); if (!storage.load()) { KMessageBox::error(mCalendarView, i18n("Could not load calendar %1.", file)); } else { QStringList eventSummaries; const KCalendarCore::Event::List events = calendar()->events(); eventSummaries.reserve(events.count()); for (const KCalendarCore::Event::Ptr &event : events) { eventSummaries.append(event->summary()); } const int result = KMessageBox::warningContinueCancelList( mCalendarView, i18n("The downloaded events will be merged into your current calendar."), eventSummaries); if (result != KMessageBox::Continue) { // FIXME (KNS2): hm, no way out here :-) } if (importURL(QUrl::fromLocalFile(file), true)) { // FIXME (KNS2): here neither } } } delete dialog; } QString ActionManager::localFileName() { return mFile; } class ActionManager::ActionStringsVisitor : public KCalendarCore::Visitor { public: ActionStringsVisitor() : mShow(nullptr) , mEdit(nullptr) , mDelete(nullptr) { } bool act(KCalendarCore::IncidenceBase::Ptr incidence, QAction *show, QAction *edit, QAction *del) { mShow = show; mEdit = edit; mDelete = del; return incidence->accept(*this, incidence); } protected: bool visit(const KCalendarCore::Event::Ptr &) override { if (mShow) { mShow->setText(i18n("&Show Event")); } if (mEdit) { mEdit->setText(i18n("&Edit Event...")); } if (mDelete) { mDelete->setText(i18n("&Delete Event")); } return true; } bool visit(const KCalendarCore::Todo::Ptr &) override { if (mShow) { mShow->setText(i18n("&Show To-do")); } if (mEdit) { mEdit->setText(i18n("&Edit To-do...")); } if (mDelete) { mDelete->setText(i18n("&Delete To-do")); } return true; } bool visit(const KCalendarCore::Journal::Ptr &) override { return assignDefaultStrings(); } bool visit(const KCalendarCore::FreeBusy::Ptr &) override // to inhibit hidden virtual compile warning { return false; } protected: bool assignDefaultStrings() { if (mShow) { mShow->setText(i18n("&Show")); } if (mEdit) { mEdit->setText(i18n("&Edit...")); } if (mDelete) { mDelete->setText(i18n("&Delete")); } return true; } QAction *mShow = nullptr; QAction *mEdit = nullptr; QAction *mDelete = nullptr; }; void ActionManager::processIncidenceSelection(const Akonadi::Item &item, const QDate &date) { //qCDebug(KORGANIZER_LOG) << "ActionManager::processIncidenceSelection()"; Q_UNUSED(date); const KCalendarCore::Incidence::Ptr incidence = CalendarSupport::incidence(item); if (!incidence) { enableIncidenceActions(false); return; } enableIncidenceActions(true); if (!mCalendarView->calendar()->hasRight(item, Akonadi::Collection::CanDeleteItem)) { mCutAction->setEnabled(false); mDeleteAction->setEnabled(false); } ActionStringsVisitor v; if (!v.act(incidence, mShowIncidenceAction, mEditIncidenceAction, mDeleteIncidenceAction)) { mShowIncidenceAction->setText(i18n("&Show")); mEditIncidenceAction->setText(i18n("&Edit...")); mDeleteIncidenceAction->setText(i18n("&Delete")); } } void ActionManager::enableIncidenceActions(bool enabled) { mShowIncidenceAction->setEnabled(enabled); mEditIncidenceAction->setEnabled(enabled); mDeleteIncidenceAction->setEnabled(enabled); mCutAction->setEnabled(enabled); mCopyAction->setEnabled(enabled); mDeleteAction->setEnabled(enabled); mPublishEvent->setEnabled(enabled); mForwardEvent->setEnabled(enabled); mSendInvitation->setEnabled(enabled); mSendCancel->setEnabled(enabled); mSendStatusUpdate->setEnabled(enabled); mRequestChange->setEnabled(enabled); mRequestUpdate->setEnabled(enabled); } Akonadi::Collection ActionManager::selectedCollection() const { const QModelIndex index = mCollectionView->view()->currentIndex(); if (!index.isValid()) { return Akonadi::Collection(); } return index.data(Akonadi::EntityTreeModel::CollectionRole).value(); } void ActionManager::keyBindings() { KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsDisallowed, view()); if (mMainWindow) { dlg.addCollection(mMainWindow->getActionCollection()); } for (KOrg::Part *part : qAsConst(mParts)) { if (part) { dlg.addCollection(part->actionCollection(), part->shortInfo()); } } dlg.configure(); } void ActionManager::loadParts() { mParts = KOCore::self()->loadParts(mMainWindow); } void ActionManager::setTitle() { mMainWindow->setTitle(); } void ActionManager::openEventEditor(const QString &text) { mCalendarView->newEvent(text); } void ActionManager::openEventEditor(const QString &summary, const QString &description, const QStringList &attachments) { mCalendarView->newEvent(summary, description, attachments); } void ActionManager::openEventEditor(const QString &summary, const QString &description, const QStringList &attachments, const QStringList &attendees) { mCalendarView->newEvent(summary, description, attachments, attendees); } void ActionManager::openEventEditor(const QString &summary, const QString &description, const QString &uri, const QString &file, const QStringList &attendees, const QString &attachmentMimetype) { int action = IncidenceEditorNG::IncidenceEditorSettings::self()->defaultEmailAttachMethod(); if (attachmentMimetype != QLatin1String("message/rfc822")) { action = IncidenceEditorNG::IncidenceEditorSettings::Link; } else if (IncidenceEditorNG::IncidenceEditorSettings::self()->defaultEmailAttachMethod() == IncidenceEditorNG::IncidenceEditorSettings::Ask) { QMenu *menu = new QMenu(nullptr); QAction *attachLink = menu->addAction(i18n("Attach as &link")); QAction *attachInline = menu->addAction(i18n("Attach &inline")); QAction *attachBody = menu->addAction(i18n("Attach inline &without attachments")); menu->addSeparator(); menu->addAction(QIcon::fromTheme(QStringLiteral("dialog-cancel")), i18n("C&ancel")); QAction *ret = menu->exec(QCursor::pos()); delete menu; if (ret == attachLink) { action = IncidenceEditorNG::IncidenceEditorSettings::Link; } else if (ret == attachInline) { action = IncidenceEditorNG::IncidenceEditorSettings::InlineFull; } else if (ret == attachBody) { action = IncidenceEditorNG::IncidenceEditorSettings::InlineBody; } else { return; } } QString attData; QTemporaryFile tf; tf.setAutoRemove(true); switch (action) { case IncidenceEditorNG::IncidenceEditorSettings::Link: attData = uri; break; case IncidenceEditorNG::IncidenceEditorSettings::InlineFull: attData = file; break; case IncidenceEditorNG::IncidenceEditorSettings::InlineBody: { QFile f(file); if (!f.open(QFile::ReadOnly)) { return; } KMime::Message *msg = new KMime::Message(); msg->setContent(f.readAll()); msg->parse(); if (msg == msg->textContent() || msg->textContent() == nullptr) { // no attachments attData = file; } else { if (KMessageBox::warningContinueCancel( nullptr, i18n("Removing attachments from an email might invalidate its signature."), i18n("Remove Attachments"), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), QStringLiteral("BodyOnlyInlineAttachment")) != KMessageBox::Continue) { delete msg; return; } KMime::Message *newMsg = new KMime::Message(); newMsg->setHead(msg->head()); newMsg->setBody(msg->textContent()->body()); newMsg->parse(); newMsg->contentTransferEncoding()->from7BitString( msg->textContent()->contentTransferEncoding()->as7BitString()); newMsg->contentType()->from7BitString(msg->textContent()->contentType()->as7BitString()); newMsg->assemble(); tf.write(newMsg->encodedContent()); attData = tf.fileName(); } tf.close(); delete msg; break; } default: return; } mCalendarView->newEvent(summary, description, QStringList(attData), attendees, QStringList(attachmentMimetype), action != IncidenceEditorNG::IncidenceEditorSettings::Link); } void ActionManager::openTodoEditor(const QString &text) { mCalendarView->newTodo(text); } void ActionManager::openTodoEditor(const QString &summary, const QString &description, const QStringList &attachments) { mCalendarView->newTodo(summary, description, attachments); } void ActionManager::openTodoEditor(const QString &summary, const QString &description, const QStringList &attachments, const QStringList &attendees) { mCalendarView->newTodo(summary, description, attachments, attendees); } void ActionManager::openTodoEditor(const QString &summary, const QString &description, const QString &uri, const QString &file, const QStringList &attendees, const QString &attachmentMimetype) { int action = KOPrefs::instance()->defaultTodoAttachMethod(); if (attachmentMimetype != QLatin1String("message/rfc822")) { action = KOPrefs::TodoAttachLink; } else if (KOPrefs::instance()->defaultTodoAttachMethod() == KOPrefs::TodoAttachAsk) { QMenu *menu = new QMenu(nullptr); QAction *attachLink = menu->addAction(i18n("Attach as &link")); QAction *attachInline = menu->addAction(i18n("Attach &inline")); menu->addSeparator(); menu->addAction(QIcon::fromTheme(QStringLiteral("dialog-cancel")), i18n("C&ancel")); QAction *ret = menu->exec(QCursor::pos()); delete menu; if (ret == attachLink) { action = KOPrefs::TodoAttachLink; } else if (ret == attachInline) { action = KOPrefs::TodoAttachInlineFull; } else { return; } } QString attData; switch (action) { case KOPrefs::TodoAttachLink: attData = uri; break; case KOPrefs::TodoAttachInlineFull: attData = file; break; default: return; } mCalendarView->newTodo(summary, description, QStringList(attData), attendees, QStringList(attachmentMimetype), action != KOPrefs::TodoAttachLink); } void ActionManager::openJournalEditor(const QDate &date) { mCalendarView->newJournal(date); } void ActionManager::openJournalEditor(const QString &text, const QDate &date) { mCalendarView->newJournal(text, date); } void ActionManager::openJournalEditor(const QString &text) { mCalendarView->newJournal(text); } void ActionManager::showJournalView() { mCalendarView->viewManager()->showJournalView(); } void ActionManager::showTodoView() { mCalendarView->viewManager()->showTodoView(); } void ActionManager::showEventView() { mCalendarView->viewManager()->showEventView(); } void ActionManager::goDate(const QDate &date) { mCalendarView->goDate(date); } void ActionManager::goDate(const QString &date) { goDate(QLocale().toDate(date)); } void ActionManager::showDate(const QDate &date) { mCalendarView->showDate(date); } void ActionManager::updateUndoRedoActions() { Akonadi::History *history = mCalendarView->incidenceChanger()->history(); if (history->undoAvailable()) { mUndoAction->setEnabled(true); mUndoAction->setText(i18n("Undo: %1", history->nextUndoDescription())); } else { mUndoAction->setEnabled(false); mUndoAction->setText(i18n("Undo")); } if (history->redoAvailable()) { mRedoAction->setEnabled(true); mRedoAction->setText(i18n("Redo: %1", history->nextRedoDescription())); } else { mRedoAction->setEnabled(false); mRedoAction->setText(i18n("Redo")); } mUndoAction->setIconText(i18n("Undo")); } bool ActionManager::queryClose() { return true; } void ActionManager::importCalendar(const QUrl &url) { if (!url.isValid()) { KMessageBox::error(dialogParent(), i18n("URL '%1' is invalid.", url.toDisplayString())); return; } const QString questionText = i18nc("@info", "

Would you like to merge this calendar item into an existing calendar " "or use it to create a brand new calendar?

" "

If you select merge, then you will be given the opportunity to select " "the destination calendar.

" "

If you select add, then a new calendar will be created for you automatically.

"); const int answer = KMessageBox::questionYesNoCancel( dialogParent(), questionText, i18nc("@title:window", "Import Calendar"), KGuiItem(i18n("Merge into existing calendar")), KGuiItem(i18n("Add as new calendar"))); switch (answer) { case KMessageBox::Yes: //merge importURL(url, true); break; case KMessageBox::No: //import importURL(url, false); break; default: return; } } void ActionManager::slotAutoArchivingSettingsModified() { if (CalendarSupport::KCalPrefs::instance()->mAutoArchive) { mAutoArchiveTimer->start(4 * 60 * 60 * 1000); // check again in 4 hours } else { mAutoArchiveTimer->stop(); } } void ActionManager::slotAutoArchive() { if (!mCalendarView->calendar()) { // can this happen? return; } mAutoArchiveTimer->stop(); CalendarSupport::EventArchiver archiver; archiver.runAuto(calendar(), mCalendarView->incidenceChanger(), mCalendarView, false /*no gui*/); // restart timer with the correct delay ( especially useful for the first time ) slotAutoArchivingSettingsModified(); } QWidget *ActionManager::dialogParent() { return mCalendarView->topLevelWidget(); } void ActionManager::openTodoEditor(const QString &summary, const QString &description, const QStringList &attachmentUris, const QStringList &attendees, const QStringList &attachmentMimetypes, bool attachmentIsInline) { Q_UNUSED(summary); Q_UNUSED(description); Q_UNUSED(attachmentUris); Q_UNUSED(attendees); Q_UNUSED(attachmentMimetypes); Q_UNUSED(attachmentIsInline); qCWarning(KORGANIZER_LOG) << "Not implemented in korg-desktop"; } void ActionManager::openEventEditor(const QString &summary, const QString &description, const QStringList &attachmentUris, const QStringList &attendees, const QStringList &attachmentMimetypes, bool attachmentIsInline) { Q_UNUSED(summary); Q_UNUSED(description); Q_UNUSED(attachmentUris); Q_UNUSED(attendees); Q_UNUSED(attachmentMimetypes); Q_UNUSED(attachmentIsInline); qCWarning(KORGANIZER_LOG) << "Not implemented in korg-desktop"; } void ActionManager::setHelpText(QAction *act, const QString &text) { act->setStatusTip(text); act->setToolTip(text); if (act->whatsThis().isEmpty()) { act->setWhatsThis(text); } } diff --git a/src/data/korganizer.knsrc b/src/data/korganizer.knsrc index 62474347..5eb760dc 100644 --- a/src/data/korganizer.knsrc +++ b/src/data/korganizer.knsrc @@ -1,26 +1,26 @@ [KNewStuff3] Name=KOrganizer Calendar Name[ca]=Calendari del KOrganizer Name[ca@valencia]=Calendari del KOrganizer Name[cs]=Kalendář KOrganizer Name[de]=KOrganizer-Kalender Name[en_GB]=KOrganizer Calendar Name[es]=Calendario de KOrganizer Name[fi]=KOrganizer-kalenteri Name[fr]=Calendrier KOrganizer Name[gl]=Calendario de KOrganizer Name[it]=Calendario di KOrganizer Name[ko]=KOrganizer 달력 Name[nl]=KOrganizer-agenda Name[pl]=Kalendarz KOrganizera Name[pt]=Calendário do KOrganizer Name[pt_BR]=Calendário do KOrganizer Name[ru]=Служба календаря KOrganizer Name[sk]=KOrganizer Kalendár Name[sv]=Korganizer-kalender Name[uk]=Календар KOrganizer Name[x-test]=xxKOrganizer Calendarxx Name[zh_TW]=KOrganizer 行事曆 -ProvidersUrl=https://autoconfig.kde.org/ocs/providers.xml Categories=KOrganizer Calendar TargetDir=korganizer +Uncompress=archive