/* 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() { KAction *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 KAction( i18n("Import &Event/Calendar (ICS-/VCS-File)..."), 0, TQT_TQOBJECT(this), TQT_SLOT( file_merge() ), mACollection, "import_icalendar" ); new KAction( i18n("&Import From UNIX Ical tool (.calendar-File)"), 0, TQT_TQOBJECT(this), TQT_SLOT( file_icalimport() ), mACollection, "import_ical" ); new KAction( i18n("Get &Hot New Stuff..."), 0, this, TQT_SLOT( downloadNewStuff() ), mACollection, "downloadnewstuff" ); new KAction( i18n("Export &Web Page..."), "webexport", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( exportWeb() ), mACollection, "export_web" ); new KAction( i18n("&iCalendar..."), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( exportICalendar() ), mACollection, "export_icalendar" ); new KAction( i18n("&vCalendar..."), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( exportVCalendar() ), mACollection, "export_vcalendar" ); new KAction( i18n("Upload &Hot New Stuff..."), 0, TQT_TQOBJECT(this), TQT_SLOT( uploadNewStuff() ), mACollection, "uploadnewstuff" ); new KAction( i18n("Archive O&ld Entries..."), 0, TQT_TQOBJECT(this), TQT_SLOT( file_archive() ), mACollection, "file_archive" ); new KAction( i18n("delete completed to-dos", "Pur&ge Completed To-dos"), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( purgeCompleted() ), mACollection, "purge_completed" ); //************************** EDIT MENU ********************************* KAction *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 KAction( i18n("&Delete"), "editdelete", 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 KAction( i18n("What's &Next"), KOGlobals::self()->smallIcon( "whatsnext" ), 0, mCalendarView->viewManager(), TQT_SLOT( showWhatsNextView() ), mACollection, "view_whatsnext" ); new KAction( i18n("&Day"), KOGlobals::self()->smallIcon( "1day" ), 0, mCalendarView->viewManager(), TQT_SLOT( showDayView() ), mACollection, "view_day" ); mNextXDays = new KAction( "", 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 KAction( i18n("W&ork Week"), KOGlobals::self()->smallIcon( "5days" ), 0, mCalendarView->viewManager(), TQT_SLOT( showWorkWeekView() ), mACollection, "view_workweek" ); new KAction( i18n("&Week"), KOGlobals::self()->smallIcon( "7days" ), 0, mCalendarView->viewManager(), TQT_SLOT( showWeekView() ), mACollection, "view_week" ); new KAction( i18n("&Month"), KOGlobals::self()->smallIcon( "month" ), 0, mCalendarView->viewManager(), TQT_SLOT( showMonthView() ), mACollection, "view_month" ); new KAction( i18n("&List"), KOGlobals::self()->smallIcon( "list" ), 0, mCalendarView->viewManager(), TQT_SLOT( showListView() ), mACollection, "view_list" ); new KAction( i18n("&To-do List"), KOGlobals::self()->smallIcon( "todo" ), 0, mCalendarView->viewManager(), TQT_SLOT( showTodoView() ), mACollection, "view_todo" ); new KAction( i18n("&Journal"), KOGlobals::self()->smallIcon( "journal" ), 0, mCalendarView->viewManager(), TQT_SLOT( showJournalView() ), mACollection, "view_journal" ); new KAction( i18n("&Timeline View"), KOGlobals::self()->smallIcon( "timeline" ), 0, mCalendarView->viewManager(), TQT_SLOT( showTimelineView() ), mACollection, "view_timeline" ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~ FILTERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ new KAction( i18n("&Refresh"), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( updateView() ), mACollection, "update" ); // TODO: // new KAction( i18n("Hide &Completed To-dos"), 0, // mCalendarView, TQT_SLOT( toggleHideCompleted() ), // mACollection, "hide_completed_todos" ); mFilterAction = new KSelectAction( 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 KAction( i18n( "Zoom In Horizontally" ), "viewmag+", 0, mCalendarView->viewManager(), TQT_SLOT( zoomInHorizontally() ), mACollection, "zoom_in_horizontally" ); new KAction( i18n( "Zoom Out Horizontally" ), "viewmag-", 0, mCalendarView->viewManager(), TQT_SLOT( zoomOutHorizontally() ), mACollection, "zoom_out_horizontally" ); new KAction( i18n( "Zoom In Vertically" ), "viewmag+", 0, mCalendarView->viewManager(), TQT_SLOT( zoomInVertically() ), mACollection, "zoom_in_vertically" ); new KAction( i18n( "Zoom Out Vertically" ), "viewmag-", 0, mCalendarView->viewManager(), TQT_SLOT( zoomOutVertically() ), mACollection, "zoom_out_vertically" ); //************************** Actions MENU ********************************* new KAction( i18n("Go to &Today"), "today", 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( goToday() ), mACollection, "go_today" ); bool isRTL = TQApplication::reverseLayout(); action = new KAction( 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 KAction( 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 KAction( i18n("New E&vent..."), KOGlobals::self()->smallIcon( "newappointment" ), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(newEvent()), mACollection, "new_event" ); new KAction( i18n("New &To-do..."), KOGlobals::self()->smallIcon( "newtodo" ), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(newTodo()), mACollection, "new_todo" ); action = new KAction( 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 KAction( i18n("New &Journal..."), KOGlobals::self()->smallIcon( "newjournal" ), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(newJournal()), mACollection, "new_journal" ); mShowIncidenceAction = new KAction( i18n("&Show"), 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( showIncidence() ), mACollection, "show_incidence" ); mEditIncidenceAction = new KAction( i18n("&Edit..."), 0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( editIncidence() ), mACollection, "edit_incidence" ); mDeleteIncidenceAction = new KAction( i18n("&Delete"), Key_Delete, TQT_TQOBJECT(mCalendarView),TQT_SLOT( deleteIncidence()), mACollection, "delete_incidence" ); action = new KAction( 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 KAction( 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 KToggleAction( i18n("&Activate Reminder"), 0, // mCalendarView, TQT_SLOT( toggleAlarm()), // mACollection, "activate_alarm" ); //************************** SCHEDULE MENU ******************************** mPublishEvent = new KAction( i18n("&Publish Item Information..."), "mail_send", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( schedule_publish() ), mACollection, "schedule_publish" ); mPublishEvent->setEnabled( false ); mSendInvitation = new KAction( 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 KAction( 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 KAction( 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 KAction( i18n( "Send Status &Update" ), "mail_reply", 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 KAction( 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 KAction( i18n("&Send as iCalendar..."), "mail_forward", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_forward()), mACollection, "schedule_forward" ); mForwardEvent->setEnabled( false ); action = new KAction( i18n("&Mail Free Busy Information..."), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( mailFreeBusy() ), mACollection, "mail_freebusy" ); action->setEnabled( true ); action = new KAction( i18n("&Upload Free Busy Information"), 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( uploadFreeBusy() ), mACollection, "upload_freebusy" ); action->setEnabled( true ); if ( !mIsPart ) { action = new KAction( i18n("&Addressbook"),"contents",0, TQT_TQOBJECT(mCalendarView),TQT_SLOT( openAddressbook() ), mACollection,"addressbook" ); } //************************** SETTINGS MENU ******************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mDateNavigatorShowAction = new KToggleAction( i18n("Show Date Navigator"), 0, TQT_TQOBJECT(this), TQT_SLOT( toggleDateNavigator() ), mACollection, "show_datenavigator" ); mTodoViewShowAction = new KToggleAction ( i18n("Show To-do View"), 0, TQT_TQOBJECT(this), TQT_SLOT( toggleTodoView() ), mACollection, "show_todoview" ); mEventViewerShowAction = new KToggleAction ( 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 KToggleAction ( i18n("Show Resource View"), 0, TQT_TQOBJECT(this), TQT_SLOT( toggleResourceView() ), mACollection, "show_resourceview" ); mResourceButtonsAction = new KToggleAction( 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 KAction( 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 KAction( i18n("Manage &Resources..."), 0, // TQT_TQOBJECT(this), TQT_SLOT( manageResources() ), // mACollection, "conf_resources" ); new KAction( i18n("Manage View &Filters..."), "configure", 0, TQT_TQOBJECT(mCalendarView), TQT_SLOT( editFilters() ), mACollection, "edit_filters" ); new KAction( i18n("Manage C&ategories..."), 0, TQT_TQOBJECT(mCalendarView->dialogManager()), TQT_SLOT( showCategoryEditDialog() ), mACollection, "edit_categories" ); if ( mIsPart ) { new KAction( 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 KAction( 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 ( !KStandardDirs::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, KAction *show, KAction *edit, KAction *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; } KAction *mShow; KAction *mEdit; KAction *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 ) { KPopupMenu *menu = new KPopupMenu( 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 ) { KPopupMenu *menu = new KPopupMenu( 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"