xref: /aoo41x/main/sfx2/source/dialog/versdlg.cxx (revision cdf0e10c)
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