/* 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 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 TQt, and distribute the resulting executable, without including the source code for TQt in the source distribution. */ #include "actionmanager.h" #include "previewdialog.h" #include "alarmclient.h" #include "calendarview.h" #include "kocore.h" #include "kodialogmanager.h" #include "koglobals.h" #include "koprefs.h" #include "koviewmanager.h" #include "koagendaview.h" #include "multiagendaview.h" #include "kowindowlist.h" #include "kprocess.h" #include "konewstuff.h" #include "history.h" #include "kogroupware.h" #include "resourceview.h" #include "previewdialog.h" #include "eventarchiver.h" #include "stdcalendar.h" #include "freebusymanager.h" #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 // FIXME: Several places in the file don't use TDEConfigXT yet! KOWindowList *ActionManager::mWindowList = 0; ActionManager::ActionManager( KXMLGUIClient *client, CalendarView *widget, TQObject *parent, KOrg::MainWindow *mainWindow, bool isPart ) : TQObject( parent ), KCalendarIface(), mRecent( 0 ), mResourceButtonsAction( 0 ), mResourceViewShowAction( 0 ), mCalendar( 0 ), mCalendarResources( 0 ), mResourceView( 0 ), mIsClosing( false ) { mGUIClient = client; mACollection = mGUIClient->actionCollection(); mCalendarView = widget; mIsPart = isPart; mTempFile = 0; mNewStuff = 0; mHtmlExportSync = false; mMainWindow = mainWindow; } ActionManager::~ActionManager() { delete mNewStuff; // Remove Part plugins KOCore::self()->unloadParts( mMainWindow, mParts ); delete mTempFile; // Take this window out of the window list. mWindowList->removeWindow( mMainWindow ); delete mCalendarView; delete mCalendar; kdDebug(5850) << "~ActionManager() done" << endl; } // see the Note: below for why this method is necessary void ActionManager::init() { // Construct the groupware object KOGroupware::create( mCalendarView, mCalendarResources ); // add this instance of the window to the static list. if ( !mWindowList ) { mWindowList = new KOWindowList; // Show tip of the day, when the first calendar is shown. if ( !mIsPart ) TQTimer::singleShot( 0, TQT_TQOBJECT(this), TQT_SLOT( showTipOnStart() ) ); } // 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 ); initActions(); // set up autoSaving stuff mAutoSaveTimer = new TQTimer( this ); connect( mAutoSaveTimer,TQT_SIGNAL( timeout() ), TQT_SLOT( checkAutoSave() ) ); if ( KOPrefs::instance()->mAutoSave && KOPrefs::instance()->mAutoSaveInterval > 0 ) { mAutoSaveTimer->start( 1000 * 60 * KOPrefs::instance()->mAutoSaveInterval ); } mAutoArchiveTimer = new TQTimer( this ); connect( mAutoArchiveTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( slotAutoArchive() ) ); // First auto-archive should be in 5 minutes (like in kmail). if ( KOPrefs::instance()->mAutoArchive ) mAutoArchiveTimer->start( 5 * 60 * 1000, true ); // singleshot setTitle(); connect( mCalendarView, TQT_SIGNAL( modifiedChanged( bool ) ), TQT_SLOT( setTitle() ) ); connect( mCalendarView, TQT_SIGNAL( configChanged() ), TQT_SLOT( updateConfig() ) ); connect( mCalendarView, TQT_SIGNAL( incidenceSelected( Incidence *,const TQDate & ) ), TQT_TQOBJECT(this), TQT_SLOT( processIncidenceSelection( Incidence *,const TQDate & ) ) ); connect( mCalendarView, TQT_SIGNAL( exportHTML( HTMLExportSettings * ) ), TQT_TQOBJECT(this), TQT_SLOT( exportHTML( HTMLExportSettings * ) ) ); processIncidenceSelection( 0, TQDate() ); // Update state of paste action mCalendarView->checkClipboard(); } void ActionManager::createCalendarLocal() { mCalendar = new CalendarLocal( KOPrefs::instance()->mTimeZoneId ); mCalendarView->setCalendar( mCalendar ); mCalendarView->readSettings(); initCalendar( mCalendar ); } void ActionManager::createCalendarResources() { mCalendarResources = KOrg::StdCalendar::self(); CalendarResourceManager *manager = mCalendarResources->resourceManager(); kdDebug(5850) << "CalendarResources used by KOrganizer:" << endl; CalendarResourceManager::Iterator it; for( it = manager->begin(); it != manager->end(); ++it ) { kdDebug(5850) << " " << (*it)->resourceName() << endl; (*it)->setResolveConflict( true ); // (*it)->dump(); } setDestinationPolicy(); mCalendarView->setCalendar( mCalendarResources ); mCalendarView->readSettings(); ResourceViewFactory factory( mCalendarResources, mCalendarView ); mCalendarView->addExtension( &factory ); mResourceView = factory.resourceView(); connect( mCalendarResources, TQT_SIGNAL( calendarChanged() ), mCalendarView, TQT_SLOT( resourcesChanged() ) ); connect( mCalendarResources, TQT_SIGNAL( signalErrorMessage( const TQString & ) ), mCalendarView, TQT_SLOT( showErrorMessage( const TQString & ) ) ); connect( mCalendarView, TQT_SIGNAL( configChanged() ), TQT_SLOT( updateConfig() ) ); initCalendar( mCalendarResources ); } void ActionManager::initCalendar( Calendar *cal ) { cal->setOwner( Person( KOPrefs::instance()->fullName(), KOPrefs::instance()->email() ) ); // setting fullName and email do not really count as modifying the calendar mCalendarView->setModified( false ); } void ActionManager::initActions() { TDEAction *action; //*************************** FILE MENU ********************************** //~~~~~~~~~~~~~~~~~~~~~~~ LOADING / SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ( mIsPart ) { if ( mMainWindow->hasDocument() ) { KStdAction::openNew( TQT_TQOBJECT(this), TQT_SLOT(file_new()), mACollection, "korganizer_openNew" ); KStdAction::open( TQT_TQOBJECT(this), TQT_SLOT( file_open() ), mACollection, "korganizer_open" ); mRecent = KStdAction::openRecent( TQT_TQOBJECT(this), TQT_SLOT( file_open( const KURL& ) ), mACollection, "korganizer_openRecent" ); KStdAction::revert( this,TQT_SLOT( file_revert() ), mACollection, "korganizer_revert" ); KStdAction::saveAs( TQT_TQOBJECT(this), TQT_SLOT( file_saveas() ), mACollection, "korganizer_saveAs" ); KStdAction::save( TQT_TQOBJECT(this), TQT_SLOT( file_save() ), mACollection, "korganizer_save" ); } KStdAction::print( TQT_TQOBJECT(mCalendarView), TQT_SLOT( print() ), mACollection, "korganizer_print" ); } else { KStdAction::openNew( TQT_TQOBJECT(this), TQT_SLOT( file_new() ), mACollection ); KStdAction::open( TQT_TQOBJECT(this), TQT_SLOT( file_open() ), mACollection ); mRecent = KStdAction::openRecent( TQT_TQOBJECT(this), TQT_SLOT( file_open( const KURL& ) ), mACollection ); if ( mMainWindow->hasDocument() ) { KStdAction::revert( this,TQT_SLOT( file_revert() ), mACollection ); KStdAction::save( TQT_TQOBJECT(this), TQT_SLOT( file_save() ), mACollection ); KStdAction::saveAs( TQT_TQOBJECT(this), TQT_SLOT( file_saveas() ), mACollection ); } KStdAction::print( TQT_TQOBJECT(mCalendarView), TQT_SLOT( print() ), mACollection ); } //~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT / EXPORT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ new TDEAction( i18n("Import &Event/Calendar (ICS-/VCS-File)..."), 0, TQT_TQOBJECT(this), TQT_SLOT( file_merge() ), mACollection, "import_icalendar" ); new TDEAction( i18n("&Import From UNIX Ical tool (.calendar-File)"), 0, TQT_TQOBJECT(this), TQT_SLOT( file_icalimport() ), mACollection, "import_ical" ); new TDEAction( i18n("Get &Hot New Stuff..."), 0, this, TQT_SLOT( downloadNewStuff() ), mACollection, "downloadnewstuff" ); new TDEAction( i18n("Export &Web Page..."), "webexport", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( exportWeb() ), mACollection, "export_web" ); new TDEAction( i18n("&iCalendar..."), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( exportICalendar() ), mACollection, "export_icalendar" ); new TDEAction( i18n("&vCalendar..."), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( exportVCalendar() ), mACollection, "export_vcalendar" ); new TDEAction( i18n("Upload &Hot New Stuff..."), 0, TQT_TQOBJECT(this), TQT_SLOT( uploadNewStuff() ), mACollection, "uploadnewstuff" ); new TDEAction( i18n("Archive O&ld Entries..."), 0, TQT_TQOBJECT(this), TQT_SLOT( file_archive() ), mACollection, "file_archive" ); new TDEAction( i18n("delete completed to-dos", "Pur&ge Completed To-dos"), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( purgeCompleted() ), mACollection, "purge_completed" ); //************************** EDIT MENU ********************************* TDEAction *pasteAction; KOrg::History *h = mCalendarView->history(); if ( mIsPart ) { // edit menu mCutAction = KStdAction::cut( TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_cut() ), mACollection, "korganizer_cut" ); mCopyAction = KStdAction::copy( TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_copy() ), mACollection, "korganizer_copy" ); pasteAction = KStdAction::paste( TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_paste() ), mACollection, "korganizer_paste" ); mUndoAction = KStdAction::undo( h, TQT_SLOT( undo() ), mACollection, "korganizer_undo" ); mRedoAction = KStdAction::redo( h, TQT_SLOT( redo() ), mACollection, "korganizer_redo" ); } else { mCutAction = KStdAction::cut( TQT_TQOBJECT(mCalendarView),TQT_SLOT( edit_cut() ), mACollection ); mCopyAction = KStdAction::copy( TQT_TQOBJECT(mCalendarView),TQT_SLOT( edit_copy() ), mACollection ); pasteAction = KStdAction::paste( TQT_TQOBJECT(mCalendarView),TQT_SLOT( edit_paste() ), mACollection ); mUndoAction = KStdAction::undo( TQT_TQOBJECT(h), TQT_SLOT( undo() ), mACollection ); mRedoAction = KStdAction::redo( TQT_TQOBJECT(h), TQT_SLOT( redo() ), mACollection ); } mDeleteAction = new TDEAction( i18n("&Delete"), "edit-delete", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( appointment_delete() ), mACollection, "edit_delete" ); if ( mIsPart ) { KStdAction::find( mCalendarView->dialogManager(), TQT_SLOT( showSearchDialog() ), mACollection, "korganizer_find" ); } else { KStdAction::find( mCalendarView->dialogManager(), TQT_SLOT( showSearchDialog() ), mACollection ); } pasteAction->setEnabled( false ); mUndoAction->setEnabled( false ); mRedoAction->setEnabled( false ); connect( mCalendarView, TQT_SIGNAL( pasteEnabled( bool ) ), pasteAction, TQT_SLOT( setEnabled( bool ) ) ); connect( h, TQT_SIGNAL( undoAvailable( const TQString & ) ), TQT_SLOT( updateUndoAction( const TQString & ) ) ); connect( h, TQT_SIGNAL( redoAvailable( const TQString & ) ), TQT_SLOT( updateRedoAction( const TQString & ) ) ); //************************** VIEW MENU ********************************* //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VIEWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ new TDEAction( i18n("What's &Next"), KOGlobals::self()->smallIcon( "whatsnext" ), 0, mCalendarView->viewManager(), TQT_SLOT( showWhatsNextView() ), mACollection, "view_whatsnext" ); new TDEAction( i18n("&Day"), KOGlobals::self()->smallIcon( "1day" ), 0, mCalendarView->viewManager(), TQT_SLOT( showDayView() ), mACollection, "view_day" ); mNextXDays = new TDEAction( "", KOGlobals::self()->smallIcon( "xdays" ), 0, mCalendarView->viewManager(), TQT_SLOT( showNextXView() ), mACollection, "view_nextx" ); mNextXDays->setText( i18n( "&Next Day", "Ne&xt %n Days", KOPrefs::instance()->mNextXDays ) ); new TDEAction( i18n("W&ork Week"), KOGlobals::self()->smallIcon( "5days" ), 0, mCalendarView->viewManager(), TQT_SLOT( showWorkWeekView() ), mACollection, "view_workweek" ); new TDEAction( i18n("&Week"), KOGlobals::self()->smallIcon( "7days" ), 0, mCalendarView->viewManager(), TQT_SLOT( showWeekView() ), mACollection, "view_week" ); new TDEAction( i18n("&Month"), KOGlobals::self()->smallIcon( "month" ), 0, mCalendarView->viewManager(), TQT_SLOT( showMonthView() ), mACollection, "view_month" ); new TDEAction( i18n("&List"), KOGlobals::self()->smallIcon( "list" ), 0, mCalendarView->viewManager(), TQT_SLOT( showListView() ), mACollection, "view_list" ); new TDEAction( i18n("&To-do List"), KOGlobals::self()->smallIcon( "todo" ), 0, mCalendarView->viewManager(), TQT_SLOT( showTodoView() ), mACollection, "view_todo" ); new TDEAction( i18n("&Journal"), KOGlobals::self()->smallIcon( "journal" ), 0, mCalendarView->viewManager(), TQT_SLOT( showJournalView() ), mACollection, "view_journal" ); new TDEAction( i18n("&Timeline View"), KOGlobals::self()->smallIcon( "timeline" ), 0, mCalendarView->viewManager(), TQT_SLOT( showTimelineView() ), mACollection, "view_timeline" ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~ FILTERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ new TDEAction( i18n("&Refresh"), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( updateView() ), mACollection, "update" ); // TODO: // new TDEAction( i18n("Hide &Completed To-dos"), 0, // mCalendarView, TQT_SLOT( toggleHideCompleted() ), // mACollection, "hide_completed_todos" ); mFilterAction = new TDESelectAction( i18n("F&ilter"), 0, mACollection, "filter_select" ); mFilterAction->setEditable( false ); connect( mFilterAction, TQT_SIGNAL( activated(int) ), mCalendarView, TQT_SLOT( filterActivated( int ) ) ); connect( mCalendarView, TQT_SIGNAL( newFilterListSignal( const TQStringList & ) ), mFilterAction, TQT_SLOT( setItems( const TQStringList & ) ) ); connect( mCalendarView, TQT_SIGNAL( selectFilterSignal( int ) ), mFilterAction, TQT_SLOT( setCurrentItem( int ) ) ); connect( mCalendarView, TQT_SIGNAL( filterChanged() ), TQT_TQOBJECT(this), TQT_SLOT( setTitle() ) ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ZOOM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TODO: try to find / create better icons for the following 4 actions new TDEAction( i18n( "Zoom In Horizontally" ), "zoom-in", 0, mCalendarView->viewManager(), TQT_SLOT( zoomInHorizontally() ), mACollection, "zoom_in_horizontally" ); new TDEAction( i18n( "Zoom Out Horizontally" ), "zoom-out", 0, mCalendarView->viewManager(), TQT_SLOT( zoomOutHorizontally() ), mACollection, "zoom_out_horizontally" ); new TDEAction( i18n( "Zoom In Vertically" ), "zoom-in", 0, mCalendarView->viewManager(), TQT_SLOT( zoomInVertically() ), mACollection, "zoom_in_vertically" ); new TDEAction( i18n( "Zoom Out Vertically" ), "zoom-out", 0, mCalendarView->viewManager(), TQT_SLOT( zoomOutVertically() ), mACollection, "zoom_out_vertically" ); //************************** Actions MENU ********************************* new TDEAction( i18n("Go to &Today"), "today", 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( goToday() ), mACollection, "go_today" ); bool isRTL = TQApplication::reverseLayout(); action = new TDEAction( i18n("Go &Backward"), isRTL ? "forward" : "back", 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( goPrevious() ), mACollection, "go_previous" ); // 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, TQT_SIGNAL( changeNavStringPrev( const TQString & ) ), action, TQT_SLOT( setText( const TQString & ) ) ); connect( mCalendarView, TQT_SIGNAL( changeNavStringPrev( const TQString & ) ), TQT_TQOBJECT(this), TQT_SLOT( dumpText( const TQString & ) ) );*/ action = new TDEAction( i18n("Go &Forward"), isRTL ? "back" : "forward", 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( goNext() ), mACollection, "go_next" ); /* connect( mCalendarView,TQT_SIGNAL( changeNavStringNext( const TQString & ) ), action,TQT_SLOT( setText( const TQString & ) ) ); */ //************************** Actions MENU ********************************* new TDEAction( i18n("New E&vent..."), KOGlobals::self()->smallIcon( "newappointment" ), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(newEvent()), mACollection, "new_event" ); new TDEAction( i18n("New &To-do..."), KOGlobals::self()->smallIcon( "newtodo" ), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(newTodo()), mACollection, "new_todo" ); action = new TDEAction( i18n("New Su&b-to-do..."), 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( newSubTodo() ), mACollection, "new_subtodo" ); action->setEnabled( false ); connect( mCalendarView,TQT_SIGNAL( todoSelected( bool ) ), action,TQT_SLOT( setEnabled( bool ) ) ); new TDEAction( i18n("New &Journal..."), KOGlobals::self()->smallIcon( "newjournal" ), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(newJournal()), mACollection, "new_journal" ); mShowIncidenceAction = new TDEAction( i18n("&Show"), 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( showIncidence() ), mACollection, "show_incidence" ); mEditIncidenceAction = new TDEAction( i18n("&Edit..."), 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( editIncidence() ), mACollection, "edit_incidence" ); mDeleteIncidenceAction = new TDEAction( i18n("&Delete"), Key_Delete, TQT_TQOBJECT(mCalendarView),TQT_SLOT( deleteIncidence()), mACollection, "delete_incidence" ); action = new TDEAction( i18n("&Make Sub-to-do Independent"), 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( todo_unsub() ), mACollection, "unsub_todo" ); action->setEnabled( false ); connect( mCalendarView,TQT_SIGNAL( subtodoSelected( bool ) ), action,TQT_SLOT( setEnabled( bool ) ) ); // TODO: Add item to move the incidence to different resource // mAssignResourceAction = new TDEAction( i18n("Assign &Resource..."), 0, // mCalendarView, TQT_SLOT( assignResource()), // mACollection, "assign_resource" ); // TODO: Add item to quickly toggle the reminder of a given incidence // mToggleAlarmAction = new TDEToggleAction( i18n("&Activate Reminder"), 0, // mCalendarView, TQT_SLOT( toggleAlarm()), // mACollection, "activate_alarm" ); //************************** SCHEDULE MENU ******************************** mPublishEvent = new TDEAction( i18n("&Publish Item Information..."), "mail-send", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( schedule_publish() ), mACollection, "schedule_publish" ); mPublishEvent->setEnabled( false ); mSendInvitation = new TDEAction( i18n( "Send &Invitation to Attendees" ), "mail_generic", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_request()), mACollection, "schedule_request" ); mSendInvitation->setEnabled( false ); connect( mCalendarView, TQT_SIGNAL(organizerEventsSelected(bool)), mSendInvitation, TQT_SLOT(setEnabled(bool)) ); mRequestUpdate = new TDEAction( i18n( "Re&quest Update" ), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_refresh()), mACollection, "schedule_refresh" ); mRequestUpdate->setEnabled( false ); connect( mCalendarView, TQT_SIGNAL(groupEventsSelected(bool)), mRequestUpdate, TQT_SLOT(setEnabled(bool)) ); mSendCancel = new TDEAction( i18n( "Send &Cancelation to Attendees" ), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_cancel()), mACollection, "schedule_cancel" ); mSendCancel->setEnabled( false ); connect( mCalendarView, TQT_SIGNAL(organizerEventsSelected(bool)), mSendCancel, TQT_SLOT(setEnabled(bool)) ); mSendStatusUpdate = new TDEAction( i18n( "Send Status &Update" ), "mail-reply-sender", 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT(schedule_reply()), mACollection, "schedule_reply" ); mSendStatusUpdate->setEnabled( false ); connect( mCalendarView, TQT_SIGNAL(groupEventsSelected(bool)), mSendStatusUpdate, TQT_SLOT(setEnabled(bool)) ); mRequestChange = new TDEAction( i18n( "counter proposal", "Request Chan&ge" ), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_counter()), mACollection, "schedule_counter" ); mRequestChange->setEnabled( false ); connect( mCalendarView, TQT_SIGNAL(groupEventsSelected(bool)), mRequestChange, TQT_SLOT(setEnabled(bool)) ); mForwardEvent = new TDEAction( i18n("&Send as iCalendar..."), "mail-forward", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_forward()), mACollection, "schedule_forward" ); mForwardEvent->setEnabled( false ); action = new TDEAction( i18n("&Mail Free Busy Information..."), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( mailFreeBusy() ), mACollection, "mail_freebusy" ); action->setEnabled( true ); action = new TDEAction( i18n("&Upload Free Busy Information"), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( uploadFreeBusy() ), mACollection, "upload_freebusy" ); action->setEnabled( true ); if ( !mIsPart ) { action = new TDEAction( i18n("&Addressbook"),"contents",0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( openAddressbook() ), mACollection,"addressbook" ); } //************************** SETTINGS MENU ******************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mDateNavigatorShowAction = new TDEToggleAction( i18n("Show Date Navigator"), 0, TQT_TQOBJECT(this), TQT_SLOT( toggleDateNavigator() ), mACollection, "show_datenavigator" ); mTodoViewShowAction = new TDEToggleAction ( i18n("Show To-do View"), 0, TQT_TQOBJECT(this), TQT_SLOT( toggleTodoView() ), mACollection, "show_todoview" ); mEventViewerShowAction = new TDEToggleAction ( i18n("Show Item Viewer"), 0, TQT_TQOBJECT(this), TQT_SLOT( toggleEventViewer() ), mACollection, "show_eventviewer" ); TDEConfig *config = KOGlobals::self()->config(); config->setGroup( "Settings" ); mDateNavigatorShowAction->setChecked( config->readBoolEntry( "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->readBoolEntry( "TodoViewVisible", mIsPart ? false : true ) ); mEventViewerShowAction->setChecked( config->readBoolEntry( "EventViewerVisible", true ) ); toggleDateNavigator(); toggleTodoView(); toggleEventViewer(); if ( !mMainWindow->hasDocument() ) { mResourceViewShowAction = new TDEToggleAction ( i18n("Show Resource View"), 0, TQT_TQOBJECT(this), TQT_SLOT( toggleResourceView() ), mACollection, "show_resourceview" ); mResourceButtonsAction = new TDEToggleAction( i18n("Show &Resource Buttons"), 0, TQT_TQOBJECT(this), TQT_SLOT( toggleResourceButtons() ), mACollection, "show_resourcebuttons" ); mResourceViewShowAction->setChecked( config->readBoolEntry( "ResourceViewVisible", true ) ); mResourceButtonsAction->setChecked( config->readBoolEntry( "ResourceButtonsVisible", true ) ); toggleResourceView(); toggleResourceButtons(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ new TDEAction( i18n("Configure &Date && Time..."), 0, TQT_TQOBJECT(this), TQT_SLOT( configureDateTime() ), mACollection, "conf_datetime" ); // TODO: Add an item to show the resource management dlg // new TDEAction( i18n("Manage &Resources..."), 0, // TQT_TQOBJECT(this), TQT_SLOT( manageResources() ), // mACollection, "conf_resources" ); new TDEAction( i18n("Manage View &Filters..."), "configure", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( editFilters() ), mACollection, "edit_filters" ); new TDEAction( i18n("Manage C&ategories..."), 0, TQT_TQOBJECT(mCalendarView->dialogManager()), TQT_SLOT( showCategoryEditDialog() ), mACollection, "edit_categories" ); if ( mIsPart ) { new TDEAction( i18n("&Configure Calendar..."), "configure", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_options() ), mACollection, "korganizer_configure" ); KStdAction::keyBindings( TQT_TQOBJECT(this), TQT_SLOT( keyBindings() ), mACollection, "korganizer_configure_shortcuts" ); } else { KStdAction::preferences( TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_options() ), mACollection ); KStdAction::keyBindings( TQT_TQOBJECT(this), TQT_SLOT( keyBindings() ), mACollection ); } //**************************** HELP MENU ********************************** KStdAction::tipOfDay( TQT_TQOBJECT(this), TQT_SLOT( showTip() ), mACollection, "help_tipofday" ); // new TDEAction( i18n("Show Intro Page"), 0, // mCalendarView,TQT_SLOT( showIntro() ), // mACollection,"show_intro" ); //************************* TOOLBAR ACTIONS ******************************* TQLabel *filterLabel = new TQLabel( i18n("Filter: "), mCalendarView ); filterLabel->hide(); new KWidgetAction( filterLabel, i18n("Filter: "), 0, 0, 0, mACollection, "filter_label" ); } void ActionManager::readSettings() { // read settings from the TDEConfig, supplying reasonable // defaults where none are to be found TDEConfig *config = KOGlobals::self()->config(); if ( mRecent ) mRecent->loadEntries( config ); mCalendarView->readSettings(); } void ActionManager::writeSettings() { kdDebug(5850) << "ActionManager::writeSettings" << endl; TDEConfig *config = KOGlobals::self()->config(); mCalendarView->writeSettings(); config->setGroup( "Settings" ); if ( mResourceButtonsAction ) { config->writeEntry( "ResourceButtonsVisible", mResourceButtonsAction->isChecked() ); } if ( mDateNavigatorShowAction ) { config->writeEntry( "DateNavigatorVisible", mDateNavigatorShowAction->isChecked() ); } if ( mTodoViewShowAction ) { config->writeEntry( "TodoViewVisible", mTodoViewShowAction->isChecked() ); } if ( mResourceViewShowAction ) { config->writeEntry( "ResourceViewVisible", mResourceViewShowAction->isChecked() ); } if ( mEventViewerShowAction ) { config->writeEntry( "EventViewerVisible", mEventViewerShowAction->isChecked() ); } if ( mRecent ) mRecent->saveEntries( config ); config->sync(); if ( mCalendarResources ) { mCalendarResources->resourceManager()->writeConfig(); } } void ActionManager::file_new() { emit actionNew(); } void ActionManager::file_open() { KURL url; TQString defaultPath = locateLocal( "data","korganizer/" ); url = KFileDialog::getOpenURL( defaultPath,i18n("*.vcs *.ics|Calendar Files"), dialogParent() ); file_open( url ); } void ActionManager::file_open( const KURL &url ) { if ( url.isEmpty() ) return; // is that URL already opened somewhere else? Activate that window KOrg::MainWindow *korg=ActionManager::findInstance( url ); if ( ( 0 != korg )&&( korg != mMainWindow ) ) { KWin::activateWindow( korg->topLevelWidget()->winId() ); return; } kdDebug(5850) << "ActionManager::file_open(): " << url.prettyURL() << endl; // Open the calendar file in the same window only if we have an empty calendar window, and not the resource calendar if ( !mCalendarView->isModified() && mFile.isEmpty() && !mCalendarResources ) { openURL( url ); } else { emit actionNew( url ); } } void ActionManager::file_icalimport() { // FIXME: eventually, we will need a dialog box to select import type, etc. // for now, hard-coded to ical file, $HOME/.calendar. int retVal = -1; TQString progPath; KTempFile tmpfn; TQString homeDir = TQDir::homeDirPath() + TQString::fromLatin1( "/.calendar" ); if ( !TQFile::exists( homeDir ) ) { KMessageBox::error( dialogParent(), i18n( "You have no .calendar file in your home directory.\n" "Import cannot proceed.\n" ) ); return; } TDEProcess proc; proc << "ical2vcal" << tmpfn.name(); bool success = proc.start( TDEProcess::Block ); if ( !success ) { kdDebug(5850) << "Error starting ical2vcal." << endl; return; } else { retVal = proc.exitStatus(); } kdDebug(5850) << "ical2vcal return value: " << retVal << endl; if ( retVal >= 0 && retVal <= 2 ) { // now we need to MERGE what is in the iCal to the current calendar. mCalendarView->openCalendar( tmpfn.name(),1 ); if ( !retVal ) KMessageBox::information( dialogParent(), i18n( "KOrganizer successfully imported and " "merged your .calendar file from ical " "into the currently opened calendar." ), "dotCalendarImportSuccess" ); else KMessageBox::information( dialogParent(), i18n( "KOrganizer encountered some unknown fields while " "parsing your .calendar ical file, and had to " "discard them; please check to see that all " "your relevant data was correctly imported." ), i18n("ICal Import Successful with Warning") ); } else if ( retVal == -1 ) { KMessageBox::error( dialogParent(), i18n( "KOrganizer encountered an error parsing your " ".calendar file from ical; import has failed." ) ); } else if ( retVal == -2 ) { KMessageBox::error( dialogParent(), i18n( "KOrganizer does not think that your .calendar " "file is a valid ical calendar; import has failed." ) ); } tmpfn.unlink(); } void ActionManager::file_merge() { KURL url = KFileDialog::getOpenURL( locateLocal( "data","korganizer/" ), i18n("*.vcs *.ics|Calendar Files"), dialogParent() ); if ( ! url.isEmpty() ) // isEmpty if user cancelled the dialog importCalendar( url ); } void ActionManager::file_archive() { mCalendarView->archiveCalendar(); } void ActionManager::file_revert() { openURL( mURL ); } void ActionManager::file_saveas() { KURL url = getSaveURL(); if ( url.isEmpty() ) return; saveAsURL( url ); } void ActionManager::file_save() { if ( mMainWindow->hasDocument() ) { if ( mURL.isEmpty() ) { file_saveas(); return; } else { saveURL(); } } else { mCalendarView->calendar()->save(); } // export to HTML if ( KOPrefs::instance()->mHtmlWithSave ) { exportHTML(); } } void ActionManager::file_close() { if ( !saveModifiedURL() ) return; mCalendarView->closeCalendar(); TDEIO::NetAccess::removeTempFile( mFile ); mURL=""; mFile=""; setTitle(); } bool ActionManager::openURL( const KURL &url,bool merge ) { kdDebug(5850) << "ActionManager::openURL()" << endl; if ( url.isEmpty() ) { kdDebug(5850) << "ActionManager::openURL(): Error! Empty URL." << endl; return false; } if ( !url.isValid() ) { kdDebug(5850) << "ActionManager::openURL(): Error! URL is malformed." << endl; return false; } if ( url.isLocalFile() ) { mURL = url; mFile = url.path(); if ( !TDEStandardDirs::exists( mFile ) ) { mMainWindow->showStatusMessage( i18n("New calendar '%1'.") .arg( url.prettyURL() ) ); mCalendarView->setModified(); } else { bool success = mCalendarView->openCalendar( mFile, merge ); if ( success ) { showStatusMessageOpen( url, merge ); } } setTitle(); } else { TQString tmpFile; if( TDEIO::NetAccess::download( url, tmpFile, view() ) ) { kdDebug(5850) << "--- Downloaded to " << tmpFile << endl; bool success = mCalendarView->openCalendar( tmpFile, merge ); if ( merge ) { TDEIO::NetAccess::removeTempFile( tmpFile ); if ( success ) showStatusMessageOpen( url, merge ); } else { if ( success ) { TDEIO::NetAccess::removeTempFile( mFile ); mURL = url; mFile = tmpFile; TDEConfig *config = KOGlobals::self()->config(); config->setGroup( "General" ); setTitle(); kdDebug(5850) << "-- Add recent URL: " << url.prettyURL() << endl; if ( mRecent ) mRecent->addURL( url ); showStatusMessageOpen( url, merge ); } } return success; } else { TQString msg; msg = i18n("Cannot download calendar from '%1'.").arg( url.prettyURL() ); KMessageBox::error( dialogParent(), msg ); return false; } } return true; } bool ActionManager::addResource( const KURL &mUrl ) { CalendarResources *cr = KOrg::StdCalendar::self(); CalendarResourceManager *manager = cr->resourceManager(); ResourceCalendar *resource = 0; TQString name; kdDebug(5850) << "URL: " << mUrl << endl; if ( mUrl.isLocalFile() ) { kdDebug(5850) << "Local Resource" << endl; resource = manager->createResource( "file" ); if ( resource ) resource->setValue( "File", mUrl.path() ); name = mUrl.path(); } else { kdDebug(5850) << "Remote Resource" << endl; resource = manager->createResource( "remote" ); if ( resource ) resource->setValue( "DownloadURL", mUrl.url() ); name = mUrl.prettyURL(); resource->setReadOnly( true ); } if ( resource ) { resource->setTimeZoneId( KOPrefs::instance()->mTimeZoneId ); resource->setResourceName( name ); manager->add( resource ); mMainWindow->showStatusMessage( i18n( "Added calendar resource for URL '%1'." ) .arg( name ) ); // we have to call resourceAdded manually, because for in-process changes // the dcop signals are not connected, so the resource's signals would not // be connected otherwise if ( mCalendarResources ) mCalendarResources->resourceAdded( resource ); } else { TQString msg = i18n("Unable to create calendar resource '%1'.") .arg( name ); KMessageBox::error( dialogParent(), msg ); } return true; } void ActionManager::showStatusMessageOpen( const KURL &url, bool merge ) { if ( merge ) { mMainWindow->showStatusMessage( i18n("Merged calendar '%1'.") .arg( url.prettyURL() ) ); } else { mMainWindow->showStatusMessage( i18n("Opened calendar '%1'.") .arg( url.prettyURL() ) ); } } void ActionManager::closeURL() { kdDebug(5850) << "ActionManager::closeURL()" << endl; file_close(); } bool ActionManager::saveURL() { TQString ext; if ( mURL.isLocalFile() ) { ext = mFile.right( 4 ); } else { ext = mURL.filename().right( 4 ); } if ( ext == ".vcs" ) { int result = KMessageBox::warningContinueCancel( dialogParent(), i18n( "Your calendar will be saved in iCalendar format. Use " "'Export vCalendar' to save in vCalendar format." ), i18n("Format Conversion"), i18n("Proceed"), "dontaskFormatConversion", true ); if ( result != KMessageBox::Continue ) return false; TQString filename = mURL.fileName(); filename.replace( filename.length() - 4, 4, ".ics" ); mURL.setFileName( filename ); if ( mURL.isLocalFile() ) { mFile = mURL.path(); } setTitle(); if ( mRecent ) mRecent->addURL( mURL ); } if ( !mCalendarView->saveCalendar( mFile ) ) { kdDebug(5850) << "ActionManager::saveURL(): calendar view save failed." << endl; return false; } else { mCalendarView->setModified( false ); } if ( !mURL.isLocalFile() ) { if ( !TDEIO::NetAccess::upload( mFile, mURL, view() ) ) { TQString msg = i18n("Cannot upload calendar to '%1'") .arg( mURL.prettyURL() ); KMessageBox::error( dialogParent() ,msg ); return false; } } // keep saves on a regular interval if ( KOPrefs::instance()->mAutoSave ) { mAutoSaveTimer->stop(); mAutoSaveTimer->start( 1000*60*KOPrefs::instance()->mAutoSaveInterval ); } mMainWindow->showStatusMessage( i18n("Saved calendar '%1'.").arg( mURL.prettyURL() ) ); return true; } void ActionManager::exportHTML() { HTMLExportSettings settings( "KOrganizer" ); // Manually read in the config, because parametrized tdeconfigxt objects don't // seem to load the config theirselves settings.readConfig(); TQDate qd1; qd1 = TQDate::currentDate(); TQDate qd2; qd2 = TQDate::currentDate(); if ( settings.monthView() ) qd2.addMonths( 1 ); else qd2.addDays( 7 ); settings.setDateStart( qd1 ); settings.setDateEnd( qd2 ); exportHTML( &settings ); } void ActionManager::exportHTML( HTMLExportSettings *settings ) { if ( !settings || settings->outputFile().isEmpty() ) return; kdDebug()<<" settings->outputFile() :"<outputFile()<outputFile() ).exists() ) { if(KMessageBox::questionYesNo( dialogParent(), i18n("Do you want to overwrite file \"%1\"").arg( settings->outputFile()) ) == KMessageBox::No) return; } settings->setEMail( KOPrefs::instance()->email() ); settings->setName( KOPrefs::instance()->fullName() ); settings->setCreditName( "KOrganizer" ); settings->setCreditURL( "http://korganizer.kde.org" ); KCal::HtmlExport mExport( mCalendarView->calendar(), settings ); TQDate cdate = settings->dateStart().date(); TQDate qd2 = settings->dateEnd().date(); while ( cdate <= qd2 ) { TQStringList holidays = KOGlobals::self()->holiday( cdate ); if ( !holidays.isEmpty() ) { TQStringList::ConstIterator it = holidays.begin(); for ( ; it != holidays.end(); ++it ) { mExport.addHoliday( cdate, *it ); } } cdate = cdate.addDays( 1 ); } KURL dest( settings->outputFile() ); if ( dest.isLocalFile() ) { mExport.save( dest.path() ); } else { KTempFile tf; TQString tfile = tf.name(); tf.close(); mExport.save( tfile ); if ( !TDEIO::NetAccess::upload( tfile, dest, view() ) ) { KNotifyClient::event ( view()->winId(), i18n("Could not upload file.") ); } tf.unlink(); } } bool ActionManager::saveAsURL( const KURL &url ) { kdDebug(5850) << "ActionManager::saveAsURL() " << url.prettyURL() << endl; if ( url.isEmpty() ) { kdDebug(5850) << "ActionManager::saveAsURL(): Empty URL." << endl; return false; } if ( !url.isValid() ) { kdDebug(5850) << "ActionManager::saveAsURL(): Malformed URL." << endl; return false; } TQString fileOrig = mFile; KURL URLOrig = mURL; KTempFile *tempFile = 0; if ( url.isLocalFile() ) { mFile = url.path(); } else { tempFile = new KTempFile; mFile = tempFile->name(); } mURL = url; bool success = saveURL(); // Save local file and upload local file if ( success ) { delete mTempFile; mTempFile = tempFile; TDEIO::NetAccess::removeTempFile( fileOrig ); TDEConfig *config = KOGlobals::self()->config(); config->setGroup( "General" ); setTitle(); if ( mRecent ) mRecent->addURL( mURL ); } else { KMessageBox::sorry( dialogParent(), i18n("Unable to save calendar to the file %1.").arg( mFile ), i18n("Error") ); kdDebug(5850) << "ActionManager::saveAsURL() failed" << endl; mURL = URLOrig; mFile = fileOrig; delete tempFile; } return success; } bool ActionManager::saveModifiedURL() { kdDebug(5850) << "ActionManager::saveModifiedURL()" << endl; // If calendar isn't modified do nothing. if ( !mCalendarView->isModified() ) return true; mHtmlExportSync = true; if ( KOPrefs::instance()->mAutoSave && !mURL.isEmpty() ) { // Save automatically, when auto save is enabled. return saveURL(); } else { int result = KMessageBox::warningYesNoCancel( dialogParent(), i18n("The calendar has been modified.\nDo you want to save it?"), TQString(), KStdGuiItem::save(), KStdGuiItem::discard() ); switch( result ) { case KMessageBox::Yes: if ( mURL.isEmpty() ) { KURL url = getSaveURL(); return saveAsURL( url ); } else { return saveURL(); } case KMessageBox::No: return true; case KMessageBox::Cancel: default: { mHtmlExportSync = false; return false; } } } } KURL ActionManager::getSaveURL() { KURL url = KFileDialog::getSaveURL( locateLocal( "data","korganizer/" ), i18n("*.vcs *.ics|Calendar Files"), dialogParent() ); if ( url.isEmpty() ) return url; TQString filename = url.fileName( false ); TQString e = filename.right( 4 ); if ( e != ".vcs" && e != ".ics" ) { // Default save format is iCalendar filename += ".ics"; } url.setFileName( filename ); kdDebug(5850) << "ActionManager::getSaveURL(): url: " << url.url() << endl; return url; } void ActionManager::saveProperties( TDEConfig *config ) { kdDebug(5850) << "ActionManager::saveProperties" << endl; config->writeEntry( "UseResourceCalendar", !mMainWindow->hasDocument() ); if ( mMainWindow->hasDocument() ) { config->writePathEntry( "Calendar",mURL.url() ); } } void ActionManager::readProperties( TDEConfig *config ) { kdDebug(5850) << "ActionManager::readProperties" << endl; bool isResourceCalendar( config->readBoolEntry( "UseResourceCalendar", true ) ); TQString calendarUrl = config->readPathEntry( "Calendar" ); if ( !isResourceCalendar && !calendarUrl.isEmpty() ) { mMainWindow->init( true ); KURL u( calendarUrl ); openURL( u ); } else { mMainWindow->init( false ); } } void ActionManager::checkAutoSave() { kdDebug(5850) << "ActionManager::checkAutoSave()" << endl; // Don't save if auto save interval is zero if ( KOPrefs::instance()->mAutoSaveInterval == 0 ) return; // has this calendar been saved before? If yes automatically save it. if ( KOPrefs::instance()->mAutoSave ) { if ( mCalendarResources || ( mCalendar && !url().isEmpty() ) ) { saveCalendar(); } } } // Configuration changed as a result of the options dialog. void ActionManager::updateConfig() { kdDebug(5850) << "ActionManager::updateConfig()" << endl; if ( KOPrefs::instance()->mAutoSave && !mAutoSaveTimer->isActive() ) { checkAutoSave(); if ( KOPrefs::instance()->mAutoSaveInterval > 0 ) { mAutoSaveTimer->start( 1000 * 60 * KOPrefs::instance()->mAutoSaveInterval ); } } if ( !KOPrefs::instance()->mAutoSave ) mAutoSaveTimer->stop(); mNextXDays->setText( i18n( "&Next Day", "&Next %n Days", KOPrefs::instance()->mNextXDays ) ); KOCore::self()->reloadPlugins(); mParts = KOCore::self()->reloadParts( mMainWindow, mParts ); setDestinationPolicy(); if ( mResourceView ) mResourceView->updateView(); KOGroupware::instance()->freeBusyManager()->setBrokenUrl( false ); } void ActionManager::setDestinationPolicy() { if ( mCalendarResources ) { if ( KOPrefs::instance()->mDestination == KOPrefs::askDestination ) mCalendarResources->setAskDestinationPolicy(); else mCalendarResources->setStandardDestinationPolicy(); } } void ActionManager::configureDateTime() { TDEProcess *proc = new TDEProcess; *proc << "tdecmshell" << "language"; connect( proc,TQT_SIGNAL( processExited( TDEProcess * ) ), TQT_SLOT( configureDateTimeFinished( TDEProcess * ) ) ); if ( !proc->start() ) { KMessageBox::sorry( dialogParent(), i18n("Could not start control module for date and time format.") ); delete proc; } } void ActionManager::showTip() { KTipDialog::showTip( dialogParent(),TQString(),true ); } void ActionManager::showTipOnStart() { KTipDialog::showTip( dialogParent() ); } KOrg::MainWindow *ActionManager::findInstance( const KURL &url ) { if ( mWindowList ) { if ( url.isEmpty() ) return mWindowList->defaultInstance(); else return mWindowList->findInstance( url ); } else { return 0; } } void ActionManager::dumpText( const TQString &str ) { kdDebug(5850) << "ActionManager::dumpText(): " << str << endl; } 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() { bool visible = mResourceViewShowAction->isChecked(); kdDebug(5850) << "toggleResourceView: " << endl; if ( mResourceView ) { if ( visible ) mResourceView->show(); else mResourceView->hide(); } } void ActionManager::toggleResourceButtons() { bool visible = mResourceButtonsAction->isChecked(); kdDebug(5850) << "RESOURCE VIEW " << long( mResourceView ) << endl; if ( mResourceView ) mResourceView->showButtons( visible ); } bool ActionManager::openURL( const TQString &url ) { return openURL( KURL( url ) ); } bool ActionManager::mergeURL( const TQString &url ) { return openURL( KURL( url ),true ); } bool ActionManager::saveAsURL( const TQString &url ) { return saveAsURL( KURL( url ) ); } TQString ActionManager::getCurrentURLasString() const { return mURL.url(); } bool ActionManager::editIncidence( const TQString &uid ) { return mCalendarView->editIncidence( uid ); } bool ActionManager::editIncidence( const TQString &uid, const TQDate &date ) { return mCalendarView->editIncidence( uid, date ); } bool ActionManager::deleteIncidence( const TQString& uid, bool force ) { return mCalendarView->deleteIncidence( uid, force ); } bool ActionManager::addIncidence( const TQString& ical ) { return mCalendarView->addIncidence( ical ); } void ActionManager::configureDateTimeFinished( TDEProcess *proc ) { delete proc; } void ActionManager::downloadNewStuff() { kdDebug(5850) << "ActionManager::downloadNewStuff()" << endl; if ( !mNewStuff ) mNewStuff = new KONewStuff( mCalendarView ); mNewStuff->download(); } void ActionManager::uploadNewStuff() { if ( !mNewStuff ) mNewStuff = new KONewStuff( mCalendarView ); mNewStuff->upload(); } TQString ActionManager::localFileName() { return mFile; } class ActionManager::ActionStringsVisitor : public IncidenceBase::Visitor { public: ActionStringsVisitor() : mShow( 0 ), mEdit( 0 ), mDelete( 0 ) {} bool act( IncidenceBase *incidence, TDEAction *show, TDEAction *edit, TDEAction *del ) { mShow = show; mEdit = edit; mDelete = del; return incidence->accept( *this ); } protected: bool visit( Event * ) { 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( Todo * ) { 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( Journal * ) { return assignDefaultStrings(); } protected: bool assignDefaultStrings() { if ( mShow ) mShow->setText( i18n("&Show") ); if ( mEdit ) mEdit->setText( i18n("&Edit...") ); if ( mDelete ) mDelete->setText( i18n("&Delete") ); return true; } TDEAction *mShow; TDEAction *mEdit; TDEAction *mDelete; }; void ActionManager::processIncidenceSelection( Incidence *incidence, const TQDate & ) { // kdDebug(5850) << "ActionManager::processIncidenceSelection()" << endl; if ( !incidence ) { enableIncidenceActions( false ); return; } enableIncidenceActions( true ); if ( incidence->isReadOnly() ) { 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 ); // mAssignResourceAction->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 ); } void ActionManager::keyBindings() { KKeyDialog dlg( false, view() ); if ( mMainWindow ) dlg.insert( mMainWindow->getActionCollection() ); KOrg::Part *part; for ( part = mParts.first(); part; part = mParts.next() ) { dlg.insert( part->actionCollection(), part->shortInfo() ); } dlg.configure(); } void ActionManager::loadParts() { mParts = KOCore::self()->loadParts( mMainWindow ); } void ActionManager::setTitle() { mMainWindow->setTitle(); } KCalendarIface::ResourceRequestReply ActionManager::resourceRequest( const TQValueList >&, const TQCString& resource, const TQString& vCalIn ) { kdDebug(5850) << k_funcinfo << "resource=" << resource << " vCalIn=" << vCalIn << endl; KCalendarIface::ResourceRequestReply reply; reply.vCalOut = "VCalOut"; return reply; } TQPair ActionManager::viewSubResourceCalendar() { TQPair p( 0, TQString() ); // return now if we are running as a part and we aren't the currently active part if ( mIsPart && !mMainWindow->isCurrentlyActivePart() ) { return p; } KOrg::BaseView *cV = mCalendarView->viewManager()->currentView(); if ( cV && cV == mCalendarView->viewManager()->multiAgendaView() ) { cV = mCalendarView->viewManager()->multiAgendaView()->selectedAgendaView(); } if ( cV ) { p = tqMakePair( cV->resourceCalendar(), cV->subResourceCalendar() ); } return p; } bool ActionManager::isWritable( ResourceCalendar *res, const TQString &subRes, const TQString &contentsType ) { if ( res && res->isActive() ) { // Check specified resource for writability. if ( res->readOnly() || !res->subresourceWritable( subRes ) ) { TQString resName = res->resourceName(); if ( res->canHaveSubresources() ) { resName = res->labelForSubresource( subRes ); } KMessageBox::sorry( dialogParent(), i18n( "\"%1\" is read-only. " "Please select a writable calendar before attempting to create a new item." ). arg( resName ), i18n( "Read-only calendar" ) ); return false; } else { return true; } } else { // No specific resource so let's check all possible calendars for writability. CalendarResourceManager *m = mCalendarResources->resourceManager(); CalendarResourceManager::ActiveIterator it; for ( it = m->activeBegin(); it != m->activeEnd(); ++it ) { ResourceCalendar *res = (*it); if ( res->canHaveSubresources() ) { TQStringList subResources = res->subresources(); for ( TQStringList::ConstIterator subit = subResources.constBegin(); subit != subResources.constEnd(); ++subit ) { if ( res->subresourceWritable( (*subit) ) && res->subresourceActive( (*subit) ) ) { if ( res->subresourceType( *subit ).isEmpty() || res->subresourceType( *subit ) == contentsType ) { return true; } } } } else if ( !res->readOnly() ) { return true; } } // we don't have any writable calendars TQString errorText; if ( contentsType == "event" ) { errorText = i18n( "You have no active, writable event folder so saving will not be possible.\n" "Please create or activate at least one writable event folder and try again." ); } else if ( contentsType == "todo" ) { errorText = i18n( "You have no active, writable to-do (task) folders so saving will not be possible.\n" "Please create or activate at least one writable to-do folder and try again." ); } else if ( contentsType == "journal" ) { errorText = i18n( "You have no active, writable journal folder so saving will not be possible.\n" "Please create or activate at least one writable journal folder and try again." ); } else { errorText = i18n( "You have no active, writable calendar folder so saving will not be possible.\n" "Please create or activate at least one writable calendar folder and try again." ); } KMessageBox::sorry( dialogParent(), errorText, i18n( "No writable calendar" ) ); return false; } } void ActionManager::openEventEditor( const TQString& text ) { TQPairp = viewSubResourceCalendar(); if ( isWritable( p.first, p.second, "event" ) ) { mCalendarView->newEvent( p.first, p.second, text ); } } void ActionManager::openEventEditor( const TQString& summary, const TQString& description, const TQString& attachment ) { TQPairp = viewSubResourceCalendar(); mCalendarView->newEvent( p.first, p.second, summary, description, attachment ); } void ActionManager::openEventEditor( const TQString& summary, const TQString& description, const TQString& attachment, const TQStringList& attendees ) { mCalendarView->newEvent( 0, TQString(), summary, description, attachment, attendees ); } void ActionManager::openEventEditor( const TQString & summary, const TQString & description, const TQString & uri, const TQString & file, const TQStringList & attendees, const TQString & attachmentMimetype ) { int action = KOPrefs::instance()->defaultEmailAttachMethod(); if ( attachmentMimetype != "message/rfc822" ) { action = KOPrefs::Link; } else if ( KOPrefs::instance()->defaultEmailAttachMethod() == KOPrefs::Ask ) { TDEPopupMenu *menu = new TDEPopupMenu( 0 ); menu->insertItem( i18n("Attach as &link"), KOPrefs::Link ); menu->insertItem( i18n("Attach &inline"), KOPrefs::InlineFull ); menu->insertItem( i18n("Attach inline &without attachments"), KOPrefs::InlineBody ); menu->insertSeparator(); menu->insertItem( SmallIcon("cancel"), i18n("C&ancel"), KOPrefs::Ask ); action = menu->exec( TQCursor::pos(), 0 ); delete menu; } TQString attData; KTempFile tf; tf.setAutoDelete( true ); switch ( action ) { case KOPrefs::Ask: return; case KOPrefs::Link: attData = uri; break; case KOPrefs::InlineFull: attData = file; break; case KOPrefs::InlineBody: { TQFile f( file ); if ( !f.open( IO_ReadOnly ) ) return; KMime::Message *msg = new KMime::Message(); msg->setContent( TQCString( f.readAll() ) ); TQCString head = msg->head(); msg->parse(); if ( msg == msg->textContent() || msg->textContent() == 0 ) { // no attachments attData = file; } else { if ( KMessageBox::warningContinueCancel( 0, i18n("Removing attachments from an email might invalidate its signature."), i18n("Remove Attachments"), KStdGuiItem::cont(), "BodyOnlyInlineAttachment" ) != KMessageBox::Continue ) return; // due to kmime shortcomings in KDE3, we need to assemble the result manually int begin = 0; int end = head.find( '\n' ); bool skipFolded = false; while ( end >= 0 && end > begin ) { if ( head.find( "Content-Type:", begin, false ) != begin && head.find( "Content-Transfer-Encoding:", begin, false ) != begin && !(skipFolded && (head[begin] == ' ' || head[end] == '\t')) ) { TQCString line = head.mid( begin, end - begin ); tf.file()->writeBlock( line.data(), line.length() ); tf.file()->writeBlock( "\n", 1 ); skipFolded = false; } else { skipFolded = true; } begin = end + 1; end = head.find( '\n', begin ); if ( end < 0 && begin < (int)head.length() ) end = head.length() - 1; } TQCString cte = msg->textContent()->contentTransferEncoding()->as7BitString(); if ( !cte.stripWhiteSpace().isEmpty() ) { tf.file()->writeBlock( cte.data(), cte.length() ); tf.file()->writeBlock( "\n", 1 ); } TQCString ct = msg->textContent()->contentType()->as7BitString(); if ( !ct.stripWhiteSpace().isEmpty() ) tf.file()->writeBlock( ct.data(), ct.length() ); tf.file()->writeBlock( "\n", 1 ); tf.file()->writeBlock( msg->textContent()->body() ); attData = tf.name(); } tf.close(); delete msg; break; } default: // menu could have been closed by cancel, if so, do nothing return; } TQPairp = viewSubResourceCalendar(); mCalendarView->newEvent( p.first, p.second, summary, description, attData, attendees, attachmentMimetype, action != KOPrefs::Link ); } void ActionManager::openTodoEditor( const TQString& text ) { TQPairp = viewSubResourceCalendar(); if ( isWritable( p.first, p.second, "todo" ) ) { mCalendarView->newTodo( p.first, p.second, text ); } } void ActionManager::openTodoEditor( const TQString& summary, const TQString& description, const TQString& attachment ) { TQPairp = viewSubResourceCalendar(); mCalendarView->newTodo( p.first, p.second, summary, description, attachment ); } void ActionManager::openTodoEditor( const TQString& summary, const TQString& description, const TQString& attachment, const TQStringList& attendees ) { TQPairp = viewSubResourceCalendar(); mCalendarView->newTodo( p.first, p.second, summary, description, attachment, attendees ); } void ActionManager::openTodoEditor(const TQString & summary, const TQString & description, const TQString & uri, const TQString & file, const TQStringList & attendees, const TQString & attachmentMimetype, bool isTask ) { int action = KOPrefs::instance()->defaultTodoAttachMethod(); if ( attachmentMimetype != "message/rfc822" ) { action = KOPrefs::TodoAttachLink; } else if ( KOPrefs::instance()->defaultTodoAttachMethod() == KOPrefs::TodoAttachAsk ) { TDEPopupMenu *menu = new TDEPopupMenu( 0 ); menu->insertItem( i18n("Attach as &link"), KOPrefs::TodoAttachLink ); menu->insertItem( i18n("Attach &inline"), KOPrefs::TodoAttachInlineFull ); menu->insertSeparator(); menu->insertItem( SmallIcon("cancel"), i18n("C&ancel"), KOPrefs::TodoAttachAsk ); action = menu->exec( TQCursor::pos(), 0 ); delete menu; } TQStringList attData; switch ( action ) { case KOPrefs::TodoAttachAsk: return; case KOPrefs::TodoAttachLink: attData << uri; break; case KOPrefs::TodoAttachInlineFull: attData << file; break; default: // menu could have been closed by cancel, if so, do nothing return; } TQPairp = viewSubResourceCalendar(); mCalendarView->newTodo( p.first, p.second, summary, description, attData, attendees, TQStringList( attachmentMimetype ), action != KOPrefs::TodoAttachLink, isTask ); } void ActionManager::openJournalEditor( const TQDate& date ) { TQPairp = viewSubResourceCalendar(); mCalendarView->newJournal( p.first, p.second, date ); } void ActionManager::openJournalEditor( const TQString& text, const TQDate& date ) { TQPairp = viewSubResourceCalendar(); mCalendarView->newJournal( p.first, p.second, text, date ); } void ActionManager::openJournalEditor( const TQString& text ) { TQPairp = viewSubResourceCalendar(); if ( isWritable( p.first, p.second, "journal" ) ) { mCalendarView->newJournal( p.first, p.second, text ); } } //TODO: // void ActionManager::openJournalEditor( const TQString& summary, // const TQString& description, // const TQString& attachment ) // { // TQPairp = viewSubResourceCalendar(); // mCalendarView->newJournal( p.first, p.second, summary, description, attachment ); // } void ActionManager::showJournalView() { mCalendarView->viewManager()->showJournalView(); } void ActionManager::showTodoView() { mCalendarView->viewManager()->showTodoView(); } void ActionManager::showEventView() { mCalendarView->viewManager()->showEventView(); } void ActionManager::goDate( const TQDate& date ) { mCalendarView->goDate( date ); } void ActionManager::goDate( const TQString& date ) { goDate( TDEGlobal::locale()->readDate( date ) ); } void ActionManager::showDate(const TQDate & date) { mCalendarView->showDate( date ); } void ActionManager::updateUndoAction( const TQString &text ) { if ( text.isNull() ) { mUndoAction->setEnabled( false ); mUndoAction->setText( i18n("Undo") ); } else { mUndoAction->setEnabled( true ); if ( text.isEmpty() ) mUndoAction->setText( i18n("Undo") ); else mUndoAction->setText( i18n("Undo (%1)").arg( text ) ); } } void ActionManager::updateRedoAction( const TQString &text ) { if ( text.isNull() ) { mRedoAction->setEnabled( false ); mRedoAction->setText( i18n( "Redo" ) ); } else { mRedoAction->setEnabled( true ); if ( text.isEmpty() ) mRedoAction->setText( i18n("Redo") ); else mRedoAction->setText( i18n( "Redo (%1)" ).arg( text ) ); } } bool ActionManager::queryClose() { kdDebug(5850) << "ActionManager::queryClose()" << endl; bool close = true; if ( mCalendar && mCalendar->isModified() ) { int res = KMessageBox::questionYesNoCancel( dialogParent(), i18n("The calendar contains unsaved changes. Do you want to save them before exiting?"), TQString(), KStdGuiItem::save(), KStdGuiItem::discard() ); // Exit on yes and no, don't exit on cancel. If saving fails, ask for exiting. if ( res == KMessageBox::Yes ) { close = saveModifiedURL(); if ( !close ) { int res1 = KMessageBox::questionYesNo( dialogParent(), i18n("Unable to save the calendar. Do you still want to close this window?"), TQString(), KStdGuiItem::close(), KStdGuiItem::cancel() ); close = ( res1 == KMessageBox::Yes ); } } else { close = ( res == KMessageBox::No ); } } else if ( mCalendarResources ) { if ( !mIsClosing ) { kdDebug(5850) << "!mIsClosing" << endl; if ( !saveResourceCalendar() ) return false; // FIXME: Put main window into a state indicating final saving. mIsClosing = true; // FIXME: Close main window when save is finished // connect( mCalendarResources, TQT_SIGNAL( calendarSaved() ), // mMainWindow, TQT_SLOT( close() ) ); } if ( mCalendarResources->isSaving() ) { kdDebug(5850) << "ActionManager::queryClose(): isSaving" << endl; close = false; KMessageBox::information( dialogParent(), i18n("Unable to exit. Saving still in progress.") ); } else { kdDebug(5850) << "ActionManager::queryClose(): close = true" << endl; close = true; } } else { close = true; } return close; } void ActionManager::saveCalendar() { if ( mCalendar ) { if ( view()->isModified() ) { if ( !url().isEmpty() ) { saveURL(); } else { TQString location = locateLocal( "data", "korganizer/kontact.ics" ); saveAsURL( location ); } } } else if ( mCalendarResources ) { mCalendarResources->save(); // FIXME: Make sure that asynchronous saves don't fail. } } bool ActionManager::saveResourceCalendar() { if ( !mCalendarResources ) return false; CalendarResourceManager *m = mCalendarResources->resourceManager(); CalendarResourceManager::ActiveIterator it; for ( it = m->activeBegin(); it != m->activeEnd(); ++it ) { if ( (*it)->readOnly() ) continue; if ( !(*it)->save() ) { int result = KMessageBox::warningContinueCancel( view(), i18n( "Saving of '%1' failed. Check that the resource is " "properly configured.\nIgnore problem and continue without " "saving or cancel save?" ).arg( (*it)->resourceName() ), i18n("Save Error"), KStdGuiItem::dontSave() ); if ( result == KMessageBox::Cancel ) return false; } } return true; } void ActionManager::loadResourceCalendar() { if ( !mCalendarResources ) return; CalendarResourceManager *m = mCalendarResources->resourceManager(); CalendarResourceManager::ActiveIterator it; for ( it = m->activeBegin(); it != m->activeEnd(); ++it ) { (*it)->load(); } } void ActionManager::importCalendar( const KURL &url ) { if ( !url.isValid() ) { KMessageBox::error( dialogParent(), i18n("URL '%1' is invalid.").arg( url.prettyURL() ) ); return; } PreviewDialog *dialog; dialog = new PreviewDialog( url, mMainWindow->topLevelWidget() ); connect( dialog, TQT_SIGNAL( dialogFinished( PreviewDialog * ) ), TQT_SLOT( slotPreviewDialogFinished( PreviewDialog * ) ) ); connect( dialog, TQT_SIGNAL( openURL( const KURL &, bool ) ), TQT_SLOT( openURL( const KURL &, bool ) ) ); connect( dialog, TQT_SIGNAL( addResource( const KURL & ) ), TQT_SLOT( addResource( const KURL & ) ) ); if ( dialog->loadCalendar() ) { dialog->show(); } else { KMessageBox::error( dialogParent(), i18n("Unable to open the calendar") ); } } void ActionManager::slotPreviewDialogFinished( PreviewDialog *dlg ) { dlg->deleteLater(); mCalendarView->updateView(); } void ActionManager::slotAutoArchivingSettingsModified() { if ( KOPrefs::instance()->mAutoArchive ) mAutoArchiveTimer->start( 4 * 60 * 60 * 1000, true ); // check again in 4 hours else mAutoArchiveTimer->stop(); } void ActionManager::slotAutoArchive() { if ( !mCalendarView->calendar() ) // can this happen? return; mAutoArchiveTimer->stop(); EventArchiver archiver; connect( &archiver, TQT_SIGNAL( eventsDeleted() ), mCalendarView, TQT_SLOT( updateView() ) ); archiver.runAuto( mCalendarView->calendar(), mCalendarView, false /*no gui*/ ); // restart timer with the correct delay ( especially useful for the first time ) slotAutoArchivingSettingsModified(); } void ActionManager::loadProfile( const TQString & path ) { KOPrefs::instance()->writeConfig(); TDEConfig* const cfg = KOPrefs::instance()->config(); const TDEConfig profile( path+"/korganizerrc", /*read-only=*/false, /*useglobals=*/false ); const TQStringList groups = profile.groupList(); for ( TQStringList::ConstIterator it = groups.begin(), end = groups.end(); it != end; ++it ) { cfg->setGroup( *it ); typedef TQMap StringMap; const StringMap entries = profile.entryMap( *it ); for ( StringMap::ConstIterator it2 = entries.begin(), end = entries.end(); it2 != end; ++it2 ) { cfg->writeEntry( it2.key(), it2.data() ); } } cfg->sync(); KOPrefs::instance()->readConfig(); } namespace { void copyConfigEntry( TDEConfig* source, TDEConfig* dest, const TQString& group, const TQString& key, const TQString& defaultValue=TQString() ) { source->setGroup( group ); dest->setGroup( group ); dest->writeEntry( key, source->readEntry( key, defaultValue ) ); } } void ActionManager::saveToProfile( const TQString & path ) const { KOPrefs::instance()->writeConfig(); TDEConfig* const cfg = KOPrefs::instance()->config(); TDEConfig profile( path+"/korganizerrc", /*read-only=*/false, /*useglobals=*/false ); ::copyConfigEntry( cfg, &profile, "Views", "Agenda View Calendar Display" ); } bool ActionManager::handleCommandLine() { TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); KOrg::MainWindow *mainWindow = ActionManager::findInstance( KURL() ); bool ret = true; if ( !mainWindow ) { kdError() << "Unable to find default calendar resources view." << endl; ret = false; } else if ( args->count() <= 0 ) { // No filenames given => all other args are meaningless, show main Window mainWindow->topLevelWidget()->show(); } else if ( !args->isSet( "open" ) ) { // Import, merge, or ask => we need the resource calendar window anyway. mainWindow->topLevelWidget()->show(); // Check for import, merge or ask if ( args->isSet( "import" ) ) { for( int i = 0; i < args->count(); ++i ) { mainWindow->actionManager()->addResource( args->url( i ) ); } } else if ( args->isSet( "merge" ) ) { for( int i = 0; i < args->count(); ++i ) { mainWindow->actionManager()->mergeURL( args->url( i ).url() ); } } else { for( int i = 0; i < args->count(); ++i ) { mainWindow->actionManager()->importCalendar( args->url( i ) ); } } } return ret; } TQWidget *ActionManager::dialogParent() { return mCalendarView->topLevelWidget(); } #include "actionmanager.moc"