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