1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <sfx2/templateabstractview.hxx>
12 #include <comphelper/processfactory.hxx>
13 #include <sfx2/sfxresid.hxx>
14 #include <sfx2/templatecontaineritem.hxx>
15 #include <sfx2/templateviewitem.hxx>
16 #include <tools/urlobj.hxx>
17 #include <unotools/ucbstreamhelper.hxx>
18 #include <vcl/pngread.hxx>
20 #include <com/sun/star/embed/ElementModes.hpp>
21 #include <com/sun/star/embed/XStorage.hpp>
22 #include <com/sun/star/embed/StorageFactory.hpp>
23 #include <com/sun/star/lang/XComponent.hpp>
24 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
25 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
27 #include "../doc/doc.hrc"
28 #include "templateview.hrc"
30 bool ViewFilter_Application::isValid (const OUString
&rPath
) const
34 INetURLObject
aUrl(rPath
);
35 OUString aExt
= aUrl
.getExtension();
36 if (mApp
== FILTER_APP_WRITER
)
38 bRet
= aExt
== "ott" || aExt
== "stw" || aExt
== "oth" || aExt
== "dot" || aExt
== "dotx";
40 else if (mApp
== FILTER_APP_CALC
)
42 bRet
= aExt
== "ots" || aExt
== "stc" || aExt
== "xlt" || aExt
== "xltm" || aExt
== "xltx";
44 else if (mApp
== FILTER_APP_IMPRESS
)
46 bRet
= aExt
== "otp" || aExt
== "sti" || aExt
== "pot" || aExt
== "potm" || aExt
== "potx";
48 else if (mApp
== FILTER_APP_DRAW
)
50 bRet
= aExt
== "otg" || aExt
== "std";
56 bool ViewFilter_Application::operator () (const ThumbnailViewItem
*pItem
)
58 const TemplateViewItem
*pTempItem
= dynamic_cast<const TemplateViewItem
*>(pItem
);
60 return isValid(pTempItem
->getPath());
62 TemplateContainerItem
*pContainerItem
= const_cast<TemplateContainerItem
*>(dynamic_cast<const TemplateContainerItem
*>(pItem
));
65 std::vector
<TemplateItemProperties
> &rTemplates
= pContainerItem
->maTemplates
;
70 pContainerItem
->maPreview1
.Clear();
71 pContainerItem
->maPreview2
.Clear();
72 pContainerItem
->maPreview3
.Clear();
73 pContainerItem
->maPreview4
.Clear();
75 for (size_t i
= 0, n
= rTemplates
.size(); i
< n
&& pContainerItem
->HasMissingPreview(); ++i
)
77 if (isValid(rTemplates
[i
].aPath
))
80 if ( pContainerItem
->maPreview1
.IsEmpty( ) )
82 pContainerItem
->maPreview1
= TemplateAbstractView::scaleImg(rTemplates
[i
].aThumbnail
,
83 TEMPLATE_THUMBNAIL_MAX_WIDTH
*0.75,
84 TEMPLATE_THUMBNAIL_MAX_HEIGHT
*0.75);
86 else if ( pContainerItem
->maPreview2
.IsEmpty() )
88 pContainerItem
->maPreview2
= TemplateAbstractView::scaleImg(rTemplates
[i
].aThumbnail
,
89 TEMPLATE_THUMBNAIL_MAX_WIDTH
*0.75,
90 TEMPLATE_THUMBNAIL_MAX_HEIGHT
*0.75);
92 else if ( pContainerItem
->maPreview3
.IsEmpty() )
94 pContainerItem
->maPreview3
= TemplateAbstractView::scaleImg(rTemplates
[i
].aThumbnail
,
95 TEMPLATE_THUMBNAIL_MAX_WIDTH
*0.75,
96 TEMPLATE_THUMBNAIL_MAX_HEIGHT
*0.75);
98 else if ( pContainerItem
->maPreview4
.IsEmpty() )
100 pContainerItem
->maPreview4
= TemplateAbstractView::scaleImg(rTemplates
[i
].aThumbnail
,
101 TEMPLATE_THUMBNAIL_MAX_WIDTH
*0.75,
102 TEMPLATE_THUMBNAIL_MAX_HEIGHT
*0.75);
110 bool ViewFilter_Keyword::operator ()(const ThumbnailViewItem
*pItem
)
114 return pItem
->maTitle
.matchIgnoreAsciiCase(maKeyword
);
117 TemplateAbstractView::TemplateAbstractView (Window
*pParent
, WinBits nWinStyle
, bool bDisableTransientChildren
)
118 : ThumbnailView(pParent
,nWinStyle
,bDisableTransientChildren
),
120 maAllButton(this, SfxResId(BTN_ALL_TEMPLATES
)),
121 maFTName(this, SfxResId(FT_NAME
))
124 maAllButton
.SetStyle(maAllButton
.GetStyle() | WB_FLATBUTTON
);
125 maAllButton
.SetClickHdl(LINK(this,TemplateAbstractView
,ShowRootRegionHdl
));
129 TemplateAbstractView::TemplateAbstractView(Window
*pParent
, const ResId
&rResId
, bool bDisableTransientChildren
)
130 : ThumbnailView(pParent
,rResId
,bDisableTransientChildren
),
132 maAllButton(this, SfxResId(BTN_ALL_TEMPLATES
)),
133 maFTName(this, SfxResId(FT_NAME
))
136 maAllButton
.SetStyle(maAllButton
.GetStyle() | WB_FLATBUTTON
);
137 maAllButton
.SetClickHdl(LINK(this,TemplateAbstractView
,ShowRootRegionHdl
));
141 TemplateAbstractView::~TemplateAbstractView ()
145 void TemplateAbstractView::insertItem(const TemplateItemProperties
&rTemplate
)
147 const TemplateItemProperties
*pCur
= &rTemplate
;
149 TemplateViewItem
*pChild
= new TemplateViewItem(*this);
150 pChild
->mnId
= pCur
->nId
;
151 pChild
->mnDocId
= pCur
->nDocId
;
152 pChild
->mnRegionId
= pCur
->nRegionId
;
153 pChild
->maTitle
= pCur
->aName
;
154 pChild
->setPath(pCur
->aPath
);
155 pChild
->maPreview1
= pCur
->aThumbnail
;
157 if ( pCur
->aThumbnail
.IsEmpty() )
159 // Use the default thumbnail if we have nothing else
160 pChild
->maPreview1
= TemplateAbstractView::getDefaultThumbnail(pCur
->aPath
);
163 pChild
->setSelectClickHdl(LINK(this,ThumbnailView
,OnItemSelected
));
167 CalculateItemPositions();
171 void TemplateAbstractView::insertItems(const std::vector
<TemplateItemProperties
> &rTemplates
)
173 std::vector
<ThumbnailViewItem
*> aItems(rTemplates
.size());
174 for (size_t i
= 0, n
= rTemplates
.size(); i
< n
; ++i
)
176 //TODO: CHECK IF THE ITEM IS A FOLDER OR NOT
177 TemplateViewItem
*pChild
= new TemplateViewItem(*this);
178 const TemplateItemProperties
*pCur
= &rTemplates
[i
];
180 pChild
->mnId
= pCur
->nId
;
181 pChild
->mnDocId
= pCur
->nDocId
;
182 pChild
->mnRegionId
= pCur
->nRegionId
;
183 pChild
->maTitle
= pCur
->aName
;
184 pChild
->setPath(pCur
->aPath
);
185 pChild
->maPreview1
= pCur
->aThumbnail
;
187 if ( pCur
->aThumbnail
.IsEmpty() )
189 // Use the default thumbnail if we have nothing else
190 pChild
->maPreview1
= TemplateAbstractView::getDefaultThumbnail(pCur
->aPath
);
193 pChild
->setSelectClickHdl(LINK(this,ThumbnailView
,OnItemSelected
));
201 sal_uInt16
TemplateAbstractView::getCurRegionId() const
203 return mnCurRegionId
;
206 const OUString
&TemplateAbstractView::getCurRegionName() const
208 return maCurRegionName
;
211 bool TemplateAbstractView::isNonRootRegionVisible () const
213 return mnCurRegionId
;
216 void TemplateAbstractView::setOpenRegionHdl(const Link
&rLink
)
218 maOpenRegionHdl
= rLink
;
221 void TemplateAbstractView::setOpenTemplateHdl(const Link
&rLink
)
223 maOpenTemplateHdl
= rLink
;
226 BitmapEx
TemplateAbstractView::scaleImg (const BitmapEx
&rImg
, long width
, long height
)
228 BitmapEx aImg
= rImg
;
230 if ( !rImg
.IsEmpty() )
233 const Size
& aImgSize
= aImg
.GetSizePixel();
234 double nRatio
= double(aImgSize
.getWidth()) / double(aImgSize
.getHeight());
236 long nDestWidth
= aImgSize
.getWidth();
237 long nDestHeight
= aImgSize
.getHeight();
239 // Which one side is the overflowing most?
240 long nDistW
= aImgSize
.getWidth() - width
;
241 long nDistH
= aImgSize
.getHeight() - height
;
243 // Use the biggest overflow side to make it fit the destination
244 if ( nDistW
>= nDistH
&& nDistW
> 0 )
247 nDestHeight
= width
/ nRatio
;
249 else if ( nDistW
< nDistH
&& nDistH
> 0 )
251 nDestHeight
= height
;
252 nDestWidth
= height
* nRatio
;
255 aImg
.Scale(Size(nDestWidth
,nDestHeight
));
261 BitmapEx
TemplateAbstractView::getDefaultThumbnail( const OUString
& rPath
)
263 INetURLObject
aUrl(rPath
);
264 OUString aExt
= aUrl
.getExtension();
267 if ( aExt
== "ott" || aExt
== "stw" || aExt
== "oth" || aExt
== "dot" || aExt
== "dotx" )
269 aImg
= BitmapEx ( SfxResId( SFX_THUMBNAIL_TEXT
) );
271 else if ( aExt
== "ots" || aExt
== "stc" || aExt
== "xlt" || aExt
== "xltm" || aExt
== "xltx" )
273 aImg
= BitmapEx ( SfxResId( SFX_THUMBNAIL_SHEET
) );
275 else if ( aExt
== "otp" || aExt
== "sti" || aExt
== "pot" || aExt
== "potm" || aExt
== "potx" )
277 aImg
= BitmapEx ( SfxResId( SFX_THUMBNAIL_PRESENTATION
) );
279 else if ( aExt
== "otg" || aExt
== "std" )
281 aImg
= BitmapEx ( SfxResId( SFX_THUMBNAIL_DRAWING
) );
286 BitmapEx
TemplateAbstractView::fetchThumbnail (const OUString
&msURL
, long width
, long height
)
288 using namespace ::com::sun::star
;
289 using namespace ::com::sun::star::uno
;
291 // Load the thumbnail from a template document.
292 uno::Reference
<io::XInputStream
> xIStream
;
294 uno::Reference
< uno::XComponentContext
> xContext (comphelper::getProcessComponentContext());
298 uno::Reference
<lang::XSingleServiceFactory
> xStorageFactory
= embed::StorageFactory::create( xContext
);
300 uno::Sequence
<uno::Any
> aArgs (2);
302 aArgs
[1] <<= embed::ElementModes::READ
;
303 uno::Reference
<embed::XStorage
> xDocStorage (
304 xStorageFactory
->createInstanceWithArguments(aArgs
),
309 if (xDocStorage
.is())
311 uno::Reference
<embed::XStorage
> xStorage (
312 xDocStorage
->openStorageElement(
314 embed::ElementModes::READ
));
317 uno::Reference
<io::XStream
> xThumbnailCopy (
318 xStorage
->cloneStreamElement("thumbnail.png"));
319 if (xThumbnailCopy
.is())
320 xIStream
= xThumbnailCopy
->getInputStream();
324 catch (const uno::Exception
& rException
)
327 "caught exception while trying to access Thumbnail/thumbnail.png of %s: %s",
328 OUStringToOString(msURL
,
329 RTL_TEXTENCODING_UTF8
).getStr(),
330 OUStringToOString(rException
.Message
,
331 RTL_TEXTENCODING_UTF8
).getStr());
336 // An (older) implementation had a bug - The storage
337 // name was "Thumbnail" instead of "Thumbnails". The
338 // old name is still used as fallback but this code can
340 if ( ! xIStream
.is())
342 uno::Reference
<embed::XStorage
> xStorage (
343 xDocStorage
->openStorageElement( "Thumbnail",
344 embed::ElementModes::READ
));
347 uno::Reference
<io::XStream
> xThumbnailCopy (
348 xStorage
->cloneStreamElement("thumbnail.png"));
349 if (xThumbnailCopy
.is())
350 xIStream
= xThumbnailCopy
->getInputStream();
354 catch (const uno::Exception
& rException
)
357 "caught exception while trying to access Thumbnails/thumbnail.png of %s: %s",
358 OUStringToOString(msURL
,
359 RTL_TEXTENCODING_UTF8
).getStr(),
360 OUStringToOString(rException
.Message
,
361 RTL_TEXTENCODING_UTF8
).getStr());
364 catch (const uno::Exception
& rException
)
367 "caught exception while trying to access tuhmbnail of %s: %s",
368 OUStringToOString(msURL
,
369 RTL_TEXTENCODING_UTF8
).getStr(),
370 OUStringToOString(rException
.Message
,
371 RTL_TEXTENCODING_UTF8
).getStr());
374 // Extract the image from the stream.
378 ::std::auto_ptr
<SvStream
> pStream (
379 ::utl::UcbStreamHelper::CreateStream (xIStream
));
380 ::vcl::PNGReader
aReader (*pStream
);
381 aThumbnail
= aReader
.Read ();
384 return TemplateAbstractView::scaleImg(aThumbnail
,width
,height
);
387 IMPL_LINK_NOARG(TemplateAbstractView
, ShowRootRegionHdl
)
393 void TemplateAbstractView::OnItemDblClicked (ThumbnailViewItem
*pItem
)
395 //Check if the item is a TemplateContainerItem (Folder) or a TemplateViewItem (File)
397 TemplateContainerItem
* pContainerItem
= dynamic_cast<TemplateContainerItem
*>(pItem
);
398 if ( pContainerItem
)
402 mnCurRegionId
= pContainerItem
->mnRegionId
+1;
403 maCurRegionName
= pContainerItem
->maTitle
;
404 maFTName
.SetText(maCurRegionName
);
409 maOpenTemplateHdl
.Call(pItem
);
413 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */