korganizer

actionmanager.cpp

00001 /*
00002   This file is part of KOrganizer.
00003 
00004   Copyright (c) 2002 Mike Pilone <mpilone@slac.com>
00005   Copyright (c) 2002 Don Sanders <sanders@kde.org>
00006   Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
00007   Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00008 
00009   This program is free software; you can redistribute it and/or modify
00010   it under the terms of the GNU General Public License as published by
00011   the Free Software Foundation; either version 2 of the License, or
00012   (at your option) any later version.
00013 
00014   This program is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017   GNU General Public License for more details.
00018 
00019   You should have received a copy of the GNU General Public License
00020   along with this program; if not, write to the Free Software
00021   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022 
00023   As a special exception, permission is given to link this program
00024   with any edition of Qt, and distribute the resulting executable,
00025   without including the source code for Qt in the source distribution.
00026 */
00027 
00028 #include "actionmanager.h"
00029 
00030 #include "alarmclient.h"
00031 #include "calendarview.h"
00032 #include "kocore.h"
00033 #include "kodialogmanager.h"
00034 #include "koglobals.h"
00035 #include "koprefs.h"
00036 #include "koviewmanager.h"
00037 #include "kowindowlist.h"
00038 #include "kprocess.h"
00039 #include "konewstuff.h"
00040 #include "history.h"
00041 #include "kogroupware.h"
00042 #include "resourceview.h"
00043 #include "importdialog.h"
00044 #include "eventarchiver.h"
00045 #include "stdcalendar.h"
00046 #include "freebusymanager.h"
00047 
00048 #include <libkcal/calendarlocal.h>
00049 #include <libkcal/calendarresources.h>
00050 #include <libkcal/htmlexport.h>
00051 #include <libkcal/htmlexportsettings.h>
00052 
00053 #include <dcopclient.h>
00054 #include <kaction.h>
00055 #include <kfiledialog.h>
00056 #include <kio/netaccess.h>
00057 #include <kkeydialog.h>
00058 #include <kpopupmenu.h>
00059 #include <kstandarddirs.h>
00060 #include <ktip.h>
00061 #include <ktempfile.h>
00062 #include <kxmlguiclient.h>
00063 #include <kwin.h>
00064 #include <knotifyclient.h>
00065 #include <kstdguiitem.h>
00066 #include <kdeversion.h>
00067 #include <kactionclasses.h>
00068 
00069 #include <qapplication.h>
00070 #include <qtimer.h>
00071 #include <qlabel.h>
00072 
00073 
00074 // FIXME: Several places in the file don't use KConfigXT yet!
00075 KOWindowList *ActionManager::mWindowList = 0;
00076 
00077 ActionManager::ActionManager( KXMLGUIClient *client, CalendarView *widget,
00078                               QObject *parent, KOrg::MainWindow *mainWindow,
00079                               bool isPart )
00080   : QObject( parent ), KCalendarIface(), mRecent( 0 ),
00081     mResourceButtonsAction( 0 ), mResourceViewShowAction( 0 ), mCalendar( 0 ),
00082     mCalendarResources( 0 ), mResourceView( 0 ), mIsClosing( false )
00083 {
00084   mGUIClient = client;
00085   mACollection = mGUIClient->actionCollection();
00086   mCalendarView = widget;
00087   mIsPart = isPart;
00088   mTempFile = 0;
00089   mNewStuff = 0;
00090   mHtmlExportSync = false;
00091   mMainWindow = mainWindow;
00092 }
00093 
00094 ActionManager::~ActionManager()
00095 {
00096   delete mNewStuff;
00097 
00098   // Remove Part plugins
00099   KOCore::self()->unloadParts( mMainWindow, mParts );
00100 
00101   delete mTempFile;
00102 
00103   // Take this window out of the window list.
00104   mWindowList->removeWindow( mMainWindow );
00105 
00106   delete mCalendarView;
00107 
00108   delete mCalendar;
00109 
00110   kdDebug(5850) << "~ActionManager() done" << endl;
00111 }
00112 
00113 // see the Note: below for why this method is necessary
00114 void ActionManager::init()
00115 {
00116   // Construct the groupware object
00117   KOGroupware::create( mCalendarView, mCalendarResources );
00118 
00119   // add this instance of the window to the static list.
00120   if ( !mWindowList ) {
00121     mWindowList = new KOWindowList;
00122     // Show tip of the day, when the first calendar is shown.
00123     if ( !mIsPart )
00124       QTimer::singleShot( 0, this, SLOT( showTipOnStart() ) );
00125   }
00126   // Note: We need this ActionManager to be fully constructed, and
00127   // parent() to have a valid reference to it before the following
00128   // addWindow is called.
00129   mWindowList->addWindow( mMainWindow );
00130 
00131   initActions();
00132 
00133   // set up autoSaving stuff
00134   mAutoSaveTimer = new QTimer( this );
00135   connect( mAutoSaveTimer,SIGNAL( timeout() ), SLOT( checkAutoSave() ) );
00136   if ( KOPrefs::instance()->mAutoSave &&
00137        KOPrefs::instance()->mAutoSaveInterval > 0 ) {
00138     mAutoSaveTimer->start( 1000 * 60 * KOPrefs::instance()->mAutoSaveInterval );
00139   }
00140 
00141   mAutoArchiveTimer = new QTimer( this );
00142   connect( mAutoArchiveTimer, SIGNAL( timeout() ), SLOT( slotAutoArchive() ) );
00143   // First auto-archive should be in 5 minutes (like in kmail).
00144   if ( KOPrefs::instance()->mAutoArchive )
00145     mAutoArchiveTimer->start( 5 * 60 * 1000, true ); // singleshot
00146 
00147   setTitle();
00148 
00149   connect( mCalendarView, SIGNAL( modifiedChanged( bool ) ), SLOT( setTitle() ) );
00150   connect( mCalendarView, SIGNAL( configChanged() ), SLOT( updateConfig() ) );
00151 
00152   connect( mCalendarView, SIGNAL( incidenceSelected( Incidence * ) ),
00153            this, SLOT( processIncidenceSelection( Incidence * ) ) );
00154   connect( mCalendarView, SIGNAL( exportHTML( HTMLExportSettings * ) ),
00155            this, SLOT( exportHTML( HTMLExportSettings * ) ) );
00156 
00157   processIncidenceSelection( 0 );
00158 
00159   // Update state of paste action
00160   mCalendarView->checkClipboard();
00161 }
00162 
00163 void ActionManager::createCalendarLocal()
00164 {
00165   mCalendar = new CalendarLocal( KOPrefs::instance()->mTimeZoneId );
00166   mCalendarView->setCalendar( mCalendar );
00167   mCalendarView->readSettings();
00168 
00169   initCalendar( mCalendar );
00170 }
00171 
00172 void ActionManager::createCalendarResources()
00173 {
00174   mCalendarResources = KOrg::StdCalendar::self();
00175 
00176   CalendarResourceManager *manager = mCalendarResources->resourceManager();
00177 
00178   kdDebug(5850) << "CalendarResources used by KOrganizer:" << endl;
00179   CalendarResourceManager::Iterator it;
00180   for( it = manager->begin(); it != manager->end(); ++it ) {
00181     kdDebug(5850) << "  " << (*it)->resourceName() << endl;
00182     (*it)->setResolveConflict( true );
00183 //    (*it)->dump();
00184   }
00185 
00186   setDestinationPolicy();
00187 
00188   mCalendarView->setCalendar( mCalendarResources );
00189   mCalendarView->readSettings();
00190 
00191   ResourceViewFactory factory( mCalendarResources, mCalendarView );
00192   mCalendarView->addExtension( &factory );
00193   mResourceView = factory.resourceView();
00194 
00195   connect( mCalendarResources, SIGNAL( calendarChanged() ),
00196            mCalendarView, SLOT( slotCalendarChanged() ) );
00197   connect( mCalendarResources, SIGNAL( signalErrorMessage( const QString & ) ),
00198            mCalendarView, SLOT( showErrorMessage( const QString & ) ) );
00199 
00200   connect( mCalendarView, SIGNAL( configChanged() ),
00201            SLOT( updateConfig() ) );
00202 
00203   initCalendar( mCalendarResources );
00204 }
00205 
00206 void ActionManager::initCalendar( Calendar *cal )
00207 {
00208   cal->setOwner( Person( KOPrefs::instance()->fullName(),
00209                          KOPrefs::instance()->email() ) );
00210   // setting fullName and email do not really count as modifying the calendar
00211   mCalendarView->setModified( false );
00212 }
00213 
00214 void ActionManager::initActions()
00215 {
00216   KAction *action;
00217 
00218 
00219   //*************************** FILE MENU **********************************
00220 
00221   //~~~~~~~~~~~~~~~~~~~~~~~ LOADING / SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00222   if ( mIsPart ) {
00223     if ( mMainWindow->hasDocument() ) {
00224       KStdAction::openNew( this, SLOT(file_new()), mACollection, "korganizer_openNew" );
00225       KStdAction::open( this, SLOT( file_open() ), mACollection, "korganizer_open" );
00226       mRecent = KStdAction::openRecent( this, SLOT( file_open( const KURL& ) ),
00227                                      mACollection, "korganizer_openRecent" );
00228       KStdAction::revert( this,SLOT( file_revert() ), mACollection, "korganizer_revert" );
00229       KStdAction::saveAs( this, SLOT( file_saveas() ), mACollection,
00230                    "korganizer_saveAs" );
00231       KStdAction::save( this, SLOT( file_save() ), mACollection, "korganizer_save" );
00232     }
00233     KStdAction::print( mCalendarView, SLOT( print() ), mACollection, "korganizer_print" );
00234   } else {
00235     KStdAction::openNew( this, SLOT( file_new() ), mACollection );
00236     KStdAction::open( this, SLOT( file_open() ), mACollection );
00237     mRecent = KStdAction::openRecent( this, SLOT( file_open( const KURL& ) ),
00238                                      mACollection );
00239     if ( mMainWindow->hasDocument() ) {
00240       KStdAction::revert( this,SLOT( file_revert() ), mACollection );
00241       KStdAction::save( this, SLOT( file_save() ), mACollection );
00242       KStdAction::saveAs( this, SLOT( file_saveas() ), mACollection );
00243     }
00244     KStdAction::print( mCalendarView, SLOT( print() ), mACollection );
00245   }
00246 
00247 
00248   //~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT / EXPORT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00249   new KAction( i18n("Import &Calendar..."), 0, this, SLOT( file_merge() ),
00250                mACollection, "import_icalendar" );
00251   new KAction( i18n("&Import From UNIX Ical tool"), 0, this, SLOT( file_icalimport() ),
00252                mACollection, "import_ical" );
00253   new KAction( i18n("Get &Hot New Stuff..."), 0, this,
00254                SLOT( downloadNewStuff() ), mACollection,
00255                "downloadnewstuff" );
00256 
00257   new KAction( i18n("Export &Web Page..."), "webexport", 0,
00258                mCalendarView, SLOT( exportWeb() ),
00259                mACollection, "export_web" );
00260   new KAction( i18n("&iCalendar..."), 0,
00261                mCalendarView, SLOT( exportICalendar() ),
00262                mACollection, "export_icalendar" );
00263   new KAction( i18n("&vCalendar..."), 0,
00264                mCalendarView, SLOT( exportVCalendar() ),
00265                mACollection, "export_vcalendar" );
00266   new KAction( i18n("Upload &Hot New Stuff..."), 0, this,
00267                SLOT( uploadNewStuff() ), mACollection,
00268                "uploadnewstuff" );
00269 
00270 
00271 
00272   new KAction( i18n("Archive O&ld Entries..."), 0, this, SLOT( file_archive() ),
00273                     mACollection, "file_archive" );
00274   new KAction( i18n("delete completed to-dos", "Pur&ge Completed To-dos"), 0,
00275                mCalendarView, SLOT( purgeCompleted() ), mACollection,
00276                "purge_completed" );
00277 
00278 
00279 
00280 
00281   //************************** EDIT MENU *********************************
00282   KAction *pasteAction;
00283   KOrg::History *h = mCalendarView->history();
00284   if ( mIsPart ) {
00285     // edit menu
00286     mCutAction = KStdAction::cut( mCalendarView, SLOT( edit_cut() ),
00287                                   mACollection, "korganizer_cut" );
00288     mCopyAction = KStdAction::copy( mCalendarView, SLOT( edit_copy() ),
00289                                     mACollection, "korganizer_copy" );
00290     pasteAction = KStdAction::paste( mCalendarView, SLOT( edit_paste() ),
00291                                      mACollection, "korganizer_paste" );
00292     mUndoAction = KStdAction::undo( h, SLOT( undo() ),
00293                                     mACollection, "korganizer_undo" );
00294     mRedoAction = KStdAction::redo( h, SLOT( redo() ),
00295                                     mACollection, "korganizer_redo" );
00296   } else {
00297     mCutAction = KStdAction::cut( mCalendarView,SLOT( edit_cut() ),
00298                                   mACollection );
00299     mCopyAction = KStdAction::copy( mCalendarView,SLOT( edit_copy() ),
00300                                     mACollection );
00301     pasteAction = KStdAction::paste( mCalendarView,SLOT( edit_paste() ),
00302                                      mACollection );
00303     mUndoAction = KStdAction::undo( h, SLOT( undo() ), mACollection );
00304     mRedoAction = KStdAction::redo( h, SLOT( redo() ), mACollection );
00305   }
00306   mDeleteAction = new KAction( i18n("&Delete"), "editdelete", 0,
00307                                mCalendarView, SLOT( appointment_delete() ),
00308                                mACollection, "edit_delete" );
00309   if ( mIsPart ) {
00310     KStdAction::find( mCalendarView->dialogManager(), SLOT( showSearchDialog() ),
00311                      mACollection, "korganizer_find" );
00312   } else {
00313     KStdAction::find( mCalendarView->dialogManager(), SLOT( showSearchDialog() ),
00314                      mACollection );
00315   }
00316   pasteAction->setEnabled( false );
00317   mUndoAction->setEnabled( false );
00318   mRedoAction->setEnabled( false );
00319   connect( mCalendarView, SIGNAL( pasteEnabled( bool ) ),
00320            pasteAction, SLOT( setEnabled( bool ) ) );
00321   connect( h, SIGNAL( undoAvailable( const QString & ) ),
00322            SLOT( updateUndoAction( const QString & ) ) );
00323   connect( h, SIGNAL( redoAvailable( const QString & ) ),
00324            SLOT( updateRedoAction( const QString & ) ) );
00325 
00326 
00327 
00328 
00329   //************************** VIEW MENU *********************************
00330 
00331   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VIEWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00332   new KAction( i18n("What's &Next"),
00333                KOGlobals::self()->smallIcon( "whatsnext" ), 0,
00334                mCalendarView->viewManager(), SLOT( showWhatsNextView() ),
00335                mACollection, "view_whatsnext" );
00336   new KAction( i18n("&Day"),
00337                KOGlobals::self()->smallIcon( "1day" ), 0,
00338                mCalendarView->viewManager(), SLOT( showDayView() ),
00339                mACollection, "view_day" );
00340   mNextXDays = new KAction( "",
00341                             KOGlobals::self()->smallIcon( "xdays" ), 0,
00342                             mCalendarView->viewManager(),
00343                             SLOT( showNextXView() ),
00344                             mACollection, "view_nextx" );
00345   mNextXDays->setText( i18n( "&Next Day", "&Next %n Days",
00346                              KOPrefs::instance()->mNextXDays ) );
00347   new KAction( i18n("W&ork Week"),
00348                KOGlobals::self()->smallIcon( "5days" ), 0,
00349                mCalendarView->viewManager(), SLOT( showWorkWeekView() ),
00350                mACollection, "view_workweek" );
00351   new KAction( i18n("&Week"),
00352                KOGlobals::self()->smallIcon( "7days" ), 0,
00353                mCalendarView->viewManager(), SLOT( showWeekView() ),
00354                mACollection, "view_week" );
00355   new KAction( i18n("&Month"),
00356                KOGlobals::self()->smallIcon( "month" ), 0,
00357                mCalendarView->viewManager(), SLOT( showMonthView() ),
00358                mACollection, "view_month" );
00359   new KAction( i18n("&List"),
00360                KOGlobals::self()->smallIcon( "list" ), 0,
00361                mCalendarView->viewManager(), SLOT( showListView() ),
00362                mACollection, "view_list" );
00363   new KAction( i18n("&To-do List"),
00364                KOGlobals::self()->smallIcon( "todo" ), 0,
00365                mCalendarView->viewManager(), SLOT( showTodoView() ),
00366                mACollection, "view_todo" );
00367   new KAction( i18n("&Journal"),
00368                KOGlobals::self()->smallIcon( "journal" ), 0,
00369                mCalendarView->viewManager(), SLOT( showJournalView() ),
00370                mACollection, "view_journal" );
00371 
00372   //~~~~~~~~~~~~~~~~~~~~~~~~~~~ FILTERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00373   new KAction( i18n("&Refresh"), 0,
00374                     mCalendarView, SLOT( updateView() ),
00375                     mACollection, "update" );
00376 // TODO:
00377 //   new KAction( i18n("Hide &Completed To-dos"), 0,
00378 //                     mCalendarView, SLOT( toggleHideCompleted() ),
00379 //                     mACollection, "hide_completed_todos" );
00380 
00381   mFilterAction = new KSelectAction( i18n("F&ilter"), 0,
00382                   mACollection, "filter_select" );
00383   mFilterAction->setEditable( false );
00384   connect( mFilterAction, SIGNAL( activated(int) ),
00385            mCalendarView, SLOT( filterActivated( int ) ) );
00386   connect( mCalendarView, SIGNAL( newFilterListSignal( const QStringList & ) ),
00387            mFilterAction, SLOT( setItems( const QStringList & ) ) );
00388   connect( mCalendarView, SIGNAL( selectFilterSignal( int ) ),
00389            mFilterAction, SLOT( setCurrentItem( int ) ) );
00390   connect( mCalendarView, SIGNAL( filterChanged() ),
00391            this, SLOT( setTitle() ) );
00392 
00393 
00394   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ZOOM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00395   // TODO: try to find / create better icons for the following 4 actions
00396   new KAction( i18n( "Zoom In Horizontally" ), "viewmag+", 0,
00397                     mCalendarView->viewManager(), SLOT( zoomInHorizontally() ),
00398                     mACollection, "zoom_in_horizontally" );
00399   new KAction( i18n( "Zoom Out Horizontally" ), "viewmag-", 0,
00400                     mCalendarView->viewManager(), SLOT( zoomOutHorizontally() ),
00401                     mACollection, "zoom_out_horizontally" );
00402   new KAction( i18n( "Zoom In Vertically" ), "viewmag+", 0,
00403                     mCalendarView->viewManager(), SLOT( zoomInVertically() ),
00404                     mACollection, "zoom_in_vertically" );
00405   new KAction( i18n( "Zoom Out Vertically" ), "viewmag-", 0,
00406                     mCalendarView->viewManager(), SLOT( zoomOutVertically() ),
00407                     mACollection, "zoom_out_vertically" );
00408 
00409 
00410 
00411 
00412   //************************** Actions MENU *********************************
00413 
00414   new KAction( i18n("Go to &Today"), "today", 0,
00415                     mCalendarView,SLOT( goToday() ),
00416                     mACollection, "go_today" );
00417   bool isRTL = QApplication::reverseLayout();
00418   action = new KAction( i18n("Go &Backward"), isRTL ? "forward" : "back", 0,
00419                         mCalendarView,SLOT( goPrevious() ),
00420                         mACollection, "go_previous" );
00421 
00422   // Changing the action text by setText makes the toolbar button disappear.
00423   // This has to be fixed first, before the connects below can be reenabled.
00424   /*
00425   connect( mCalendarView, SIGNAL( changeNavStringPrev( const QString & ) ),
00426            action, SLOT( setText( const QString & ) ) );
00427   connect( mCalendarView, SIGNAL( changeNavStringPrev( const QString & ) ),
00428            this, SLOT( dumpText( const QString & ) ) );*/
00429 
00430   action = new KAction( i18n("Go &Forward"), isRTL ? "back" : "forward", 0,
00431                         mCalendarView,SLOT( goNext() ),
00432                         mACollection, "go_next" );
00433   /*
00434   connect( mCalendarView,SIGNAL( changeNavStringNext( const QString & ) ),
00435            action,SLOT( setText( const QString & ) ) );
00436   */
00437 
00438 
00439   //************************** Actions MENU *********************************
00440   new KAction( i18n("New E&vent..."),
00441                KOGlobals::self()->smallIcon( "newappointment" ), 0,
00442                mCalendarView, SLOT( newEvent() ),
00443                mACollection, "new_event" );
00444   new KAction( i18n("New &To-do..."),
00445                KOGlobals::self()->smallIcon( "newtodo" ), 0,
00446                mCalendarView, SLOT( newTodo() ),
00447                mACollection, "new_todo" );
00448   action = new KAction( i18n("New Su&b-to-do..."), 0,
00449                         mCalendarView,SLOT( newSubTodo() ),
00450                         mACollection, "new_subtodo" );
00451   action->setEnabled( false );
00452   connect( mCalendarView,SIGNAL( todoSelected( bool ) ),
00453            action,SLOT( setEnabled( bool ) ) );
00454   new KAction( i18n("New &Journal..."),
00455                KOGlobals::self()->smallIcon( "newjournal" ), 0,
00456                mCalendarView, SLOT( newJournal() ),
00457                mACollection, "new_journal" );
00458 
00459   mShowIncidenceAction = new KAction( i18n("&Show"), 0,
00460                                       mCalendarView,SLOT( showIncidence() ),
00461                                       mACollection, "show_incidence" );
00462   mEditIncidenceAction = new KAction( i18n("&Edit..."), 0,
00463                                       mCalendarView,SLOT( editIncidence() ),
00464                                       mACollection, "edit_incidence" );
00465   mDeleteIncidenceAction = new KAction( i18n("&Delete"), Key_Delete,
00466                                         mCalendarView,SLOT( deleteIncidence()),
00467                                         mACollection, "delete_incidence" );
00468 
00469   action = new KAction( i18n("&Make Sub-to-do Independent"), 0,
00470                         mCalendarView,SLOT( todo_unsub() ),
00471                         mACollection, "unsub_todo" );
00472   action->setEnabled( false );
00473   connect( mCalendarView,SIGNAL( subtodoSelected( bool ) ),
00474            action,SLOT( setEnabled( bool ) ) );
00475 // TODO: Add item to move the incidence to different resource
00476 //   mAssignResourceAction = new KAction( i18n("Assign &Resource..."), 0,
00477 //                                        mCalendarView, SLOT( assignResource()),
00478 //                                        mACollection, "assign_resource" );
00479 // TODO: Add item to quickly toggle the reminder of a given incidence
00480 //   mToggleAlarmAction = new KToggleAction( i18n("&Activate Reminder"), 0,
00481 //                                         mCalendarView, SLOT( toggleAlarm()),
00482 //                                         mACollection, "activate_alarm" );
00483 
00484 
00485 
00486 
00487   //************************** SCHEDULE MENU ********************************
00488   mPublishEvent = new KAction( i18n("&Publish Item Information..."), "mail_send", 0,
00489                                mCalendarView, SLOT( schedule_publish() ),
00490                                mACollection, "schedule_publish" );
00491   mPublishEvent->setEnabled( false );
00492 
00493   action = new KAction( i18n("Send &Invitation to Attendees"),"mail_generic",0,
00494                         mCalendarView,SLOT( schedule_request() ),
00495                         mACollection,"schedule_request" );
00496   action->setEnabled( false );
00497   connect( mCalendarView, SIGNAL( organizerEventsSelected( bool ) ),
00498            action, SLOT( setEnabled( bool ) ) );
00499 
00500   action = new KAction( i18n("Re&quest Update"), 0,
00501                         mCalendarView, SLOT( schedule_refresh() ),
00502                         mACollection, "schedule_refresh" );
00503   action->setEnabled( false );
00504   connect( mCalendarView,SIGNAL( groupEventsSelected( bool ) ),
00505            action,SLOT( setEnabled( bool ) ) );
00506 
00507   action = new KAction( i18n("Send &Cancelation to Attendees"), 0,
00508                         mCalendarView, SLOT( schedule_cancel() ),
00509                         mACollection, "schedule_cancel" );
00510   action->setEnabled( false );
00511   connect( mCalendarView,SIGNAL( organizerEventsSelected( bool ) ),
00512            action,SLOT( setEnabled( bool ) ) );
00513 
00514   action = new KAction( i18n("Send Status &Update"),"mail_reply",0,
00515                         mCalendarView,SLOT( schedule_reply() ),
00516                         mACollection,"schedule_reply" );
00517   action->setEnabled( false );
00518   connect( mCalendarView,SIGNAL( groupEventsSelected( bool ) ),
00519            action,SLOT( setEnabled( bool ) ) );
00520 
00521   action = new KAction( i18n("counter proposal","Request Chan&ge"),0,
00522                         mCalendarView,SLOT( schedule_counter() ),
00523                         mACollection, "schedule_counter" );
00524   action->setEnabled( false );
00525   connect( mCalendarView,SIGNAL( groupEventsSelected( bool ) ),
00526            action,SLOT( setEnabled( bool ) ) );
00527 
00528   action = new KAction( i18n("&Mail Free Busy Information..."), 0,
00529                         mCalendarView, SLOT( mailFreeBusy() ),
00530                         mACollection, "mail_freebusy" );
00531   action->setEnabled( true );
00532 
00533   action = new KAction( i18n("&Upload Free Busy Information"), 0,
00534                         mCalendarView, SLOT( uploadFreeBusy() ),
00535                         mACollection, "upload_freebusy" );
00536   action->setEnabled( true );
00537 
00538   if ( !mIsPart ) {
00539       action = new KAction( i18n("&Addressbook"),"contents",0,
00540                             mCalendarView,SLOT( openAddressbook() ),
00541                             mACollection,"addressbook" );
00542   }
00543 
00544 
00545 
00546 
00547   //************************** SETTINGS MENU ********************************
00548 
00549   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00550   mDateNavigatorShowAction = new KToggleAction( i18n("Show Date Navigator"), 0,
00551                       this, SLOT( toggleDateNavigator() ),
00552                       mACollection, "show_datenavigator" );
00553   mTodoViewShowAction = new KToggleAction ( i18n("Show To-do View"), 0,
00554                       this, SLOT( toggleTodoView() ),
00555                       mACollection, "show_todoview" );
00556   mEventViewerShowAction = new KToggleAction ( i18n("Show Item Viewer"), 0,
00557                       this, SLOT( toggleEventViewer() ),
00558                       mACollection, "show_eventviewer" );
00559   KConfig *config = KOGlobals::self()->config();
00560   config->setGroup( "Settings" );
00561   mDateNavigatorShowAction->setChecked(
00562       config->readBoolEntry( "DateNavigatorVisible", true ) );
00563   // if we are a kpart, then let's not show the todo in the left pane by
00564   // default since there's also a Todo part and we'll assume they'll be
00565   // using that as well, so let's not duplicate it (by default) here
00566   mTodoViewShowAction->setChecked(
00567       config->readBoolEntry( "TodoViewVisible", mIsPart ? false : true ) );
00568   mEventViewerShowAction->setChecked(
00569       config->readBoolEntry( "EventViewerVisible", true ) );
00570   toggleDateNavigator();
00571   toggleTodoView();
00572   toggleEventViewer();
00573 
00574   if ( !mMainWindow->hasDocument() ) {
00575     mResourceViewShowAction = new KToggleAction ( i18n("Show Resource View"), 0,
00576                         this, SLOT( toggleResourceView() ),
00577                         mACollection, "show_resourceview" );
00578     mResourceButtonsAction = new KToggleAction( i18n("Show &Resource Buttons"), 0,
00579                         this, SLOT( toggleResourceButtons() ),
00580                         mACollection, "show_resourcebuttons" );
00581     mResourceViewShowAction->setChecked(
00582         config->readBoolEntry( "ResourceViewVisible", true ) );
00583     mResourceButtonsAction->setChecked(
00584         config->readBoolEntry( "ResourceButtonsVisible", true ) );
00585 
00586     toggleResourceView();
00587     toggleResourceButtons();
00588   }
00589 
00590 
00591   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00592 
00593   new KAction( i18n("Configure &Date && Time..."), 0,
00594                     this, SLOT( configureDateTime() ),
00595                     mACollection, "conf_datetime" );
00596 // TODO: Add an item to show the resource management dlg
00597 //   new KAction( i18n("Manage &Resources..."), 0,
00598 //                     this, SLOT( manageResources() ),
00599 //                     mACollection, "conf_resources" );
00600   new KAction( i18n("Manage View &Filters..."), "configure", 0,
00601                mCalendarView, SLOT( editFilters() ),
00602                mACollection, "edit_filters" );
00603   new KAction( i18n("Manage C&ategories..."), 0,
00604                mCalendarView->dialogManager(), SLOT( showCategoryEditDialog() ),
00605                mACollection, "edit_categories" );
00606   if ( mIsPart ) {
00607     new KAction( i18n("&Configure Calendar..."), "configure", 0,
00608                  mCalendarView, SLOT( edit_options() ),
00609                  mACollection, "korganizer_configure" );
00610     KStdAction::keyBindings( this, SLOT( keyBindings() ),
00611                              mACollection, "korganizer_configure_shortcuts" );
00612   } else {
00613     KStdAction::preferences( mCalendarView, SLOT( edit_options() ),
00614                             mACollection );
00615     KStdAction::keyBindings( this, SLOT( keyBindings() ), mACollection );
00616   }
00617 
00618 
00619 
00620 
00621   //**************************** HELP MENU **********************************
00622   KStdAction::tipOfDay( this, SLOT( showTip() ), mACollection,
00623                         "help_tipofday" );
00624 //   new KAction( i18n("Show Intro Page"), 0,
00625 //                     mCalendarView,SLOT( showIntro() ),
00626 //                     mACollection,"show_intro" );
00627 
00628 
00629 
00630 
00631   //************************* TOOLBAR ACTIONS *******************************
00632   QLabel *filterLabel = new QLabel( i18n("Filter: "), mCalendarView );
00633   filterLabel->hide();
00634   new KWidgetAction( filterLabel, i18n("Filter: "), 0, 0, 0,
00635                      mACollection, "filter_label" );
00636 
00637 }
00638 
00639 void ActionManager::readSettings()
00640 {
00641   // read settings from the KConfig, supplying reasonable
00642   // defaults where none are to be found
00643 
00644   KConfig *config = KOGlobals::self()->config();
00645   if ( mRecent ) mRecent->loadEntries( config );
00646   mCalendarView->readSettings();
00647 }
00648 
00649 void ActionManager::writeSettings()
00650 {
00651   kdDebug(5850) << "ActionManager::writeSettings" << endl;
00652 
00653   KConfig *config = KOGlobals::self()->config();
00654   mCalendarView->writeSettings();
00655 
00656   config->setGroup( "Settings" );
00657   if ( mResourceButtonsAction ) {
00658     config->writeEntry( "ResourceButtonsVisible",
00659                         mResourceButtonsAction->isChecked() );
00660   }
00661   if ( mDateNavigatorShowAction ) {
00662     config->writeEntry( "DateNavigatorVisible",
00663                         mDateNavigatorShowAction->isChecked() );
00664   }
00665   if ( mTodoViewShowAction ) {
00666     config->writeEntry( "TodoViewVisible",
00667                         mTodoViewShowAction->isChecked() );
00668   }
00669   if ( mResourceViewShowAction ) {
00670     config->writeEntry( "ResourceViewVisible",
00671                         mResourceViewShowAction->isChecked() );
00672   }
00673   if ( mEventViewerShowAction ) {
00674     config->writeEntry( "EventViewerVisible",
00675                         mEventViewerShowAction->isChecked() );
00676   }
00677 
00678   if ( mRecent ) mRecent->saveEntries( config );
00679 
00680   config->sync();
00681 
00682   if ( mCalendarResources ) {
00683     mCalendarResources->resourceManager()->writeConfig();
00684   }
00685 }
00686 
00687 void ActionManager::file_new()
00688 {
00689   emit actionNew();
00690 }
00691 
00692 void ActionManager::file_open()
00693 {
00694   KURL url;
00695   QString defaultPath = locateLocal( "data","korganizer/" );
00696   url = KFileDialog::getOpenURL( defaultPath,i18n("*.vcs *.ics|Calendar Files"),
00697                                 dialogParent() );
00698 
00699   file_open( url );
00700 }
00701 
00702 void ActionManager::file_open( const KURL &url )
00703 {
00704   if ( url.isEmpty() ) return;
00705 
00706   // is that URL already opened somewhere else? Activate that window
00707   KOrg::MainWindow *korg=ActionManager::findInstance( url );
00708   if ( ( 0 != korg )&&( korg != mMainWindow ) ) {
00709     KWin::setActiveWindow( korg->topLevelWidget()->winId() );
00710     return;
00711   }
00712 
00713   kdDebug(5850) << "ActionManager::file_open(): " << url.prettyURL() << endl;
00714 
00715   // Open the calendar file in the same window only if we have an empty calendar window, and not the resource calendar
00716   if ( !mCalendarView->isModified() && mFile.isEmpty() && !mCalendarResources ) {
00717     openURL( url );
00718   } else {
00719     emit actionNew( url );
00720   }
00721 }
00722 
00723 void ActionManager::file_icalimport()
00724 {
00725   // FIXME: eventually, we will need a dialog box to select import type, etc.
00726   // for now, hard-coded to ical file, $HOME/.calendar.
00727   int retVal = -1;
00728   QString progPath;
00729   KTempFile tmpfn;
00730 
00731   QString homeDir = QDir::homeDirPath() + QString::fromLatin1( "/.calendar" );
00732 
00733   if ( !QFile::exists( homeDir ) ) {
00734     KMessageBox::error( dialogParent(),
00735                        i18n( "You have no ical file in your home directory.\n"
00736                             "Import cannot proceed.\n" ) );
00737     return;
00738   }
00739 
00740   KProcess proc;
00741   proc << "ical2vcal" << tmpfn.name();
00742   bool success = proc.start( KProcess::Block );
00743 
00744   if ( !success ) {
00745     kdDebug(5850) << "Error starting ical2vcal." << endl;
00746     return;
00747   } else {
00748     retVal = proc.exitStatus();
00749   }
00750 
00751   kdDebug(5850) << "ical2vcal return value: " << retVal << endl;
00752 
00753   if ( retVal >= 0 && retVal <= 2 ) {
00754     // now we need to MERGE what is in the iCal to the current calendar.
00755     mCalendarView->openCalendar( tmpfn.name(),1 );
00756     if ( !retVal )
00757       KMessageBox::information( dialogParent(),
00758                                i18n( "KOrganizer successfully imported and "
00759                                     "merged your .calendar file from ical "
00760                                     "into the currently opened calendar." ),
00761                                "dotCalendarImportSuccess" );
00762     else
00763       KMessageBox::information( dialogParent(),
00764                            i18n( "KOrganizer encountered some unknown fields while "
00765                                 "parsing your .calendar ical file, and had to "
00766                                 "discard them; please check to see that all "
00767                                 "your relevant data was correctly imported." ),
00768                                  i18n("ICal Import Successful with Warning") );
00769   } else if ( retVal == -1 ) {
00770     KMessageBox::error( dialogParent(),
00771                          i18n( "KOrganizer encountered an error parsing your "
00772                               ".calendar file from ical; import has failed." ) );
00773   } else if ( retVal == -2 ) {
00774     KMessageBox::error( dialogParent(),
00775                          i18n( "KOrganizer does not think that your .calendar "
00776                               "file is a valid ical calendar; import has failed." ) );
00777   }
00778   tmpfn.unlink();
00779 }
00780 
00781 void ActionManager::file_merge()
00782 {
00783   KURL url = KFileDialog::getOpenURL( locateLocal( "data","korganizer/" ),
00784                                      i18n("*.vcs *.ics|Calendar Files"),
00785                                      dialogParent() );
00786   if ( ! url.isEmpty() )  // isEmpty if user cancelled the dialog
00787     importCalendar( url );
00788 }
00789 
00790 void ActionManager::file_archive()
00791 {
00792   mCalendarView->archiveCalendar();
00793 }
00794 
00795 void ActionManager::file_revert()
00796 {
00797   openURL( mURL );
00798 }
00799 
00800 void ActionManager::file_saveas()
00801 {
00802   KURL url = getSaveURL();
00803 
00804   if ( url.isEmpty() ) return;
00805 
00806   saveAsURL( url );
00807 }
00808 
00809 void ActionManager::file_save()
00810 {
00811   if ( mMainWindow->hasDocument() ) {
00812     if ( mURL.isEmpty() ) {
00813       file_saveas();
00814       return;
00815     } else {
00816       saveURL();
00817     }
00818   } else {
00819     mCalendarView->calendar()->save();
00820   }
00821 
00822   // export to HTML
00823   if ( KOPrefs::instance()->mHtmlWithSave ) {
00824     exportHTML();
00825   }
00826 }
00827 
00828 void ActionManager::file_close()
00829 {
00830   if ( !saveModifiedURL() ) return;
00831 
00832   mCalendarView->closeCalendar();
00833   KIO::NetAccess::removeTempFile( mFile );
00834   mURL="";
00835   mFile="";
00836 
00837   setTitle();
00838 }
00839 
00840 bool ActionManager::openURL( const KURL &url,bool merge )
00841 {
00842   kdDebug(5850) << "ActionManager::openURL()" << endl;
00843 
00844   if ( url.isEmpty() ) {
00845     kdDebug(5850) << "ActionManager::openURL(): Error! Empty URL." << endl;
00846     return false;
00847   }
00848   if ( !url.isValid() ) {
00849     kdDebug(5850) << "ActionManager::openURL(): Error! URL is malformed." << endl;
00850     return false;
00851   }
00852 
00853   if ( url.isLocalFile() ) {
00854     mURL = url;
00855     mFile = url.path();
00856     if ( !KStandardDirs::exists( mFile ) ) {
00857       mMainWindow->showStatusMessage( i18n("New calendar '%1'.")
00858                                       .arg( url.prettyURL() ) );
00859       mCalendarView->setModified();
00860     } else {
00861       bool success = mCalendarView->openCalendar( mFile, merge );
00862       if ( success ) {
00863         showStatusMessageOpen( url, merge );
00864       }
00865     }
00866     setTitle();
00867   } else {
00868     QString tmpFile;
00869     if( KIO::NetAccess::download( url, tmpFile, view() ) ) {
00870       kdDebug(5850) << "--- Downloaded to " << tmpFile << endl;
00871       bool success = mCalendarView->openCalendar( tmpFile, merge );
00872       if ( merge ) {
00873         KIO::NetAccess::removeTempFile( tmpFile );
00874         if ( success )
00875           showStatusMessageOpen( url, merge );
00876       } else {
00877         if ( success ) {
00878           KIO::NetAccess::removeTempFile( mFile );
00879           mURL = url;
00880           mFile = tmpFile;
00881           KConfig *config = KOGlobals::self()->config();
00882           config->setGroup( "General" );
00883           setTitle();
00884           kdDebug(5850) << "-- Add recent URL: " << url.prettyURL() << endl;
00885           if ( mRecent ) mRecent->addURL( url );
00886           showStatusMessageOpen( url, merge );
00887         }
00888       }
00889       return success;
00890     } else {
00891       QString msg;
00892       msg = i18n("Cannot download calendar from '%1'.").arg( url.prettyURL() );
00893       KMessageBox::error( dialogParent(), msg );
00894       return false;
00895     }
00896   }
00897   return true;
00898 }
00899 
00900 bool ActionManager::addResource( const KURL &mUrl )
00901 {
00902   CalendarResources *cr = KOrg::StdCalendar::self();
00903 
00904   CalendarResourceManager *manager = cr->resourceManager();
00905 
00906   ResourceCalendar *resource = 0;
00907 
00908   QString name;
00909 
00910   kdDebug(5850) << "URL: " << mUrl << endl;
00911   if ( mUrl.isLocalFile() ) {
00912     kdDebug(5850) << "Local Resource" << endl;
00913     resource = manager->createResource( "file" );
00914     if ( resource )
00915       resource->setValue( "File", mUrl.path() );
00916     name = mUrl.path();
00917   } else {
00918     kdDebug(5850) << "Remote Resource" << endl;
00919     resource = manager->createResource( "remote" );
00920     if ( resource )
00921       resource->setValue( "DownloadURL", mUrl.url() );
00922     name = mUrl.prettyURL();
00923     resource->setReadOnly( true );
00924   }
00925 
00926   if ( resource ) {
00927     resource->setTimeZoneId( KOPrefs::instance()->mTimeZoneId );
00928     resource->setResourceName( name );
00929     manager->add( resource );
00930     mMainWindow->showStatusMessage( i18n( "Added calendar resource for URL '%1'." )
00931                .arg( name ) );
00932     // we have to call resourceAdded manually, because for in-process changes
00933     // the dcop signals are not connected, so the resource's signals would not
00934     // be connected otherwise
00935     if ( mCalendarResources )
00936       mCalendarResources->resourceAdded( resource );
00937   } else {
00938     QString msg = i18n("Unable to create calendar resource '%1'.")
00939                       .arg( name );
00940     KMessageBox::error( dialogParent(), msg );
00941   }
00942   return true;
00943 }
00944 
00945 
00946 void ActionManager::showStatusMessageOpen( const KURL &url, bool merge )
00947 {
00948   if ( merge ) {
00949     mMainWindow->showStatusMessage( i18n("Merged calendar '%1'.")
00950                                     .arg( url.prettyURL() ) );
00951   } else {
00952     mMainWindow->showStatusMessage( i18n("Opened calendar '%1'.")
00953                                     .arg( url.prettyURL() ) );
00954   }
00955 }
00956 
00957 void ActionManager::closeURL()
00958 {
00959   kdDebug(5850) << "ActionManager::closeURL()" << endl;
00960 
00961   file_close();
00962 }
00963 
00964 bool ActionManager::saveURL()
00965 {
00966   QString ext;
00967 
00968   if ( mURL.isLocalFile() ) {
00969     ext = mFile.right( 4 );
00970   } else {
00971     ext = mURL.filename().right( 4 );
00972   }
00973 
00974   if ( ext == ".vcs" ) {
00975     int result = KMessageBox::warningContinueCancel(
00976         dialogParent(),
00977         i18n( "Your calendar will be saved in iCalendar format. Use "
00978               "'Export vCalendar' to save in vCalendar format." ),
00979         i18n("Format Conversion"), i18n("Proceed"), "dontaskFormatConversion",
00980         true );
00981     if ( result != KMessageBox::Continue ) return false;
00982 
00983     QString filename = mURL.fileName();
00984     filename.replace( filename.length() - 4, 4, ".ics" );
00985     mURL.setFileName( filename );
00986     if ( mURL.isLocalFile() ) {
00987       mFile = mURL.path();
00988     }
00989     setTitle();
00990     if ( mRecent ) mRecent->addURL( mURL );
00991   }
00992 
00993   if ( !mCalendarView->saveCalendar( mFile ) ) {
00994     kdDebug(5850) << "ActionManager::saveURL(): calendar view save failed."
00995                   << endl;
00996     return false;
00997   } else {
00998     mCalendarView->setModified( false );
00999   }
01000 
01001   if ( !mURL.isLocalFile() ) {
01002     if ( !KIO::NetAccess::upload( mFile, mURL, view() ) ) {
01003       QString msg = i18n("Cannot upload calendar to '%1'")
01004                     .arg( mURL.prettyURL() );
01005       KMessageBox::error( dialogParent() ,msg );
01006       return false;
01007     }
01008   }
01009 
01010   // keep saves on a regular interval
01011   if ( KOPrefs::instance()->mAutoSave ) {
01012     mAutoSaveTimer->stop();
01013     mAutoSaveTimer->start( 1000*60*KOPrefs::instance()->mAutoSaveInterval );
01014   }
01015 
01016   mMainWindow->showStatusMessage( i18n("Saved calendar '%1'.").arg( mURL.prettyURL() ) );
01017 
01018   return true;
01019 }
01020 
01021 void ActionManager::exportHTML()
01022 {
01023   HTMLExportSettings settings( "KOrganizer" );
01024   // Manually read in the config, because parametrized kconfigxt objects don't
01025   // seem to load the config theirselves
01026   settings.readConfig();
01027 
01028   QDate qd1;
01029   qd1 = QDate::currentDate();
01030   QDate qd2;
01031   qd2 = QDate::currentDate();
01032   if ( settings.monthView() )
01033     qd2.addMonths( 1 );
01034   else
01035     qd2.addDays( 7 );
01036   settings.setDateStart( qd1 );
01037   settings.setDateEnd( qd2 );
01038   exportHTML( &settings );
01039 }
01040 
01041 void ActionManager::exportHTML( HTMLExportSettings *settings )
01042 {
01043   if ( !settings || settings->outputFile().isEmpty() )
01044     return;
01045   settings->setEMail( KOPrefs::instance()->email() );
01046   settings->setName( KOPrefs::instance()->fullName() );
01047 
01048   settings->setCreditName( "KOrganizer" );
01049   settings->setCreditURL( "http://korganizer.kde.org" );
01050 
01051   KCal::HtmlExport mExport( mCalendarView->calendar(), settings );
01052 
01053   QDate cdate = settings->dateStart().date();
01054   QDate qd2 = settings->dateEnd().date();
01055   while ( cdate <= qd2 ) {
01056     QStringList holidays = KOGlobals::self()->holiday( cdate );
01057     if ( !holidays.isEmpty() ) {
01058       QStringList::ConstIterator it = holidays.begin();
01059       for ( ; it != holidays.end(); ++it ) {
01060         mExport.addHoliday( cdate, *it );
01061       }
01062     }
01063     cdate = cdate.addDays( 1 );
01064   }
01065 
01066   KURL dest( settings->outputFile() );
01067   if ( dest.isLocalFile() ) {
01068     mExport.save( dest.path() );
01069   } else {
01070     KTempFile tf;
01071     QString tfile = tf.name();
01072     tf.close();
01073     mExport.save( tfile );
01074     if ( !KIO::NetAccess::upload( tfile, dest, view() ) ) {
01075       KNotifyClient::event ( view()->winId(),
01076                             i18n("Could not upload file.") );
01077     }
01078     tf.unlink();
01079   }
01080 }
01081 
01082 bool ActionManager::saveAsURL( const KURL &url )
01083 {
01084   kdDebug(5850) << "ActionManager::saveAsURL() " << url.prettyURL() << endl;
01085 
01086   if ( url.isEmpty() ) {
01087     kdDebug(5850) << "ActionManager::saveAsURL(): Empty URL." << endl;
01088     return false;
01089   }
01090   if ( !url.isValid() ) {
01091     kdDebug(5850) << "ActionManager::saveAsURL(): Malformed URL." << endl;
01092     return false;
01093   }
01094 
01095   QString fileOrig = mFile;
01096   KURL URLOrig = mURL;
01097 
01098   KTempFile *tempFile = 0;
01099   if ( url.isLocalFile() ) {
01100     mFile = url.path();
01101   } else {
01102     tempFile = new KTempFile;
01103     mFile = tempFile->name();
01104   }
01105   mURL = url;
01106 
01107   bool success = saveURL(); // Save local file and upload local file
01108   if ( success ) {
01109     delete mTempFile;
01110     mTempFile = tempFile;
01111     KIO::NetAccess::removeTempFile( fileOrig );
01112     KConfig *config = KOGlobals::self()->config();
01113     config->setGroup( "General" );
01114     setTitle();
01115     if ( mRecent ) mRecent->addURL( mURL );
01116   } else {
01117     KMessageBox::sorry( dialogParent(), i18n("Unable to save calendar to the file %1.").arg( mFile ), i18n("Error") );
01118     kdDebug(5850) << "ActionManager::saveAsURL() failed" << endl;
01119     mURL = URLOrig;
01120     mFile = fileOrig;
01121     delete tempFile;
01122   }
01123 
01124   return success;
01125 }
01126 
01127 
01128 bool ActionManager::saveModifiedURL()
01129 {
01130   kdDebug(5850) << "ActionManager::saveModifiedURL()" << endl;
01131 
01132   // If calendar isn't modified do nothing.
01133   if ( !mCalendarView->isModified() ) return true;
01134 
01135   mHtmlExportSync = true;
01136   if ( KOPrefs::instance()->mAutoSave && !mURL.isEmpty() ) {
01137     // Save automatically, when auto save is enabled.
01138     return saveURL();
01139   } else {
01140     int result = KMessageBox::warningYesNoCancel(
01141         dialogParent(),
01142         i18n("The calendar has been modified.\nDo you want to save it?"),
01143         QString::null,
01144         KStdGuiItem::save(), KStdGuiItem::discard() );
01145     switch( result ) {
01146       case KMessageBox::Yes:
01147         if ( mURL.isEmpty() ) {
01148           KURL url = getSaveURL();
01149           return saveAsURL( url );
01150         } else {
01151           return saveURL();
01152         }
01153       case KMessageBox::No:
01154         return true;
01155       case KMessageBox::Cancel:
01156       default:
01157         {
01158           mHtmlExportSync = false;
01159           return false;
01160         }
01161     }
01162   }
01163 }
01164 
01165 
01166 KURL ActionManager::getSaveURL()
01167 {
01168   KURL url = KFileDialog::getSaveURL( locateLocal( "data","korganizer/" ),
01169                                      i18n("*.vcs *.ics|Calendar Files"),
01170                                      dialogParent() );
01171 
01172   if ( url.isEmpty() ) return url;
01173 
01174   QString filename = url.fileName( false );
01175 
01176   QString e = filename.right( 4 );
01177   if ( e != ".vcs" && e != ".ics" ) {
01178     // Default save format is iCalendar
01179     filename += ".ics";
01180   }
01181 
01182   url.setFileName( filename );
01183 
01184   kdDebug(5850) << "ActionManager::getSaveURL(): url: " << url.url() << endl;
01185 
01186   return url;
01187 }
01188 
01189 void ActionManager::saveProperties( KConfig *config )
01190 {
01191   kdDebug(5850) << "ActionManager::saveProperties" << endl;
01192 
01193   config->writeEntry( "UseResourceCalendar", !mMainWindow->hasDocument() );
01194   if ( mMainWindow->hasDocument() ) {
01195     config->writePathEntry( "Calendar",mURL.url() );
01196   }
01197 }
01198 
01199 void ActionManager::readProperties( KConfig *config )
01200 {
01201   kdDebug(5850) << "ActionManager::readProperties" << endl;
01202 
01203   bool isResourceCalendar(
01204     config->readBoolEntry( "UseResourceCalendar", true ) );
01205   QString calendarUrl = config->readPathEntry( "Calendar" );
01206 
01207   if ( !isResourceCalendar && !calendarUrl.isEmpty() ) {
01208     mMainWindow->init( true );
01209     KURL u( calendarUrl );
01210     openURL( u );
01211   } else {
01212     mMainWindow->init( false );
01213   }
01214 }
01215 
01216 void ActionManager::checkAutoSave()
01217 {
01218   kdDebug(5850) << "ActionManager::checkAutoSave()" << endl;
01219 
01220   // Don't save if auto save interval is zero
01221   if ( KOPrefs::instance()->mAutoSaveInterval == 0 ) return;
01222 
01223   // has this calendar been saved before? If yes automatically save it.
01224   if ( KOPrefs::instance()->mAutoSave ) {
01225     if ( mCalendarResources || ( mCalendar && !url().isEmpty() ) ) {
01226       saveCalendar();
01227     }
01228   }
01229 }
01230 
01231 
01232 // Configuration changed as a result of the options dialog.
01233 void ActionManager::updateConfig()
01234 {
01235   kdDebug(5850) << "ActionManager::updateConfig()" << endl;
01236 
01237   if ( KOPrefs::instance()->mAutoSave && !mAutoSaveTimer->isActive() ) {
01238     checkAutoSave();
01239     if ( KOPrefs::instance()->mAutoSaveInterval > 0 ) {
01240       mAutoSaveTimer->start( 1000 * 60 *
01241                              KOPrefs::instance()->mAutoSaveInterval );
01242     }
01243   }
01244   if ( !KOPrefs::instance()->mAutoSave ) mAutoSaveTimer->stop();
01245   mNextXDays->setText( i18n( "&Next Day", "&Next %n Days",
01246                              KOPrefs::instance()->mNextXDays ) );
01247 
01248   KOCore::self()->reloadPlugins();
01249   mParts = KOCore::self()->reloadParts( mMainWindow, mParts );
01250 
01251   setDestinationPolicy();
01252 
01253   if ( mResourceView )
01254     mResourceView->updateView();
01255 
01256   KOGroupware::instance()->freeBusyManager()->setBrokenUrl( false );
01257 }
01258 
01259 void ActionManager::setDestinationPolicy()
01260 {
01261   if ( mCalendarResources ) {
01262     if ( KOPrefs::instance()->mDestination == KOPrefs::askDestination )
01263       mCalendarResources->setAskDestinationPolicy();
01264     else
01265       mCalendarResources->setStandardDestinationPolicy();
01266   }
01267 }
01268 
01269 void ActionManager::configureDateTime()
01270 {
01271   KProcess *proc = new KProcess;
01272   *proc << "kcmshell" << "language";
01273 
01274   connect( proc,SIGNAL( processExited( KProcess * ) ),
01275           SLOT( configureDateTimeFinished( KProcess * ) ) );
01276 
01277   if ( !proc->start() ) {
01278       KMessageBox::sorry( dialogParent(),
01279         i18n("Could not start control module for date and time format.") );
01280       delete proc;
01281   }
01282 }
01283 
01284 void ActionManager::showTip()
01285 {
01286   KTipDialog::showTip( dialogParent(),QString::null,true );
01287 }
01288 
01289 void ActionManager::showTipOnStart()
01290 {
01291   KTipDialog::showTip( dialogParent() );
01292 }
01293 
01294 KOrg::MainWindow *ActionManager::findInstance( const KURL &url )
01295 {
01296   if ( mWindowList ) {
01297     if ( url.isEmpty() ) return mWindowList->defaultInstance();
01298     else return mWindowList->findInstance( url );
01299   } else {
01300     return 0;
01301   }
01302 }
01303 
01304 void ActionManager::dumpText( const QString &str )
01305 {
01306   kdDebug(5850) << "ActionManager::dumpText(): " << str << endl;
01307 }
01308 
01309 void ActionManager::toggleDateNavigator()
01310 {
01311   bool visible = mDateNavigatorShowAction->isChecked();
01312   if ( mCalendarView ) mCalendarView->showDateNavigator( visible );
01313 }
01314 
01315 void ActionManager::toggleTodoView()
01316 {
01317   bool visible = mTodoViewShowAction->isChecked();
01318   if ( mCalendarView ) mCalendarView->showTodoView( visible );
01319 }
01320 
01321 void ActionManager::toggleEventViewer()
01322 {
01323   bool visible = mEventViewerShowAction->isChecked();
01324   if ( mCalendarView ) mCalendarView->showEventViewer( visible );
01325 }
01326 
01327 void ActionManager::toggleResourceView()
01328 {
01329   bool visible = mResourceViewShowAction->isChecked();
01330   kdDebug(5850) << "toggleResourceView: " << endl;
01331   if ( mResourceView ) {
01332     if ( visible ) mResourceView->show();
01333     else mResourceView->hide();
01334   }
01335 }
01336 
01337 void ActionManager::toggleResourceButtons()
01338 {
01339   bool visible = mResourceButtonsAction->isChecked();
01340 
01341   kdDebug(5850) << "RESOURCE VIEW " << long( mResourceView ) << endl;
01342 
01343   if ( mResourceView ) mResourceView->showButtons( visible );
01344 }
01345 
01346 bool ActionManager::openURL( const QString &url )
01347 {
01348   return openURL( KURL( url ) );
01349 }
01350 
01351 bool ActionManager::mergeURL( const QString &url )
01352 {
01353   return openURL( KURL( url ),true );
01354 }
01355 
01356 bool ActionManager::saveAsURL( const QString &url )
01357 {
01358   return saveAsURL( KURL( url ) );
01359 }
01360 
01361 QString ActionManager::getCurrentURLasString() const
01362 {
01363   return mURL.url();
01364 }
01365 
01366 bool ActionManager::editIncidence( const QString& uid )
01367 {
01368   return mCalendarView->editIncidence( uid );
01369 }
01370 
01371 bool ActionManager::deleteIncidence( const QString& uid, bool force )
01372 {
01373   return mCalendarView->deleteIncidence( uid, force );
01374 }
01375 
01376 bool ActionManager::addIncidence( const QString& ical )
01377 {
01378   return mCalendarView->addIncidence( ical );
01379 }
01380 
01381 void ActionManager::configureDateTimeFinished( KProcess *proc )
01382 {
01383   delete proc;
01384 }
01385 
01386 void ActionManager::downloadNewStuff()
01387 {
01388   kdDebug(5850) << "ActionManager::downloadNewStuff()" << endl;
01389 
01390   if ( !mNewStuff ) mNewStuff = new KONewStuff( mCalendarView );
01391   mNewStuff->download();
01392 }
01393 
01394 void ActionManager::uploadNewStuff()
01395 {
01396   if ( !mNewStuff ) mNewStuff = new KONewStuff( mCalendarView );
01397   mNewStuff->upload();
01398 }
01399 
01400 QString ActionManager::localFileName()
01401 {
01402   return mFile;
01403 }
01404 
01405 class ActionManager::ActionStringsVisitor : public IncidenceBase::Visitor
01406 {
01407   public:
01408     ActionStringsVisitor() : mShow( 0 ), mEdit( 0 ), mDelete( 0 ) {}
01409 
01410     bool act( IncidenceBase *incidence, KAction *show, KAction *edit, KAction *del )
01411     {
01412       mShow = show;
01413       mEdit = edit;
01414       mDelete = del;
01415       return incidence->accept( *this );
01416     }
01417 
01418   protected:
01419     bool visit( Event * ) {
01420       if ( mShow ) mShow->setText( i18n("&Show Event") );
01421       if ( mEdit ) mEdit->setText( i18n("&Edit Event...") );
01422       if ( mDelete ) mDelete->setText( i18n("&Delete Event") );
01423       return true;
01424     }
01425     bool visit( Todo * ) {
01426       if ( mShow ) mShow->setText( i18n("&Show To-do") );
01427       if ( mEdit ) mEdit->setText( i18n("&Edit To-do...") );
01428       if ( mDelete ) mDelete->setText( i18n("&Delete To-do") );
01429       return true;
01430     }
01431     bool visit( Journal * ) { return assignDefaultStrings(); }
01432   protected:
01433     bool assignDefaultStrings() {
01434       if ( mShow ) mShow->setText( i18n("&Show") );
01435       if ( mEdit ) mEdit->setText( i18n("&Edit...") );
01436       if ( mDelete ) mDelete->setText( i18n("&Delete") );
01437       return true;
01438     }
01439     KAction *mShow;
01440     KAction *mEdit;
01441     KAction *mDelete;
01442 };
01443 
01444 void ActionManager::processIncidenceSelection( Incidence *incidence )
01445 {
01446 //  kdDebug(5850) << "ActionManager::processIncidenceSelection()" << endl;
01447 
01448   if ( !incidence ) {
01449     enableIncidenceActions( false );
01450     return;
01451   }
01452 
01453   enableIncidenceActions( true );
01454 
01455   if ( incidence->isReadOnly() ) {
01456     mCutAction->setEnabled( false );
01457     mDeleteAction->setEnabled( false );
01458   }
01459 
01460   ActionStringsVisitor v;
01461   if ( !v.act( incidence, mShowIncidenceAction, mEditIncidenceAction, mDeleteIncidenceAction ) ) {
01462     mShowIncidenceAction->setText( i18n("&Show") );
01463     mEditIncidenceAction->setText( i18n("&Edit...") );
01464     mDeleteIncidenceAction->setText( i18n("&Delete") );
01465   }
01466 }
01467 
01468 void ActionManager::enableIncidenceActions( bool enabled )
01469 {
01470   mShowIncidenceAction->setEnabled( enabled );
01471   mEditIncidenceAction->setEnabled( enabled );
01472   mDeleteIncidenceAction->setEnabled( enabled );
01473 //   mAssignResourceAction->setEnabled( enabled );
01474 
01475   mCutAction->setEnabled( enabled );
01476   mCopyAction->setEnabled( enabled );
01477   mDeleteAction->setEnabled( enabled );
01478   mPublishEvent->setEnabled( enabled );
01479 }
01480 
01481 void ActionManager::keyBindings()
01482 {
01483   KKeyDialog dlg( false, view() );
01484   if ( mMainWindow )
01485     dlg.insert( mMainWindow->getActionCollection() );
01486 
01487   KOrg::Part *part;
01488   for ( part = mParts.first(); part; part = mParts.next() ) {
01489     dlg.insert( part->actionCollection(), part->shortInfo() );
01490   }
01491   dlg.configure();
01492 }
01493 
01494 void ActionManager::loadParts()
01495 {
01496   mParts = KOCore::self()->loadParts( mMainWindow );
01497 }
01498 
01499 void ActionManager::setTitle()
01500 {
01501   mMainWindow->setTitle();
01502 }
01503 
01504 KCalendarIface::ResourceRequestReply ActionManager::resourceRequest( const QValueList<QPair<QDateTime, QDateTime> >&,
01505  const QCString& resource,
01506  const QString& vCalIn )
01507 {
01508     kdDebug(5850) << k_funcinfo << "resource=" << resource << " vCalIn=" << vCalIn << endl;
01509     KCalendarIface::ResourceRequestReply reply;
01510     reply.vCalOut = "VCalOut";
01511     return reply;
01512 }
01513 
01514 void ActionManager::openEventEditor( const QString& text )
01515 {
01516   mCalendarView->newEvent( text );
01517 }
01518 
01519 void ActionManager::openEventEditor( const QString& summary,
01520                                      const QString& description,
01521                                      const QString& attachment )
01522 {
01523   mCalendarView->newEvent( summary, description, attachment );
01524 }
01525 
01526 void ActionManager::openEventEditor( const QString& summary,
01527                                      const QString& description,
01528                                      const QString& attachment,
01529                                      const QStringList& attendees )
01530 {
01531   mCalendarView->newEvent( summary, description, attachment, attendees );
01532 }
01533 
01534 void ActionManager::openTodoEditor( const QString& text )
01535 {
01536   mCalendarView->newTodo( text );
01537 }
01538 
01539 void ActionManager::openTodoEditor( const QString& summary,
01540                                     const QString& description,
01541                                     const QString& attachment )
01542 {
01543   mCalendarView->newTodo( summary, description, attachment );
01544 }
01545 
01546 void ActionManager::openTodoEditor( const QString& summary,
01547                                     const QString& description,
01548                                     const QString& attachment,
01549                                     const QStringList& attendees )
01550 {
01551   mCalendarView->newTodo( summary, description, attachment, attendees );
01552 }
01553 
01554 void ActionManager::openJournalEditor( const QDate& date )
01555 {
01556   mCalendarView->newJournal( date );
01557 }
01558 
01559 void ActionManager::openJournalEditor( const QString& text, const QDate& date )
01560 {
01561   mCalendarView->newJournal( text, date );
01562 }
01563 
01564 void ActionManager::openJournalEditor( const QString& text )
01565 {
01566   mCalendarView->newJournal( text );
01567 }
01568 
01569 //TODO:
01570 // void ActionManager::openJournalEditor( const QString& summary,
01571 //                                        const QString& description,
01572 //                                        const QString& attachment )
01573 // {
01574 //   mCalendarView->newJournal( summary, description, attachment );
01575 // }
01576 
01577 
01578 void ActionManager::showJournalView()
01579 {
01580   mCalendarView->viewManager()->showJournalView();
01581 }
01582 
01583 void ActionManager::showTodoView()
01584 {
01585   mCalendarView->viewManager()->showTodoView();
01586 }
01587 
01588 void ActionManager::showEventView()
01589 {
01590   mCalendarView->viewManager()->showEventView();
01591 }
01592 
01593 void ActionManager::goDate( const QDate& date )
01594 {
01595   mCalendarView->goDate( date );
01596 }
01597 
01598 void ActionManager::goDate( const QString& date )
01599 {
01600   goDate( KGlobal::locale()->readDate( date ) );
01601 }
01602 
01603 void ActionManager::updateUndoAction( const QString &text )
01604 {
01605   if ( text.isNull() ) {
01606     mUndoAction->setEnabled( false );
01607     mUndoAction->setText( i18n("Undo") );
01608   } else {
01609     mUndoAction->setEnabled( true );
01610     if ( text.isEmpty() ) mUndoAction->setText( i18n("Undo") );
01611     else mUndoAction->setText( i18n("Undo (%1)").arg( text ) );
01612   }
01613 }
01614 
01615 void ActionManager::updateRedoAction( const QString &text )
01616 {
01617   if ( text.isNull() ) {
01618     mRedoAction->setEnabled( false );
01619     mRedoAction->setText( i18n( "Redo" ) );
01620   } else {
01621     mRedoAction->setEnabled( true );
01622     if ( text.isEmpty() ) mRedoAction->setText( i18n("Redo") );
01623     else mRedoAction->setText( i18n( "Redo (%1)" ).arg( text ) );
01624   }
01625 }
01626 
01627 bool ActionManager::queryClose()
01628 {
01629   kdDebug(5850) << "ActionManager::queryClose()" << endl;
01630 
01631   bool close = true;
01632 
01633   if ( mCalendar && mCalendar->isModified() ) {
01634     int res = KMessageBox::questionYesNoCancel( dialogParent(),
01635       i18n("The calendar contains unsaved changes. Do you want to save them before exiting?"), QString::null, KStdGuiItem::save(), KStdGuiItem::discard() );
01636     // Exit on yes and no, don't exit on cancel. If saving fails, ask for exiting.
01637     if ( res == KMessageBox::Yes ) {
01638       close = saveModifiedURL();
01639       if ( !close ) {
01640         int res1 = KMessageBox::questionYesNo( dialogParent(), i18n("Unable to save the calendar. Do you still want to close this window?"), QString::null, KStdGuiItem::close(), KStdGuiItem::cancel() );
01641         close = ( res1 == KMessageBox::Yes );
01642       }
01643     } else {
01644       close = ( res == KMessageBox::No );
01645     }
01646   } else if ( mCalendarResources ) {
01647     if ( !mIsClosing ) {
01648       kdDebug(5850) << "!mIsClosing" << endl;
01649       if ( !saveResourceCalendar() ) return false;
01650 
01651       // FIXME: Put main window into a state indicating final saving.
01652       mIsClosing = true;
01653 // FIXME: Close main window when save is finished
01654 //      connect( mCalendarResources, SIGNAL( calendarSaved() ),
01655 //               mMainWindow, SLOT( close() ) );
01656     }
01657     if ( mCalendarResources->isSaving() ) {
01658       kdDebug(5850) << "ActionManager::queryClose(): isSaving" << endl;
01659       close = false;
01660       KMessageBox::information( dialogParent(),
01661           i18n("Unable to exit. Saving still in progress.") );
01662     } else {
01663       kdDebug(5850) << "ActionManager::queryClose(): close = true" << endl;
01664       close = true;
01665     }
01666   } else {
01667     close = true;
01668   }
01669 
01670   return close;
01671 }
01672 
01673 void ActionManager::saveCalendar()
01674 {
01675   if ( mCalendar ) {
01676     if ( view()->isModified() ) {
01677       if ( !url().isEmpty() ) {
01678         saveURL();
01679       } else {
01680         QString location = locateLocal( "data", "korganizer/kontact.ics" );
01681         saveAsURL( location );
01682       }
01683     }
01684   } else if ( mCalendarResources ) {
01685     mCalendarResources->save();
01686     // FIXME: Make sure that asynchronous saves don't fail.
01687   }
01688 }
01689 
01690 bool ActionManager::saveResourceCalendar()
01691 {
01692   if ( !mCalendarResources ) return false;
01693   CalendarResourceManager *m = mCalendarResources->resourceManager();
01694 
01695   CalendarResourceManager::ActiveIterator it;
01696   for ( it = m->activeBegin(); it != m->activeEnd(); ++it ) {
01697     if ( (*it)->readOnly() ) continue;
01698     if ( !(*it)->save() ) {
01699       int result = KMessageBox::warningContinueCancel( view(),
01700         i18n( "Saving of '%1' failed. Check that the resource is "
01701              "properly configured.\nIgnore problem and continue without "
01702              "saving or cancel save?" ).arg( (*it)->resourceName() ),
01703         i18n("Save Error"), KStdGuiItem::dontSave() );
01704       if ( result == KMessageBox::Cancel ) return false;
01705     }
01706   }
01707   return true;
01708 }
01709 
01710 void ActionManager::importCalendar( const KURL &url )
01711 {
01712   if ( !url.isValid() ) {
01713     KMessageBox::error( dialogParent(),
01714                         i18n("URL '%1' is invalid.").arg( url.prettyURL() ) );
01715     return;
01716   }
01717 
01718   ImportDialog *dialog;
01719   dialog = new ImportDialog( url, mMainWindow->topLevelWidget() );
01720   connect( dialog, SIGNAL( dialogFinished( ImportDialog * ) ),
01721            SLOT( slotImportDialogFinished( ImportDialog * ) ) );
01722   connect( dialog, SIGNAL( openURL( const KURL &, bool ) ),
01723            SLOT( openURL( const KURL &, bool ) ) );
01724   connect( dialog, SIGNAL( newWindow( const KURL & ) ),
01725            SIGNAL( actionNew( const KURL & ) ) );
01726   connect( dialog, SIGNAL( addResource( const KURL & ) ),
01727            SLOT( addResource( const KURL & ) ) );
01728 
01729   dialog->show();
01730 }
01731 
01732 void ActionManager::slotImportDialogFinished( ImportDialog *dlg )
01733 {
01734   dlg->deleteLater();
01735   mCalendarView->updateView();
01736 }
01737 
01738 void ActionManager::slotAutoArchivingSettingsModified()
01739 {
01740   if ( KOPrefs::instance()->mAutoArchive )
01741     mAutoArchiveTimer->start( 4 * 60 * 60 * 1000, true ); // check again in 4 hours
01742   else
01743     mAutoArchiveTimer->stop();
01744 }
01745 
01746 void ActionManager::slotAutoArchive()
01747 {
01748   if ( !mCalendarView->calendar() ) // can this happen?
01749     return;
01750   mAutoArchiveTimer->stop();
01751   EventArchiver archiver;
01752   connect( &archiver, SIGNAL( eventsDeleted() ), mCalendarView, SLOT( updateView() ) );
01753   archiver.runAuto( mCalendarView->calendar(), mCalendarView, false /*no gui*/ );
01754   // restart timer with the correct delay ( especially useful for the first time )
01755   slotAutoArchivingSettingsModified();
01756 }
01757 
01758 QWidget *ActionManager::dialogParent()
01759 {
01760   return mCalendarView->topLevelWidget();
01761 }
01762 
01763 #include "actionmanager.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys