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