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 : #include <sfx2/templatecontaineritem.hxx>
12 :
13 : #include <comphelper/processfactory.hxx>
14 : #include <sfx2/templateview.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 0 : bool ViewFilter_Application::isValid (const OUString &rPath) const
28 : {
29 0 : bool bRet = true;
30 :
31 0 : INetURLObject aUrl(rPath);
32 0 : OUString aExt = aUrl.getExtension();
33 0 : if (mApp == FILTER_APP_WRITER)
34 : {
35 0 : bRet = aExt == "ott" || aExt == "stw" || aExt == "oth" || aExt == "dot" || aExt == "dotx";
36 : }
37 0 : else if (mApp == FILTER_APP_CALC)
38 : {
39 0 : bRet = aExt == "ots" || aExt == "stc" || aExt == "xlt" || aExt == "xltm" || aExt == "xltx";
40 : }
41 0 : else if (mApp == FILTER_APP_IMPRESS)
42 : {
43 0 : bRet = aExt == "otp" || aExt == "sti" || aExt == "pot" || aExt == "potm" || aExt == "potx";
44 : }
45 0 : else if (mApp == FILTER_APP_DRAW)
46 : {
47 0 : bRet = aExt == "otg" || aExt == "std";
48 : }
49 :
50 0 : return bRet;
51 : }
52 :
53 0 : bool ViewFilter_Application::operator () (const ThumbnailViewItem *pItem)
54 : {
55 0 : const TemplateViewItem *pTempItem = dynamic_cast<const TemplateViewItem*>(pItem);
56 0 : if (pTempItem)
57 0 : return isValid(pTempItem->getPath());
58 :
59 0 : TemplateContainerItem *pContainerItem = const_cast<TemplateContainerItem*>(dynamic_cast<const TemplateContainerItem*>(pItem));
60 0 : if (pContainerItem)
61 : {
62 0 : std::vector<TemplateItemProperties> &rTemplates = pContainerItem->maTemplates;
63 :
64 0 : size_t nVisCount = 0;
65 :
66 : // Clear thumbnails
67 0 : pContainerItem->maPreview1.Clear();
68 0 : pContainerItem->maPreview2.Clear();
69 :
70 0 : for (size_t i = 0, n = rTemplates.size(); i < n; ++i)
71 : {
72 0 : if (isValid(rTemplates[i].aPath))
73 : {
74 0 : ++nVisCount;
75 0 : if ( pContainerItem->maPreview1.IsEmpty( ) )
76 : {
77 0 : pContainerItem->maPreview1 = TemplateAbstractView::scaleImg(rTemplates[i].aThumbnail,
78 : TEMPLATE_THUMBNAIL_MAX_WIDTH*0.75,
79 0 : TEMPLATE_THUMBNAIL_MAX_HEIGHT*0.75);
80 : }
81 0 : else if ( pContainerItem->maPreview2.IsEmpty() )
82 : {
83 0 : pContainerItem->maPreview2 = TemplateAbstractView::scaleImg(rTemplates[i].aThumbnail,
84 : TEMPLATE_THUMBNAIL_MAX_WIDTH*0.75,
85 0 : TEMPLATE_THUMBNAIL_MAX_HEIGHT*0.75);
86 : }
87 : }
88 : }
89 :
90 0 : return mApp != FILTER_APP_NONE ? nVisCount : true ;
91 : }
92 0 : return true;
93 : }
94 :
95 0 : bool ViewFilter_Keyword::operator ()(const ThumbnailViewItem *pItem)
96 : {
97 : assert(pItem);
98 :
99 0 : return pItem->maTitle.matchIgnoreAsciiCase(maKeyword);
100 : }
101 :
102 0 : TemplateAbstractView::TemplateAbstractView (Window *pParent, WinBits nWinStyle, bool bDisableTransientChildren)
103 : : ThumbnailView(pParent,nWinStyle,bDisableTransientChildren),
104 0 : mpItemView(new TemplateView(this)),
105 : mbFilteredResults(false),
106 0 : meFilterOption(FILTER_APP_NONE)
107 : {
108 0 : mpItemView->setItemStateHdl(LINK(this,TemplateAbstractView,OverlayItemStateHdl));
109 0 : }
110 :
111 0 : TemplateAbstractView::TemplateAbstractView(Window *pParent, const ResId &rResId, bool bDisableTransientChildren)
112 : : ThumbnailView(pParent,rResId,bDisableTransientChildren),
113 0 : mpItemView(new TemplateView(this)),
114 : mbFilteredResults(false),
115 0 : meFilterOption(FILTER_APP_NONE)
116 : {
117 0 : mpItemView->setItemStateHdl(LINK(this,TemplateAbstractView,OverlayItemStateHdl));
118 0 : }
119 :
120 0 : TemplateAbstractView::~TemplateAbstractView ()
121 : {
122 0 : delete mpItemView;
123 0 : }
124 :
125 0 : void TemplateAbstractView::setItemDimensions(long ItemWidth, long ThumbnailHeight, long DisplayHeight, int itemPadding)
126 : {
127 0 : ThumbnailView::setItemDimensions(ItemWidth,ThumbnailHeight,DisplayHeight,itemPadding);
128 :
129 0 : mpItemView->setItemDimensions(ItemWidth,ThumbnailHeight,DisplayHeight,itemPadding);
130 0 : }
131 :
132 0 : sal_uInt16 TemplateAbstractView::getOverlayRegionId() const
133 : {
134 0 : return mpItemView->getId();
135 : }
136 :
137 0 : const OUString &TemplateAbstractView::getOverlayName() const
138 : {
139 0 : return mpItemView->getName();
140 : }
141 :
142 0 : bool TemplateAbstractView::isOverlayVisible () const
143 : {
144 0 : return mpItemView->IsVisible();
145 : }
146 :
147 0 : void TemplateAbstractView::deselectOverlayItems()
148 : {
149 0 : mpItemView->deselectItems();
150 0 : }
151 :
152 0 : void TemplateAbstractView::deselectOverlayItem(const sal_uInt16 nItemId)
153 : {
154 0 : mpItemView->deselectItem(nItemId);
155 0 : }
156 :
157 0 : void TemplateAbstractView::sortOverlayItems(const boost::function<bool (const ThumbnailViewItem*,
158 : const ThumbnailViewItem*) > &func)
159 : {
160 0 : mpItemView->sortItems(func);
161 0 : }
162 :
163 0 : void TemplateAbstractView::filterTemplatesByApp (const FILTER_APPLICATION &eApp)
164 : {
165 0 : meFilterOption = eApp;
166 :
167 0 : if (mpItemView->IsVisible())
168 : {
169 0 : mbFilteredResults = true;
170 0 : mpItemView->filterItems(ViewFilter_Application(eApp));
171 : }
172 : else
173 : {
174 0 : filterItems(ViewFilter_Application(eApp));
175 : }
176 0 : }
177 :
178 0 : void TemplateAbstractView::filterTemplatesByKeyword(const OUString &rKeyword)
179 : {
180 0 : if (mpItemView->IsVisible())
181 0 : mpItemView->filterItems(ViewFilter_Keyword(rKeyword));
182 0 : }
183 :
184 0 : void TemplateAbstractView::setOverlayDblClickHdl(const Link &rLink)
185 : {
186 0 : mpItemView->setDblClickHdl(rLink);
187 0 : }
188 :
189 0 : void TemplateAbstractView::setOverlayCloseHdl(const Link &rLink)
190 : {
191 0 : mpItemView->setCloseHdl(rLink);
192 0 : }
193 :
194 0 : BitmapEx TemplateAbstractView::scaleImg (const BitmapEx &rImg, long width, long height)
195 : {
196 0 : BitmapEx aImg = rImg;
197 :
198 0 : if ( !rImg.IsEmpty() )
199 : {
200 :
201 0 : const Size& aImgSize = aImg.GetSizePixel();
202 0 : double nRatio = double(aImgSize.getWidth()) / double(aImgSize.getHeight());
203 :
204 0 : long nDestWidth = aImgSize.getWidth();
205 0 : long nDestHeight = aImgSize.getHeight();
206 :
207 : // Which one side is the overflowing most?
208 0 : long nDistW = aImgSize.getWidth() - width;
209 0 : long nDistH = aImgSize.getHeight() - height;
210 :
211 : // Use the biggest overflow side to make it fit the destination
212 0 : if ( nDistW >= nDistH && nDistW > 0 )
213 : {
214 0 : nDestWidth = width;
215 0 : nDestHeight = width / nRatio;
216 : }
217 0 : else if ( nDistW < nDistH && nDistH > 0 )
218 : {
219 0 : nDestHeight = height;
220 0 : nDestWidth = height * nRatio;
221 : }
222 :
223 0 : aImg.Scale(Size(nDestWidth,nDestHeight));
224 : }
225 :
226 0 : return aImg;
227 : }
228 :
229 0 : BitmapEx TemplateAbstractView::fetchThumbnail (const OUString &msURL, long width, long height)
230 : {
231 : using namespace ::com::sun::star;
232 : using namespace ::com::sun::star::uno;
233 :
234 : // Load the thumbnail from a template document.
235 0 : uno::Reference<io::XInputStream> xIStream;
236 :
237 0 : uno::Reference< uno::XComponentContext > xContext (comphelper::getProcessComponentContext());
238 :
239 : try
240 : {
241 0 : uno::Reference<lang::XSingleServiceFactory> xStorageFactory = embed::StorageFactory::create( xContext );
242 :
243 0 : uno::Sequence<uno::Any> aArgs (2);
244 0 : aArgs[0] <<= msURL;
245 0 : aArgs[1] <<= embed::ElementModes::READ;
246 : uno::Reference<embed::XStorage> xDocStorage (
247 0 : xStorageFactory->createInstanceWithArguments(aArgs),
248 0 : uno::UNO_QUERY);
249 :
250 : try
251 : {
252 0 : if (xDocStorage.is())
253 : {
254 : uno::Reference<embed::XStorage> xStorage (
255 0 : xDocStorage->openStorageElement(
256 : "Thumbnails",
257 0 : embed::ElementModes::READ));
258 0 : if (xStorage.is())
259 : {
260 : uno::Reference<io::XStream> xThumbnailCopy (
261 0 : xStorage->cloneStreamElement("thumbnail.png"));
262 0 : if (xThumbnailCopy.is())
263 0 : xIStream = xThumbnailCopy->getInputStream();
264 0 : }
265 : }
266 : }
267 0 : catch (const uno::Exception& rException)
268 : {
269 : OSL_TRACE (
270 : "caught exception while trying to access Thumbnail/thumbnail.png of %s: %s",
271 : ::rtl::OUStringToOString(msURL,
272 : RTL_TEXTENCODING_UTF8).getStr(),
273 : ::rtl::OUStringToOString(rException.Message,
274 : RTL_TEXTENCODING_UTF8).getStr());
275 : }
276 :
277 : try
278 : {
279 : // An (older) implementation had a bug - The storage
280 : // name was "Thumbnail" instead of "Thumbnails". The
281 : // old name is still used as fallback but this code can
282 : // be removed soon.
283 0 : if ( ! xIStream.is())
284 : {
285 : uno::Reference<embed::XStorage> xStorage (
286 0 : xDocStorage->openStorageElement( "Thumbnail",
287 0 : embed::ElementModes::READ));
288 0 : if (xStorage.is())
289 : {
290 : uno::Reference<io::XStream> xThumbnailCopy (
291 0 : xStorage->cloneStreamElement("thumbnail.png"));
292 0 : if (xThumbnailCopy.is())
293 0 : xIStream = xThumbnailCopy->getInputStream();
294 0 : }
295 : }
296 : }
297 0 : catch (const uno::Exception& rException)
298 : {
299 : OSL_TRACE (
300 : "caught exception while trying to access Thumbnails/thumbnail.png of %s: %s",
301 : ::rtl::OUStringToOString(msURL,
302 : RTL_TEXTENCODING_UTF8).getStr(),
303 : ::rtl::OUStringToOString(rException.Message,
304 : RTL_TEXTENCODING_UTF8).getStr());
305 0 : }
306 : }
307 0 : catch (const uno::Exception& rException)
308 : {
309 : OSL_TRACE (
310 : "caught exception while trying to access tuhmbnail of %s: %s",
311 : ::rtl::OUStringToOString(msURL,
312 : RTL_TEXTENCODING_UTF8).getStr(),
313 : ::rtl::OUStringToOString(rException.Message,
314 : RTL_TEXTENCODING_UTF8).getStr());
315 : }
316 :
317 : // Extract the image from the stream.
318 0 : BitmapEx aThumbnail;
319 0 : if (xIStream.is())
320 : {
321 : ::std::auto_ptr<SvStream> pStream (
322 0 : ::utl::UcbStreamHelper::CreateStream (xIStream));
323 0 : ::vcl::PNGReader aReader (*pStream);
324 0 : aThumbnail = aReader.Read ();
325 : }
326 :
327 0 : return TemplateAbstractView::scaleImg(aThumbnail,width,height);
328 : }
329 :
330 0 : void TemplateAbstractView::Resize()
331 : {
332 0 : mpItemView->SetSizePixel(GetSizePixel());
333 0 : ThumbnailView::Resize();
334 0 : }
335 :
336 0 : void TemplateAbstractView::Paint(const Rectangle &rRect)
337 : {
338 0 : if (!mpItemView->IsVisible())
339 0 : ThumbnailView::Paint(rRect);
340 0 : }
341 :
342 0 : void TemplateAbstractView::DrawItem(ThumbnailViewItem *pItem)
343 : {
344 0 : if (!mpItemView->IsVisible())
345 0 : ThumbnailView::DrawItem(pItem);
346 0 : }
347 :
348 0 : IMPL_LINK(TemplateAbstractView, OverlayItemStateHdl, const ThumbnailViewItem*, pItem)
349 : {
350 0 : maOverlayItemStateHdl.Call((void*)pItem);
351 0 : return 0;
352 : }
353 :
354 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|