Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <com/sun/star/uno/Reference.hxx>
22 :
23 : #include <com/sun/star/document/DocumentProperties.hpp>
24 : #include <com/sun/star/document/XDocumentProperties.hpp>
25 : #include <com/sun/star/document/UpdateDocMode.hpp>
26 : #include <com/sun/star/frame/XLayoutManager.hpp>
27 : #include <com/sun/star/embed/ElementModes.hpp>
28 : #include <vcl/msgbox.hxx>
29 : #include <svl/style.hxx>
30 : #include <vcl/wrkwin.hxx>
31 :
32 : #include <svl/stritem.hxx>
33 : #include <svl/intitem.hxx>
34 : #include <svl/rectitem.hxx>
35 : #include <svl/eitem.hxx>
36 : #include <svl/urihelper.hxx>
37 : #include <svl/ctloptions.hxx>
38 : #include <comphelper/storagehelper.hxx>
39 : #include <comphelper/processfactory.hxx>
40 : #include <unotools/securityoptions.hxx>
41 : #include <svtools/sfxecode.hxx>
42 : #include <svtools/ehdl.hxx>
43 : #include <tools/datetime.hxx>
44 : #include <rtl/logfile.hxx>
45 : #include <math.h>
46 :
47 : #include <unotools/saveopt.hxx>
48 : #include <unotools/useroptions.hxx>
49 : #include <unotools/localfilehelper.hxx>
50 : #include <vcl/virdev.hxx>
51 : #include <vcl/oldprintadaptor.hxx>
52 :
53 : #include <sfx2/app.hxx>
54 : #include "sfx2/sfxresid.hxx"
55 : #include "appdata.hxx"
56 : #include <sfx2/dinfdlg.hxx>
57 : #include "fltfnc.hxx"
58 : #include <sfx2/docfac.hxx>
59 : #include <sfx2/viewsh.hxx>
60 : #include <sfx2/objsh.hxx>
61 : #include "objshimp.hxx"
62 : #include <sfx2/evntconf.hxx>
63 : #include "sfx2/sfxhelp.hxx"
64 : #include <sfx2/dispatch.hxx>
65 : #include <sfx2/printer.hxx>
66 : #include "sfx2/basmgr.hxx"
67 : #include <sfx2/viewfrm.hxx>
68 : #include <sfx2/doctempl.hxx>
69 : #include "doc.hrc"
70 : #include <sfx2/sfxbasemodel.hxx>
71 : #include <sfx2/docfile.hxx>
72 : #include <sfx2/request.hxx>
73 : #include "openflag.hxx"
74 : #include "querytemplate.hxx"
75 :
76 : using namespace ::com::sun::star;
77 : using namespace ::com::sun::star::uno;
78 :
79 : //====================================================================
80 :
81 : static
82 0 : bool operator> (const util::DateTime& i_rLeft, const util::DateTime& i_rRight)
83 : {
84 0 : if ( i_rLeft.Year != i_rRight.Year )
85 0 : return i_rLeft.Year > i_rRight.Year;
86 :
87 0 : if ( i_rLeft.Month != i_rRight.Month )
88 0 : return i_rLeft.Month > i_rRight.Month;
89 :
90 0 : if ( i_rLeft.Day != i_rRight.Day )
91 0 : return i_rLeft.Day > i_rRight.Day;
92 :
93 0 : if ( i_rLeft.Hours != i_rRight.Hours )
94 0 : return i_rLeft.Hours > i_rRight.Hours;
95 :
96 0 : if ( i_rLeft.Minutes != i_rRight.Minutes )
97 0 : return i_rLeft.Minutes > i_rRight.Minutes;
98 :
99 0 : if ( i_rLeft.Seconds != i_rRight.Seconds )
100 0 : return i_rLeft.Seconds > i_rRight.Seconds;
101 :
102 0 : if ( i_rLeft.HundredthSeconds != i_rRight.HundredthSeconds )
103 0 : return i_rLeft.HundredthSeconds > i_rRight.HundredthSeconds;
104 :
105 0 : return sal_False;
106 : }
107 :
108 : ::boost::shared_ptr<GDIMetaFile>
109 2291 : SfxObjectShell::GetPreviewMetaFile( sal_Bool bFullContent ) const
110 : {
111 2291 : return CreatePreviewMetaFile_Impl( bFullContent );
112 : }
113 :
114 : ::boost::shared_ptr<GDIMetaFile>
115 2291 : SfxObjectShell::CreatePreviewMetaFile_Impl( sal_Bool bFullContent ) const
116 : {
117 : // DoDraw can only be called when no printing is done, otherwise
118 : // the printer may be turned off
119 2291 : SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
120 2293 : if ( pFrame && pFrame->GetViewShell() &&
121 2 : pFrame->GetViewShell()->GetPrinter() &&
122 0 : pFrame->GetViewShell()->GetPrinter()->IsPrinting() )
123 0 : return ::boost::shared_ptr<GDIMetaFile>();
124 :
125 2291 : ::boost::shared_ptr<GDIMetaFile> pFile(new GDIMetaFile);
126 :
127 2291 : VirtualDevice aDevice;
128 2291 : aDevice.EnableOutput( sal_False );
129 :
130 2291 : MapMode aMode( ((SfxObjectShell*)this)->GetMapUnit() );
131 2291 : aDevice.SetMapMode( aMode );
132 2291 : pFile->SetPrefMapMode( aMode );
133 :
134 2291 : Size aTmpSize;
135 : sal_Int8 nAspect;
136 2291 : if ( bFullContent )
137 : {
138 2288 : nAspect = ASPECT_CONTENT;
139 2288 : aTmpSize = GetVisArea( nAspect ).GetSize();
140 : }
141 : else
142 : {
143 3 : nAspect = ASPECT_THUMBNAIL;
144 3 : aTmpSize = ((SfxObjectShell*)this)->GetFirstPageSize();
145 : }
146 :
147 2291 : pFile->SetPrefSize( aTmpSize );
148 : DBG_ASSERT( aTmpSize.Height()*aTmpSize.Width(),
149 : "size of first page is 0, overload GetFirstPageSize or set vis-area!" );
150 :
151 2291 : pFile->Record( &aDevice );
152 :
153 : LanguageType eLang;
154 2291 : SvtCTLOptions aCTLOptions;
155 2291 : if ( SvtCTLOptions::NUMERALS_HINDI == aCTLOptions.GetCTLTextNumerals() )
156 0 : eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
157 2291 : else if ( SvtCTLOptions::NUMERALS_ARABIC == aCTLOptions.GetCTLTextNumerals() )
158 2291 : eLang = LANGUAGE_ENGLISH;
159 : else
160 0 : eLang = (LanguageType) Application::GetSettings().GetLanguageTag().getLanguageType();
161 :
162 2291 : aDevice.SetDigitLanguage( eLang );
163 :
164 : {
165 2291 : RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "PERFORMANCE SfxObjectShell::CreatePreviewMetaFile_Impl" );
166 2291 : ((SfxObjectShell*)this)->DoDraw( &aDevice, Point(0,0), aTmpSize, JobSetup(), nAspect );
167 : }
168 2291 : pFile->Stop();
169 :
170 2291 : return pFile;
171 : }
172 :
173 : //====================================================================
174 :
175 4 : void SfxObjectShell::UpdateDocInfoForSave()
176 : {
177 4 : uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());
178 :
179 : // clear user data if recommend (see 'Tools - Options - Open/StarOffice - Security')
180 8 : if ( SvtSecurityOptions().IsOptionSet(
181 8 : SvtSecurityOptions::E_DOCWARN_REMOVEPERSONALINFO ) )
182 : {
183 0 : xDocProps->resetUserData( ::rtl::OUString() );
184 : }
185 4 : else if ( IsModified() )
186 : {
187 0 : String aUserName = SvtUserOptions().GetFullName();
188 0 : if ( !IsUseUserData() )
189 : {
190 : // remove all data pointing to the current user
191 0 : if (xDocProps->getAuthor().equals(aUserName)) {
192 0 : xDocProps->setAuthor( ::rtl::OUString() );
193 : }
194 0 : xDocProps->setModifiedBy( ::rtl::OUString() );
195 0 : if (xDocProps->getPrintedBy().equals(aUserName)) {
196 0 : xDocProps->setPrintedBy( ::rtl::OUString() );
197 : }
198 : }
199 : else
200 : {
201 : // update ModificationAuthor, revision and editing time
202 0 : ::DateTime now( ::DateTime::SYSTEM );
203 0 : xDocProps->setModificationDate( util::DateTime(
204 0 : now.Get100Sec(), now.GetSec(), now.GetMin(),
205 0 : now.GetHour(), now.GetDay(), now.GetMonth(),
206 0 : now.GetYear() ) );
207 0 : xDocProps->setModifiedBy( aUserName );
208 0 : if ( !HasName() || pImp->bIsSaving )
209 : // QUESTION: not in case of "real" SaveAs as this is meant to create a new document
210 0 : UpdateTime_Impl( xDocProps );
211 0 : }
212 4 : }
213 4 : }
214 :
215 : //--------------------------------------------------------------------
216 :
217 : static void
218 0 : lcl_add(util::Duration & rDur, Time const& rTime)
219 : {
220 : // here we don't care about overflow: rDur is converted back to seconds
221 : // anyway, and Time cannot store more than ~4000 hours
222 0 : rDur.Hours += rTime.GetHour();
223 0 : rDur.Minutes += rTime.GetMin();
224 0 : rDur.Seconds += rTime.GetSec();
225 0 : }
226 :
227 : // Update the processing time
228 0 : void SfxObjectShell::UpdateTime_Impl(
229 : const uno::Reference<document::XDocumentProperties> & i_xDocProps)
230 : {
231 : // Get old time from documentinfo
232 0 : const sal_Int32 secs = i_xDocProps->getEditingDuration();
233 : util::Duration editDuration(sal_False, 0, 0, 0,
234 0 : secs/3600, (secs%3600)/60, secs%60, 0);
235 :
236 : // Initialize some local member! Its neccessary for wollow operations!
237 0 : DateTime aNow( DateTime::SYSTEM ); // Date and time at current moment
238 0 : Time n24Time (24,0,0,0) ; // Time-value for 24 hours - see follow calculation
239 0 : sal_uIntPtr nDays = 0 ; // Count of days between now and last editing
240 0 : Time nAddTime (0) ; // Value to add on aOldTime
241 :
242 : // Safe impossible cases!
243 : // User has changed time to the past between last editing and now ... its not possible!!!
244 : DBG_ASSERT( !(aNow.GetDate()<pImp->nTime.GetDate()), "Timestamp of last change is in the past ?!..." );
245 :
246 : // Do the follow only, if user has NOT changed time to the past.
247 : // Else add a time of 0 to aOldTime ... !!!
248 0 : if (aNow.GetDate()>=pImp->nTime.GetDate())
249 : {
250 : // Get count of days last editing.
251 0 : nDays = aNow.GetSecFromDateTime(pImp->nTime.GetDate())/86400 ;
252 :
253 0 : if (nDays==0)
254 : {
255 : // If no day between now and last editing - calculate time directly.
256 0 : nAddTime = (const Time&)aNow - (const Time&)pImp->nTime ;
257 : }
258 0 : else if (nDays<=31)
259 : {
260 : // If time of working without save greater then 1 month (!) ....
261 : // we add 0 to aOldTime!
262 :
263 : // If 1 or up to 31 days between now and last editing - calculate time indirectly.
264 : // nAddTime = (24h - nTime) + (nDays * 24h) + aNow
265 0 : --nDays;
266 0 : nAddTime = nDays*n24Time.GetTime() ;
267 0 : nAddTime += n24Time-(const Time&)pImp->nTime ;
268 0 : nAddTime += aNow ;
269 : }
270 :
271 0 : lcl_add(editDuration, nAddTime);
272 : }
273 :
274 0 : pImp->nTime = aNow;
275 : try {
276 : const sal_Int32 newSecs( (editDuration.Hours*3600)
277 0 : + (editDuration.Minutes*60) + editDuration.Seconds);
278 0 : i_xDocProps->setEditingDuration(newSecs);
279 0 : i_xDocProps->setEditingCycles(i_xDocProps->getEditingCycles() + 1);
280 : }
281 0 : catch (const lang::IllegalArgumentException &)
282 : {
283 : // ignore overflow
284 : }
285 0 : }
286 :
287 : //--------------------------------------------------------------------
288 :
289 0 : SfxDocumentInfoDialog* SfxObjectShell::CreateDocumentInfoDialog
290 : (
291 : Window* pParent,
292 : const SfxItemSet& rSet
293 : )
294 : {
295 0 : return new SfxDocumentInfoDialog(pParent, rSet);
296 : }
297 :
298 : //--------------------------------------------------------------------
299 :
300 0 : SfxStyleSheetBasePool* SfxObjectShell::GetStyleSheetPool()
301 : {
302 0 : return 0;
303 : }
304 :
305 0 : void SfxObjectShell::SetOrganizerSearchMask(
306 : SfxStyleSheetBasePool* pStylePool) const
307 : {
308 : pStylePool->SetSearchMask(
309 : SFX_STYLE_FAMILY_ALL,
310 0 : SFXSTYLEBIT_USERDEF | SFXSTYLEBIT_USED);
311 0 : }
312 :
313 : //--------------------------------------------------------------------
314 :
315 0 : sal_uInt16 SfxObjectShell::GetContentCount(sal_uInt16 nIdx)
316 : {
317 0 : switch(nIdx)
318 : {
319 : case INDEX_IGNORE:
320 0 : return DEF_CONTENT_COUNT;
321 : case CONTENT_STYLE:
322 : {
323 0 : SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
324 0 : if(!pStylePool)
325 0 : return 0;
326 0 : SetOrganizerSearchMask(pStylePool);
327 0 : return pStylePool->Count();
328 : }
329 : case CONTENT_MACRO:
330 0 : break;
331 : }
332 0 : return 0;
333 : }
334 :
335 :
336 : //--------------------------------------------------------------------
337 : //TODO/CLEANUP: remove this method
338 0 : void SfxObjectShell::TriggerHelpPI(sal_uInt16 nIdx1, sal_uInt16 nIdx2)
339 : {
340 0 : if(nIdx1==CONTENT_STYLE && nIdx2 != INDEX_IGNORE) //StyleSheets
341 : {
342 0 : SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
343 0 : SetOrganizerSearchMask(pStylePool);
344 : }
345 0 : }
346 :
347 0 : sal_Bool SfxObjectShell::CanHaveChildren(sal_uInt16 nIdx1, sal_uInt16 nIdx2)
348 : {
349 0 : switch(nIdx1)
350 : {
351 : case INDEX_IGNORE:
352 0 : return true;
353 : case CONTENT_STYLE:
354 0 : return INDEX_IGNORE == nIdx2 || !GetStyleSheetPool() ? false : true;
355 : case CONTENT_MACRO:
356 0 : return false;
357 : }
358 0 : return false;
359 : }
360 :
361 : //--------------------------------------------------------------------
362 :
363 0 : void SfxObjectShell::GetContent(String &rText,
364 : Bitmap &rClosedBitmap,
365 : Bitmap &rOpenedBitmap,
366 : sal_Bool &bCanDel,
367 : sal_uInt16 i,
368 : sal_uInt16 nIdx
369 : )
370 : {
371 0 : bCanDel=true;
372 :
373 0 : switch(nIdx)
374 : {
375 : case INDEX_IGNORE:
376 : {
377 0 : sal_uInt16 nTextResId = 0;
378 0 : sal_uInt16 nClosedBitmapResId = 0; // evtl. sp"ater mal unterschiedliche
379 0 : sal_uInt16 nOpenedBitmapResId = 0; // " " " "
380 0 : switch(i)
381 : {
382 : case CONTENT_STYLE:
383 0 : nTextResId = STR_STYLES;
384 0 : nClosedBitmapResId= BMP_STYLES_CLOSED;
385 0 : nOpenedBitmapResId= BMP_STYLES_OPENED;
386 0 : break;
387 : case CONTENT_MACRO:
388 0 : nTextResId = STR_MACROS;
389 0 : nClosedBitmapResId= BMP_STYLES_CLOSED;
390 0 : nOpenedBitmapResId= BMP_STYLES_OPENED;
391 0 : break;
392 : }
393 :
394 0 : if ( nTextResId )
395 : {
396 0 : rText = SfxResId(nTextResId).toString();
397 0 : rClosedBitmap = Bitmap(SfxResId(nClosedBitmapResId));
398 0 : rOpenedBitmap = Bitmap(SfxResId(nOpenedBitmapResId));
399 : }
400 0 : break;
401 : }
402 :
403 : case CONTENT_STYLE:
404 : {
405 0 : SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
406 0 : SetOrganizerSearchMask(pStylePool);
407 0 : SfxStyleSheetBase *pStyle = (*pStylePool)[i];
408 0 : rText = pStyle->GetName();
409 0 : bCanDel=((pStyle->GetMask() & SFXSTYLEBIT_USERDEF)
410 0 : == SFXSTYLEBIT_USERDEF);
411 : rClosedBitmap = rOpenedBitmap =
412 0 : GetStyleFamilyBitmap(pStyle->GetFamily());
413 : }
414 0 : break;
415 : case CONTENT_MACRO:
416 0 : break;
417 : }
418 0 : }
419 :
420 : //--------------------------------------------------------------------
421 :
422 0 : Bitmap SfxObjectShell::GetStyleFamilyBitmap(SfxStyleFamily eFamily)
423 : {
424 0 : sal_uInt16 nResId = 0;
425 0 : switch(eFamily)
426 : {
427 : case SFX_STYLE_FAMILY_CHAR:
428 0 : nResId = BMP_STYLES_FAMILY1;
429 0 : break;
430 : case SFX_STYLE_FAMILY_PARA:
431 0 : nResId = BMP_STYLES_FAMILY2;
432 0 : break;
433 : case SFX_STYLE_FAMILY_FRAME:
434 0 : nResId = BMP_STYLES_FAMILY3;
435 0 : break;
436 : case SFX_STYLE_FAMILY_PAGE :
437 0 : nResId = BMP_STYLES_FAMILY4;
438 0 : break;
439 : case SFX_STYLE_FAMILY_PSEUDO:
440 : case SFX_STYLE_FAMILY_ALL:
441 0 : break;
442 : }
443 :
444 0 : if ( nResId )
445 0 : return Bitmap(SfxResId(nResId));
446 : else
447 0 : return Bitmap();
448 : }
449 :
450 :
451 : //--------------------------------------------------------------------
452 :
453 0 : sal_Bool SfxObjectShell::Insert(SfxObjectShell &rSource,
454 : sal_uInt16 nSourceIdx1,
455 : sal_uInt16 nSourceIdx2,
456 : sal_uInt16 /*nSourceIdx3*/,
457 : sal_uInt16 &nIdx1,
458 : sal_uInt16 &nIdx2,
459 : sal_uInt16 &/*nIdx3*/,
460 : sal_uInt16 &/*nDeleted*/)
461 : {
462 0 : sal_Bool bRet = sal_False;
463 :
464 0 : if (INDEX_IGNORE == nIdx1 && CONTENT_STYLE == nSourceIdx1)
465 0 : nIdx1 = CONTENT_STYLE;
466 :
467 0 : if (CONTENT_STYLE == nSourceIdx1 && CONTENT_STYLE == nIdx1)
468 : {
469 0 : SfxStyleSheetBasePool* pHisPool = rSource.GetStyleSheetPool();
470 0 : SfxStyleSheetBasePool* pMyPool = GetStyleSheetPool();
471 0 : SetOrganizerSearchMask(pHisPool);
472 0 : SetOrganizerSearchMask(pMyPool);
473 0 : SfxStyleSheetBase* pHisSheet = NULL;
474 :
475 0 : if ( pHisPool && pHisPool->Count() > nSourceIdx2 )
476 0 : pHisSheet = (*pHisPool)[nSourceIdx2];
477 :
478 : // Pasting is only needed if a style sheet is moved between
479 : // different (!) Pools
480 :
481 0 : if ( pHisSheet && pMyPool != pHisPool )
482 : {
483 0 : if (INDEX_IGNORE == nIdx2)
484 : {
485 0 : nIdx2 = pMyPool->Count();
486 : }
487 :
488 : // if such a template already exists: delete!
489 0 : String aOldName(pHisSheet->GetName());
490 0 : SfxStyleFamily eOldFamily = pHisSheet->GetFamily();
491 :
492 0 : SfxStyleSheetBase* pExist = pMyPool->Find(aOldName, eOldFamily);
493 : sal_Bool bUsedOrUserDefined;
494 0 : if( pExist )
495 : {
496 : bUsedOrUserDefined =
497 0 : pExist->IsUsed() || pExist->IsUserDefined();
498 0 : if( ErrorHandler::HandleError(
499 0 : *new MessageInfo( ERRCODE_SFXMSG_STYLEREPLACE, aOldName ) )
500 : != ERRCODE_BUTTON_OK )
501 0 : return sal_False;
502 : else
503 : {
504 0 : pMyPool->Replace( *pHisSheet, *pExist );
505 0 : SetModified( sal_True );
506 0 : nIdx2 = nIdx1 = INDEX_IGNORE;
507 0 : return sal_True;
508 : }
509 : }
510 :
511 : SfxStyleSheetBase& rNewSheet = pMyPool->Make(
512 : aOldName, eOldFamily,
513 0 : pHisSheet->GetMask(), nIdx2);
514 :
515 : // Fill the Itemset of the new template
516 0 : rNewSheet.GetItemSet().Set(pHisSheet->GetItemSet());
517 :
518 : // Who gets the new one as a Parent?
519 : // Who is using the new one as Follow?
520 0 : SfxStyleSheetBase* pTestSheet = pMyPool->First();
521 0 : while (pTestSheet)
522 : {
523 0 : if (pTestSheet->GetFamily() == eOldFamily &&
524 0 : pTestSheet->HasParentSupport() &&
525 0 : pTestSheet->GetParent() == aOldName)
526 : {
527 0 : pTestSheet->SetParent(aOldName);
528 : // Rebuild Link
529 : }
530 :
531 0 : if (pTestSheet->GetFamily() == eOldFamily &&
532 0 : pTestSheet->HasFollowSupport() &&
533 0 : pTestSheet->GetFollow() == aOldName)
534 : {
535 0 : pTestSheet->SetFollow(aOldName);
536 : // Rebuild Link
537 : }
538 :
539 0 : pTestSheet = pMyPool->Next();
540 : }
541 : bUsedOrUserDefined =
542 0 : rNewSheet.IsUsed() || rNewSheet.IsUserDefined();
543 :
544 :
545 : // has a New Parent? if so, start search with the same name
546 0 : if (pHisSheet->HasParentSupport())
547 : {
548 0 : const String& rParentName = pHisSheet->GetParent();
549 0 : if (0 != rParentName.Len())
550 : {
551 : SfxStyleSheetBase* pParentOfNew =
552 0 : pMyPool->Find(rParentName, eOldFamily);
553 0 : if (pParentOfNew)
554 0 : rNewSheet.SetParent(rParentName);
555 : }
556 : }
557 :
558 : // Has the new got a Follow? if so start search
559 : // with the same name.
560 0 : if (pHisSheet->HasFollowSupport())
561 : {
562 0 : const String& rFollowName = pHisSheet->GetFollow();
563 0 : if (0 != rFollowName.Len())
564 : {
565 : SfxStyleSheetBase* pFollowOfNew =
566 0 : pMyPool->Find(rFollowName, eOldFamily);
567 0 : if (pFollowOfNew)
568 0 : rNewSheet.SetFollow(rFollowName);
569 : }
570 : }
571 :
572 0 : SetModified( sal_True );
573 0 : if( !bUsedOrUserDefined ) nIdx2 = nIdx1 = INDEX_IGNORE;
574 :
575 0 : bRet = sal_True;
576 : }
577 : else
578 0 : bRet = sal_False;
579 : }
580 :
581 0 : return bRet;
582 : }
583 :
584 : //--------------------------------------------------------------------
585 :
586 0 : sal_Bool SfxObjectShell::Remove
587 : (
588 : sal_uInt16 nIdx1,
589 : sal_uInt16 nIdx2,
590 : sal_uInt16 /*nIdx3*/
591 : )
592 : {
593 0 : sal_Bool bRet = sal_False;
594 :
595 0 : if (CONTENT_STYLE == nIdx1)
596 : {
597 0 : SfxStyleSheetBasePool* pMyPool = GetStyleSheetPool();
598 :
599 0 : SetOrganizerSearchMask(pMyPool);
600 :
601 0 : SfxStyleSheetBase* pMySheet = (*pMyPool)[nIdx2];
602 0 : String aName(pMySheet->GetName());
603 0 : String aEmpty;
604 0 : SfxStyleFamily eFamily = pMySheet->GetFamily();
605 0 : pMyPool->Remove(pMySheet);
606 0 : bRet = sal_True;
607 :
608 0 : SfxStyleSheetBase* pTestSheet = pMyPool->First();
609 0 : while (pTestSheet)
610 : {
611 0 : if (pTestSheet->GetFamily() == eFamily &&
612 0 : pTestSheet->HasParentSupport() &&
613 0 : pTestSheet->GetParent() == aName)
614 : {
615 0 : pTestSheet->SetParent(aEmpty); // Remove link
616 : }
617 :
618 0 : if (pTestSheet->GetFamily() == eFamily &&
619 0 : pTestSheet->HasFollowSupport() &&
620 0 : pTestSheet->GetFollow() == aName)
621 : {
622 0 : pTestSheet->SetFollow(aEmpty); // Remove link
623 : }
624 :
625 0 : pTestSheet = pMyPool->Next();
626 : }
627 :
628 0 : SetModified( sal_True );
629 : }
630 :
631 0 : return bRet;
632 : }
633 :
634 : //--------------------------------------------------------------------
635 :
636 0 : sal_Bool SfxObjectShell::Print
637 : (
638 : Printer& rPrt,
639 : sal_uInt16 nIdx1,
640 : sal_uInt16 /*nIdx2*/,
641 : sal_uInt16 /*nIdx3*/,
642 : const String* pObjectName
643 : )
644 : {
645 0 : switch(nIdx1)
646 : {
647 : case CONTENT_STYLE:
648 : {
649 0 : SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
650 0 : SetOrganizerSearchMask(pStylePool);
651 : SfxStyleSheetIterator* pIter = pStylePool->CreateIterator(
652 0 : pStylePool->GetSearchFamily(), pStylePool->GetSearchMask() );
653 0 : SfxStyleSheetBase *pStyle = pIter->First();
654 0 : if ( !pStyle )
655 0 : return sal_True;
656 :
657 : // prepare adaptor for old style StartPage/EndPage printing
658 0 : boost::shared_ptr< Printer > pPrinter( new Printer( rPrt.GetJobSetup() ) );
659 0 : vcl::OldStylePrintAdaptor* pAdaptor = new vcl::OldStylePrintAdaptor( pPrinter );
660 0 : boost::shared_ptr< vcl::PrinterController > pController( pAdaptor );
661 :
662 0 : pAdaptor->StartPage();
663 :
664 0 : pPrinter->SetMapMode(MapMode(MAP_10TH_MM));
665 0 : Font aFont( DEFINE_CONST_UNICODE( "Arial" ), Size(0, 64)); // 18pt
666 0 : aFont.SetWeight(WEIGHT_BOLD);
667 0 : pPrinter->SetFont(aFont);
668 0 : const Size aPageSize(pPrinter->GetOutputSize());
669 0 : const sal_uInt16 nXIndent = 200;
670 0 : sal_uInt16 nYIndent = 200;
671 0 : Point aOutPos(nXIndent, nYIndent);
672 0 : String aHeader(SfxResId(STR_PRINT_STYLES_HEADER).toString());
673 0 : if ( pObjectName )
674 0 : aHeader += *pObjectName;
675 : else
676 0 : aHeader += GetTitle();
677 0 : long nTextHeight( pPrinter->GetTextHeight() );
678 0 : pPrinter->DrawText(aOutPos, aHeader);
679 0 : aOutPos.Y() += nTextHeight;
680 0 : aOutPos.Y() += nTextHeight/2;
681 0 : aFont.SetSize(Size(0, 35)); // 10pt
682 0 : while(pStyle)
683 : {
684 : // print template name
685 0 : String aStr(pStyle->GetName());
686 0 : aFont.SetWeight(WEIGHT_BOLD);
687 0 : pPrinter->SetFont(aFont);
688 0 : nTextHeight = pPrinter->GetTextHeight();
689 : // check for new page
690 0 : if ( aOutPos.Y() + nTextHeight*2 >
691 0 : aPageSize.Height() - (long) nYIndent )
692 : {
693 0 : pAdaptor->EndPage();
694 0 : pAdaptor->StartPage();
695 0 : aOutPos.Y() = nYIndent;
696 : }
697 0 : pPrinter->DrawText(aOutPos, aStr);
698 0 : aOutPos.Y() += nTextHeight;
699 :
700 : // print template description
701 0 : aFont.SetWeight(WEIGHT_NORMAL);
702 0 : pPrinter->SetFont(aFont);
703 0 : aStr = pStyle->GetDescription();
704 0 : const char cDelim = ' ';
705 0 : sal_uInt16 nStart = 0, nIdx = 0;
706 :
707 0 : nTextHeight = pPrinter->GetTextHeight();
708 : // break text into lines
709 0 : while(nIdx < aStr.Len())
710 : {
711 0 : sal_uInt16 nOld = nIdx;
712 : long nTextWidth;
713 0 : nIdx = aStr.Search(cDelim, nStart);
714 0 : nTextWidth = pPrinter->GetTextWidth(aStr, nStart, nIdx-nStart);
715 0 : while(nIdx != STRING_NOTFOUND &&
716 0 : aOutPos.X() + nTextWidth <
717 0 : aPageSize.Width() - (long) nXIndent)
718 : {
719 0 : nOld = nIdx;
720 0 : nIdx = aStr.Search(cDelim, nIdx+1);
721 0 : nTextWidth = pPrinter->GetTextWidth(aStr, nStart, nIdx-nStart);
722 : }
723 : String aTmp(aStr, nStart, nIdx == STRING_NOTFOUND?
724 : STRING_LEN :
725 0 : nOld-nStart);
726 0 : if ( aTmp.Len() )
727 : {
728 0 : nStart = nOld+1; // trailing space
729 : }
730 : else
731 : {
732 0 : sal_uInt16 nChar = 1;
733 0 : while(
734 0 : nStart + nChar < aStr.Len() &&
735 0 : aOutPos.X() + pPrinter->GetTextWidth(
736 0 : aStr, nStart, nChar) <
737 0 : aPageSize.Width() - nXIndent)
738 0 : ++nChar;
739 0 : aTmp = String(aStr, nStart, nChar-1);
740 0 : nIdx = nStart + nChar;
741 0 : nStart = nIdx;
742 : }
743 0 : if ( aOutPos.Y() + nTextHeight*2 >
744 0 : aPageSize.Height() - nYIndent )
745 : {
746 0 : pAdaptor->EndPage();
747 0 : pAdaptor->StartPage();
748 0 : aOutPos.Y() = nYIndent;
749 : }
750 0 : pPrinter->DrawText(aOutPos, aTmp);
751 0 : aOutPos.Y() += pPrinter->GetTextHeight();
752 0 : }
753 0 : pStyle = pIter->Next();
754 0 : }
755 0 : pAdaptor->EndPage();
756 :
757 0 : Printer::PrintJob( pController, rPrt.GetJobSetup() );
758 :
759 0 : delete pIter;
760 0 : break;
761 : }
762 : default:
763 0 : return sal_False;
764 : }
765 0 : return sal_True;
766 : }
767 :
768 : //--------------------------------------------------------------------
769 :
770 0 : void SfxObjectShell::LoadStyles
771 : (
772 : SfxObjectShell &rSource /* the document template from which
773 : the styles are to be loaded */
774 : )
775 :
776 : /* [Description]
777 :
778 : This method is called by the SFx if template styles are to be loaded.
779 : Existing styles are in this case overwritten. The document has then to be
780 : newly formatted. Therefore, the application of this method is usually
781 : overloaded and its implementation is calling the implementation in
782 : the base class.
783 : */
784 :
785 : {
786 : struct Styles_Impl
787 : {
788 : SfxStyleSheetBase *pSource;
789 : SfxStyleSheetBase *pDest;
790 : };
791 :
792 0 : SfxStyleSheetBasePool *pSourcePool = rSource.GetStyleSheetPool();
793 : DBG_ASSERT(pSourcePool, "Source-DocumentShell ohne StyleSheetPool");
794 0 : SfxStyleSheetBasePool *pMyPool = GetStyleSheetPool();
795 : DBG_ASSERT(pMyPool, "Dest-DocumentShell ohne StyleSheetPool");
796 0 : pSourcePool->SetSearchMask(SFX_STYLE_FAMILY_ALL, SFXSTYLEBIT_ALL);
797 0 : Styles_Impl *pFound = new Styles_Impl[pSourcePool->Count()];
798 0 : sal_uInt16 nFound = 0;
799 :
800 0 : SfxStyleSheetBase *pSource = pSourcePool->First();
801 0 : while ( pSource )
802 : {
803 : SfxStyleSheetBase *pDest =
804 0 : pMyPool->Find( pSource->GetName(), pSource->GetFamily() );
805 0 : if ( !pDest )
806 : {
807 0 : pDest = &pMyPool->Make( pSource->GetName(),
808 0 : pSource->GetFamily(), pSource->GetMask());
809 : // Setting of Parents, the next style
810 : }
811 0 : pFound[nFound].pSource = pSource;
812 0 : pFound[nFound].pDest = pDest;
813 0 : ++nFound;
814 0 : pSource = pSourcePool->Next();
815 : }
816 :
817 0 : for ( sal_uInt16 i = 0; i < nFound; ++i )
818 : {
819 0 : pFound[i].pDest->GetItemSet().PutExtended(pFound[i].pSource->GetItemSet(), SFX_ITEM_DONTCARE, SFX_ITEM_DEFAULT);
820 0 : if(pFound[i].pSource->HasParentSupport())
821 0 : pFound[i].pDest->SetParent(pFound[i].pSource->GetParent());
822 0 : if(pFound[i].pSource->HasFollowSupport())
823 0 : pFound[i].pDest->SetFollow(pFound[i].pSource->GetParent());
824 : }
825 0 : delete [] pFound;
826 0 : }
827 :
828 : //--------------------------------------------------------------------
829 :
830 240 : void SfxObjectShell::UpdateFromTemplate_Impl( )
831 :
832 : /* [Description]
833 :
834 : This internal method checks whether the document was created from a
835 : template, and if this is newer than the document. If this is the case,
836 : the user is asked if the Templates (StyleSheets) should be updated.
837 : If this is answered positively, the StyleSheets are updated.
838 : */
839 :
840 : {
841 : // Storage-medium?
842 240 : SfxMedium *pFile = GetMedium();
843 : DBG_ASSERT( pFile, "cannot UpdateFromTemplate without medium" );
844 240 : if ( !pFile )
845 : return;
846 :
847 240 : if ( !::utl::LocalFileHelper::IsLocalFile( pFile->GetName() ) )
848 : // update only for documents loaded from the local file system
849 : return;
850 :
851 : // only for own storage formats
852 235 : uno::Reference< embed::XStorage > xDocStor = pFile->GetStorage();
853 235 : if ( !pFile->GetFilter() || !pFile->GetFilter()->IsOwnFormat() )
854 : return;
855 :
856 15 : SFX_ITEMSET_ARG( pFile->GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
857 15 : sal_Int16 bCanUpdateFromTemplate = pUpdateDocItem ? pUpdateDocItem->GetValue() : document::UpdateDocMode::NO_UPDATE;
858 :
859 : // created from template?
860 15 : uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());
861 15 : ::rtl::OUString aTemplName( xDocProps->getTemplateName() );
862 15 : ::rtl::OUString aTemplURL( xDocProps->getTemplateURL() );
863 15 : String aFoundName;
864 :
865 15 : if ( !aTemplName.isEmpty() || (!aTemplURL.isEmpty() && !IsReadOnly()) )
866 : {
867 : // try to locate template, first using filename this must be done
868 : // because writer global document uses this "great" idea to manage
869 : // the templates of all parts in the master document but it is NOT
870 : // an error if the template filename points not to a valid file
871 3 : SfxDocumentTemplates aTempl;
872 3 : aTempl.Construct();
873 3 : if ( !aTemplURL.isEmpty() )
874 : {
875 0 : String aURL;
876 0 : if( ::utl::LocalFileHelper::ConvertSystemPathToURL( aTemplURL, GetMedium()->GetName(), aURL ) )
877 0 : aFoundName = aURL;
878 : }
879 :
880 3 : if( !aFoundName.Len() && !aTemplName.isEmpty() )
881 : // if the template filename did not lead to success,
882 : // try to get a file name for the logical template name
883 3 : aTempl.GetFull( String(), aTemplName, aFoundName );
884 : }
885 :
886 15 : if ( aFoundName.Len() )
887 : {
888 : // check existence of template storage
889 0 : aTemplURL = aFoundName;
890 0 : sal_Bool bLoad = sal_False;
891 :
892 : // should the document checked against changes in the template ?
893 0 : if ( IsQueryLoadTemplate() )
894 : {
895 : // load document properties of template
896 0 : bool bOK = false;
897 0 : util::DateTime aTemplDate;
898 : try
899 : {
900 : Reference<document::XDocumentProperties> const
901 : xTemplateDocProps( document::DocumentProperties::create(
902 0 : ::comphelper::getProcessComponentContext()));
903 0 : xTemplateDocProps->loadFromMedium(aTemplURL,
904 0 : Sequence<beans::PropertyValue>());
905 0 : aTemplDate = xTemplateDocProps->getModificationDate();
906 0 : bOK = true;
907 : }
908 0 : catch (const Exception& e)
909 : {
910 : SAL_INFO("sfx2.doc", "caught exception" << e.Message);
911 : }
912 :
913 : // if modify date was read successfully
914 0 : if ( bOK )
915 : {
916 : // compare modify data of template with the last check date of the document
917 0 : const util::DateTime aInfoDate( xDocProps->getTemplateDate() );
918 0 : if ( aTemplDate > aInfoDate )
919 : {
920 : // ask user
921 0 : if( bCanUpdateFromTemplate == document::UpdateDocMode::QUIET_UPDATE
922 : || bCanUpdateFromTemplate == document::UpdateDocMode::FULL_UPDATE )
923 0 : bLoad = sal_True;
924 0 : else if ( bCanUpdateFromTemplate == document::UpdateDocMode::ACCORDING_TO_CONFIG )
925 : {
926 0 : String sMessage( SfxResId(STR_QRYTEMPL_MESSAGE).toString() );
927 0 : sMessage.SearchAndReplace( rtl::OUString("$(ARG1)"), aTemplName );
928 0 : sfx2::QueryTemplateBox aBox( GetDialogParent(), sMessage );
929 0 : if ( RET_YES == aBox.Execute() )
930 0 : bLoad = sal_True;
931 : }
932 :
933 0 : if( !bLoad )
934 : {
935 : // user refuses, so don't ask again for this document
936 0 : SetQueryLoadTemplate(sal_False);
937 0 : SetModified( sal_True );
938 : }
939 : }
940 : }
941 :
942 0 : if ( bLoad )
943 : {
944 : // styles should be updated, create document in organizer mode to read in the styles
945 : //TODO: testen!
946 0 : SfxObjectShellLock xTemplDoc = CreateObjectByFactoryName( GetFactory().GetFactoryName(), SFX_CREATE_MODE_ORGANIZER );
947 0 : xTemplDoc->DoInitNew(0);
948 :
949 : // TODO/MBA: do we need a BaseURL? Then LoadFrom must be extended!
950 : //xTemplDoc->SetBaseURL( aFoundName );
951 :
952 : // TODO/LATER: make sure that we don't use binary templates!
953 0 : SfxMedium aMedium( aFoundName, STREAM_STD_READ );
954 0 : if ( xTemplDoc->LoadFrom( aMedium ) )
955 : {
956 : // transfer styles from xTemplDoc to this document
957 : // TODO/MBA: make sure that no BaseURL is needed in *this* document
958 0 : LoadStyles(*xTemplDoc);
959 :
960 : // remember date/time of check
961 0 : xDocProps->setTemplateDate(aTemplDate);
962 : // TODO/LATER: new functionality to store document info is required ( didn't work for SO7 XML format )
963 0 : }
964 : }
965 : }
966 15 : }
967 : }
968 :
969 1085 : sal_Bool SfxObjectShell::IsHelpDocument() const
970 : {
971 1085 : const SfxFilter* pFilter = GetMedium()->GetFilter();
972 1085 : return ( pFilter && pFilter->GetFilterName().CompareToAscii("writer_web_HTML_help") == COMPARE_EQUAL );
973 : }
974 :
975 1 : void SfxObjectShell::ResetFromTemplate( const String& rTemplateName, const String& rFileName )
976 : {
977 : // only care about reseting this data for openoffice formats otherwise
978 1 : if ( IsOwnStorageFormat_Impl( *GetMedium()) )
979 : {
980 1 : uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());
981 1 : xDocProps->setTemplateURL( ::rtl::OUString() );
982 1 : xDocProps->setTemplateName( ::rtl::OUString() );
983 1 : xDocProps->setTemplateDate( util::DateTime() );
984 1 : xDocProps->resetUserData( ::rtl::OUString() );
985 :
986 : // TODO/REFACTOR:
987 : // Title?
988 :
989 1 : if( ::utl::LocalFileHelper::IsLocalFile( rFileName ) )
990 : {
991 1 : String aFoundName;
992 1 : if( SFX_APP()->Get_Impl()->GetDocumentTemplates()->GetFull( String(), rTemplateName, aFoundName ) )
993 : {
994 0 : INetURLObject aObj( rFileName );
995 0 : xDocProps->setTemplateURL( aObj.GetMainURL(INetURLObject::DECODE_TO_IURI) );
996 0 : xDocProps->setTemplateName( rTemplateName );
997 :
998 0 : ::DateTime now( ::DateTime::SYSTEM );
999 0 : xDocProps->setTemplateDate( util::DateTime(
1000 0 : now.Get100Sec(), now.GetSec(), now.GetMin(),
1001 0 : now.GetHour(), now.GetDay(), now.GetMonth(),
1002 0 : now.GetYear() ) );
1003 :
1004 0 : SetQueryLoadTemplate( sal_True );
1005 1 : }
1006 1 : }
1007 : }
1008 1 : }
1009 :
1010 6 : sal_Bool SfxObjectShell::IsQueryLoadTemplate() const
1011 : {
1012 6 : return pImp->bQueryLoadTemplate;
1013 : }
1014 :
1015 6 : sal_Bool SfxObjectShell::IsUseUserData() const
1016 : {
1017 6 : return pImp->bUseUserData;
1018 : }
1019 :
1020 42 : void SfxObjectShell::SetQueryLoadTemplate( sal_Bool bNew )
1021 : {
1022 42 : if ( pImp->bQueryLoadTemplate != bNew )
1023 2 : SetModified( sal_True );
1024 42 : pImp->bQueryLoadTemplate = bNew;
1025 42 : }
1026 :
1027 42 : void SfxObjectShell::SetUseUserData( sal_Bool bNew )
1028 : {
1029 42 : if ( pImp->bUseUserData != bNew )
1030 2 : SetModified( sal_True );
1031 42 : pImp->bUseUserData = bNew;
1032 42 : }
1033 :
1034 531 : sal_Bool SfxObjectShell::IsLoadReadonly() const
1035 : {
1036 531 : return pImp->bLoadReadonly;
1037 : }
1038 :
1039 6 : sal_Bool SfxObjectShell::IsSaveVersionOnClose() const
1040 : {
1041 6 : return pImp->bSaveVersionOnClose;
1042 : }
1043 :
1044 42 : void SfxObjectShell::SetLoadReadonly( sal_Bool bNew )
1045 : {
1046 42 : if ( pImp->bLoadReadonly != bNew )
1047 0 : SetModified( sal_True );
1048 42 : pImp->bLoadReadonly = bNew;
1049 42 : }
1050 :
1051 42 : void SfxObjectShell::SetSaveVersionOnClose( sal_Bool bNew )
1052 : {
1053 42 : if ( pImp->bSaveVersionOnClose != bNew )
1054 0 : SetModified( sal_True );
1055 42 : pImp->bSaveVersionOnClose = bNew;
1056 42 : }
1057 :
1058 396 : sal_uInt32 SfxObjectShell::GetModifyPasswordHash() const
1059 : {
1060 396 : return pImp->m_nModifyPasswordHash;
1061 : }
1062 :
1063 141 : sal_Bool SfxObjectShell::SetModifyPasswordHash( sal_uInt32 nHash )
1064 : {
1065 141 : if ( ( !IsReadOnly() && !IsReadOnlyUI() )
1066 0 : || !(pImp->nFlagsInProgress & SFX_LOADED_MAINDOCUMENT ) )
1067 : {
1068 : // the hash can be changed only in editable documents,
1069 : // or during loading of document
1070 141 : pImp->m_nModifyPasswordHash = nHash;
1071 141 : return sal_True;
1072 : }
1073 :
1074 0 : return sal_False;
1075 : }
1076 :
1077 398 : uno::Sequence< beans::PropertyValue > SfxObjectShell::GetModifyPasswordInfo() const
1078 : {
1079 398 : return pImp->m_aModifyPasswordInfo;
1080 : }
1081 :
1082 110 : sal_Bool SfxObjectShell::SetModifyPasswordInfo( const uno::Sequence< beans::PropertyValue >& aInfo )
1083 : {
1084 110 : if ( ( !IsReadOnly() && !IsReadOnlyUI() )
1085 0 : || !(pImp->nFlagsInProgress & SFX_LOADED_MAINDOCUMENT ) )
1086 : {
1087 : // the hash can be changed only in editable documents,
1088 : // or during loading of document
1089 110 : pImp->m_aModifyPasswordInfo = aInfo;
1090 110 : return sal_True;
1091 : }
1092 :
1093 0 : return sal_False;
1094 : }
1095 :
1096 0 : void SfxObjectShell::SetModifyPasswordEntered( sal_Bool bEntered )
1097 : {
1098 0 : pImp->m_bModifyPasswordEntered = bEntered;
1099 0 : }
1100 :
1101 1 : sal_Bool SfxObjectShell::IsModifyPasswordEntered()
1102 : {
1103 1 : return pImp->m_bModifyPasswordEntered;
1104 66 : }
1105 :
1106 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|