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 :
10 : #include <sfx2/templateabstractview.hxx>
11 :
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>
19 :
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>
26 :
27 : #include "../doc/doc.hrc"
28 : #include "templateview.hrc"
29 :
30 0 : bool ViewFilter_Application::isValid (const OUString &rPath) const
31 : {
32 0 : bool bRet = true;
33 :
34 0 : INetURLObject aUrl(rPath);
35 0 : OUString aExt = aUrl.getExtension();
36 0 : if (mApp == FILTER_APP_WRITER)
37 : {
38 0 : bRet = aExt == "ott" || aExt == "stw" || aExt == "oth" || aExt == "dot" || aExt == "dotx";
39 : }
40 0 : else if (mApp == FILTER_APP_CALC)
41 : {
42 0 : bRet = aExt == "ots" || aExt == "stc" || aExt == "xlt" || aExt == "xltm" || aExt == "xltx";
43 : }
44 0 : else if (mApp == FILTER_APP_IMPRESS)
45 : {
46 0 : bRet = aExt == "otp" || aExt == "sti" || aExt == "pot" || aExt == "potm" || aExt == "potx";
47 : }
48 0 : else if (mApp == FILTER_APP_DRAW)
49 : {
50 0 : bRet = aExt == "otg" || aExt == "std";
51 : }
52 :
53 0 : return bRet;
54 : }
55 :
56 0 : bool ViewFilter_Application::operator () (const ThumbnailViewItem *pItem)
57 : {
58 0 : const TemplateViewItem *pTempItem = dynamic_cast<const TemplateViewItem*>(pItem);
59 0 : if (pTempItem)
60 0 : return isValid(pTempItem->getPath());
61 :
62 0 : TemplateContainerItem *pContainerItem = const_cast<TemplateContainerItem*>(dynamic_cast<const TemplateContainerItem*>(pItem));
63 0 : if (pContainerItem)
64 : {
65 0 : std::vector<TemplateItemProperties> &rTemplates = pContainerItem->maTemplates;
66 :
67 0 : size_t nVisCount = 0;
68 :
69 : // Clear thumbnails
70 0 : pContainerItem->maPreview1.Clear();
71 0 : pContainerItem->maPreview2.Clear();
72 0 : pContainerItem->maPreview3.Clear();
73 0 : pContainerItem->maPreview4.Clear();
74 :
75 0 : for (size_t i = 0, n = rTemplates.size(); i < n && pContainerItem->HasMissingPreview(); ++i)
76 : {
77 0 : if (isValid(rTemplates[i].aPath))
78 : {
79 0 : ++nVisCount;
80 0 : if ( pContainerItem->maPreview1.IsEmpty( ) )
81 : {
82 0 : pContainerItem->maPreview1 = TemplateAbstractView::scaleImg(rTemplates[i].aThumbnail,
83 : TEMPLATE_THUMBNAIL_MAX_WIDTH*0.75,
84 0 : TEMPLATE_THUMBNAIL_MAX_HEIGHT*0.75);
85 : }
86 0 : else if ( pContainerItem->maPreview2.IsEmpty() )
87 : {
88 0 : pContainerItem->maPreview2 = TemplateAbstractView::scaleImg(rTemplates[i].aThumbnail,
89 : TEMPLATE_THUMBNAIL_MAX_WIDTH*0.75,
90 0 : TEMPLATE_THUMBNAIL_MAX_HEIGHT*0.75);
91 : }
92 0 : else if ( pContainerItem->maPreview3.IsEmpty() )
93 : {
94 0 : pContainerItem->maPreview3 = TemplateAbstractView::scaleImg(rTemplates[i].aThumbnail,
95 : TEMPLATE_THUMBNAIL_MAX_WIDTH*0.75,
96 0 : TEMPLATE_THUMBNAIL_MAX_HEIGHT*0.75);
97 : }
98 0 : else if ( pContainerItem->maPreview4.IsEmpty() )
99 : {
100 0 : pContainerItem->maPreview4 = TemplateAbstractView::scaleImg(rTemplates[i].aThumbnail,
101 : TEMPLATE_THUMBNAIL_MAX_WIDTH*0.75,
102 0 : TEMPLATE_THUMBNAIL_MAX_HEIGHT*0.75);
103 : }
104 : }
105 : }
106 : }
107 0 : return true;
108 : }
109 :
110 0 : bool ViewFilter_Keyword::operator ()(const ThumbnailViewItem *pItem)
111 : {
112 : assert(pItem);
113 :
114 0 : return pItem->maTitle.matchIgnoreAsciiCase(maKeyword);
115 : }
116 :
117 0 : TemplateAbstractView::TemplateAbstractView (Window *pParent, WinBits nWinStyle, bool bDisableTransientChildren)
118 : : ThumbnailView(pParent,nWinStyle,bDisableTransientChildren),
119 : mnCurRegionId(0),
120 : maAllButton(this, SfxResId(BTN_ALL_TEMPLATES)),
121 0 : maFTName(this, SfxResId(FT_NAME))
122 : {
123 0 : maAllButton.Hide();
124 0 : maAllButton.SetStyle(maAllButton.GetStyle() | WB_FLATBUTTON);
125 0 : maAllButton.SetClickHdl(LINK(this,TemplateAbstractView,ShowRootRegionHdl));
126 0 : maFTName.Hide();
127 0 : }
128 :
129 0 : TemplateAbstractView::TemplateAbstractView(Window *pParent, const ResId &rResId, bool bDisableTransientChildren)
130 : : ThumbnailView(pParent,rResId,bDisableTransientChildren),
131 : mnCurRegionId(0),
132 : maAllButton(this, SfxResId(BTN_ALL_TEMPLATES)),
133 0 : maFTName(this, SfxResId(FT_NAME))
134 : {
135 0 : maAllButton.Hide();
136 0 : maAllButton.SetStyle(maAllButton.GetStyle() | WB_FLATBUTTON);
137 0 : maAllButton.SetClickHdl(LINK(this,TemplateAbstractView,ShowRootRegionHdl));
138 0 : maFTName.Hide();
139 0 : }
140 :
141 0 : TemplateAbstractView::~TemplateAbstractView ()
142 : {
143 0 : }
144 :
145 0 : void TemplateAbstractView::insertItem(const TemplateItemProperties &rTemplate)
146 : {
147 0 : const TemplateItemProperties *pCur = &rTemplate;
148 :
149 0 : TemplateViewItem *pChild = new TemplateViewItem(*this);
150 0 : pChild->mnId = pCur->nId;
151 0 : pChild->mnDocId = pCur->nDocId;
152 0 : pChild->mnRegionId = pCur->nRegionId;
153 0 : pChild->maTitle = pCur->aName;
154 0 : pChild->setPath(pCur->aPath);
155 0 : pChild->maPreview1 = pCur->aThumbnail;
156 :
157 0 : if ( pCur->aThumbnail.IsEmpty() )
158 : {
159 : // Use the default thumbnail if we have nothing else
160 0 : pChild->maPreview1 = TemplateAbstractView::getDefaultThumbnail(pCur->aPath);
161 : }
162 :
163 0 : pChild->setSelectClickHdl(LINK(this,ThumbnailView,OnItemSelected));
164 :
165 0 : AppendItem(pChild);
166 :
167 0 : CalculateItemPositions();
168 0 : Invalidate();
169 0 : }
170 :
171 0 : void TemplateAbstractView::insertItems(const std::vector<TemplateItemProperties> &rTemplates)
172 : {
173 0 : std::vector<ThumbnailViewItem*> aItems(rTemplates.size());
174 0 : for (size_t i = 0, n = rTemplates.size(); i < n; ++i )
175 : {
176 : //TODO: CHECK IF THE ITEM IS A FOLDER OR NOT
177 0 : TemplateViewItem *pChild = new TemplateViewItem(*this);
178 0 : const TemplateItemProperties *pCur = &rTemplates[i];
179 :
180 0 : pChild->mnId = pCur->nId;
181 0 : pChild->mnDocId = pCur->nDocId;
182 0 : pChild->mnRegionId = pCur->nRegionId;
183 0 : pChild->maTitle = pCur->aName;
184 0 : pChild->setPath(pCur->aPath);
185 0 : pChild->maPreview1 = pCur->aThumbnail;
186 :
187 0 : if ( pCur->aThumbnail.IsEmpty() )
188 : {
189 : // Use the default thumbnail if we have nothing else
190 0 : pChild->maPreview1 = TemplateAbstractView::getDefaultThumbnail(pCur->aPath);
191 : }
192 :
193 0 : pChild->setSelectClickHdl(LINK(this,ThumbnailView,OnItemSelected));
194 :
195 0 : aItems[i] = pChild;
196 : }
197 :
198 0 : updateItems(aItems);
199 0 : }
200 :
201 0 : sal_uInt16 TemplateAbstractView::getCurRegionId() const
202 : {
203 0 : return mnCurRegionId;
204 : }
205 :
206 0 : const OUString &TemplateAbstractView::getCurRegionName() const
207 : {
208 0 : return maCurRegionName;
209 : }
210 :
211 0 : bool TemplateAbstractView::isNonRootRegionVisible () const
212 : {
213 0 : return mnCurRegionId;
214 : }
215 :
216 0 : void TemplateAbstractView::setOpenRegionHdl(const Link &rLink)
217 : {
218 0 : maOpenRegionHdl = rLink;
219 0 : }
220 :
221 0 : void TemplateAbstractView::setOpenTemplateHdl(const Link &rLink)
222 : {
223 0 : maOpenTemplateHdl = rLink;
224 0 : }
225 :
226 0 : BitmapEx TemplateAbstractView::scaleImg (const BitmapEx &rImg, long width, long height)
227 : {
228 0 : BitmapEx aImg = rImg;
229 :
230 0 : if ( !rImg.IsEmpty() )
231 : {
232 :
233 0 : const Size& aImgSize = aImg.GetSizePixel();
234 0 : double nRatio = double(aImgSize.getWidth()) / double(aImgSize.getHeight());
235 :
236 0 : long nDestWidth = aImgSize.getWidth();
237 0 : long nDestHeight = aImgSize.getHeight();
238 :
239 : // Which one side is the overflowing most?
240 0 : long nDistW = aImgSize.getWidth() - width;
241 0 : long nDistH = aImgSize.getHeight() - height;
242 :
243 : // Use the biggest overflow side to make it fit the destination
244 0 : if ( nDistW >= nDistH && nDistW > 0 )
245 : {
246 0 : nDestWidth = width;
247 0 : nDestHeight = width / nRatio;
248 : }
249 0 : else if ( nDistW < nDistH && nDistH > 0 )
250 : {
251 0 : nDestHeight = height;
252 0 : nDestWidth = height * nRatio;
253 : }
254 :
255 0 : aImg.Scale(Size(nDestWidth,nDestHeight));
256 : }
257 :
258 0 : return aImg;
259 : }
260 :
261 0 : BitmapEx TemplateAbstractView::getDefaultThumbnail( const OUString& rPath )
262 : {
263 0 : INetURLObject aUrl(rPath);
264 0 : OUString aExt = aUrl.getExtension();
265 :
266 0 : BitmapEx aImg;
267 0 : if ( aExt == "ott" || aExt == "stw" || aExt == "oth" || aExt == "dot" || aExt == "dotx" )
268 : {
269 0 : aImg = BitmapEx ( SfxResId( SFX_THUMBNAIL_TEXT ) );
270 : }
271 0 : else if ( aExt == "ots" || aExt == "stc" || aExt == "xlt" || aExt == "xltm" || aExt == "xltx" )
272 : {
273 0 : aImg = BitmapEx ( SfxResId( SFX_THUMBNAIL_SHEET ) );
274 : }
275 0 : else if ( aExt == "otp" || aExt == "sti" || aExt == "pot" || aExt == "potm" || aExt == "potx" )
276 : {
277 0 : aImg = BitmapEx ( SfxResId( SFX_THUMBNAIL_PRESENTATION ) );
278 : }
279 0 : else if ( aExt == "otg" || aExt == "std" )
280 : {
281 0 : aImg = BitmapEx ( SfxResId( SFX_THUMBNAIL_DRAWING ) );
282 : }
283 0 : return aImg;
284 : }
285 :
286 0 : BitmapEx TemplateAbstractView::fetchThumbnail (const OUString &msURL, long width, long height)
287 : {
288 : using namespace ::com::sun::star;
289 : using namespace ::com::sun::star::uno;
290 :
291 : // Load the thumbnail from a template document.
292 0 : uno::Reference<io::XInputStream> xIStream;
293 :
294 0 : uno::Reference< uno::XComponentContext > xContext (comphelper::getProcessComponentContext());
295 :
296 : try
297 : {
298 0 : uno::Reference<lang::XSingleServiceFactory> xStorageFactory = embed::StorageFactory::create( xContext );
299 :
300 0 : uno::Sequence<uno::Any> aArgs (2);
301 0 : aArgs[0] <<= msURL;
302 0 : aArgs[1] <<= embed::ElementModes::READ;
303 : uno::Reference<embed::XStorage> xDocStorage (
304 0 : xStorageFactory->createInstanceWithArguments(aArgs),
305 0 : uno::UNO_QUERY);
306 :
307 : try
308 : {
309 0 : if (xDocStorage.is())
310 : {
311 : uno::Reference<embed::XStorage> xStorage (
312 0 : xDocStorage->openStorageElement(
313 : "Thumbnails",
314 0 : embed::ElementModes::READ));
315 0 : if (xStorage.is())
316 : {
317 : uno::Reference<io::XStream> xThumbnailCopy (
318 0 : xStorage->cloneStreamElement("thumbnail.png"));
319 0 : if (xThumbnailCopy.is())
320 0 : xIStream = xThumbnailCopy->getInputStream();
321 0 : }
322 : }
323 : }
324 0 : catch (const uno::Exception& rException)
325 : {
326 : OSL_TRACE (
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());
332 : }
333 :
334 : try
335 : {
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
339 : // be removed soon.
340 0 : if ( ! xIStream.is())
341 : {
342 : uno::Reference<embed::XStorage> xStorage (
343 0 : xDocStorage->openStorageElement( "Thumbnail",
344 0 : embed::ElementModes::READ));
345 0 : if (xStorage.is())
346 : {
347 : uno::Reference<io::XStream> xThumbnailCopy (
348 0 : xStorage->cloneStreamElement("thumbnail.png"));
349 0 : if (xThumbnailCopy.is())
350 0 : xIStream = xThumbnailCopy->getInputStream();
351 0 : }
352 : }
353 : }
354 0 : catch (const uno::Exception& rException)
355 : {
356 : OSL_TRACE (
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());
362 0 : }
363 : }
364 0 : catch (const uno::Exception& rException)
365 : {
366 : OSL_TRACE (
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());
372 : }
373 :
374 : // Extract the image from the stream.
375 0 : BitmapEx aThumbnail;
376 0 : if (xIStream.is())
377 : {
378 : ::std::auto_ptr<SvStream> pStream (
379 0 : ::utl::UcbStreamHelper::CreateStream (xIStream));
380 0 : ::vcl::PNGReader aReader (*pStream);
381 0 : aThumbnail = aReader.Read ();
382 : }
383 :
384 0 : return TemplateAbstractView::scaleImg(aThumbnail,width,height);
385 : }
386 :
387 0 : IMPL_LINK_NOARG(TemplateAbstractView, ShowRootRegionHdl)
388 : {
389 0 : showRootRegion();
390 0 : return 0;
391 : }
392 :
393 0 : void TemplateAbstractView::OnItemDblClicked (ThumbnailViewItem *pItem)
394 : {
395 : //Check if the item is a TemplateContainerItem (Folder) or a TemplateViewItem (File)
396 :
397 0 : TemplateContainerItem* pContainerItem = dynamic_cast<TemplateContainerItem*>(pItem);
398 0 : if ( pContainerItem )
399 : {
400 : // Fill templates
401 :
402 0 : mnCurRegionId = pContainerItem->mnRegionId+1;
403 0 : maCurRegionName = pContainerItem->maTitle;
404 0 : maFTName.SetText(maCurRegionName);
405 0 : showRegion(pItem);
406 : }
407 : else
408 : {
409 0 : maOpenTemplateHdl.Call(pItem);
410 : }
411 408 : }
412 :
413 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|