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 : #include <sax/tools/converter.hxx>
21 : #include <sfx2/recentdocsview.hxx>
22 : #include <sfx2/templateabstractview.hxx>
23 : #include <sfx2/app.hxx>
24 : #include <sfx2/sfx.hrc>
25 : #include <sfx2/sfxresid.hxx>
26 : #include <unotools/historyoptions.hxx>
27 : #include <vcl/builder.hxx>
28 : #include <vcl/pngread.hxx>
29 : #include <vcl/svapp.hxx>
30 : #include <tools/urlobj.hxx>
31 : #include <com/sun/star/util/URLTransformer.hpp>
32 : #include <com/sun/star/frame/Desktop.hpp>
33 : #include <com/sun/star/frame/XFrame.hpp>
34 : #include <templateview.hrc>
35 :
36 : using namespace ::com::sun::star;
37 : using namespace com::sun::star::uno;
38 : using namespace com::sun::star::lang;
39 : using namespace com::sun::star::frame;
40 : using namespace com::sun::star::beans;
41 :
42 0 : RecentDocsView::RecentDocsView( Window* pParent )
43 : : ThumbnailView(pParent)
44 : , mnFileTypes(TYPE_NONE)
45 : , mnTextHeight(30)
46 : , mnItemPadding(5)
47 : , mnItemMaxTextLength(30)
48 : , maWelcomeImage(SfxResId(IMG_WELCOME))
49 : , maWelcomeLine1(SfxResId(STR_WELCOME_LINE1))
50 0 : , maWelcomeLine2(SfxResId(STR_WELCOME_LINE2))
51 : {
52 0 : Rectangle aScreen = Application::GetScreenPosSizePixel(Application::GetDisplayBuiltInScreen());
53 0 : mnItemMaxSize = std::min(aScreen.GetWidth(),aScreen.GetHeight()) > 800 ? 256 : 192;
54 :
55 0 : SetStyle(GetStyle() | WB_VSCROLL);
56 0 : setItemMaxTextLength( mnItemMaxTextLength );
57 0 : setItemDimensions( mnItemMaxSize, mnItemMaxSize, mnTextHeight, mnItemPadding );
58 0 : }
59 :
60 0 : extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeRecentDocsView(Window *pParent, VclBuilder::stringmap &)
61 : {
62 0 : return new RecentDocsView(pParent);
63 : }
64 :
65 0 : RecentDocsView::~RecentDocsView()
66 : {
67 0 : }
68 :
69 0 : bool RecentDocsView::typeMatchesExtension(ApplicationType type, const OUString &rExt)
70 : {
71 0 : bool bRet = false;
72 :
73 0 : if (rExt == "odt" || rExt == "doc" || rExt == "docx" ||
74 0 : rExt == "rtf" || rExt == "txt")
75 : {
76 0 : bRet = type & TYPE_WRITER;
77 : }
78 0 : else if (rExt == "ods" || rExt == "xls" || rExt == "xlsx")
79 : {
80 0 : bRet = type & TYPE_CALC;
81 : }
82 0 : else if (rExt == "odp" || rExt == "pps" || rExt == "ppt" ||
83 0 : rExt == "pptx")
84 : {
85 0 : bRet = type & TYPE_IMPRESS;
86 : }
87 0 : else if (rExt == "odg")
88 : {
89 0 : bRet = type & TYPE_DRAW;
90 : }
91 0 : else if (rExt == "odb")
92 : {
93 0 : bRet = type & TYPE_DATABASE;
94 : }
95 0 : else if (rExt == "odf")
96 : {
97 0 : bRet = type & TYPE_MATH;
98 : }
99 : else
100 : {
101 0 : bRet = type & TYPE_OTHER;
102 : }
103 :
104 0 : return bRet;
105 : }
106 :
107 0 : bool RecentDocsView::isAcceptedFile(const OUString &rURL) const
108 : {
109 0 : INetURLObject aUrl(rURL);
110 0 : OUString aExt = aUrl.getExtension();
111 0 : return (mnFileTypes & TYPE_WRITER && typeMatchesExtension(TYPE_WRITER, aExt)) ||
112 0 : (mnFileTypes & TYPE_CALC && typeMatchesExtension(TYPE_CALC, aExt)) ||
113 0 : (mnFileTypes & TYPE_IMPRESS && typeMatchesExtension(TYPE_IMPRESS, aExt)) ||
114 0 : (mnFileTypes & TYPE_DRAW && typeMatchesExtension(TYPE_DRAW, aExt)) ||
115 0 : (mnFileTypes & TYPE_DATABASE && typeMatchesExtension(TYPE_DATABASE,aExt)) ||
116 0 : (mnFileTypes & TYPE_MATH && typeMatchesExtension(TYPE_MATH, aExt)) ||
117 0 : (mnFileTypes & TYPE_OTHER && typeMatchesExtension(TYPE_OTHER, aExt));
118 : }
119 :
120 0 : BitmapEx RecentDocsView::getDefaultThumbnail(const OUString &rURL)
121 : {
122 0 : BitmapEx aImg;
123 0 : INetURLObject aUrl(rURL);
124 0 : OUString aExt = aUrl.getExtension();
125 :
126 0 : if ( typeMatchesExtension( TYPE_WRITER, aExt) )
127 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_TEXT ) );
128 0 : else if ( typeMatchesExtension( TYPE_CALC, aExt) )
129 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_SHEET ) );
130 0 : else if ( typeMatchesExtension( TYPE_IMPRESS, aExt) )
131 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_PRESENTATION ) );
132 0 : else if ( typeMatchesExtension( TYPE_DRAW, aExt) )
133 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_DRAWING ) );
134 0 : else if ( typeMatchesExtension( TYPE_DATABASE, aExt) )
135 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_DATABASE ) );
136 0 : else if ( typeMatchesExtension( TYPE_MATH, aExt) )
137 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_MATH ) );
138 : else
139 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_DEFAULT ) );
140 :
141 0 : return aImg;
142 : }
143 :
144 0 : void RecentDocsView::insertItem(const OUString &rURL, const OUString &rTitle, const BitmapEx &rThumbnail, sal_uInt16 nId)
145 : {
146 0 : RecentDocsViewItem *pChild = new RecentDocsViewItem(*this, rURL, rTitle, rThumbnail, nId);
147 :
148 0 : AppendItem(pChild);
149 0 : }
150 :
151 0 : void RecentDocsView::loadRecentDocs()
152 : {
153 0 : Clear();
154 :
155 0 : Sequence< Sequence< PropertyValue > > aHistoryList = SvtHistoryOptions().GetList( ePICKLIST );
156 0 : for ( int i = 0; i < aHistoryList.getLength(); i++ )
157 : {
158 0 : Sequence< PropertyValue >& rRecentEntry = aHistoryList[i];
159 :
160 0 : OUString aURL;
161 0 : OUString aTitle;
162 0 : BitmapEx aThumbnail;
163 :
164 0 : for ( int j = 0; j < rRecentEntry.getLength(); j++ )
165 : {
166 0 : Any a = rRecentEntry[j].Value;
167 :
168 0 : if (rRecentEntry[j].Name == "URL")
169 0 : a >>= aURL;
170 0 : else if (rRecentEntry[j].Name == "Title")
171 0 : a >>= aTitle;
172 0 : else if (rRecentEntry[j].Name == "Thumbnail")
173 : {
174 0 : OUString aBase64;
175 0 : a >>= aBase64;
176 0 : if (!aBase64.isEmpty())
177 : {
178 0 : Sequence<sal_Int8> aDecoded;
179 0 : sax::Converter::decodeBase64(aDecoded, aBase64);
180 :
181 0 : SvMemoryStream aStream(aDecoded.getArray(), aDecoded.getLength(), STREAM_READ);
182 0 : vcl::PNGReader aReader(aStream);
183 0 : aThumbnail = aReader.Read();
184 0 : }
185 : }
186 0 : }
187 :
188 0 : if (isAcceptedFile(aURL))
189 : {
190 0 : insertItem(aURL, aTitle, aThumbnail, i+1);
191 : }
192 0 : }
193 :
194 0 : CalculateItemPositions();
195 0 : Invalidate();
196 :
197 : // Set prefered width
198 0 : if( mFilteredItemList.empty() )
199 : {
200 0 : Font aOldFont(GetFont());
201 0 : Font aNewFont(aOldFont);
202 0 : aNewFont.SetHeight(20);
203 0 : SetFont(aNewFont);
204 0 : set_width_request(std::max(GetTextWidth(maWelcomeLine1),GetTextWidth(maWelcomeLine2)));
205 0 : SetFont(aOldFont);
206 : }
207 : else
208 : {
209 0 : set_width_request(mnTextHeight + mnItemMaxSize + 2*mnItemPadding);
210 0 : }
211 0 : }
212 :
213 0 : void RecentDocsView::MouseButtonDown( const MouseEvent& rMEvt )
214 : {
215 0 : if ( rMEvt.IsLeft() )
216 : {
217 0 : if( rMEvt.GetClicks() > 1 )
218 0 : return;
219 :
220 0 : size_t nPos = ImplGetItem(rMEvt.GetPosPixel());
221 0 : ThumbnailViewItem* pItem = ImplGetItem(nPos);
222 :
223 0 : if (pItem)
224 : {
225 0 : OpenItem(pItem);
226 0 : return;
227 : }
228 : }
229 0 : ThumbnailView::MouseButtonDown( rMEvt );
230 : }
231 :
232 0 : void RecentDocsView::OnItemDblClicked(ThumbnailViewItem *pItem)
233 : {
234 0 : OpenItem( pItem );
235 0 : }
236 :
237 0 : void RecentDocsView::OpenItem( const ThumbnailViewItem *pItem )
238 : {
239 0 : const RecentDocsViewItem* pRecentItem = dynamic_cast<const RecentDocsViewItem*>(pItem);
240 0 : if (!pRecentItem)
241 0 : return;
242 :
243 : // show busy mouse pointer
244 0 : SetPointer(Pointer(POINTER_WAIT));
245 :
246 0 : Reference< XDispatch > xDispatch;
247 0 : Reference< XDispatchProvider > xDispatchProvider;
248 0 : css::util::URL aTargetURL;
249 0 : Sequence< PropertyValue > aArgsList;
250 :
251 0 : uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( ::comphelper::getProcessComponentContext() );
252 0 : uno::Reference< frame::XFrame > xActiveFrame = xDesktop->getActiveFrame();
253 :
254 0 : osl::ClearableMutexGuard aLock( m_aMutex );
255 0 : xDispatchProvider = Reference< XDispatchProvider >( xActiveFrame, UNO_QUERY );
256 0 : aLock.clear();
257 :
258 0 : aTargetURL.Complete = pRecentItem->maURL;
259 : Reference< ::com::sun::star::util::XURLTransformer > xTrans(
260 : ::com::sun::star::util::URLTransformer::create(
261 0 : ::comphelper::getProcessComponentContext() ) );
262 0 : xTrans->parseStrict( aTargetURL );
263 :
264 0 : sal_Int32 nSize = 2;
265 0 : aArgsList.realloc( nSize );
266 0 : aArgsList[0].Name = "Referer";
267 0 : aArgsList[0].Value = makeAny( OUString( "private:user" ) );
268 :
269 : // documents will never be opened as templates
270 0 : aArgsList[1].Name = "AsTemplate";
271 0 : aArgsList[1].Value = makeAny( false );
272 :
273 0 : xDispatch = xDispatchProvider->queryDispatch( aTargetURL, "_default", 0 );
274 :
275 0 : if ( xDispatch.is() )
276 : {
277 : // Call dispatch asychronously as we can be destroyed while dispatch is
278 : // executed. VCL is not able to survive this as it wants to call listeners
279 : // after select!!!
280 0 : LoadRecentFile* pLoadRecentFile = new LoadRecentFile;
281 0 : pLoadRecentFile->xDispatch = xDispatch;
282 0 : pLoadRecentFile->aTargetURL = aTargetURL;
283 0 : pLoadRecentFile->aArgSeq = aArgsList;
284 :
285 0 : Application::PostUserEvent( STATIC_LINK(0, RecentDocsView, ExecuteHdl_Impl), pLoadRecentFile );
286 0 : }
287 : }
288 :
289 0 : void RecentDocsView::Paint( const Rectangle &aRect )
290 : {
291 0 : if ( mItemList.size() == 0 )
292 : {
293 : // No recent files to be shown yet. Show a welcome screen.
294 0 : Font aOldFont(GetFont());
295 0 : Font aNewFont(aOldFont);
296 0 : aNewFont.SetHeight(20);
297 0 : SetFont(aNewFont);
298 :
299 0 : long nTextHeight = GetTextHeight();
300 :
301 0 : long nTextWidth1 = GetTextWidth(maWelcomeLine1);
302 0 : long nTextWidth2 = GetTextWidth(maWelcomeLine2);
303 :
304 0 : const Size & rImgSize = maWelcomeImage.GetSizePixel();
305 0 : const Size & rSize = GetSizePixel();
306 :
307 0 : const int nX = (rSize.Width() - rImgSize.Width())/2;
308 0 : const int nY = (rSize.Height() - 3 * nTextHeight - rImgSize.Height())/2;
309 :
310 0 : Point aImgPoint(nX, nY);
311 0 : Point aStr1Point((rSize.Width() - nTextWidth1)/2, nY + rImgSize.Height() + 0.7 * nTextHeight);
312 0 : Point aStr2Point((rSize.Width() - nTextWidth2)/2, nY + rImgSize.Height() + 1.7 * nTextHeight);
313 :
314 0 : DrawImage(aImgPoint, rImgSize, maWelcomeImage, IMAGE_DRAW_SEMITRANSPARENT);
315 0 : DrawText(aStr1Point, maWelcomeLine1);
316 0 : DrawText(aStr2Point, maWelcomeLine2);
317 :
318 0 : SetFont(aOldFont);
319 : }
320 : else
321 0 : ThumbnailView::Paint(aRect);
322 0 : }
323 :
324 0 : void RecentDocsView::LoseFocus()
325 : {
326 0 : deselectItems();
327 :
328 0 : ThumbnailView::LoseFocus();
329 0 : }
330 :
331 0 : long RecentDocsView::GetThumbnailSize() const
332 : {
333 0 : return mnItemMaxSize;
334 : }
335 :
336 0 : void RecentDocsView::Clear()
337 : {
338 0 : Font aOldFont(GetFont());
339 0 : Font aNewFont(aOldFont);
340 0 : aNewFont.SetHeight(20);
341 0 : SetFont(aNewFont);
342 0 : set_width_request(std::max(GetTextWidth(maWelcomeLine1),GetTextWidth(maWelcomeLine2)));
343 0 : SetFont(aOldFont);
344 :
345 0 : ThumbnailView::Clear();
346 0 : }
347 :
348 0 : IMPL_STATIC_LINK_NOINSTANCE( RecentDocsView, ExecuteHdl_Impl, LoadRecentFile*, pLoadRecentFile )
349 : {
350 : try
351 : {
352 : // Asynchronous execution as this can lead to our own destruction!
353 : // Framework can recycle our current frame and the layout manager disposes all user interface
354 : // elements if a component gets detached from its frame!
355 0 : pLoadRecentFile->xDispatch->dispatch( pLoadRecentFile->aTargetURL, pLoadRecentFile->aArgSeq );
356 : }
357 0 : catch ( const Exception& )
358 : {
359 : }
360 :
361 0 : delete pLoadRecentFile;
362 0 : return 0;
363 : }
364 :
365 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|