Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / doc / objcont.cxx
blob398cf85808f354de568fa0f25c9fe6e0159f443c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <com/sun/star/uno/Reference.hxx>
32 #include <com/sun/star/document/XDocumentProperties.hpp>
33 #include <com/sun/star/document/UpdateDocMode.hpp>
34 #include <com/sun/star/frame/XLayoutManager.hpp>
35 #include <com/sun/star/embed/ElementModes.hpp>
36 #include <com/sun/star/document/XStandaloneDocumentInfo.hpp>
37 #include <com/sun/star/beans/XFastPropertySet.hpp>
38 #include <vcl/msgbox.hxx>
39 #include <svl/style.hxx>
40 #include <vcl/wrkwin.hxx>
42 #include <svl/stritem.hxx>
43 #include <svl/intitem.hxx>
44 #include <svl/rectitem.hxx>
45 #include <svl/eitem.hxx>
46 #include <svl/urihelper.hxx>
47 #include <svl/ctloptions.hxx>
48 #include <comphelper/storagehelper.hxx>
49 #include <comphelper/processfactory.hxx>
50 #include <unotools/securityoptions.hxx>
51 #include <svtools/sfxecode.hxx>
52 #include <svtools/ehdl.hxx>
53 #include <tools/datetime.hxx>
54 #include <rtl/logfile.hxx>
55 #include <math.h>
57 #include <unotools/saveopt.hxx>
58 #include <unotools/useroptions.hxx>
59 #include <unotools/localfilehelper.hxx>
60 #include <vcl/virdev.hxx>
61 #include <vcl/oldprintadaptor.hxx>
63 #include <sfx2/app.hxx>
64 #include "sfx2/sfxresid.hxx"
65 #include "appdata.hxx"
66 #include <sfx2/dinfdlg.hxx>
67 #include "fltfnc.hxx"
68 #include <sfx2/docfac.hxx>
69 #include <sfx2/viewsh.hxx>
70 #include <sfx2/objsh.hxx>
71 #include "objshimp.hxx"
72 #include <sfx2/evntconf.hxx>
73 #include "sfx2/sfxhelp.hxx"
74 #include <sfx2/dispatch.hxx>
75 #include <sfx2/printer.hxx>
76 #include "sfx2/basmgr.hxx"
77 #include <sfx2/viewfrm.hxx>
78 #include <sfx2/doctempl.hxx>
79 #include "doc.hrc"
80 #include <sfx2/sfxbasemodel.hxx>
81 #include <sfx2/docfile.hxx>
82 #include <sfx2/request.hxx>
83 #include "openflag.hxx"
84 #include "querytemplate.hxx"
86 using namespace ::com::sun::star;
87 using namespace ::com::sun::star::uno;
89 //====================================================================
91 static
92 bool operator> (const util::DateTime& i_rLeft, const util::DateTime& i_rRight)
94 if ( i_rLeft.Year != i_rRight.Year )
95 return i_rLeft.Year > i_rRight.Year;
97 if ( i_rLeft.Month != i_rRight.Month )
98 return i_rLeft.Month > i_rRight.Month;
100 if ( i_rLeft.Day != i_rRight.Day )
101 return i_rLeft.Day > i_rRight.Day;
103 if ( i_rLeft.Hours != i_rRight.Hours )
104 return i_rLeft.Hours > i_rRight.Hours;
106 if ( i_rLeft.Minutes != i_rRight.Minutes )
107 return i_rLeft.Minutes > i_rRight.Minutes;
109 if ( i_rLeft.Seconds != i_rRight.Seconds )
110 return i_rLeft.Seconds > i_rRight.Seconds;
112 if ( i_rLeft.HundredthSeconds != i_rRight.HundredthSeconds )
113 return i_rLeft.HundredthSeconds > i_rRight.HundredthSeconds;
115 return sal_False;
118 ::boost::shared_ptr<GDIMetaFile>
119 SfxObjectShell::GetPreviewMetaFile( sal_Bool bFullContent ) const
121 return CreatePreviewMetaFile_Impl( bFullContent );
124 ::boost::shared_ptr<GDIMetaFile>
125 SfxObjectShell::CreatePreviewMetaFile_Impl( sal_Bool bFullContent ) const
127 // DoDraw can only be called when no printing is done, otherwise
128 // the printer may be turned off
129 SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
130 if ( pFrame && pFrame->GetViewShell() &&
131 pFrame->GetViewShell()->GetPrinter() &&
132 pFrame->GetViewShell()->GetPrinter()->IsPrinting() )
133 return ::boost::shared_ptr<GDIMetaFile>();
135 ::boost::shared_ptr<GDIMetaFile> pFile(new GDIMetaFile);
137 VirtualDevice aDevice;
138 aDevice.EnableOutput( sal_False );
140 MapMode aMode( ((SfxObjectShell*)this)->GetMapUnit() );
141 aDevice.SetMapMode( aMode );
142 pFile->SetPrefMapMode( aMode );
144 Size aTmpSize;
145 sal_Int8 nAspect;
146 if ( bFullContent )
148 nAspect = ASPECT_CONTENT;
149 aTmpSize = GetVisArea( nAspect ).GetSize();
151 else
153 nAspect = ASPECT_THUMBNAIL;
154 aTmpSize = ((SfxObjectShell*)this)->GetFirstPageSize();
157 pFile->SetPrefSize( aTmpSize );
158 DBG_ASSERT( aTmpSize.Height()*aTmpSize.Width(),
159 "size of first page is 0, overload GetFirstPageSize or set vis-area!" );
161 pFile->Record( &aDevice );
163 LanguageType eLang;
164 SvtCTLOptions aCTLOptions;
165 if ( SvtCTLOptions::NUMERALS_HINDI == aCTLOptions.GetCTLTextNumerals() )
166 eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
167 else if ( SvtCTLOptions::NUMERALS_ARABIC == aCTLOptions.GetCTLTextNumerals() )
168 eLang = LANGUAGE_ENGLISH;
169 else
170 eLang = (LanguageType) Application::GetSettings().GetLanguage();
172 aDevice.SetDigitLanguage( eLang );
175 RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "PERFORMANCE SfxObjectShell::CreatePreviewMetaFile_Impl" );
176 ((SfxObjectShell*)this)->DoDraw( &aDevice, Point(0,0), aTmpSize, JobSetup(), nAspect );
178 pFile->Stop();
180 return pFile;
183 //====================================================================
185 void SfxObjectShell::UpdateDocInfoForSave()
187 uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());
189 // clear user data if recommend (see 'Tools - Options - Open/StarOffice - Security')
190 if ( SvtSecurityOptions().IsOptionSet(
191 SvtSecurityOptions::E_DOCWARN_REMOVEPERSONALINFO ) )
193 xDocProps->resetUserData( ::rtl::OUString() );
195 else if ( IsModified() )
197 String aUserName = SvtUserOptions().GetFullName();
198 if ( !IsUseUserData() )
200 // remove all data pointing to the current user
201 if (xDocProps->getAuthor().equals(aUserName)) {
202 xDocProps->setAuthor( ::rtl::OUString() );
204 xDocProps->setModifiedBy( ::rtl::OUString() );
205 if (xDocProps->getPrintedBy().equals(aUserName)) {
206 xDocProps->setPrintedBy( ::rtl::OUString() );
209 else
211 // update ModificationAuthor, revision and editing time
212 ::DateTime now( ::DateTime::SYSTEM );
213 xDocProps->setModificationDate( util::DateTime(
214 now.Get100Sec(), now.GetSec(), now.GetMin(),
215 now.GetHour(), now.GetDay(), now.GetMonth(),
216 now.GetYear() ) );
217 xDocProps->setModifiedBy( aUserName );
218 if ( !HasName() || pImp->bIsSaving )
219 // QUESTION: not in case of "real" SaveAs as this is meant to create a new document
220 UpdateTime_Impl( xDocProps );
225 //--------------------------------------------------------------------
227 static void
228 lcl_add(util::Duration & rDur, Time const& rTime)
230 // here we don't care about overflow: rDur is converted back to seconds
231 // anyway, and Time cannot store more than ~4000 hours
232 rDur.Hours += rTime.GetHour();
233 rDur.Minutes += rTime.GetMin();
234 rDur.Seconds += rTime.GetSec();
237 // Update the processing time
238 void SfxObjectShell::UpdateTime_Impl(
239 const uno::Reference<document::XDocumentProperties> & i_xDocProps)
241 // Get old time from documentinfo
242 const sal_Int32 secs = i_xDocProps->getEditingDuration();
243 util::Duration editDuration(sal_False, 0, 0, 0,
244 secs/3600, (secs%3600)/60, secs%60, 0);
246 // Initialize some local member! Its neccessary for wollow operations!
247 DateTime aNow( DateTime::SYSTEM ); // Date and time at current moment
248 Time n24Time (24,0,0,0) ; // Time-value for 24 hours - see follow calculation
249 sal_uIntPtr nDays = 0 ; // Count of days between now and last editing
250 Time nAddTime (0) ; // Value to add on aOldTime
252 // Safe impossible cases!
253 // User has changed time to the past between last editing and now ... its not possible!!!
254 DBG_ASSERT( !(aNow.GetDate()<pImp->nTime.GetDate()), "Timestamp of last change is in the past ?!..." );
256 // Do the follow only, if user has NOT changed time to the past.
257 // Else add a time of 0 to aOldTime ... !!!
258 if (aNow.GetDate()>=pImp->nTime.GetDate())
260 // Get count of days last editing.
261 nDays = aNow.GetSecFromDateTime(pImp->nTime.GetDate())/86400 ;
263 if (nDays==0)
265 // If no day between now and last editing - calculate time directly.
266 nAddTime = (const Time&)aNow - (const Time&)pImp->nTime ;
268 else
269 // If time of working without save greater then 1 month (!) ....
270 // we add 0 to aOldTime!
271 if (nDays<=31)
273 // If 1 or up to 31 days between now and last editing - calculate time indirectly.
274 // nAddTime = (24h - nTime) + (nDays * 24h) + aNow
275 --nDays;
276 nAddTime = nDays*n24Time.GetTime() ;
277 nAddTime += n24Time-(const Time&)pImp->nTime ;
278 nAddTime += aNow ;
281 lcl_add(editDuration, nAddTime);
284 pImp->nTime = aNow;
285 try {
286 const sal_Int32 newSecs( (editDuration.Hours*3600)
287 + (editDuration.Minutes*60) + editDuration.Seconds);
288 i_xDocProps->setEditingDuration(newSecs);
289 i_xDocProps->setEditingCycles(i_xDocProps->getEditingCycles() + 1);
291 catch (const lang::IllegalArgumentException &)
293 // ignore overflow
297 //--------------------------------------------------------------------
299 SfxDocumentInfoDialog* SfxObjectShell::CreateDocumentInfoDialog
301 Window* pParent,
302 const SfxItemSet& rSet
305 return new SfxDocumentInfoDialog(pParent, rSet);
308 //--------------------------------------------------------------------
310 SfxStyleSheetBasePool* SfxObjectShell::GetStyleSheetPool()
312 return 0;
315 void SfxObjectShell::SetOrganizerSearchMask(
316 SfxStyleSheetBasePool* pStylePool) const
318 pStylePool->SetSearchMask(
319 SFX_STYLE_FAMILY_ALL,
320 SFXSTYLEBIT_USERDEF | SFXSTYLEBIT_USED);
323 //--------------------------------------------------------------------
325 sal_uInt16 SfxObjectShell::GetContentCount(sal_uInt16 nIdx)
327 switch(nIdx)
329 case INDEX_IGNORE:
330 return DEF_CONTENT_COUNT;
331 case CONTENT_STYLE:
333 SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
334 if(!pStylePool)
335 return 0;
336 SetOrganizerSearchMask(pStylePool);
337 return pStylePool->Count();
339 case CONTENT_MACRO:
340 break;
342 return 0;
346 //--------------------------------------------------------------------
347 //TODO/CLEANUP: remove this method
348 void SfxObjectShell::TriggerHelpPI(sal_uInt16 nIdx1, sal_uInt16 nIdx2)
350 if(nIdx1==CONTENT_STYLE && nIdx2 != INDEX_IGNORE) //StyleSheets
352 SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
353 SetOrganizerSearchMask(pStylePool);
357 sal_Bool SfxObjectShell::CanHaveChildren(sal_uInt16 nIdx1, sal_uInt16 nIdx2)
359 switch(nIdx1)
361 case INDEX_IGNORE:
362 return true;
363 case CONTENT_STYLE:
364 return INDEX_IGNORE == nIdx2 || !GetStyleSheetPool() ? false : true;
365 case CONTENT_MACRO:
366 return false;
368 return false;
371 //--------------------------------------------------------------------
373 void SfxObjectShell::GetContent(String &rText,
374 Bitmap &rClosedBitmap,
375 Bitmap &rOpenedBitmap,
376 sal_Bool &bCanDel,
377 sal_uInt16 i,
378 sal_uInt16 nIdx
381 bCanDel=true;
383 switch(nIdx)
385 case INDEX_IGNORE:
387 sal_uInt16 nTextResId = 0;
388 sal_uInt16 nClosedBitmapResId = 0; // evtl. sp"ater mal unterschiedliche
389 sal_uInt16 nOpenedBitmapResId = 0; // " " " "
390 switch(i)
392 case CONTENT_STYLE:
393 nTextResId = STR_STYLES;
394 nClosedBitmapResId= BMP_STYLES_CLOSED;
395 nOpenedBitmapResId= BMP_STYLES_OPENED;
396 break;
397 case CONTENT_MACRO:
398 nTextResId = STR_MACROS;
399 nClosedBitmapResId= BMP_STYLES_CLOSED;
400 nOpenedBitmapResId= BMP_STYLES_OPENED;
401 break;
404 if ( nTextResId )
406 rText = String(SfxResId(nTextResId));
407 rClosedBitmap = Bitmap(SfxResId(nClosedBitmapResId));
408 rOpenedBitmap = Bitmap(SfxResId(nOpenedBitmapResId));
410 break;
413 case CONTENT_STYLE:
415 SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
416 SetOrganizerSearchMask(pStylePool);
417 SfxStyleSheetBase *pStyle = (*pStylePool)[i];
418 rText = pStyle->GetName();
419 bCanDel=((pStyle->GetMask() & SFXSTYLEBIT_USERDEF)
420 == SFXSTYLEBIT_USERDEF);
421 rClosedBitmap = rOpenedBitmap =
422 GetStyleFamilyBitmap(pStyle->GetFamily());
424 break;
425 case CONTENT_MACRO:
426 break;
430 //--------------------------------------------------------------------
432 Bitmap SfxObjectShell::GetStyleFamilyBitmap(SfxStyleFamily eFamily)
434 sal_uInt16 nResId = 0;
435 switch(eFamily)
437 case SFX_STYLE_FAMILY_CHAR:
438 nResId = BMP_STYLES_FAMILY1;
439 break;
440 case SFX_STYLE_FAMILY_PARA:
441 nResId = BMP_STYLES_FAMILY2;
442 break;
443 case SFX_STYLE_FAMILY_FRAME:
444 nResId = BMP_STYLES_FAMILY3;
445 break;
446 case SFX_STYLE_FAMILY_PAGE :
447 nResId = BMP_STYLES_FAMILY4;
448 break;
449 case SFX_STYLE_FAMILY_PSEUDO:
450 case SFX_STYLE_FAMILY_ALL:
451 break;
454 if ( nResId )
455 return Bitmap(SfxResId(nResId));
456 else
457 return Bitmap();
461 //--------------------------------------------------------------------
463 sal_Bool SfxObjectShell::Insert(SfxObjectShell &rSource,
464 sal_uInt16 nSourceIdx1,
465 sal_uInt16 nSourceIdx2,
466 sal_uInt16 /*nSourceIdx3*/,
467 sal_uInt16 &nIdx1,
468 sal_uInt16 &nIdx2,
469 sal_uInt16 &/*nIdx3*/,
470 sal_uInt16 &/*nDeleted*/)
472 sal_Bool bRet = sal_False;
474 if (INDEX_IGNORE == nIdx1 && CONTENT_STYLE == nSourceIdx1)
475 nIdx1 = CONTENT_STYLE;
477 if (CONTENT_STYLE == nSourceIdx1 && CONTENT_STYLE == nIdx1)
479 SfxStyleSheetBasePool* pHisPool = rSource.GetStyleSheetPool();
480 SfxStyleSheetBasePool* pMyPool = GetStyleSheetPool();
481 SetOrganizerSearchMask(pHisPool);
482 SetOrganizerSearchMask(pMyPool);
483 SfxStyleSheetBase* pHisSheet = NULL;
485 if ( pHisPool && pHisPool->Count() > nSourceIdx2 )
486 pHisSheet = (*pHisPool)[nSourceIdx2];
488 // Pasting is only needed if a style sheet is moved between
489 // different (!) Pools
491 if ( pHisSheet && pMyPool != pHisPool )
493 if (INDEX_IGNORE == nIdx2)
495 nIdx2 = pMyPool->Count();
498 // if such a template already exists: delete!
499 String aOldName(pHisSheet->GetName());
500 SfxStyleFamily eOldFamily = pHisSheet->GetFamily();
502 SfxStyleSheetBase* pExist = pMyPool->Find(aOldName, eOldFamily);
503 sal_Bool bUsedOrUserDefined;
504 if( pExist )
506 bUsedOrUserDefined =
507 pExist->IsUsed() || pExist->IsUserDefined();
508 if( ErrorHandler::HandleError(
509 *new MessageInfo( ERRCODE_SFXMSG_STYLEREPLACE, aOldName ) )
510 != ERRCODE_BUTTON_OK )
511 return sal_False;
512 else
514 pMyPool->Replace( *pHisSheet, *pExist );
515 SetModified( sal_True );
516 nIdx2 = nIdx1 = INDEX_IGNORE;
517 return sal_True;
521 SfxStyleSheetBase& rNewSheet = pMyPool->Make(
522 aOldName, eOldFamily,
523 pHisSheet->GetMask(), nIdx2);
525 // Fill the Itemset of the new template
526 rNewSheet.GetItemSet().Set(pHisSheet->GetItemSet());
528 // Who gets the new one as a Parent?
529 // Who is using the new one as Follow?
530 SfxStyleSheetBase* pTestSheet = pMyPool->First();
531 while (pTestSheet)
533 if (pTestSheet->GetFamily() == eOldFamily &&
534 pTestSheet->HasParentSupport() &&
535 pTestSheet->GetParent() == aOldName)
537 pTestSheet->SetParent(aOldName);
538 // Rebuild Link
541 if (pTestSheet->GetFamily() == eOldFamily &&
542 pTestSheet->HasFollowSupport() &&
543 pTestSheet->GetFollow() == aOldName)
545 pTestSheet->SetFollow(aOldName);
546 // Rebuild Link
549 pTestSheet = pMyPool->Next();
551 bUsedOrUserDefined =
552 rNewSheet.IsUsed() || rNewSheet.IsUserDefined();
555 // has a New Parent? if so, start search with the same name
556 if (pHisSheet->HasParentSupport())
558 const String& rParentName = pHisSheet->GetParent();
559 if (0 != rParentName.Len())
561 SfxStyleSheetBase* pParentOfNew =
562 pMyPool->Find(rParentName, eOldFamily);
563 if (pParentOfNew)
564 rNewSheet.SetParent(rParentName);
568 // Has the new got a Follow? if so start search
569 // with the same name.
570 if (pHisSheet->HasFollowSupport())
572 const String& rFollowName = pHisSheet->GetFollow();
573 if (0 != rFollowName.Len())
575 SfxStyleSheetBase* pFollowOfNew =
576 pMyPool->Find(rFollowName, eOldFamily);
577 if (pFollowOfNew)
578 rNewSheet.SetFollow(rFollowName);
582 SetModified( sal_True );
583 if( !bUsedOrUserDefined ) nIdx2 = nIdx1 = INDEX_IGNORE;
585 bRet = sal_True;
587 else
588 bRet = sal_False;
591 return bRet;
594 //--------------------------------------------------------------------
596 sal_Bool SfxObjectShell::Remove
598 sal_uInt16 nIdx1,
599 sal_uInt16 nIdx2,
600 sal_uInt16 /*nIdx3*/
603 sal_Bool bRet = sal_False;
605 if (CONTENT_STYLE == nIdx1)
607 SfxStyleSheetBasePool* pMyPool = GetStyleSheetPool();
609 SetOrganizerSearchMask(pMyPool);
611 SfxStyleSheetBase* pMySheet = (*pMyPool)[nIdx2];
612 String aName(pMySheet->GetName());
613 String aEmpty;
614 SfxStyleFamily eFamily = pMySheet->GetFamily();
615 pMyPool->Remove(pMySheet);
616 bRet = sal_True;
618 SfxStyleSheetBase* pTestSheet = pMyPool->First();
619 while (pTestSheet)
621 if (pTestSheet->GetFamily() == eFamily &&
622 pTestSheet->HasParentSupport() &&
623 pTestSheet->GetParent() == aName)
625 pTestSheet->SetParent(aEmpty); // Remove link
628 if (pTestSheet->GetFamily() == eFamily &&
629 pTestSheet->HasFollowSupport() &&
630 pTestSheet->GetFollow() == aName)
632 pTestSheet->SetFollow(aEmpty); // Remove link
635 pTestSheet = pMyPool->Next();
638 SetModified( sal_True );
641 return bRet;
644 //--------------------------------------------------------------------
646 sal_Bool SfxObjectShell::Print
648 Printer& rPrt,
649 sal_uInt16 nIdx1,
650 sal_uInt16 /*nIdx2*/,
651 sal_uInt16 /*nIdx3*/,
652 const String* pObjectName
655 switch(nIdx1)
657 case CONTENT_STYLE:
659 SfxStyleSheetBasePool *pStylePool = GetStyleSheetPool();
660 SetOrganizerSearchMask(pStylePool);
661 SfxStyleSheetIterator* pIter = pStylePool->CreateIterator(
662 pStylePool->GetSearchFamily(), pStylePool->GetSearchMask() );
663 SfxStyleSheetBase *pStyle = pIter->First();
664 if ( !pStyle )
665 return sal_True;
667 // prepare adaptor for old style StartPage/EndPage printing
668 boost::shared_ptr< Printer > pPrinter( new Printer( rPrt.GetJobSetup() ) );
669 vcl::OldStylePrintAdaptor* pAdaptor = new vcl::OldStylePrintAdaptor( pPrinter );
670 boost::shared_ptr< vcl::PrinterController > pController( pAdaptor );
672 pAdaptor->StartPage();
674 pPrinter->SetMapMode(MapMode(MAP_10TH_MM));
675 Font aFont( DEFINE_CONST_UNICODE( "Arial" ), Size(0, 64)); // 18pt
676 aFont.SetWeight(WEIGHT_BOLD);
677 pPrinter->SetFont(aFont);
678 const Size aPageSize(pPrinter->GetOutputSize());
679 const sal_uInt16 nXIndent = 200;
680 sal_uInt16 nYIndent = 200;
681 Point aOutPos(nXIndent, nYIndent);
682 String aHeader(SfxResId(STR_PRINT_STYLES_HEADER));
683 if ( pObjectName )
684 aHeader += *pObjectName;
685 else
686 aHeader += GetTitle();
687 long nTextHeight( pPrinter->GetTextHeight() );
688 pPrinter->DrawText(aOutPos, aHeader);
689 aOutPos.Y() += nTextHeight;
690 aOutPos.Y() += nTextHeight/2;
691 aFont.SetSize(Size(0, 35)); // 10pt
692 while(pStyle)
694 // print template name
695 String aStr(pStyle->GetName());
696 aFont.SetWeight(WEIGHT_BOLD);
697 pPrinter->SetFont(aFont);
698 nTextHeight = pPrinter->GetTextHeight();
699 // check for new page
700 if ( aOutPos.Y() + nTextHeight*2 >
701 aPageSize.Height() - (long) nYIndent )
703 pAdaptor->EndPage();
704 pAdaptor->StartPage();
705 aOutPos.Y() = nYIndent;
707 pPrinter->DrawText(aOutPos, aStr);
708 aOutPos.Y() += nTextHeight;
710 // print template description
711 aFont.SetWeight(WEIGHT_NORMAL);
712 pPrinter->SetFont(aFont);
713 aStr = pStyle->GetDescription();
714 const char cDelim = ' ';
715 sal_uInt16 nStart = 0, nIdx = 0;
717 nTextHeight = pPrinter->GetTextHeight();
718 // break text into lines
719 while(nIdx < aStr.Len())
721 sal_uInt16 nOld = nIdx;
722 long nTextWidth;
723 nIdx = aStr.Search(cDelim, nStart);
724 nTextWidth = pPrinter->GetTextWidth(aStr, nStart, nIdx-nStart);
725 while(nIdx != STRING_NOTFOUND &&
726 aOutPos.X() + nTextWidth <
727 aPageSize.Width() - (long) nXIndent)
729 nOld = nIdx;
730 nIdx = aStr.Search(cDelim, nIdx+1);
731 nTextWidth = pPrinter->GetTextWidth(aStr, nStart, nIdx-nStart);
733 String aTmp(aStr, nStart, nIdx == STRING_NOTFOUND?
734 STRING_LEN :
735 nOld-nStart);
736 if ( aTmp.Len() )
738 nStart = nOld+1; // trailing space
740 else
742 sal_uInt16 nChar = 1;
743 while(
744 nStart + nChar < aStr.Len() &&
745 aOutPos.X() + pPrinter->GetTextWidth(
746 aStr, nStart, nChar) <
747 aPageSize.Width() - nXIndent)
748 ++nChar;
749 aTmp = String(aStr, nStart, nChar-1);
750 nIdx = nStart + nChar;
751 nStart = nIdx;
753 if ( aOutPos.Y() + nTextHeight*2 >
754 aPageSize.Height() - nYIndent )
756 pAdaptor->EndPage();
757 pAdaptor->StartPage();
758 aOutPos.Y() = nYIndent;
760 pPrinter->DrawText(aOutPos, aTmp);
761 aOutPos.Y() += pPrinter->GetTextHeight();
763 pStyle = pIter->Next();
765 pAdaptor->EndPage();
767 Printer::PrintJob( pController, rPrt.GetJobSetup() );
769 delete pIter;
770 break;
772 default:
773 return sal_False;
775 return sal_True;
778 //--------------------------------------------------------------------
780 void SfxObjectShell::LoadStyles
782 SfxObjectShell &rSource /* the document template from which
783 the styles are to be loaded */
786 /* [Description]
788 This method is called by the SFx if template styles are to be loaded.
789 Existing styles are in this case overwritten. The document has then to be
790 newly formatted. Therefore, the application of this method is usually
791 overloaded and its implementation is calling the implementation in
792 the base class.
796 struct Styles_Impl
798 SfxStyleSheetBase *pSource;
799 SfxStyleSheetBase *pDest;
802 SfxStyleSheetBasePool *pSourcePool = rSource.GetStyleSheetPool();
803 DBG_ASSERT(pSourcePool, "Source-DocumentShell ohne StyleSheetPool");
804 SfxStyleSheetBasePool *pMyPool = GetStyleSheetPool();
805 DBG_ASSERT(pMyPool, "Dest-DocumentShell ohne StyleSheetPool");
806 pSourcePool->SetSearchMask(SFX_STYLE_FAMILY_ALL, 0xffff);
807 Styles_Impl *pFound = new Styles_Impl[pSourcePool->Count()];
808 sal_uInt16 nFound = 0;
810 SfxStyleSheetBase *pSource = pSourcePool->First();
811 while ( pSource )
813 SfxStyleSheetBase *pDest =
814 pMyPool->Find( pSource->GetName(), pSource->GetFamily() );
815 if ( !pDest )
817 pDest = &pMyPool->Make( pSource->GetName(),
818 pSource->GetFamily(), pSource->GetMask());
819 // Setting of Parents, the next style
821 pFound[nFound].pSource = pSource;
822 pFound[nFound].pDest = pDest;
823 ++nFound;
824 pSource = pSourcePool->Next();
827 for ( sal_uInt16 i = 0; i < nFound; ++i )
829 pFound[i].pDest->GetItemSet().PutExtended(pFound[i].pSource->GetItemSet(), SFX_ITEM_DONTCARE, SFX_ITEM_DEFAULT);
830 if(pFound[i].pSource->HasParentSupport())
831 pFound[i].pDest->SetParent(pFound[i].pSource->GetParent());
832 if(pFound[i].pSource->HasFollowSupport())
833 pFound[i].pDest->SetFollow(pFound[i].pSource->GetParent());
835 delete [] pFound;
838 //--------------------------------------------------------------------
840 void SfxObjectShell::UpdateFromTemplate_Impl( )
842 /* [Description]
844 This internal method checks whether the document was created from a
845 template, and if this is newer than the document. If this is the case,
846 the user is asked if the Templates (StyleSheets) should be updated.
847 If this is answered positively, the StyleSheets are updated.
851 // Storage-medium?
852 SfxMedium *pFile = GetMedium();
853 DBG_ASSERT( pFile, "cannot UpdateFromTemplate without medium" );
854 if ( !pFile )
855 return;
857 if ( !::utl::LocalFileHelper::IsLocalFile( pFile->GetName() ) )
858 // update only for documents loaded from the local file system
859 return;
861 // only for own storage formats
862 uno::Reference< embed::XStorage > xDocStor = pFile->GetStorage();
863 if ( !pFile->GetFilter() || !pFile->GetFilter()->IsOwnFormat() )
864 return;
866 SFX_ITEMSET_ARG( pFile->GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
867 sal_Int16 bCanUpdateFromTemplate = pUpdateDocItem ? pUpdateDocItem->GetValue() : document::UpdateDocMode::NO_UPDATE;
869 // created from template?
870 uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());
871 ::rtl::OUString aTemplName( xDocProps->getTemplateName() );
872 ::rtl::OUString aTemplURL( xDocProps->getTemplateURL() );
873 String aFoundName;
875 if ( !aTemplName.isEmpty() || (!aTemplURL.isEmpty() && !IsReadOnly()) )
877 // try to locate template, first using filename this must be done
878 // because writer global document uses this "great" idea to manage
879 // the templates of all parts in the master document but it is NOT
880 // an error if the template filename points not to a valid file
881 SfxDocumentTemplates aTempl;
882 aTempl.Construct();
883 if ( !aTemplURL.isEmpty() )
885 String aURL;
886 if( ::utl::LocalFileHelper::ConvertSystemPathToURL( aTemplURL, GetMedium()->GetName(), aURL ) )
887 aFoundName = aURL;
890 if( !aFoundName.Len() && !aTemplName.isEmpty() )
891 // if the template filename did not lead to success,
892 // try to get a file name for the logical template name
893 aTempl.GetFull( String(), aTemplName, aFoundName );
896 if ( aFoundName.Len() )
898 // check existence of template storage
899 aTemplURL = aFoundName;
900 sal_Bool bLoad = sal_False;
902 // should the document checked against changes in the template ?
903 if ( IsQueryLoadTemplate() )
905 // load document info of template
906 sal_Bool bOK = sal_False;
907 util::DateTime aTemplDate;
910 Reference < document::XStandaloneDocumentInfo > xDocInfo (
911 ::comphelper::getProcessServiceFactory()->createInstance(
912 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
913 "com.sun.star.document.StandaloneDocumentInfo") ) ),
914 UNO_QUERY_THROW );
915 Reference < beans::XFastPropertySet > xSet( xDocInfo,
916 UNO_QUERY_THROW );
917 xDocInfo->loadFromURL( aTemplURL );
918 Any aAny = xSet->getFastPropertyValue( WID_DATE_MODIFIED );
919 ::com::sun::star::util::DateTime aTmp;
920 if ( aAny >>= aTemplDate )
922 // get modify date from document info
923 bOK = sal_True;
926 catch (const Exception&)
930 // if modify date was read successfully
931 if ( bOK )
933 // compare modify data of template with the last check date of the document
934 const util::DateTime aInfoDate( xDocProps->getTemplateDate() );
935 if ( aTemplDate > aInfoDate )
937 // ask user
938 if( bCanUpdateFromTemplate == document::UpdateDocMode::QUIET_UPDATE
939 || bCanUpdateFromTemplate == document::UpdateDocMode::FULL_UPDATE )
940 bLoad = sal_True;
941 else if ( bCanUpdateFromTemplate == document::UpdateDocMode::ACCORDING_TO_CONFIG )
943 String sMessage( SfxResId( STR_QRYTEMPL_MESSAGE ) );
944 sMessage.SearchAndReplace( String::CreateFromAscii("$(ARG1)"), aTemplName );
945 sfx2::QueryTemplateBox aBox( GetDialogParent(), sMessage );
946 if ( RET_YES == aBox.Execute() )
947 bLoad = sal_True;
950 if( !bLoad )
952 // user refuses, so don't ask again for this document
953 SetQueryLoadTemplate(sal_False);
954 SetModified( sal_True );
959 if ( bLoad )
961 // styles should be updated, create document in organizer mode to read in the styles
962 //TODO: testen!
963 SfxObjectShellLock xTemplDoc = CreateObjectByFactoryName( GetFactory().GetFactoryName(), SFX_CREATE_MODE_ORGANIZER );
964 xTemplDoc->DoInitNew(0);
966 // TODO/MBA: do we need a BaseURL? Then LoadFrom must be extended!
967 //xTemplDoc->SetBaseURL( aFoundName );
969 // TODO/LATER: make sure that we don't use binary templates!
970 SfxMedium aMedium( aFoundName, STREAM_STD_READ );
971 if ( xTemplDoc->LoadFrom( aMedium ) )
973 // transfer styles from xTemplDoc to this document
974 // TODO/MBA: make sure that no BaseURL is needed in *this* document
975 LoadStyles(*xTemplDoc);
977 // remember date/time of check
978 xDocProps->setTemplateDate(aTemplDate);
979 // TODO/LATER: new functionality to store document info is required ( didn't work for SO7 XML format )
986 sal_Bool SfxObjectShell::IsHelpDocument() const
988 const SfxFilter* pFilter = GetMedium()->GetFilter();
989 return ( pFilter && pFilter->GetFilterName().CompareToAscii("writer_web_HTML_help") == COMPARE_EQUAL );
992 void SfxObjectShell::ResetFromTemplate( const String& rTemplateName, const String& rFileName )
994 // only care about reseting this data for openoffice formats otherwise
995 if ( IsOwnStorageFormat_Impl( *GetMedium()) )
997 uno::Reference<document::XDocumentProperties> xDocProps(getDocProperties());
998 xDocProps->setTemplateURL( ::rtl::OUString() );
999 xDocProps->setTemplateName( ::rtl::OUString() );
1000 xDocProps->setTemplateDate( util::DateTime() );
1001 xDocProps->resetUserData( ::rtl::OUString() );
1003 // TODO/REFACTOR:
1004 // Title?
1006 if( ::utl::LocalFileHelper::IsLocalFile( rFileName ) )
1008 String aFoundName;
1009 if( SFX_APP()->Get_Impl()->GetDocumentTemplates()->GetFull( String(), rTemplateName, aFoundName ) )
1011 INetURLObject aObj( rFileName );
1012 xDocProps->setTemplateURL( aObj.GetMainURL(INetURLObject::DECODE_TO_IURI) );
1013 xDocProps->setTemplateName( rTemplateName );
1015 ::DateTime now( ::DateTime::SYSTEM );
1016 xDocProps->setTemplateDate( util::DateTime(
1017 now.Get100Sec(), now.GetSec(), now.GetMin(),
1018 now.GetHour(), now.GetDay(), now.GetMonth(),
1019 now.GetYear() ) );
1021 SetQueryLoadTemplate( sal_True );
1027 sal_Bool SfxObjectShell::IsQueryLoadTemplate() const
1029 return pImp->bQueryLoadTemplate;
1032 sal_Bool SfxObjectShell::IsUseUserData() const
1034 return pImp->bUseUserData;
1037 void SfxObjectShell::SetQueryLoadTemplate( sal_Bool bNew )
1039 if ( pImp->bQueryLoadTemplate != bNew )
1040 SetModified( sal_True );
1041 pImp->bQueryLoadTemplate = bNew;
1044 void SfxObjectShell::SetUseUserData( sal_Bool bNew )
1046 if ( pImp->bUseUserData != bNew )
1047 SetModified( sal_True );
1048 pImp->bUseUserData = bNew;
1051 sal_Bool SfxObjectShell::IsLoadReadonly() const
1053 return pImp->bLoadReadonly;
1056 sal_Bool SfxObjectShell::IsSaveVersionOnClose() const
1058 return pImp->bSaveVersionOnClose;
1061 void SfxObjectShell::SetLoadReadonly( sal_Bool bNew )
1063 if ( pImp->bLoadReadonly != bNew )
1064 SetModified( sal_True );
1065 pImp->bLoadReadonly = bNew;
1068 void SfxObjectShell::SetSaveVersionOnClose( sal_Bool bNew )
1070 if ( pImp->bSaveVersionOnClose != bNew )
1071 SetModified( sal_True );
1072 pImp->bSaveVersionOnClose = bNew;
1075 sal_uInt32 SfxObjectShell::GetModifyPasswordHash() const
1077 return pImp->m_nModifyPasswordHash;
1080 sal_Bool SfxObjectShell::SetModifyPasswordHash( sal_uInt32 nHash )
1082 if ( ( !IsReadOnly() && !IsReadOnlyUI() )
1083 || !(pImp->nFlagsInProgress & SFX_LOADED_MAINDOCUMENT ) )
1085 // the hash can be changed only in editable documents,
1086 // or during loading of document
1087 pImp->m_nModifyPasswordHash = nHash;
1088 return sal_True;
1091 return sal_False;
1094 uno::Sequence< beans::PropertyValue > SfxObjectShell::GetModifyPasswordInfo() const
1096 return pImp->m_aModifyPasswordInfo;
1099 sal_Bool SfxObjectShell::SetModifyPasswordInfo( const uno::Sequence< beans::PropertyValue >& aInfo )
1101 if ( ( !IsReadOnly() && !IsReadOnlyUI() )
1102 || !(pImp->nFlagsInProgress & SFX_LOADED_MAINDOCUMENT ) )
1104 // the hash can be changed only in editable documents,
1105 // or during loading of document
1106 pImp->m_aModifyPasswordInfo = aInfo;
1107 return sal_True;
1110 return sal_False;
1113 void SfxObjectShell::SetModifyPasswordEntered( sal_Bool bEntered )
1115 pImp->m_bModifyPasswordEntered = bEntered;
1118 sal_Bool SfxObjectShell::IsModifyPasswordEntered()
1120 return pImp->m_bModifyPasswordEntered;
1123 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */