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 TQt, and distribute the resulting executable, 00025 without including the source code for TQt 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 <tqapplication.h> 00076 #include <tqcursor.h> 00077 #include <tqtimer.h> 00078 #include <tqlabel.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 TQObject *parent, KOrg::MainWindow *mainWindow, 00085 bool isPart ) 00086 : TQObject( 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 00114 delete mCalendar; 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 TQTimer::singleShot( 0, TQT_TQOBJECT(this), TQT_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 TQTimer( this ); 00141 connect( mAutoSaveTimer,TQT_SIGNAL( timeout() ), TQT_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 TQTimer( this ); 00148 connect( mAutoArchiveTimer, TQT_SIGNAL( timeout() ), TQT_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, TQT_SIGNAL( modifiedChanged( bool ) ), TQT_SLOT( setTitle() ) ); 00156 connect( mCalendarView, TQT_SIGNAL( configChanged() ), TQT_SLOT( updateConfig() ) ); 00157 00158 connect( mCalendarView, TQT_SIGNAL( incidenceSelected( Incidence *,const TQDate & ) ), 00159 TQT_TQOBJECT(this), TQT_SLOT( processIncidenceSelection( Incidence *,const TQDate & ) ) ); 00160 connect( mCalendarView, TQT_SIGNAL( exportHTML( HTMLExportSettings * ) ), 00161 TQT_TQOBJECT(this), TQT_SLOT( exportHTML( HTMLExportSettings * ) ) ); 00162 00163 processIncidenceSelection( 0, TQDate() ); 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, TQT_SIGNAL( calendarChanged() ), 00202 mCalendarView, TQT_SLOT( resourcesChanged() ) ); 00203 connect( mCalendarResources, TQT_SIGNAL( signalErrorMessage( const TQString & ) ), 00204 mCalendarView, TQT_SLOT( showErrorMessage( const TQString & ) ) ); 00205 00206 connect( mCalendarView, TQT_SIGNAL( configChanged() ), 00207 TQT_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( TQT_TQOBJECT(this), TQT_SLOT(file_new()), mACollection, "korganizer_openNew" ); 00231 KStdAction::open( TQT_TQOBJECT(this), TQT_SLOT( file_open() ), mACollection, "korganizer_open" ); 00232 mRecent = KStdAction::openRecent( TQT_TQOBJECT(this), TQT_SLOT( file_open( const KURL& ) ), 00233 mACollection, "korganizer_openRecent" ); 00234 KStdAction::revert( this,TQT_SLOT( file_revert() ), mACollection, "korganizer_revert" ); 00235 KStdAction::saveAs( TQT_TQOBJECT(this), TQT_SLOT( file_saveas() ), mACollection, 00236 "korganizer_saveAs" ); 00237 KStdAction::save( TQT_TQOBJECT(this), TQT_SLOT( file_save() ), mACollection, "korganizer_save" ); 00238 } 00239 KStdAction::print( TQT_TQOBJECT(mCalendarView), TQT_SLOT( print() ), mACollection, "korganizer_print" ); 00240 } else { 00241 KStdAction::openNew( TQT_TQOBJECT(this), TQT_SLOT( file_new() ), mACollection ); 00242 KStdAction::open( TQT_TQOBJECT(this), TQT_SLOT( file_open() ), mACollection ); 00243 mRecent = KStdAction::openRecent( TQT_TQOBJECT(this), TQT_SLOT( file_open( const KURL& ) ), 00244 mACollection ); 00245 if ( mMainWindow->hasDocument() ) { 00246 KStdAction::revert( this,TQT_SLOT( file_revert() ), mACollection ); 00247 KStdAction::save( TQT_TQOBJECT(this), TQT_SLOT( file_save() ), mACollection ); 00248 KStdAction::saveAs( TQT_TQOBJECT(this), TQT_SLOT( file_saveas() ), mACollection ); 00249 } 00250 KStdAction::print( TQT_TQOBJECT(mCalendarView), TQT_SLOT( print() ), mACollection ); 00251 } 00252 00253 00254 //~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT / EXPORT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00255 new KAction( i18n("Import &Event/Calendar (ICS-/VCS-File)..."), 0, TQT_TQOBJECT(this), TQT_SLOT( file_merge() ), 00256 mACollection, "import_icalendar" ); 00257 new KAction( i18n("&Import From UNIX Ical tool (.calendar-File)"), 0, TQT_TQOBJECT(this), TQT_SLOT( file_icalimport() ), 00258 mACollection, "import_ical" ); 00259 new KAction( i18n("Get &Hot New Stuff..."), 0, this, 00260 TQT_SLOT( downloadNewStuff() ), mACollection, 00261 "downloadnewstuff" ); 00262 00263 new KAction( i18n("Export &Web Page..."), "webexport", 0, 00264 TQT_TQOBJECT(mCalendarView), TQT_SLOT( exportWeb() ), 00265 mACollection, "export_web" ); 00266 new KAction( i18n("&iCalendar..."), 0, 00267 TQT_TQOBJECT(mCalendarView), TQT_SLOT( exportICalendar() ), 00268 mACollection, "export_icalendar" ); 00269 new KAction( i18n("&vCalendar..."), 0, 00270 TQT_TQOBJECT(mCalendarView), TQT_SLOT( exportVCalendar() ), 00271 mACollection, "export_vcalendar" ); 00272 new KAction( i18n("Upload &Hot New Stuff..."), 0, TQT_TQOBJECT(this), 00273 TQT_SLOT( uploadNewStuff() ), mACollection, 00274 "uploadnewstuff" ); 00275 00276 00277 00278 new KAction( i18n("Archive O&ld Entries..."), 0, TQT_TQOBJECT(this), TQT_SLOT( file_archive() ), 00279 mACollection, "file_archive" ); 00280 new KAction( i18n("delete completed to-dos", "Pur&ge Completed To-dos"), 0, 00281 TQT_TQOBJECT(mCalendarView), TQT_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( TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_cut() ), 00293 mACollection, "korganizer_cut" ); 00294 mCopyAction = KStdAction::copy( TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_copy() ), 00295 mACollection, "korganizer_copy" ); 00296 pasteAction = KStdAction::paste( TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_paste() ), 00297 mACollection, "korganizer_paste" ); 00298 mUndoAction = KStdAction::undo( h, TQT_SLOT( undo() ), 00299 mACollection, "korganizer_undo" ); 00300 mRedoAction = KStdAction::redo( h, TQT_SLOT( redo() ), 00301 mACollection, "korganizer_redo" ); 00302 } else { 00303 mCutAction = KStdAction::cut( TQT_TQOBJECT(mCalendarView),TQT_SLOT( edit_cut() ), 00304 mACollection ); 00305 mCopyAction = KStdAction::copy( TQT_TQOBJECT(mCalendarView),TQT_SLOT( edit_copy() ), 00306 mACollection ); 00307 pasteAction = KStdAction::paste( TQT_TQOBJECT(mCalendarView),TQT_SLOT( edit_paste() ), 00308 mACollection ); 00309 mUndoAction = KStdAction::undo( TQT_TQOBJECT(h), TQT_SLOT( undo() ), mACollection ); 00310 mRedoAction = KStdAction::redo( TQT_TQOBJECT(h), TQT_SLOT( redo() ), mACollection ); 00311 } 00312 mDeleteAction = new KAction( i18n("&Delete"), "editdelete", 0, 00313 TQT_TQOBJECT(mCalendarView), TQT_SLOT( appointment_delete() ), 00314 mACollection, "edit_delete" ); 00315 if ( mIsPart ) { 00316 KStdAction::find( mCalendarView->dialogManager(), TQT_SLOT( showSearchDialog() ), 00317 mACollection, "korganizer_find" ); 00318 } else { 00319 KStdAction::find( mCalendarView->dialogManager(), TQT_SLOT( showSearchDialog() ), 00320 mACollection ); 00321 } 00322 pasteAction->setEnabled( false ); 00323 mUndoAction->setEnabled( false ); 00324 mRedoAction->setEnabled( false ); 00325 connect( mCalendarView, TQT_SIGNAL( pasteEnabled( bool ) ), 00326 pasteAction, TQT_SLOT( setEnabled( bool ) ) ); 00327 connect( h, TQT_SIGNAL( undoAvailable( const TQString & ) ), 00328 TQT_SLOT( updateUndoAction( const TQString & ) ) ); 00329 connect( h, TQT_SIGNAL( redoAvailable( const TQString & ) ), 00330 TQT_SLOT( updateRedoAction( const TQString & ) ) ); 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(), TQT_SLOT( showWhatsNextView() ), 00341 mACollection, "view_whatsnext" ); 00342 new KAction( i18n("&Day"), 00343 KOGlobals::self()->smallIcon( "1day" ), 0, 00344 mCalendarView->viewManager(), TQT_SLOT( showDayView() ), 00345 mACollection, "view_day" ); 00346 mNextXDays = new KAction( "", 00347 KOGlobals::self()->smallIcon( "xdays" ), 0, 00348 mCalendarView->viewManager(), 00349 TQT_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(), TQT_SLOT( showWorkWeekView() ), 00356 mACollection, "view_workweek" ); 00357 new KAction( i18n("&Week"), 00358 KOGlobals::self()->smallIcon( "7days" ), 0, 00359 mCalendarView->viewManager(), TQT_SLOT( showWeekView() ), 00360 mACollection, "view_week" ); 00361 new KAction( i18n("&Month"), 00362 KOGlobals::self()->smallIcon( "month" ), 0, 00363 mCalendarView->viewManager(), TQT_SLOT( showMonthView() ), 00364 mACollection, "view_month" ); 00365 new KAction( i18n("&List"), 00366 KOGlobals::self()->smallIcon( "list" ), 0, 00367 mCalendarView->viewManager(), TQT_SLOT( showListView() ), 00368 mACollection, "view_list" ); 00369 new KAction( i18n("&To-do List"), 00370 KOGlobals::self()->smallIcon( "todo" ), 0, 00371 mCalendarView->viewManager(), TQT_SLOT( showTodoView() ), 00372 mACollection, "view_todo" ); 00373 new KAction( i18n("&Journal"), 00374 KOGlobals::self()->smallIcon( "journal" ), 0, 00375 mCalendarView->viewManager(), TQT_SLOT( showJournalView() ), 00376 mACollection, "view_journal" ); 00377 new KAction( i18n("&Timeline View"), 00378 KOGlobals::self()->smallIcon( "timeline" ), 0, 00379 mCalendarView->viewManager(), TQT_SLOT( showTimelineView() ), 00380 mACollection, "view_timeline" ); 00381 00382 //~~~~~~~~~~~~~~~~~~~~~~~~~~~ FILTERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00383 new KAction( i18n("&Refresh"), 0, 00384 TQT_TQOBJECT(mCalendarView), TQT_SLOT( updateView() ), 00385 mACollection, "update" ); 00386 // TODO: 00387 // new KAction( i18n("Hide &Completed To-dos"), 0, 00388 // mCalendarView, TQT_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, TQT_SIGNAL( activated(int) ), 00395 mCalendarView, TQT_SLOT( filterActivated( int ) ) ); 00396 connect( mCalendarView, TQT_SIGNAL( newFilterListSignal( const TQStringList & ) ), 00397 mFilterAction, TQT_SLOT( setItems( const TQStringList & ) ) ); 00398 connect( mCalendarView, TQT_SIGNAL( selectFilterSignal( int ) ), 00399 mFilterAction, TQT_SLOT( setCurrentItem( int ) ) ); 00400 connect( mCalendarView, TQT_SIGNAL( filterChanged() ), 00401 TQT_TQOBJECT(this), TQT_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(), TQT_SLOT( zoomInHorizontally() ), 00408 mACollection, "zoom_in_horizontally" ); 00409 new KAction( i18n( "Zoom Out Horizontally" ), "viewmag-", 0, 00410 mCalendarView->viewManager(), TQT_SLOT( zoomOutHorizontally() ), 00411 mACollection, "zoom_out_horizontally" ); 00412 new KAction( i18n( "Zoom In Vertically" ), "viewmag+", 0, 00413 mCalendarView->viewManager(), TQT_SLOT( zoomInVertically() ), 00414 mACollection, "zoom_in_vertically" ); 00415 new KAction( i18n( "Zoom Out Vertically" ), "viewmag-", 0, 00416 mCalendarView->viewManager(), TQT_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 TQT_TQOBJECT(mCalendarView),TQT_SLOT( goToday() ), 00426 mACollection, "go_today" ); 00427 bool isRTL = TQApplication::reverseLayout(); 00428 action = new KAction( i18n("Go &Backward"), isRTL ? "forward" : "back", 0, 00429 TQT_TQOBJECT(mCalendarView),TQT_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, TQT_SIGNAL( changeNavStringPrev( const TQString & ) ), 00436 action, TQT_SLOT( setText( const TQString & ) ) ); 00437 connect( mCalendarView, TQT_SIGNAL( changeNavStringPrev( const TQString & ) ), 00438 TQT_TQOBJECT(this), TQT_SLOT( dumpText( const TQString & ) ) );*/ 00439 00440 action = new KAction( i18n("Go &Forward"), isRTL ? "back" : "forward", 0, 00441 TQT_TQOBJECT(mCalendarView),TQT_SLOT( goNext() ), 00442 mACollection, "go_next" ); 00443 /* 00444 connect( mCalendarView,TQT_SIGNAL( changeNavStringNext( const TQString & ) ), 00445 action,TQT_SLOT( setText( const TQString & ) ) ); 00446 */ 00447 00448 00449 //************************** Actions MENU ********************************* 00450 new KAction( i18n("New E&vent..."), 00451 KOGlobals::self()->smallIcon( "newappointment" ), 0, 00452 TQT_TQOBJECT(mCalendarView), TQT_SLOT(newEvent()), 00453 mACollection, "new_event" ); 00454 new KAction( i18n("New &To-do..."), 00455 KOGlobals::self()->smallIcon( "newtodo" ), 0, 00456 TQT_TQOBJECT(mCalendarView), TQT_SLOT(newTodo()), 00457 mACollection, "new_todo" ); 00458 action = new KAction( i18n("New Su&b-to-do..."), 0, 00459 TQT_TQOBJECT(mCalendarView),TQT_SLOT( newSubTodo() ), 00460 mACollection, "new_subtodo" ); 00461 action->setEnabled( false ); 00462 connect( mCalendarView,TQT_SIGNAL( todoSelected( bool ) ), 00463 action,TQT_SLOT( setEnabled( bool ) ) ); 00464 new KAction( i18n("New &Journal..."), 00465 KOGlobals::self()->smallIcon( "newjournal" ), 0, 00466 TQT_TQOBJECT(mCalendarView), TQT_SLOT(newJournal()), 00467 mACollection, "new_journal" ); 00468 00469 mShowIncidenceAction = new KAction( i18n("&Show"), 0, 00470 TQT_TQOBJECT(mCalendarView),TQT_SLOT( showIncidence() ), 00471 mACollection, "show_incidence" ); 00472 mEditIncidenceAction = new KAction( i18n("&Edit..."), 0, 00473 TQT_TQOBJECT(mCalendarView),TQT_SLOT( editIncidence() ), 00474 mACollection, "edit_incidence" ); 00475 mDeleteIncidenceAction = new KAction( i18n("&Delete"), Key_Delete, 00476 TQT_TQOBJECT(mCalendarView),TQT_SLOT( deleteIncidence()), 00477 mACollection, "delete_incidence" ); 00478 00479 action = new KAction( i18n("&Make Sub-to-do Independent"), 0, 00480 TQT_TQOBJECT(mCalendarView),TQT_SLOT( todo_unsub() ), 00481 mACollection, "unsub_todo" ); 00482 action->setEnabled( false ); 00483 connect( mCalendarView,TQT_SIGNAL( subtodoSelected( bool ) ), 00484 action,TQT_SLOT( setEnabled( bool ) ) ); 00485 // TODO: Add item to move the incidence to different resource 00486 // mAssignResourceAction = new KAction( i18n("Assign &Resource..."), 0, 00487 // mCalendarView, TQT_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, TQT_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 TQT_TQOBJECT(mCalendarView), TQT_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 TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_request()), 00506 mACollection, "schedule_request" ); 00507 mSendInvitation->setEnabled( false ); 00508 connect( mCalendarView, TQT_SIGNAL(organizerEventsSelected(bool)), 00509 mSendInvitation, TQT_SLOT(setEnabled(bool)) ); 00510 00511 mRequestUpdate = new KAction( i18n( "Re&quest Update" ), 0, 00512 TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_refresh()), 00513 mACollection, "schedule_refresh" ); 00514 mRequestUpdate->setEnabled( false ); 00515 connect( mCalendarView, TQT_SIGNAL(groupEventsSelected(bool)), 00516 mRequestUpdate, TQT_SLOT(setEnabled(bool)) ); 00517 00518 mSendCancel = new KAction( i18n( "Send &Cancelation to Attendees" ), 0, 00519 TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_cancel()), 00520 mACollection, "schedule_cancel" ); 00521 mSendCancel->setEnabled( false ); 00522 connect( mCalendarView, TQT_SIGNAL(organizerEventsSelected(bool)), 00523 mSendCancel, TQT_SLOT(setEnabled(bool)) ); 00524 00525 mSendStatusUpdate = new KAction( i18n( "Send Status &Update" ), 00526 "mail_reply", 0, 00527 TQT_TQOBJECT(mCalendarView),TQT_SLOT(schedule_reply()), 00528 mACollection, "schedule_reply" ); 00529 mSendStatusUpdate->setEnabled( false ); 00530 connect( mCalendarView, TQT_SIGNAL(groupEventsSelected(bool)), 00531 mSendStatusUpdate, TQT_SLOT(setEnabled(bool)) ); 00532 00533 mRequestChange = new KAction( i18n( "counter proposal", "Request Chan&ge" ), 0, 00534 TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_counter()), 00535 mACollection, "schedule_counter" ); 00536 mRequestChange->setEnabled( false ); 00537 connect( mCalendarView, TQT_SIGNAL(groupEventsSelected(bool)), 00538 mRequestChange, TQT_SLOT(setEnabled(bool)) ); 00539 00540 mForwardEvent = new KAction( i18n("&Send as iCalendar..."), "mail_forward", 0, 00541 TQT_TQOBJECT(mCalendarView), TQT_SLOT(schedule_forward()), 00542 mACollection, "schedule_forward" ); 00543 mForwardEvent->setEnabled( false ); 00544 00545 action = new KAction( i18n("&Mail Free Busy Information..."), 0, 00546 TQT_TQOBJECT(mCalendarView), TQT_SLOT( mailFreeBusy() ), 00547 mACollection, "mail_freebusy" ); 00548 action->setEnabled( true ); 00549 00550 action = new KAction( i18n("&Upload Free Busy Information"), 0, 00551 TQT_TQOBJECT(mCalendarView), TQT_SLOT( uploadFreeBusy() ), 00552 mACollection, "upload_freebusy" ); 00553 action->setEnabled( true ); 00554 00555 if ( !mIsPart ) { 00556 action = new KAction( i18n("&Addressbook"),"contents",0, 00557 TQT_TQOBJECT(mCalendarView),TQT_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 TQT_TQOBJECT(this), TQT_SLOT( toggleDateNavigator() ), 00569 mACollection, "show_datenavigator" ); 00570 mTodoViewShowAction = new KToggleAction ( i18n("Show To-do View"), 0, 00571 TQT_TQOBJECT(this), TQT_SLOT( toggleTodoView() ), 00572 mACollection, "show_todoview" ); 00573 mEventViewerShowAction = new KToggleAction ( i18n("Show Item Viewer"), 0, 00574 TQT_TQOBJECT(this), TQT_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 TQT_TQOBJECT(this), TQT_SLOT( toggleResourceView() ), 00594 mACollection, "show_resourceview" ); 00595 mResourceButtonsAction = new KToggleAction( i18n("Show &Resource Buttons"), 0, 00596 TQT_TQOBJECT(this), TQT_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 TQT_TQOBJECT(this), TQT_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 // TQT_TQOBJECT(this), TQT_SLOT( manageResources() ), 00616 // mACollection, "conf_resources" ); 00617 new KAction( i18n("Manage View &Filters..."), "configure", 0, 00618 TQT_TQOBJECT(mCalendarView), TQT_SLOT( editFilters() ), 00619 mACollection, "edit_filters" ); 00620 new KAction( i18n("Manage C&ategories..."), 0, 00621 TQT_TQOBJECT(mCalendarView->dialogManager()), TQT_SLOT( showCategoryEditDialog() ), 00622 mACollection, "edit_categories" ); 00623 if ( mIsPart ) { 00624 new KAction( i18n("&Configure Calendar..."), "configure", 0, 00625 TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_options() ), 00626 mACollection, "korganizer_configure" ); 00627 KStdAction::keyBindings( TQT_TQOBJECT(this), TQT_SLOT( keyBindings() ), 00628 mACollection, "korganizer_configure_shortcuts" ); 00629 } else { 00630 KStdAction::preferences( TQT_TQOBJECT(mCalendarView), TQT_SLOT( edit_options() ), 00631 mACollection ); 00632 KStdAction::keyBindings( TQT_TQOBJECT(this), TQT_SLOT( keyBindings() ), mACollection ); 00633 } 00634 00635 00636 00637 00638 //**************************** HELP MENU ********************************** 00639 KStdAction::tipOfDay( TQT_TQOBJECT(this), TQT_SLOT( showTip() ), mACollection, 00640 "help_tipofday" ); 00641 // new KAction( i18n("Show Intro Page"), 0, 00642 // mCalendarView,TQT_SLOT( showIntro() ), 00643 // mACollection,"show_intro" ); 00644 00645 00646 00647 00648 //************************* TOOLBAR ACTIONS ******************************* 00649 TQLabel *filterLabel = new TQLabel( 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 TQString 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 TQString progPath; 00746 KTempFile tmpfn; 00747 00748 TQString homeDir = TQDir::homeDirPath() + TQString::fromLatin1( "/.calendar" ); 00749 00750 if ( !TQFile::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 TQString 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 TQString 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 TQString 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 TQString 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 TQString 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 TQString 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 TQString 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 TQDate qd1; 01046 qd1 = TQDate::currentDate(); 01047 TQDate qd2; 01048 qd2 = TQDate::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 ( TQFileInfo( 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 TQDate cdate = settings->dateStart().date(); 01076 TQDate qd2 = settings->dateEnd().date(); 01077 while ( cdate <= qd2 ) { 01078 TQStringList holidays = KOGlobals::self()->holiday( cdate ); 01079 if ( !holidays.isEmpty() ) { 01080 TQStringList::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 TQString 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 TQString 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 TQString(), 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 TQString filename = url.fileName( false ); 01197 01198 TQString 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 TQString 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,TQT_SIGNAL( processExited( KProcess * ) ), 01297 TQT_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(),TQString(),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 TQString &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 kdDebug(5850) << "RESOURCE VIEW " << long( mResourceView ) << endl; 01364 01365 if ( mResourceView ) mResourceView->showButtons( visible ); 01366 } 01367 01368 bool ActionManager::openURL( const TQString &url ) 01369 { 01370 return openURL( KURL( url ) ); 01371 } 01372 01373 bool ActionManager::mergeURL( const TQString &url ) 01374 { 01375 return openURL( KURL( url ),true ); 01376 } 01377 01378 bool ActionManager::saveAsURL( const TQString &url ) 01379 { 01380 return saveAsURL( KURL( url ) ); 01381 } 01382 01383 TQString ActionManager::getCurrentURLasString() const 01384 { 01385 return mURL.url(); 01386 } 01387 01388 bool ActionManager::editIncidence( const TQString &uid ) 01389 { 01390 return mCalendarView->editIncidence( uid ); 01391 } 01392 01393 bool ActionManager::editIncidence( const TQString &uid, const TQDate &date ) 01394 { 01395 return mCalendarView->editIncidence( uid, date ); 01396 } 01397 01398 bool ActionManager::deleteIncidence( const TQString& uid, bool force ) 01399 { 01400 return mCalendarView->deleteIncidence( uid, force ); 01401 } 01402 01403 bool ActionManager::addIncidence( const TQString& ical ) 01404 { 01405 return mCalendarView->addIncidence( ical ); 01406 } 01407 01408 void ActionManager::configureDateTimeFinished( KProcess *proc ) 01409 { 01410 delete proc; 01411 } 01412 01413 void ActionManager::downloadNewStuff() 01414 { 01415 kdDebug(5850) << "ActionManager::downloadNewStuff()" << endl; 01416 01417 if ( !mNewStuff ) mNewStuff = new KONewStuff( mCalendarView ); 01418 mNewStuff->download(); 01419 } 01420 01421 void ActionManager::uploadNewStuff() 01422 { 01423 if ( !mNewStuff ) mNewStuff = new KONewStuff( mCalendarView ); 01424 mNewStuff->upload(); 01425 } 01426 01427 TQString ActionManager::localFileName() 01428 { 01429 return mFile; 01430 } 01431 01432 class ActionManager::ActionStringsVisitor : public IncidenceBase::Visitor 01433 { 01434 public: 01435 ActionStringsVisitor() : mShow( 0 ), mEdit( 0 ), mDelete( 0 ) {} 01436 01437 bool act( IncidenceBase *incidence, KAction *show, KAction *edit, KAction *del ) 01438 { 01439 mShow = show; 01440 mEdit = edit; 01441 mDelete = del; 01442 return incidence->accept( *this ); 01443 } 01444 01445 protected: 01446 bool visit( Event * ) { 01447 if ( mShow ) mShow->setText( i18n("&Show Event") ); 01448 if ( mEdit ) mEdit->setText( i18n("&Edit Event...") ); 01449 if ( mDelete ) mDelete->setText( i18n("&Delete Event") ); 01450 return true; 01451 } 01452 bool visit( Todo * ) { 01453 if ( mShow ) mShow->setText( i18n("&Show To-do") ); 01454 if ( mEdit ) mEdit->setText( i18n("&Edit To-do...") ); 01455 if ( mDelete ) mDelete->setText( i18n("&Delete To-do") ); 01456 return true; 01457 } 01458 bool visit( Journal * ) { return assignDefaultStrings(); } 01459 protected: 01460 bool assignDefaultStrings() { 01461 if ( mShow ) mShow->setText( i18n("&Show") ); 01462 if ( mEdit ) mEdit->setText( i18n("&Edit...") ); 01463 if ( mDelete ) mDelete->setText( i18n("&Delete") ); 01464 return true; 01465 } 01466 KAction *mShow; 01467 KAction *mEdit; 01468 KAction *mDelete; 01469 }; 01470 01471 void ActionManager::processIncidenceSelection( Incidence *incidence, const TQDate & ) 01472 { 01473 // kdDebug(5850) << "ActionManager::processIncidenceSelection()" << endl; 01474 01475 if ( !incidence ) { 01476 enableIncidenceActions( false ); 01477 return; 01478 } 01479 01480 enableIncidenceActions( true ); 01481 01482 if ( incidence->isReadOnly() ) { 01483 mCutAction->setEnabled( false ); 01484 mDeleteAction->setEnabled( false ); 01485 } 01486 01487 ActionStringsVisitor v; 01488 if ( !v.act( incidence, mShowIncidenceAction, mEditIncidenceAction, mDeleteIncidenceAction ) ) { 01489 mShowIncidenceAction->setText( i18n("&Show") ); 01490 mEditIncidenceAction->setText( i18n("&Edit...") ); 01491 mDeleteIncidenceAction->setText( i18n("&Delete") ); 01492 } 01493 } 01494 01495 void ActionManager::enableIncidenceActions( bool enabled ) 01496 { 01497 mShowIncidenceAction->setEnabled( enabled ); 01498 mEditIncidenceAction->setEnabled( enabled ); 01499 mDeleteIncidenceAction->setEnabled( enabled ); 01500 // mAssignResourceAction->setEnabled( enabled ); 01501 01502 mCutAction->setEnabled( enabled ); 01503 mCopyAction->setEnabled( enabled ); 01504 mDeleteAction->setEnabled( enabled ); 01505 mPublishEvent->setEnabled( enabled ); 01506 mForwardEvent->setEnabled( enabled ); 01507 mSendInvitation->setEnabled( enabled ); 01508 mSendCancel->setEnabled( enabled ); 01509 mSendStatusUpdate->setEnabled( enabled ); 01510 mRequestChange->setEnabled( enabled ); 01511 mRequestUpdate->setEnabled( enabled ); 01512 } 01513 01514 void ActionManager::keyBindings() 01515 { 01516 KKeyDialog dlg( false, view() ); 01517 if ( mMainWindow ) 01518 dlg.insert( mMainWindow->getActionCollection() ); 01519 01520 KOrg::Part *part; 01521 for ( part = mParts.first(); part; part = mParts.next() ) { 01522 dlg.insert( part->actionCollection(), part->shortInfo() ); 01523 } 01524 dlg.configure(); 01525 } 01526 01527 void ActionManager::loadParts() 01528 { 01529 mParts = KOCore::self()->loadParts( mMainWindow ); 01530 } 01531 01532 void ActionManager::setTitle() 01533 { 01534 mMainWindow->setTitle(); 01535 } 01536 01537 KCalendarIface::ResourceRequestReply ActionManager::resourceRequest( const TQValueList<TQPair<TQDateTime, TQDateTime> >&, 01538 const TQCString& resource, 01539 const TQString& vCalIn ) 01540 { 01541 kdDebug(5850) << k_funcinfo << "resource=" << resource << " vCalIn=" << vCalIn << endl; 01542 KCalendarIface::ResourceRequestReply reply; 01543 reply.vCalOut = "VCalOut"; 01544 return reply; 01545 } 01546 01547 TQPair<ResourceCalendar *, TQString> ActionManager::viewSubResourceCalendar() 01548 { 01549 TQPair<ResourceCalendar *, TQString> p( 0, TQString() ); 01550 01551 // return now if we are running as a part and we aren't the currently active part 01552 if ( mIsPart && !mMainWindow->isCurrentlyActivePart() ) { 01553 return p; 01554 } 01555 01556 KOrg::BaseView *cV = mCalendarView->viewManager()->currentView(); 01557 if ( cV && cV == mCalendarView->viewManager()->multiAgendaView() ) { 01558 cV = mCalendarView->viewManager()->multiAgendaView()->selectedAgendaView(); 01559 } 01560 if ( cV ) { 01561 p = tqMakePair( cV->resourceCalendar(), cV->subResourceCalendar() ); 01562 } 01563 return p; 01564 } 01565 01566 bool ActionManager::isWritable( ResourceCalendar *res, const TQString &subRes, 01567 const TQString &contentsType ) 01568 { 01569 01570 if ( res && res->isActive() ) { 01571 // Check specified resource for writability. 01572 if ( res->readOnly() || !res->subresourceWritable( subRes ) ) { 01573 TQString resName = res->resourceName(); 01574 if ( res->canHaveSubresources() ) { 01575 resName = res->labelForSubresource( subRes ); 01576 } 01577 KMessageBox::sorry( 01578 dialogParent(), 01579 i18n( "\"%1\" is read-only. " 01580 "Please select a writable calendar before attempting to create a new item." ). 01581 arg( resName ), 01582 i18n( "Read-only calendar" ) ); 01583 return false; 01584 } else { 01585 return true; 01586 } 01587 } else { 01588 // No specific resource so let's check all possible calendars for writability. 01589 CalendarResourceManager *m = mCalendarResources->resourceManager(); 01590 CalendarResourceManager::ActiveIterator it; 01591 for ( it = m->activeBegin(); it != m->activeEnd(); ++it ) { 01592 ResourceCalendar *res = (*it); 01593 if ( res->canHaveSubresources() ) { 01594 TQStringList subResources = res->subresources(); 01595 for ( TQStringList::ConstIterator subit = subResources.constBegin(); 01596 subit != subResources.constEnd(); ++subit ) { 01597 if ( res->subresourceWritable( (*subit) ) && res->subresourceActive( (*subit) ) ) { 01598 if ( res->subresourceType( *subit ).isEmpty() || 01599 res->subresourceType( *subit ) == contentsType ) { 01600 return true; 01601 } 01602 } 01603 } 01604 } else if ( !res->readOnly() ) { 01605 return true; 01606 } 01607 } 01608 // we don't have any writable calendars 01609 TQString errorText; 01610 if ( contentsType == "event" ) { 01611 errorText = 01612 i18n( "You have no active, writable event folder so saving will not be possible.\n" 01613 "Please create or activate at least one writable event folder and try again." ); 01614 } else if ( contentsType == "todo" ) { 01615 errorText = 01616 i18n( "You have no active, writable to-do (task) folders so saving will not be possible.\n" 01617 "Please create or activate at least one writable to-do folder and try again." ); 01618 } else if ( contentsType == "journal" ) { 01619 errorText = 01620 i18n( "You have no active, writable journal folder so saving will not be possible.\n" 01621 "Please create or activate at least one writable journal folder and try again." ); 01622 } else { 01623 errorText = 01624 i18n( "You have no active, writable calendar folder so saving will not be possible.\n" 01625 "Please create or activate at least one writable calendar folder and try again." ); 01626 } 01627 KMessageBox::sorry( 01628 dialogParent(), 01629 errorText, 01630 i18n( "No writable calendar" ) ); 01631 return false; 01632 } 01633 } 01634 01635 void ActionManager::openEventEditor( const TQString& text ) 01636 { 01637 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01638 if ( isWritable( p.first, p.second, "event" ) ) { 01639 mCalendarView->newEvent( p.first, p.second, text ); 01640 } 01641 } 01642 01643 void ActionManager::openEventEditor( const TQString& summary, 01644 const TQString& description, 01645 const TQString& attachment ) 01646 { 01647 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01648 mCalendarView->newEvent( p.first, p.second, summary, description, attachment ); 01649 } 01650 01651 void ActionManager::openEventEditor( const TQString& summary, 01652 const TQString& description, 01653 const TQString& attachment, 01654 const TQStringList& attendees ) 01655 { 01656 mCalendarView->newEvent( 0, TQString(), summary, description, attachment, attendees ); 01657 } 01658 01659 void ActionManager::openEventEditor( const TQString & summary, 01660 const TQString & description, 01661 const TQString & uri, 01662 const TQString & file, 01663 const TQStringList & attendees, 01664 const TQString & attachmentMimetype ) 01665 { 01666 int action = KOPrefs::instance()->defaultEmailAttachMethod(); 01667 if ( attachmentMimetype != "message/rfc822" ) { 01668 action = KOPrefs::Link; 01669 } else if ( KOPrefs::instance()->defaultEmailAttachMethod() == KOPrefs::Ask ) { 01670 KPopupMenu *menu = new KPopupMenu( 0 ); 01671 menu->insertItem( i18n("Attach as &link"), KOPrefs::Link ); 01672 menu->insertItem( i18n("Attach &inline"), KOPrefs::InlineFull ); 01673 menu->insertItem( i18n("Attach inline &without attachments"), KOPrefs::InlineBody ); 01674 menu->insertSeparator(); 01675 menu->insertItem( SmallIcon("cancel"), i18n("C&ancel"), KOPrefs::Ask ); 01676 action = menu->exec( TQCursor::pos(), 0 ); 01677 delete menu; 01678 } 01679 01680 TQString attData; 01681 KTempFile tf; 01682 tf.setAutoDelete( true ); 01683 switch ( action ) { 01684 case KOPrefs::Ask: 01685 return; 01686 case KOPrefs::Link: 01687 attData = uri; 01688 break; 01689 case KOPrefs::InlineFull: 01690 attData = file; 01691 break; 01692 case KOPrefs::InlineBody: 01693 { 01694 TQFile f( file ); 01695 if ( !f.open( IO_ReadOnly ) ) 01696 return; 01697 KMime::Message *msg = new KMime::Message(); 01698 msg->setContent( TQCString( f.readAll() ) ); 01699 TQCString head = msg->head(); 01700 msg->parse(); 01701 if ( msg == msg->textContent() || msg->textContent() == 0 ) { // no attachments 01702 attData = file; 01703 } else { 01704 if ( KMessageBox::warningContinueCancel( 0, 01705 i18n("Removing attachments from an email might invalidate its signature."), 01706 i18n("Remove Attachments"), KStdGuiItem::cont(), "BodyOnlyInlineAttachment" ) 01707 != KMessageBox::Continue ) 01708 return; 01709 // due to kmime shortcomings in KDE3, we need to assemble the result manually 01710 int begin = 0; 01711 int end = head.find( '\n' ); 01712 bool skipFolded = false; 01713 while ( end >= 0 && end > begin ) { 01714 if ( head.find( "Content-Type:", begin, false ) != begin && 01715 head.find( "Content-Transfer-Encoding:", begin, false ) != begin && 01716 !(skipFolded && (head[begin] == ' ' || head[end] == '\t')) ) { 01717 TQCString line = head.mid( begin, end - begin ); 01718 tf.file()->writeBlock( line.data(), line.length() ); 01719 tf.file()->writeBlock( "\n", 1 ); 01720 skipFolded = false; 01721 } else { 01722 skipFolded = true; 01723 } 01724 01725 begin = end + 1; 01726 end = head.find( '\n', begin ); 01727 if ( end < 0 && begin < (int)head.length() ) 01728 end = head.length() - 1; 01729 } 01730 TQCString cte = msg->textContent()->contentTransferEncoding()->as7BitString(); 01731 if ( !cte.stripWhiteSpace().isEmpty() ) { 01732 tf.file()->writeBlock( cte.data(), cte.length() ); 01733 tf.file()->writeBlock( "\n", 1 ); 01734 } 01735 TQCString ct = msg->textContent()->contentType()->as7BitString(); 01736 if ( !ct.stripWhiteSpace().isEmpty() ) 01737 tf.file()->writeBlock( ct.data(), ct.length() ); 01738 tf.file()->writeBlock( "\n", 1 ); 01739 tf.file()->writeBlock( msg->textContent()->body() ); 01740 attData = tf.name(); 01741 } 01742 tf.close(); 01743 delete msg; 01744 break; 01745 } 01746 default: 01747 // menu could have been closed by cancel, if so, do nothing 01748 return; 01749 } 01750 01751 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01752 mCalendarView->newEvent( p.first, p.second, summary, description, attData, 01753 attendees, attachmentMimetype, action != KOPrefs::Link ); 01754 } 01755 01756 void ActionManager::openTodoEditor( const TQString& text ) 01757 { 01758 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01759 if ( isWritable( p.first, p.second, "todo" ) ) { 01760 mCalendarView->newTodo( p.first, p.second, text ); 01761 } 01762 } 01763 01764 void ActionManager::openTodoEditor( const TQString& summary, 01765 const TQString& description, 01766 const TQString& attachment ) 01767 { 01768 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01769 mCalendarView->newTodo( p.first, p.second, summary, description, attachment ); 01770 } 01771 01772 void ActionManager::openTodoEditor( const TQString& summary, 01773 const TQString& description, 01774 const TQString& attachment, 01775 const TQStringList& attendees ) 01776 { 01777 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01778 mCalendarView->newTodo( p.first, p.second, summary, description, attachment, attendees ); 01779 } 01780 01781 void ActionManager::openTodoEditor(const TQString & summary, 01782 const TQString & description, 01783 const TQString & uri, 01784 const TQString & file, 01785 const TQStringList & attendees, 01786 const TQString & attachmentMimetype, 01787 bool isTask ) 01788 { 01789 int action = KOPrefs::instance()->defaultTodoAttachMethod(); 01790 if ( attachmentMimetype != "message/rfc822" ) { 01791 action = KOPrefs::TodoAttachLink; 01792 } else if ( KOPrefs::instance()->defaultTodoAttachMethod() == KOPrefs::TodoAttachAsk ) { 01793 KPopupMenu *menu = new KPopupMenu( 0 ); 01794 menu->insertItem( i18n("Attach as &link"), KOPrefs::TodoAttachLink ); 01795 menu->insertItem( i18n("Attach &inline"), KOPrefs::TodoAttachInlineFull ); 01796 menu->insertSeparator(); 01797 menu->insertItem( SmallIcon("cancel"), i18n("C&ancel"), KOPrefs::TodoAttachAsk ); 01798 action = menu->exec( TQCursor::pos(), 0 ); 01799 delete menu; 01800 } 01801 01802 TQStringList attData; 01803 switch ( action ) { 01804 case KOPrefs::TodoAttachAsk: 01805 return; 01806 case KOPrefs::TodoAttachLink: 01807 attData << uri; 01808 break; 01809 case KOPrefs::TodoAttachInlineFull: 01810 attData << file; 01811 break; 01812 default: 01813 // menu could have been closed by cancel, if so, do nothing 01814 return; 01815 } 01816 01817 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01818 mCalendarView->newTodo( p.first, p.second, 01819 summary, description, 01820 attData, attendees, 01821 TQStringList( attachmentMimetype ), 01822 action != KOPrefs::TodoAttachLink, 01823 isTask ); 01824 } 01825 01826 void ActionManager::openJournalEditor( const TQDate& date ) 01827 { 01828 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01829 mCalendarView->newJournal( p.first, p.second, date ); 01830 } 01831 01832 void ActionManager::openJournalEditor( const TQString& text, const TQDate& date ) 01833 { 01834 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01835 mCalendarView->newJournal( p.first, p.second, text, date ); 01836 } 01837 01838 void ActionManager::openJournalEditor( const TQString& text ) 01839 { 01840 TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01841 if ( isWritable( p.first, p.second, "journal" ) ) { 01842 mCalendarView->newJournal( p.first, p.second, text ); 01843 } 01844 } 01845 01846 //TODO: 01847 // void ActionManager::openJournalEditor( const TQString& summary, 01848 // const TQString& description, 01849 // const TQString& attachment ) 01850 // { 01851 // TQPair<ResourceCalendar *, TQString>p = viewSubResourceCalendar(); 01852 // mCalendarView->newJournal( p.first, p.second, summary, description, attachment ); 01853 // } 01854 01855 01856 void ActionManager::showJournalView() 01857 { 01858 mCalendarView->viewManager()->showJournalView(); 01859 } 01860 01861 void ActionManager::showTodoView() 01862 { 01863 mCalendarView->viewManager()->showTodoView(); 01864 } 01865 01866 void ActionManager::showEventView() 01867 { 01868 mCalendarView->viewManager()->showEventView(); 01869 } 01870 01871 void ActionManager::goDate( const TQDate& date ) 01872 { 01873 mCalendarView->goDate( date ); 01874 } 01875 01876 void ActionManager::goDate( const TQString& date ) 01877 { 01878 goDate( KGlobal::locale()->readDate( date ) ); 01879 } 01880 01881 void ActionManager::showDate(const TQDate & date) 01882 { 01883 mCalendarView->showDate( date ); 01884 } 01885 01886 01887 void ActionManager::updateUndoAction( const TQString &text ) 01888 { 01889 if ( text.isNull() ) { 01890 mUndoAction->setEnabled( false ); 01891 mUndoAction->setText( i18n("Undo") ); 01892 } else { 01893 mUndoAction->setEnabled( true ); 01894 if ( text.isEmpty() ) mUndoAction->setText( i18n("Undo") ); 01895 else mUndoAction->setText( i18n("Undo (%1)").arg( text ) ); 01896 } 01897 } 01898 01899 void ActionManager::updateRedoAction( const TQString &text ) 01900 { 01901 if ( text.isNull() ) { 01902 mRedoAction->setEnabled( false ); 01903 mRedoAction->setText( i18n( "Redo" ) ); 01904 } else { 01905 mRedoAction->setEnabled( true ); 01906 if ( text.isEmpty() ) mRedoAction->setText( i18n("Redo") ); 01907 else mRedoAction->setText( i18n( "Redo (%1)" ).arg( text ) ); 01908 } 01909 } 01910 01911 bool ActionManager::queryClose() 01912 { 01913 kdDebug(5850) << "ActionManager::queryClose()" << endl; 01914 01915 bool close = true; 01916 01917 if ( mCalendar && mCalendar->isModified() ) { 01918 int res = KMessageBox::questionYesNoCancel( dialogParent(), 01919 i18n("The calendar contains unsaved changes. Do you want to save them before exiting?"), TQString(), KStdGuiItem::save(), KStdGuiItem::discard() ); 01920 // Exit on yes and no, don't exit on cancel. If saving fails, ask for exiting. 01921 if ( res == KMessageBox::Yes ) { 01922 close = saveModifiedURL(); 01923 if ( !close ) { 01924 int res1 = KMessageBox::questionYesNo( dialogParent(), i18n("Unable to save the calendar. Do you still want to close this window?"), TQString(), KStdGuiItem::close(), KStdGuiItem::cancel() ); 01925 close = ( res1 == KMessageBox::Yes ); 01926 } 01927 } else { 01928 close = ( res == KMessageBox::No ); 01929 } 01930 } else if ( mCalendarResources ) { 01931 if ( !mIsClosing ) { 01932 kdDebug(5850) << "!mIsClosing" << endl; 01933 if ( !saveResourceCalendar() ) return false; 01934 01935 // FIXME: Put main window into a state indicating final saving. 01936 mIsClosing = true; 01937 // FIXME: Close main window when save is finished 01938 // connect( mCalendarResources, TQT_SIGNAL( calendarSaved() ), 01939 // mMainWindow, TQT_SLOT( close() ) ); 01940 } 01941 if ( mCalendarResources->isSaving() ) { 01942 kdDebug(5850) << "ActionManager::queryClose(): isSaving" << endl; 01943 close = false; 01944 KMessageBox::information( dialogParent(), 01945 i18n("Unable to exit. Saving still in progress.") ); 01946 } else { 01947 kdDebug(5850) << "ActionManager::queryClose(): close = true" << endl; 01948 close = true; 01949 } 01950 } else { 01951 close = true; 01952 } 01953 01954 return close; 01955 } 01956 01957 void ActionManager::saveCalendar() 01958 { 01959 if ( mCalendar ) { 01960 if ( view()->isModified() ) { 01961 if ( !url().isEmpty() ) { 01962 saveURL(); 01963 } else { 01964 TQString location = locateLocal( "data", "korganizer/kontact.ics" ); 01965 saveAsURL( location ); 01966 } 01967 } 01968 } else if ( mCalendarResources ) { 01969 mCalendarResources->save(); 01970 // FIXME: Make sure that asynchronous saves don't fail. 01971 } 01972 } 01973 01974 bool ActionManager::saveResourceCalendar() 01975 { 01976 if ( !mCalendarResources ) return false; 01977 CalendarResourceManager *m = mCalendarResources->resourceManager(); 01978 01979 CalendarResourceManager::ActiveIterator it; 01980 for ( it = m->activeBegin(); it != m->activeEnd(); ++it ) { 01981 if ( (*it)->readOnly() ) continue; 01982 if ( !(*it)->save() ) { 01983 int result = KMessageBox::warningContinueCancel( view(), 01984 i18n( "Saving of '%1' failed. Check that the resource is " 01985 "properly configured.\nIgnore problem and continue without " 01986 "saving or cancel save?" ).arg( (*it)->resourceName() ), 01987 i18n("Save Error"), KStdGuiItem::dontSave() ); 01988 if ( result == KMessageBox::Cancel ) return false; 01989 } 01990 } 01991 return true; 01992 } 01993 01994 void ActionManager::loadResourceCalendar() 01995 { 01996 if ( !mCalendarResources ) return; 01997 CalendarResourceManager *m = mCalendarResources->resourceManager(); 01998 01999 CalendarResourceManager::ActiveIterator it; 02000 for ( it = m->activeBegin(); it != m->activeEnd(); ++it ) { 02001 (*it)->load(); 02002 } 02003 } 02004 02005 void ActionManager::importCalendar( const KURL &url ) 02006 { 02007 if ( !url.isValid() ) { 02008 KMessageBox::error( dialogParent(), 02009 i18n("URL '%1' is invalid.").arg( url.prettyURL() ) ); 02010 return; 02011 } 02012 02013 PreviewDialog *dialog; 02014 dialog = new PreviewDialog( url, mMainWindow->topLevelWidget() ); 02015 connect( dialog, TQT_SIGNAL( dialogFinished( PreviewDialog * ) ), 02016 TQT_SLOT( slotPreviewDialogFinished( PreviewDialog * ) ) ); 02017 connect( dialog, TQT_SIGNAL( openURL( const KURL &, bool ) ), 02018 TQT_SLOT( openURL( const KURL &, bool ) ) ); 02019 connect( dialog, TQT_SIGNAL( addResource( const KURL & ) ), 02020 TQT_SLOT( addResource( const KURL & ) ) ); 02021 02022 if ( dialog->loadCalendar() ) { 02023 dialog->show(); 02024 } else { 02025 KMessageBox::error( dialogParent(), i18n("Unable to open the calendar") ); 02026 } 02027 } 02028 02029 void ActionManager::slotPreviewDialogFinished( PreviewDialog *dlg ) 02030 { 02031 dlg->deleteLater(); 02032 mCalendarView->updateView(); 02033 } 02034 02035 void ActionManager::slotAutoArchivingSettingsModified() 02036 { 02037 if ( KOPrefs::instance()->mAutoArchive ) 02038 mAutoArchiveTimer->start( 4 * 60 * 60 * 1000, true ); // check again in 4 hours 02039 else 02040 mAutoArchiveTimer->stop(); 02041 } 02042 02043 void ActionManager::slotAutoArchive() 02044 { 02045 if ( !mCalendarView->calendar() ) // can this happen? 02046 return; 02047 mAutoArchiveTimer->stop(); 02048 EventArchiver archiver; 02049 connect( &archiver, TQT_SIGNAL( eventsDeleted() ), mCalendarView, TQT_SLOT( updateView() ) ); 02050 archiver.runAuto( mCalendarView->calendar(), mCalendarView, false /*no gui*/ ); 02051 // restart timer with the correct delay ( especially useful for the first time ) 02052 slotAutoArchivingSettingsModified(); 02053 } 02054 02055 void ActionManager::loadProfile( const TQString & path ) 02056 { 02057 KOPrefs::instance()->writeConfig(); 02058 KConfig* const cfg = KOPrefs::instance()->config(); 02059 02060 const KConfig profile( path+"/korganizerrc", /*read-only=*/false, /*useglobals=*/false ); 02061 const TQStringList groups = profile.groupList(); 02062 for ( TQStringList::ConstIterator it = groups.begin(), end = groups.end(); it != end; ++it ) 02063 { 02064 cfg->setGroup( *it ); 02065 typedef TQMap<TQString, TQString> StringMap; 02066 const StringMap entries = profile.entryMap( *it ); 02067 for ( StringMap::ConstIterator it2 = entries.begin(), end = entries.end(); it2 != end; ++it2 ) 02068 { 02069 cfg->writeEntry( it2.key(), it2.data() ); 02070 } 02071 } 02072 02073 cfg->sync(); 02074 KOPrefs::instance()->readConfig(); 02075 } 02076 02077 namespace { 02078 void copyConfigEntry( KConfig* source, KConfig* dest, const TQString& group, const TQString& key, const TQString& defaultValue=TQString() ) 02079 { 02080 source->setGroup( group ); 02081 dest->setGroup( group ); 02082 dest->writeEntry( key, source->readEntry( key, defaultValue ) ); 02083 } 02084 } 02085 02086 void ActionManager::saveToProfile( const TQString & path ) const 02087 { 02088 KOPrefs::instance()->writeConfig(); 02089 KConfig* const cfg = KOPrefs::instance()->config(); 02090 02091 KConfig profile( path+"/korganizerrc", /*read-only=*/false, /*useglobals=*/false ); 02092 ::copyConfigEntry( cfg, &profile, "Views", "Agenda View Calendar Display" ); 02093 } 02094 02095 bool ActionManager::handleCommandLine() 02096 { 02097 KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); 02098 KOrg::MainWindow *mainWindow = ActionManager::findInstance( KURL() ); 02099 02100 bool ret = true; 02101 02102 if ( !mainWindow ) { 02103 kdError() << "Unable to find default calendar resources view." << endl; 02104 ret = false; 02105 } else if ( args->count() <= 0 ) { 02106 // No filenames given => all other args are meaningless, show main Window 02107 mainWindow->topLevelWidget()->show(); 02108 } else if ( !args->isSet( "open" ) ) { 02109 // Import, merge, or ask => we need the resource calendar window anyway. 02110 mainWindow->topLevelWidget()->show(); 02111 02112 // Check for import, merge or ask 02113 if ( args->isSet( "import" ) ) { 02114 for( int i = 0; i < args->count(); ++i ) { 02115 mainWindow->actionManager()->addResource( args->url( i ) ); 02116 } 02117 } else if ( args->isSet( "merge" ) ) { 02118 for( int i = 0; i < args->count(); ++i ) { 02119 mainWindow->actionManager()->mergeURL( args->url( i ).url() ); 02120 } 02121 } else { 02122 for( int i = 0; i < args->count(); ++i ) { 02123 mainWindow->actionManager()->importCalendar( args->url( i ) ); 02124 } 02125 } 02126 } 02127 02128 return ret; 02129 } 02130 02131 TQWidget *ActionManager::dialogParent() 02132 { 02133 return mCalendarView->topLevelWidget(); 02134 } 02135 02136 #include "actionmanager.moc"