1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sfx2.hxx" 30 #include <unotools/localedatawrapper.hxx> 31 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX 32 #include <comphelper/processfactory.hxx> 33 #endif 34 #include <svl/eitem.hxx> 35 #include <svl/intitem.hxx> 36 #include <svl/stritem.hxx> 37 #include <svl/itemset.hxx> 38 #include <unotools/useroptions.hxx> 39 #include <vcl/msgbox.hxx> 40 #include <vcl/svapp.hxx> 41 #include <tools/datetime.hxx> 42 43 #define _SVSTDARR_STRINGSDTOR 44 #include <svl/svstdarr.hxx> 45 46 #include "versdlg.hrc" 47 #include "versdlg.hxx" 48 #include <sfx2/viewfrm.hxx> 49 #include "sfx2/sfxresid.hxx" 50 #include <sfx2/docfile.hxx> 51 #include <sfx2/objsh.hxx> 52 #include <sfx2/sfxsids.hrc> 53 #include <sfx2/dispatch.hxx> 54 #include <sfx2/request.hxx> 55 56 #include <sfx2/sfxuno.hxx> 57 58 using namespace com::sun::star; 59 60 // ************************************************************************** 61 struct SfxVersionInfo 62 { 63 String aName; 64 String aComment; 65 String aAuthor; 66 DateTime aCreationDate; 67 68 SfxVersionInfo(); 69 SfxVersionInfo( const SfxVersionInfo& rInfo ) 70 { *this = rInfo; } 71 72 SfxVersionInfo& operator=( const SfxVersionInfo &rInfo ) 73 { 74 aName = rInfo.aName; 75 aComment = rInfo.aComment; 76 aAuthor = rInfo.aAuthor; 77 aCreationDate = rInfo.aCreationDate; 78 return *this; 79 } 80 }; 81 DECLARE_LIST( _SfxVersionTable, SfxVersionInfo* ) 82 class SfxVersionTableDtor : public _SfxVersionTable 83 { 84 public: 85 SfxVersionTableDtor( const sal_uInt16 nInitSz=0, const sal_uInt16 nReSz=1 ) 86 : _SfxVersionTable( nInitSz, nReSz ) 87 {} 88 89 SfxVersionTableDtor( const SfxVersionTableDtor &rCpy ) : 90 _SfxVersionTable( rCpy ) 91 { *this = rCpy; } 92 93 SfxVersionTableDtor( const uno::Sequence < util::RevisionTag >& rInfo ); 94 95 ~SfxVersionTableDtor() 96 { DelDtor(); } 97 98 SfxVersionTableDtor& operator=( const SfxVersionTableDtor &rCpy ); 99 void DelDtor(); 100 SvStream& Read( SvStream & ); 101 SvStream& Write( SvStream & ) const; 102 SvStringsDtor* GetVersions() const; 103 }; 104 105 SfxVersionTableDtor::SfxVersionTableDtor( const uno::Sequence < util::RevisionTag >& rInfo ) 106 { 107 for ( sal_Int32 n=0; n<(sal_Int32)rInfo.getLength(); n++ ) 108 { 109 SfxVersionInfo* pInfo = new SfxVersionInfo; 110 pInfo->aName = rInfo[n].Identifier; 111 pInfo->aComment = rInfo[n].Comment; 112 pInfo->aAuthor = rInfo[n].Author; 113 114 Date aDate ( rInfo[n].TimeStamp.Day, rInfo[n].TimeStamp.Month, rInfo[n].TimeStamp.Year ); 115 Time aTime ( rInfo[n].TimeStamp.Hours, rInfo[n].TimeStamp.Minutes, rInfo[n].TimeStamp.Seconds, rInfo[n].TimeStamp.HundredthSeconds ); 116 117 pInfo->aCreationDate = DateTime( aDate, aTime ); 118 Insert( pInfo, Count() ); 119 } 120 } 121 122 void SfxVersionTableDtor::DelDtor() 123 { 124 SfxVersionInfo* pTmp = First(); 125 while( pTmp ) 126 { 127 delete pTmp; 128 pTmp = Next(); 129 } 130 Clear(); 131 } 132 133 SfxVersionTableDtor& SfxVersionTableDtor::operator=( const SfxVersionTableDtor& rTbl ) 134 { 135 DelDtor(); 136 SfxVersionInfo* pTmp = ((SfxVersionTableDtor&)rTbl).First(); 137 while( pTmp ) 138 { 139 SfxVersionInfo *pNew = new SfxVersionInfo( *pTmp ); 140 Insert( pNew, LIST_APPEND ); 141 pTmp = ((SfxVersionTableDtor&)rTbl).Next(); 142 } 143 return *this; 144 } 145 146 //---------------------------------------------------------------- 147 //---------------------------------------------------------------- 148 //---------------------------------------------------------------- 149 SfxVersionInfo::SfxVersionInfo() 150 { 151 } 152 153 static String ConvertDateTime_Impl(const DateTime& rTime, const LocaleDataWrapper& rWrapper) 154 { 155 const String pDelim ( DEFINE_CONST_UNICODE( ", ")); 156 String aStr(rWrapper.getDate(rTime)); 157 aStr += pDelim; 158 aStr += rWrapper.getTime(rTime, sal_True, sal_False); 159 return aStr; 160 } 161 162 SvStringsDtor* SfxVersionTableDtor::GetVersions() const 163 { 164 SvStringsDtor *pList = new SvStringsDtor; 165 SfxVersionInfo* pInfo = ((SfxVersionTableDtor*) this)->First(); 166 LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); 167 while ( pInfo ) 168 { 169 String *pString = new String( pInfo->aComment ); 170 (*pString) += DEFINE_CONST_UNICODE( "; " ); 171 (*pString) += ConvertDateTime_Impl( pInfo->aCreationDate, aLocaleWrapper ); 172 pList->Insert( pString, pList->Count() ); 173 pInfo = ((SfxVersionTableDtor*) this)->Next(); 174 } 175 176 return pList; 177 } 178 179 // Achtung im Code wird dieses Array direkt (0, 1, ...) indiziert 180 static long nTabs_Impl[] = 181 { 182 3, // Number of Tabs 183 0, 62, 124 184 }; 185 186 void SfxVersionsTabListBox_Impl::KeyInput( const KeyEvent& rKeyEvent ) 187 { 188 const KeyCode& rCode = rKeyEvent.GetKeyCode(); 189 switch ( rCode.GetCode() ) 190 { 191 case KEY_RETURN : 192 case KEY_ESCAPE : 193 case KEY_TAB : 194 Window::GetParent()->KeyInput( rKeyEvent ); 195 break; 196 default: 197 SvTabListBox::KeyInput( rKeyEvent ); 198 break; 199 } 200 } 201 202 SfxVersionsTabListBox_Impl::SfxVersionsTabListBox_Impl( Window* pParent, const ResId& rResId ) 203 : SvTabListBox( pParent, rResId ) 204 { 205 } 206 207 SfxVersionDialog::SfxVersionDialog ( SfxViewFrame* pVwFrame, sal_Bool bIsSaveVersionOnClose ) 208 : SfxModalDialog( NULL, SfxResId( DLG_VERSIONS ) ) 209 , aNewGroup( this, SfxResId( GB_NEWVERSIONS ) ) 210 , aSaveButton( this, SfxResId( PB_SAVE ) ) 211 , aSaveCheckBox( this, SfxResId( CB_SAVEONCLOSE ) ) 212 , aExistingGroup( this, SfxResId( GB_OLDVERSIONS ) ) 213 , aDateTimeText( this, SfxResId( FT_DATETIME ) ) 214 , aSavedByText( this, SfxResId( FT_SAVEDBY ) ) 215 , aCommentText( this, SfxResId( FT_COMMENTS ) ) 216 , aVersionBox( this, SfxResId( TLB_VERSIONS ) ) 217 , aCloseButton( this, SfxResId( PB_CLOSE ) ) 218 , aOpenButton( this, SfxResId( PB_OPEN ) ) 219 , aViewButton( this, SfxResId( PB_VIEW ) ) 220 , aDeleteButton( this, SfxResId( PB_DELETE ) ) 221 , aCompareButton( this, SfxResId( PB_COMPARE ) ) 222 , aHelpButton( this, SfxResId( PB_HELP ) ) 223 , pViewFrame( pVwFrame ) 224 , mpTable( NULL ) 225 , mpLocaleWrapper( NULL ) 226 , mbIsSaveVersionOnClose( bIsSaveVersionOnClose ) 227 { 228 FreeResource(); 229 230 Link aClickLink = LINK( this, SfxVersionDialog, ButtonHdl_Impl ); 231 aViewButton.SetClickHdl ( aClickLink ); 232 aSaveButton.SetClickHdl ( aClickLink ); 233 aDeleteButton.SetClickHdl ( aClickLink ); 234 aCompareButton.SetClickHdl ( aClickLink ); 235 aOpenButton.SetClickHdl ( aClickLink ); 236 aSaveCheckBox.SetClickHdl ( aClickLink ); 237 238 aVersionBox.SetSelectHdl( LINK( this, SfxVersionDialog, SelectHdl_Impl ) ); 239 aVersionBox.SetDoubleClickHdl( LINK( this, SfxVersionDialog, DClickHdl_Impl ) ); 240 241 aVersionBox.GrabFocus(); 242 aVersionBox.SetStyle( aVersionBox.GetStyle() | WB_HSCROLL | WB_CLIPCHILDREN ); 243 aVersionBox.SetSelectionMode( SINGLE_SELECTION ); 244 aVersionBox.SetTabs( &nTabs_Impl[0], MAP_APPFONT ); 245 aVersionBox.Resize(); // OS: Hack fuer richtige Selektion 246 RecalcDateColumn(); 247 248 // set dialog title (filename or docinfo title) 249 String sText = GetText(); 250 ( sText += ' ' ) += pViewFrame->GetObjectShell()->GetTitle(); 251 SetText( sText ); 252 253 Init_Impl(); 254 } 255 256 String ConvertWhiteSpaces_Impl( const String& rText ) 257 { 258 // converted linebreaks and tabs to blanks; it's necessary for the display 259 String sConverted; 260 const sal_Unicode* pChars = rText.GetBuffer(); 261 while ( *pChars ) 262 { 263 switch ( *pChars ) 264 { 265 case '\n' : 266 case '\t' : 267 sConverted += ' '; 268 break; 269 270 default: 271 sConverted += *pChars; 272 } 273 274 ++pChars; 275 } 276 277 return sConverted; 278 } 279 280 void SfxVersionDialog::Init_Impl() 281 { 282 SfxObjectShell *pObjShell = pViewFrame->GetObjectShell(); 283 SfxMedium* pMedium = pObjShell->GetMedium(); 284 uno::Sequence < util::RevisionTag > aVersions = pMedium->GetVersionList( true ); 285 delete mpTable; 286 mpTable = new SfxVersionTableDtor( aVersions ); 287 { 288 for ( sal_uInt16 n = 0; n < mpTable->Count(); ++n ) 289 { 290 SfxVersionInfo *pInfo = mpTable->GetObject(n); 291 String aEntry = ConvertDateTime_Impl( pInfo->aCreationDate, *mpLocaleWrapper ); 292 aEntry += '\t'; 293 aEntry += pInfo->aAuthor; 294 aEntry += '\t'; 295 aEntry += ConvertWhiteSpaces_Impl( pInfo->aComment ); 296 SvLBoxEntry *pEntry = aVersionBox.InsertEntry( aEntry ); 297 pEntry->SetUserData( pInfo ); 298 } 299 } 300 301 aSaveCheckBox.Check( mbIsSaveVersionOnClose ); 302 303 sal_Bool bEnable = !pObjShell->IsReadOnly(); 304 aSaveButton.Enable( bEnable ); 305 aSaveCheckBox.Enable( bEnable ); 306 307 aOpenButton.Disable(); 308 aViewButton.Disable(); 309 aDeleteButton.Disable(); 310 aCompareButton.Disable(); 311 312 SelectHdl_Impl( &aVersionBox ); 313 } 314 315 SfxVersionDialog::~SfxVersionDialog () 316 { 317 delete mpTable; 318 delete mpLocaleWrapper; 319 } 320 321 void SfxVersionDialog::Open_Impl() 322 { 323 SfxObjectShell *pObjShell = pViewFrame->GetObjectShell(); 324 325 SvLBoxEntry *pEntry = aVersionBox.FirstSelected(); 326 sal_uIntPtr nPos = aVersionBox.GetModel()->GetRelPos( pEntry ); 327 SfxInt16Item aItem( SID_VERSION, (short)nPos+1 ); 328 SfxStringItem aTarget( SID_TARGETNAME, DEFINE_CONST_UNICODE("_blank") ); 329 SfxStringItem aReferer( SID_REFERER, DEFINE_CONST_UNICODE("private:user") ); 330 SfxStringItem aFile( SID_FILE_NAME, pObjShell->GetMedium()->GetName() ); 331 332 uno::Sequence< beans::NamedValue > aEncryptionData; 333 if ( GetEncryptionData_Impl( pObjShell->GetMedium()->GetItemSet(), aEncryptionData ) ) 334 { 335 // there is a password, it should be used during the opening 336 SfxUnoAnyItem aEncryptionDataItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ); 337 pViewFrame->GetDispatcher()->Execute( 338 SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, &aFile, &aItem, &aTarget, &aReferer, &aEncryptionDataItem, 0L ); 339 } 340 else 341 pViewFrame->GetDispatcher()->Execute( 342 SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, &aFile, &aItem, &aTarget, &aReferer, 0L ); 343 344 Close(); 345 } 346 347 void SfxVersionDialog::RecalcDateColumn() 348 { 349 // recalculate the datetime column width 350 DateTime aNow; 351 mpLocaleWrapper = new LocaleDataWrapper( 352 ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); 353 String sDateTime = ConvertDateTime_Impl( aNow, *mpLocaleWrapper ); 354 long nWidth = aVersionBox.GetTextWidth( sDateTime ); 355 nWidth += 15; // a little offset 356 long nTab = aVersionBox.GetTab(1); 357 if ( nWidth > nTab ) 358 { 359 // resize columns 360 long nDelta = nWidth - nTab; 361 aVersionBox.SetTab( 1, nTab + nDelta, MAP_PIXEL ); 362 nTab = aVersionBox.GetTab(2); 363 aVersionBox.SetTab( 2, nTab + nDelta, MAP_PIXEL ); 364 365 // resize and move header 366 Size aSize = aDateTimeText.GetSizePixel(); 367 aSize.Width() += nDelta; 368 aDateTimeText.SetSizePixel( aSize ); 369 Point aPos = aSavedByText.GetPosPixel(); 370 aPos.X() += nDelta; 371 aSavedByText.SetPosPixel( aPos ); 372 aPos = aCommentText.GetPosPixel(); 373 aPos.X() += nDelta; 374 aCommentText.SetPosPixel( aPos ); 375 } 376 } 377 378 IMPL_LINK( SfxVersionDialog, DClickHdl_Impl, Control*, EMPTYARG ) 379 { 380 Open_Impl(); 381 return 0L; 382 } 383 384 IMPL_LINK( SfxVersionDialog, SelectHdl_Impl, Control*, EMPTYARG ) 385 { 386 bool bEnable = ( aVersionBox.FirstSelected() != NULL ); 387 SfxObjectShell* pObjShell = pViewFrame->GetObjectShell(); 388 aDeleteButton.Enable( bEnable!= false && !pObjShell->IsReadOnly() ); 389 aOpenButton.Enable( bEnable!= false ); 390 aViewButton.Enable( bEnable!= false ); 391 392 const SfxPoolItem *pDummy=NULL; 393 SfxItemState eState = pViewFrame->GetDispatcher()->QueryState( SID_DOCUMENT_MERGE, pDummy ); 394 eState = pViewFrame->GetDispatcher()->QueryState( SID_DOCUMENT_COMPARE, pDummy ); 395 aCompareButton.Enable( bEnable!= false && eState >= SFX_ITEM_AVAILABLE ); 396 397 return 0L; 398 } 399 400 IMPL_LINK( SfxVersionDialog, ButtonHdl_Impl, Button*, pButton ) 401 { 402 SfxObjectShell *pObjShell = pViewFrame->GetObjectShell(); 403 SvLBoxEntry *pEntry = aVersionBox.FirstSelected(); 404 405 if ( pButton == &aSaveCheckBox ) 406 { 407 mbIsSaveVersionOnClose = aSaveCheckBox.IsChecked(); 408 } 409 else if ( pButton == &aSaveButton ) 410 { 411 SfxVersionInfo aInfo; 412 aInfo.aAuthor = SvtUserOptions().GetFullName(); 413 SfxViewVersionDialog_Impl* pDlg = new SfxViewVersionDialog_Impl( this, aInfo, sal_True ); 414 short nRet = pDlg->Execute(); 415 if ( nRet == RET_OK ) 416 { 417 SfxStringItem aComment( SID_DOCINFO_COMMENTS, aInfo.aComment ); 418 pObjShell->SetModified( sal_True ); 419 const SfxPoolItem* aItems[2]; 420 aItems[0] = &aComment; 421 aItems[1] = NULL; 422 pViewFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, aItems, 0 ); 423 aVersionBox.SetUpdateMode( sal_False ); 424 aVersionBox.Clear(); 425 Init_Impl(); 426 aVersionBox.SetUpdateMode( sal_True ); 427 } 428 429 delete pDlg; 430 } 431 if ( pButton == &aDeleteButton && pEntry ) 432 { 433 pObjShell->GetMedium()->RemoveVersion_Impl( ((SfxVersionInfo*) pEntry->GetUserData())->aName ); 434 pObjShell->SetModified( sal_True ); 435 aVersionBox.SetUpdateMode( sal_False ); 436 aVersionBox.Clear(); 437 Init_Impl(); 438 aVersionBox.SetUpdateMode( sal_True ); 439 } 440 else if ( pButton == &aOpenButton && pEntry ) 441 { 442 Open_Impl(); 443 } 444 else if ( pButton == &aViewButton && pEntry ) 445 { 446 SfxVersionInfo* pInfo = (SfxVersionInfo*) pEntry->GetUserData(); 447 SfxViewVersionDialog_Impl* pDlg = new SfxViewVersionDialog_Impl( this, *pInfo, sal_False ); 448 pDlg->Execute(); 449 delete pDlg; 450 } 451 else if ( pEntry && pButton == &aCompareButton ) 452 { 453 SfxAllItemSet aSet( pObjShell->GetPool() ); 454 sal_uIntPtr nPos = aVersionBox.GetModel()->GetRelPos( pEntry ); 455 aSet.Put( SfxInt16Item( SID_VERSION, (short)nPos+1 ) ); 456 aSet.Put( SfxStringItem( SID_FILE_NAME, pObjShell->GetMedium()->GetName() ) ); 457 458 SfxItemSet* pSet = pObjShell->GetMedium()->GetItemSet(); 459 SFX_ITEMSET_ARG( pSet, pFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False ); 460 SFX_ITEMSET_ARG( pSet, pFilterOptItem, SfxStringItem, SID_FILE_FILTEROPTIONS, sal_False ); 461 if ( pFilterItem ) 462 aSet.Put( *pFilterItem ); 463 if ( pFilterOptItem ) 464 aSet.Put( *pFilterOptItem ); 465 466 pViewFrame->GetDispatcher()->Execute( SID_DOCUMENT_COMPARE, SFX_CALLMODE_ASYNCHRON, aSet ); 467 Close(); 468 } 469 470 return 0L; 471 } 472 473 SfxViewVersionDialog_Impl::SfxViewVersionDialog_Impl ( Window *pParent, SfxVersionInfo& rInfo, sal_Bool bEdit ) 474 : SfxModalDialog( pParent, SfxResId( DLG_COMMENTS ) ) 475 , aDateTimeText( this, SfxResId( FT_DATETIME ) ) 476 , aSavedByText( this, SfxResId( FT_SAVEDBY ) ) 477 , aEdit( this, SfxResId( ME_VERSIONS ) ) 478 , aOKButton( this, SfxResId( PB_OK ) ) 479 , aCancelButton( this, SfxResId( PB_CANCEL ) ) 480 , aCloseButton( this, SfxResId( PB_CLOSE ) ) 481 , aHelpButton( this, SfxResId( PB_HELP ) ) 482 , pInfo( &rInfo ) 483 { 484 FreeResource(); 485 486 LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); 487 aDateTimeText.SetText( aDateTimeText.GetText().Append(ConvertDateTime_Impl( pInfo->aCreationDate, aLocaleWrapper )) ); 488 aSavedByText.SetText( aSavedByText.GetText().Append(pInfo->aAuthor) ); 489 aEdit.SetText( rInfo.aComment ); 490 491 aCloseButton.SetClickHdl ( LINK( this, SfxViewVersionDialog_Impl, ButtonHdl ) ); 492 aOKButton.SetClickHdl ( LINK( this, SfxViewVersionDialog_Impl, ButtonHdl ) ); 493 494 aEdit.GrabFocus(); 495 if ( !bEdit ) 496 { 497 aOKButton.Hide(); 498 aCancelButton.Hide(); 499 aEdit.SetReadOnly( sal_True ); 500 } 501 else 502 aCloseButton.Hide(); 503 } 504 505 IMPL_LINK( SfxViewVersionDialog_Impl, ButtonHdl, Button*, pButton ) 506 { 507 if ( pButton == &aCloseButton ) 508 { 509 EndDialog( RET_CANCEL ); 510 } 511 else if ( pButton == &aOKButton ) 512 { 513 pInfo->aComment = aEdit.GetText(); 514 EndDialog( RET_OK ); 515 } 516 517 return 0L; 518 } 519 520