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/builderfactory.hxx>
28 : #include <vcl/pngread.hxx>
29 : #include <tools/urlobj.hxx>
30 : #include <com/sun/star/util/URLTransformer.hpp>
31 : #include <com/sun/star/frame/Desktop.hpp>
32 : #include <com/sun/star/frame/XFrame.hpp>
33 : #include <templateview.hrc>
34 :
35 : using namespace ::com::sun::star;
36 : using namespace com::sun::star::uno;
37 : using namespace com::sun::star::lang;
38 : using namespace com::sun::star::frame;
39 : using namespace com::sun::star::beans;
40 :
41 : namespace {
42 :
43 : /// Set (larger) font for the Welcome message.
44 6 : void SetMessageFont(vcl::RenderContext& rRenderContext)
45 : {
46 6 : vcl::Font aFont(rRenderContext.GetFont());
47 6 : aFont.SetHeight(aFont.GetHeight() * 1.3);
48 6 : rRenderContext.SetFont(aFont);
49 6 : }
50 :
51 : }
52 :
53 1 : RecentDocsView::RecentDocsView( vcl::Window* pParent )
54 : : ThumbnailView(pParent)
55 : , mnFileTypes(TYPE_NONE)
56 : , mnTextHeight(30)
57 : , mnItemPadding(5)
58 : , mnItemMaxTextLength(30)
59 : , mnLastMouseDownItem(THUMBNAILVIEW_ITEM_NOTFOUND)
60 : , maWelcomeImage(SfxResId(IMG_WELCOME))
61 : , maWelcomeLine1(SfxResId(STR_WELCOME_LINE1))
62 1 : , maWelcomeLine2(SfxResId(STR_WELCOME_LINE2))
63 : {
64 1 : Rectangle aScreen = Application::GetScreenPosSizePixel(Application::GetDisplayBuiltInScreen());
65 1 : mnItemMaxSize = std::min(aScreen.GetWidth(),aScreen.GetHeight()) > 800 ? 256 : 192;
66 :
67 1 : SetStyle(GetStyle() | WB_VSCROLL);
68 1 : setItemMaxTextLength( mnItemMaxTextLength );
69 1 : setItemDimensions( mnItemMaxSize, mnItemMaxSize, mnTextHeight, mnItemPadding );
70 1 : }
71 :
72 1 : VCL_BUILDER_FACTORY(RecentDocsView)
73 :
74 0 : bool RecentDocsView::typeMatchesExtension(ApplicationType type, const OUString &rExt)
75 : {
76 0 : bool bRet = false;
77 :
78 0 : if (rExt == "odt" || rExt == "doc" || rExt == "docx" ||
79 0 : rExt == "rtf" || rExt == "txt" || rExt == "odm" || rExt == "otm")
80 : {
81 0 : bRet = type & TYPE_WRITER;
82 : }
83 0 : else if (rExt == "ods" || rExt == "xls" || rExt == "xlsx")
84 : {
85 0 : bRet = type & TYPE_CALC;
86 : }
87 0 : else if (rExt == "odp" || rExt == "pps" || rExt == "ppt" ||
88 0 : rExt == "pptx")
89 : {
90 0 : bRet = type & TYPE_IMPRESS;
91 : }
92 0 : else if (rExt == "odg")
93 : {
94 0 : bRet = type & TYPE_DRAW;
95 : }
96 0 : else if (rExt == "odb")
97 : {
98 0 : bRet = type & TYPE_DATABASE;
99 : }
100 0 : else if (rExt == "odf")
101 : {
102 0 : bRet = type & TYPE_MATH;
103 : }
104 : else
105 : {
106 0 : bRet = type & TYPE_OTHER;
107 : }
108 :
109 0 : return bRet;
110 : }
111 :
112 0 : bool RecentDocsView::isAcceptedFile(const OUString &rURL) const
113 : {
114 0 : INetURLObject aUrl(rURL);
115 0 : OUString aExt = aUrl.getExtension();
116 0 : return (mnFileTypes & TYPE_WRITER && typeMatchesExtension(TYPE_WRITER, aExt)) ||
117 0 : (mnFileTypes & TYPE_CALC && typeMatchesExtension(TYPE_CALC, aExt)) ||
118 0 : (mnFileTypes & TYPE_IMPRESS && typeMatchesExtension(TYPE_IMPRESS, aExt)) ||
119 0 : (mnFileTypes & TYPE_DRAW && typeMatchesExtension(TYPE_DRAW, aExt)) ||
120 0 : (mnFileTypes & TYPE_DATABASE && typeMatchesExtension(TYPE_DATABASE,aExt)) ||
121 0 : (mnFileTypes & TYPE_MATH && typeMatchesExtension(TYPE_MATH, aExt)) ||
122 0 : (mnFileTypes & TYPE_OTHER && typeMatchesExtension(TYPE_OTHER, aExt));
123 : }
124 :
125 0 : BitmapEx RecentDocsView::getDefaultThumbnail(const OUString &rURL)
126 : {
127 0 : BitmapEx aImg;
128 0 : INetURLObject aUrl(rURL);
129 0 : OUString aExt = aUrl.getExtension();
130 :
131 0 : if ( typeMatchesExtension( TYPE_WRITER, aExt) )
132 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_TEXT ) );
133 0 : else if ( typeMatchesExtension( TYPE_CALC, aExt) )
134 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_SHEET ) );
135 0 : else if ( typeMatchesExtension( TYPE_IMPRESS, aExt) )
136 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_PRESENTATION ) );
137 0 : else if ( typeMatchesExtension( TYPE_DRAW, aExt) )
138 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_DRAWING ) );
139 0 : else if ( typeMatchesExtension( TYPE_DATABASE, aExt) )
140 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_DATABASE ) );
141 0 : else if ( typeMatchesExtension( TYPE_MATH, aExt) )
142 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_MATH ) );
143 : else
144 0 : aImg = BitmapEx ( SfxResId( SFX_FILE_THUMBNAIL_DEFAULT ) );
145 :
146 0 : return aImg;
147 : }
148 :
149 0 : void RecentDocsView::insertItem(const OUString &rURL, const OUString &rTitle, const BitmapEx &rThumbnail, sal_uInt16 nId)
150 : {
151 0 : RecentDocsViewItem *pChild = new RecentDocsViewItem(*this, rURL, rTitle, rThumbnail, nId, GetThumbnailSize());
152 :
153 0 : AppendItem(pChild);
154 0 : }
155 :
156 1 : void RecentDocsView::Reload()
157 : {
158 1 : Clear();
159 :
160 1 : Sequence< Sequence< PropertyValue > > aHistoryList = SvtHistoryOptions().GetList( ePICKLIST );
161 1 : for ( int i = 0; i < aHistoryList.getLength(); i++ )
162 : {
163 0 : Sequence< PropertyValue >& rRecentEntry = aHistoryList[i];
164 :
165 0 : OUString aURL;
166 0 : OUString aTitle;
167 0 : BitmapEx aThumbnail;
168 :
169 0 : for ( int j = 0; j < rRecentEntry.getLength(); j++ )
170 : {
171 0 : Any a = rRecentEntry[j].Value;
172 :
173 0 : if (rRecentEntry[j].Name == "URL")
174 0 : a >>= aURL;
175 0 : else if (rRecentEntry[j].Name == "Title")
176 0 : a >>= aTitle;
177 0 : else if (rRecentEntry[j].Name == "Thumbnail")
178 : {
179 0 : OUString aBase64;
180 0 : a >>= aBase64;
181 0 : if (!aBase64.isEmpty())
182 : {
183 0 : Sequence<sal_Int8> aDecoded;
184 0 : sax::Converter::decodeBase64(aDecoded, aBase64);
185 :
186 0 : SvMemoryStream aStream(aDecoded.getArray(), aDecoded.getLength(), StreamMode::READ);
187 0 : vcl::PNGReader aReader(aStream);
188 0 : aThumbnail = aReader.Read();
189 0 : }
190 : }
191 0 : }
192 :
193 0 : if (isAcceptedFile(aURL))
194 : {
195 0 : insertItem(aURL, aTitle, aThumbnail, i+1);
196 : }
197 0 : }
198 :
199 1 : CalculateItemPositions();
200 1 : Invalidate();
201 1 : }
202 :
203 0 : void RecentDocsView::MouseButtonDown( const MouseEvent& rMEvt )
204 : {
205 0 : if (rMEvt.IsLeft())
206 : {
207 0 : mnLastMouseDownItem = ImplGetItem(rMEvt.GetPosPixel());
208 :
209 : // ignore to avoid stuff done in ThumbnailView; we don't do selections etc.
210 0 : return;
211 : }
212 :
213 0 : ThumbnailView::MouseButtonDown(rMEvt);
214 : }
215 :
216 0 : void RecentDocsView::MouseButtonUp(const MouseEvent& rMEvt)
217 : {
218 0 : if (rMEvt.IsLeft())
219 : {
220 0 : if( rMEvt.GetClicks() > 1 )
221 0 : return;
222 :
223 0 : size_t nPos = ImplGetItem(rMEvt.GetPosPixel());
224 0 : ThumbnailViewItem* pItem = ImplGetItem(nPos);
225 :
226 0 : if (pItem && nPos == mnLastMouseDownItem)
227 0 : pItem->MouseButtonUp(rMEvt);
228 :
229 0 : mnLastMouseDownItem = THUMBNAILVIEW_ITEM_NOTFOUND;
230 :
231 0 : if (pItem)
232 0 : return;
233 : }
234 0 : ThumbnailView::MouseButtonUp(rMEvt);
235 : }
236 :
237 0 : void RecentDocsView::OnItemDblClicked(ThumbnailViewItem *pItem)
238 : {
239 0 : RecentDocsViewItem* pRecentItem = dynamic_cast< RecentDocsViewItem* >(pItem);
240 0 : if (pRecentItem)
241 0 : pRecentItem->OpenDocument();
242 0 : }
243 :
244 3 : void RecentDocsView::Paint(vcl::RenderContext& rRenderContext, const Rectangle &aRect)
245 : {
246 : // Set preferred width
247 3 : if (mFilteredItemList.empty())
248 : {
249 3 : rRenderContext.Push(PushFlags::FONT);
250 3 : SetMessageFont(rRenderContext);
251 3 : set_width_request(std::max(rRenderContext.GetTextWidth(maWelcomeLine1),
252 6 : rRenderContext.GetTextWidth(maWelcomeLine2)));
253 3 : rRenderContext.Pop();
254 : }
255 : else
256 : {
257 0 : set_width_request(mnTextHeight + mnItemMaxSize + 2 * mnItemPadding);
258 : }
259 :
260 3 : if (mItemList.size() == 0)
261 : {
262 : // No recent files to be shown yet. Show a welcome screen.
263 3 : rRenderContext.Push(PushFlags::FONT);
264 3 : SetMessageFont(rRenderContext);
265 :
266 3 : long nTextHeight = rRenderContext.GetTextHeight();
267 :
268 3 : long nTextWidth1 = rRenderContext.GetTextWidth(maWelcomeLine1);
269 3 : long nTextWidth2 = rRenderContext.GetTextWidth(maWelcomeLine2);
270 :
271 3 : const Size& rImgSize = maWelcomeImage.GetSizePixel();
272 3 : const Size& rSize = GetSizePixel();
273 :
274 3 : const int nX = (rSize.Width() - rImgSize.Width())/2;
275 3 : const int nY = (rSize.Height() - 3 * nTextHeight - rImgSize.Height())/2;
276 :
277 3 : Point aImgPoint(nX, nY);
278 3 : Point aStr1Point((rSize.Width() - nTextWidth1)/2, nY + rImgSize.Height() + 0.7 * nTextHeight);
279 3 : Point aStr2Point((rSize.Width() - nTextWidth2)/2, nY + rImgSize.Height() + 1.7 * nTextHeight);
280 :
281 3 : rRenderContext.DrawImage(aImgPoint, rImgSize, maWelcomeImage, DrawImageFlags::SemiTransparent);
282 3 : rRenderContext.DrawText(aStr1Point, maWelcomeLine1);
283 3 : rRenderContext.DrawText(aStr2Point, maWelcomeLine2);
284 :
285 3 : rRenderContext.Pop();
286 : }
287 : else
288 : {
289 0 : ThumbnailView::Paint(rRenderContext, aRect);
290 : }
291 3 : }
292 :
293 0 : void RecentDocsView::LoseFocus()
294 : {
295 0 : deselectItems();
296 :
297 0 : ThumbnailView::LoseFocus();
298 0 : }
299 :
300 :
301 1 : void RecentDocsView::Clear()
302 : {
303 1 : Invalidate();
304 1 : ThumbnailView::Clear();
305 1 : }
306 :
307 0 : IMPL_STATIC_LINK( RecentDocsView, ExecuteHdl_Impl, LoadRecentFile*, pLoadRecentFile )
308 : {
309 : try
310 : {
311 : // Asynchronous execution as this can lead to our own destruction!
312 : // Framework can recycle our current frame and the layout manager disposes all user interface
313 : // elements if a component gets detached from its frame!
314 0 : pLoadRecentFile->xDispatch->dispatch( pLoadRecentFile->aTargetURL, pLoadRecentFile->aArgSeq );
315 : }
316 0 : catch ( const Exception& )
317 : {
318 : }
319 :
320 0 : delete pLoadRecentFile;
321 0 : return 0;
322 648 : }
323 :
324 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|