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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/log.hxx>
21 #include <comphelper/DirectoryHelper.hxx>
22 #include <recentdocsview.hxx>
23 #include <sfx2/sfxresid.hxx>
24 #include <unotools/historyoptions.hxx>
25 #include <vcl/event.hxx>
26 #include <vcl/ptrstyle.hxx>
27 #include <vcl/svapp.hxx>
28 #include <tools/urlobj.hxx>
29 #include <com/sun/star/frame/XDispatch.hpp>
30 #include <sfx2/strings.hrc>
31 #include <bitmaps.hlst>
32 #include "recentdocsviewitem.hxx"
33 #include <sfx2/app.hxx>
35 #include <officecfg/Office/Common.hxx>
39 using namespace ::com::sun::star
;
40 using namespace com::sun::star::uno
;
41 using namespace com::sun::star::lang
;
42 using namespace com::sun::star::beans
;
46 /// Set (larger) font for the Welcome message.
47 void SetMessageFont(vcl::RenderContext
& rRenderContext
)
49 vcl::Font
aFont(rRenderContext
.GetFont());
50 aFont
.SetFontHeight(aFont
.GetFontHeight() * 1.3);
51 rRenderContext
.SetFont(aFont
);
59 constexpr tools::Long gnTextHeight
= 30;
60 constexpr tools::Long gnItemPadding
= 5;
62 RecentDocsView::RecentDocsView(std::unique_ptr
<weld::ScrolledWindow
> xWindow
, std::unique_ptr
<weld::Menu
> xMenu
)
63 : ThumbnailView(std::move(xWindow
), std::move(xMenu
))
64 , mnFileTypes(ApplicationType::TYPE_NONE
)
65 , mnLastMouseDownItem(THUMBNAILVIEW_ITEM_NOTFOUND
)
66 , maWelcomeLine1(SfxResId(STR_WELCOME_LINE1
))
67 , maWelcomeLine2(SfxResId(STR_WELCOME_LINE2
))
68 , mpLoadRecentFile(nullptr)
69 , m_nExecuteHdlId(nullptr)
71 mbAllowMultiSelection
= false;
72 AbsoluteScreenPixelRectangle aScreen
= Application::GetScreenPosSizePixel(Application::GetDisplayBuiltInScreen());
73 mnItemMaxSize
= std::min(aScreen
.GetWidth(),aScreen
.GetHeight()) > 800 ? 256 : 192;
75 setItemMaxTextLength( 30 );
76 setItemDimensions( mnItemMaxSize
, mnItemMaxSize
, gnTextHeight
, gnItemPadding
);
78 maFillColor
= Color(ColorTransparency
, officecfg::Office::Common::Help::StartCenter::StartCenterThumbnailsBackgroundColor::get());
79 maTextColor
= Color(ColorTransparency
, officecfg::Office::Common::Help::StartCenter::StartCenterThumbnailsTextColor::get());
81 const StyleSettings
& rSettings
= Application::GetSettings().GetStyleSettings();
82 maHighlightColor
= rSettings
.GetHighlightColor();
83 maHighlightTextColor
= rSettings
.GetHighlightTextColor();
85 mfHighlightTransparence
= 0.75;
90 RecentDocsView::~RecentDocsView()
92 Application::RemoveUserEvent(m_nExecuteHdlId
);
93 m_nExecuteHdlId
= nullptr;
96 mpLoadRecentFile
->pView
= nullptr;
97 mpLoadRecentFile
= nullptr;
101 bool RecentDocsView::typeMatchesExtension(ApplicationType type
, std::u16string_view rExt
)
105 if (rExt
== u
"odt" || rExt
== u
"fodt" || rExt
== u
"doc" || rExt
== u
"docx" ||
106 rExt
== u
"rtf" || rExt
== u
"txt" || rExt
== u
"odm" || rExt
== u
"otm")
108 bRet
= static_cast<bool>(type
& ApplicationType::TYPE_WRITER
);
110 else if (rExt
== u
"ods" || rExt
== u
"fods" || rExt
== u
"xls" || rExt
== u
"xlsx")
112 bRet
= static_cast<bool>(type
& ApplicationType::TYPE_CALC
);
114 else if (rExt
== u
"odp" || rExt
== u
"fodp" || rExt
== u
"pps" || rExt
== u
"ppt" ||
117 bRet
= static_cast<bool>(type
& ApplicationType::TYPE_IMPRESS
);
119 else if (rExt
== u
"odg" || rExt
== u
"fodg")
121 bRet
= static_cast<bool>(type
& ApplicationType::TYPE_DRAW
);
123 else if (rExt
== u
"odb")
125 bRet
= static_cast<bool>(type
& ApplicationType::TYPE_DATABASE
);
127 else if (rExt
== u
"odf")
129 bRet
= static_cast<bool>(type
& ApplicationType::TYPE_MATH
);
133 bRet
= static_cast<bool>(type
& ApplicationType::TYPE_OTHER
);
139 bool RecentDocsView::isAcceptedFile(const INetURLObject
& rURL
) const
141 const OUString aExt
= rURL
.getExtension();
142 return (mnFileTypes
& ApplicationType::TYPE_WRITER
&& typeMatchesExtension(ApplicationType::TYPE_WRITER
, aExt
)) ||
143 (mnFileTypes
& ApplicationType::TYPE_CALC
&& typeMatchesExtension(ApplicationType::TYPE_CALC
, aExt
)) ||
144 (mnFileTypes
& ApplicationType::TYPE_IMPRESS
&& typeMatchesExtension(ApplicationType::TYPE_IMPRESS
, aExt
)) ||
145 (mnFileTypes
& ApplicationType::TYPE_DRAW
&& typeMatchesExtension(ApplicationType::TYPE_DRAW
, aExt
)) ||
146 (mnFileTypes
& ApplicationType::TYPE_DATABASE
&& typeMatchesExtension(ApplicationType::TYPE_DATABASE
,aExt
)) ||
147 (mnFileTypes
& ApplicationType::TYPE_MATH
&& typeMatchesExtension(ApplicationType::TYPE_MATH
, aExt
)) ||
148 (mnFileTypes
& ApplicationType::TYPE_OTHER
&& typeMatchesExtension(ApplicationType::TYPE_OTHER
, aExt
));
151 void RecentDocsView::insertItem(const OUString
& rURL
, const OUString
& rTitle
,
152 const OUString
& rThumbnail
, bool isReadOnly
, bool isPinned
,
155 AppendItem(std::make_unique
<RecentDocsViewItem
>(*this, rURL
, rTitle
, rThumbnail
, nId
,
156 mnItemMaxSize
, isReadOnly
, isPinned
));
159 void RecentDocsView::Reload()
163 std::vector
< SvtHistoryOptions::HistoryItem
> aHistoryList
= SvtHistoryOptions::GetList( EHistoryType::PickList
);
164 for ( size_t i
= 0; i
< aHistoryList
.size(); i
++ )
166 const SvtHistoryOptions::HistoryItem
& rRecentEntry
= aHistoryList
[i
];
168 OUString aURL
= rRecentEntry
.sURL
;
169 const INetURLObject
aURLObj(aURL
);
171 if ((mnFileTypes
!= ApplicationType::TYPE_NONE
) &&
172 (!isAcceptedFile(aURLObj
)))
175 //Remove extension from url's last segment and use it as title
176 const OUString aTitle
= aURLObj
.GetBase(); //DecodeMechanism::WithCharset
178 insertItem(aURL
, aTitle
, rRecentEntry
.sThumbnail
, rRecentEntry
.isReadOnly
,
179 rRecentEntry
.isPinned
, i
+ 1);
182 CalculateItemPositions();
186 void RecentDocsView::setFilter(ApplicationType aFilter
)
188 mnFileTypes
= aFilter
;
192 void RecentDocsView::clearUnavailableFiles(){
193 std::vector
< SvtHistoryOptions::HistoryItem
> aHistoryList
= SvtHistoryOptions::GetList( EHistoryType::PickList
);
194 for ( size_t i
= 0; i
< aHistoryList
.size(); i
++ )
196 const SvtHistoryOptions::HistoryItem
& rPickListEntry
= aHistoryList
[i
];
197 if ( !comphelper::DirectoryHelper::fileExists(rPickListEntry
.sURL
) ){
198 SvtHistoryOptions::DeleteItem(EHistoryType::PickList
,rPickListEntry
.sURL
, false);
204 bool RecentDocsView::MouseButtonDown( const MouseEvent
& rMEvt
)
208 mnLastMouseDownItem
= ImplGetItem(rMEvt
.GetPosPixel());
210 // ignore to avoid stuff done in ThumbnailView; we don't do selections etc.
214 return ThumbnailView::MouseButtonDown(rMEvt
);
217 bool RecentDocsView::MouseButtonUp(const MouseEvent
& rMEvt
)
221 if( rMEvt
.GetClicks() > 1 )
224 size_t nPos
= ImplGetItem(rMEvt
.GetPosPixel());
225 ThumbnailViewItem
* pItem
= ImplGetItem(nPos
);
227 if (pItem
&& nPos
== mnLastMouseDownItem
)
229 pItem
->MouseButtonUp(rMEvt
);
231 ThumbnailViewItem
* pNewItem
= ImplGetItem(nPos
);
233 pNewItem
->setHighlight(true);
236 mnLastMouseDownItem
= THUMBNAILVIEW_ITEM_NOTFOUND
;
241 return ThumbnailView::MouseButtonUp(rMEvt
);
244 void RecentDocsView::OnItemDblClicked(ThumbnailViewItem
*pItem
)
246 RecentDocsViewItem
* pRecentItem
= dynamic_cast< RecentDocsViewItem
* >(pItem
);
248 pRecentItem
->OpenDocument();
251 void RecentDocsView::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&aRect
)
253 ThumbnailView::Paint(rRenderContext
, aRect
);
255 if (!mItemList
.empty())
258 if (maWelcomeImage
.IsEmpty())
260 const tools::Long
aWidth(aRect
.GetWidth() > aRect
.getOpenHeight() ? aRect
.GetHeight()/2 : aRect
.GetWidth()/2);
261 maWelcomeImage
= SfxApplication::GetApplicationLogo(aWidth
);
264 // No recent files to be shown yet. Show a welcome screen.
265 rRenderContext
.Push(vcl::PushFlags::FONT
| vcl::PushFlags::TEXTCOLOR
);
266 SetMessageFont(rRenderContext
);
267 rRenderContext
.SetTextColor(maTextColor
);
269 tools::Long nTextHeight
= rRenderContext
.GetTextHeight();
271 const Size
& rImgSize
= maWelcomeImage
.GetSizePixel();
272 const Size
& rSize
= GetOutputSizePixel();
274 const int nX
= (rSize
.Width() - rImgSize
.Width())/2;
275 int nY
= (rSize
.Height() - 3 * nTextHeight
- rImgSize
.Height())/2;
276 Point
aImgPoint(nX
, nY
);
277 rRenderContext
.DrawBitmapEx(aImgPoint
, rImgSize
, maWelcomeImage
);
279 nY
= nY
+ rImgSize
.Height();
280 rRenderContext
.DrawText(tools::Rectangle(0, nY
+ 1 * nTextHeight
, rSize
.Width(), nY
+ nTextHeight
),
282 DrawTextFlags::Center
);
283 rRenderContext
.DrawText(tools::Rectangle(0, nY
+ 2 * nTextHeight
, rSize
.Width(), rSize
.Height()),
285 DrawTextFlags::MultiLine
| DrawTextFlags::WordBreak
| DrawTextFlags::Center
);
287 rRenderContext
.Pop();
290 void RecentDocsView::LoseFocus()
294 ThumbnailView::LoseFocus();
297 void RecentDocsView::Clear()
300 ThumbnailView::Clear();
303 void RecentDocsView::PostLoadRecentUsedFile(LoadRecentFile
* pLoadRecentFile
)
305 assert(!mpLoadRecentFile
);
306 mpLoadRecentFile
= pLoadRecentFile
;
307 m_nExecuteHdlId
= Application::PostUserEvent(LINK(this, RecentDocsView
, ExecuteHdl_Impl
), pLoadRecentFile
);
310 void RecentDocsView::DispatchedLoadRecentUsedFile()
312 mpLoadRecentFile
= nullptr;
315 IMPL_LINK( RecentDocsView
, ExecuteHdl_Impl
, void*, p
, void )
317 m_nExecuteHdlId
= nullptr;
318 LoadRecentFile
* pLoadRecentFile
= static_cast<LoadRecentFile
*>(p
);
321 // Asynchronous execution as this can lead to our own destruction!
322 // Framework can recycle our current frame and the layout manager disposes all user interface
323 // elements if a component gets detached from its frame!
324 pLoadRecentFile
->xDispatch
->dispatch( pLoadRecentFile
->aTargetURL
, pLoadRecentFile
->aArgSeq
);
326 catch ( const Exception
& )
330 if (pLoadRecentFile
->pView
)
332 pLoadRecentFile
->pView
->DispatchedLoadRecentUsedFile();
333 pLoadRecentFile
->pView
->SetPointer(PointerStyle::Arrow
);
334 pLoadRecentFile
->pView
->Enable();
337 delete pLoadRecentFile
;
342 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */