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();
SfxVersionInfoSfxVersionInfo65 SfxVersionInfo( const SfxVersionInfo& rInfo )
66 { *this = rInfo; }
67
operator =SfxVersionInfo68 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:
SfxVersionTableDtor(const sal_uInt16 nInitSz=0,const sal_uInt16 nReSz=1)81 SfxVersionTableDtor( const sal_uInt16 nInitSz=0, const sal_uInt16 nReSz=1 )
82 : _SfxVersionTable( nInitSz, nReSz )
83 {}
84
SfxVersionTableDtor(const SfxVersionTableDtor & rCpy)85 SfxVersionTableDtor( const SfxVersionTableDtor &rCpy ) :
86 _SfxVersionTable( rCpy )
87 { *this = rCpy; }
88
89 SfxVersionTableDtor( const uno::Sequence < util::RevisionTag >& rInfo );
90
~SfxVersionTableDtor()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
SfxVersionTableDtor(const uno::Sequence<util::RevisionTag> & rInfo)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
DelDtor()118 void SfxVersionTableDtor::DelDtor()
119 {
120 SfxVersionInfo* pTmp = First();
121 while( pTmp )
122 {
123 delete pTmp;
124 pTmp = Next();
125 }
126 Clear();
127 }
128
operator =(const SfxVersionTableDtor & rTbl)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 //----------------------------------------------------------------
SfxVersionInfo()145 SfxVersionInfo::SfxVersionInfo()
146 {
147 }
148
ConvertDateTime_Impl(const DateTime & rTime,const LocaleDataWrapper & rWrapper)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
GetVersions() const158 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
KeyInput(const KeyEvent & rKeyEvent)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
SfxVersionsTabListBox_Impl(Window * pParent,const ResId & rResId)198 SfxVersionsTabListBox_Impl::SfxVersionsTabListBox_Impl( Window* pParent, const ResId& rResId )
199 : SvTabListBox( pParent, rResId )
200 {
201 }
202
SfxVersionDialog(SfxViewFrame * pVwFrame,sal_Bool bIsSaveVersionOnClose)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
ConvertWhiteSpaces_Impl(const String & rText)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
Init_Impl()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
~SfxVersionDialog()311 SfxVersionDialog::~SfxVersionDialog ()
312 {
313 delete mpTable;
314 delete mpLocaleWrapper;
315 }
316
Open_Impl()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
RecalcDateColumn()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
IMPL_LINK(SfxVersionDialog,DClickHdl_Impl,Control *,EMPTYARG)374 IMPL_LINK( SfxVersionDialog, DClickHdl_Impl, Control*, EMPTYARG )
375 {
376 Open_Impl();
377 return 0L;
378 }
379
IMPL_LINK(SfxVersionDialog,SelectHdl_Impl,Control *,EMPTYARG)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
IMPL_LINK(SfxVersionDialog,ButtonHdl_Impl,Button *,pButton)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
SfxViewVersionDialog_Impl(Window * pParent,SfxVersionInfo & rInfo,sal_Bool bEdit)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
IMPL_LINK(SfxViewVersionDialog_Impl,ButtonHdl,Button *,pButton)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