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