xref: /core/sfx2/source/dialog/backingwindow.cxx (revision cae3854f05b3e2ca65b56e8b05183d6817f9bdf5)
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 "backingwindow.hxx"
21 #include <utility>
22 #include <vcl/event.hxx>
23 #include <vcl/help.hxx>
24 #include <vcl/ptrstyle.hxx>
25 #include <vcl/settings.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/syswin.hxx>
28 
29 #include <unotools/historyoptions.hxx>
30 #include <unotools/moduleoptions.hxx>
31 #include <unotools/cmdoptions.hxx>
32 #include <unotools/configmgr.hxx>
33 #include <svtools/openfiledroptargetlistener.hxx>
34 #include <svtools/colorcfg.hxx>
35 #include <svtools/langhelp.hxx>
36 #include <templateviewitem.hxx>
37 
38 #include <comphelper/processfactory.hxx>
39 #include <comphelper/propertysequence.hxx>
40 #include <comphelper/propertyvalue.hxx>
41 #include <sfx2/app.hxx>
42 #include <officecfg/Office/Common.hxx>
43 
44 #include <i18nlangtag/languagetag.hxx>
45 #include <comphelper/diagnose_ex.hxx>
46 
47 #include <com/sun/star/configuration/theDefaultProvider.hpp>
48 #include <com/sun/star/container/XNameAccess.hpp>
49 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
50 #include <com/sun/star/document/MacroExecMode.hpp>
51 #include <com/sun/star/document/UpdateDocMode.hpp>
52 #include <com/sun/star/frame/Desktop.hpp>
53 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
54 #include <com/sun/star/system/SystemShellExecute.hpp>
55 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
56 #include <com/sun/star/util/URLTransformer.hpp>
57 #include <com/sun/star/task/InteractionHandler.hpp>
58 
59 #include <sfx2/strings.hrc>
60 #include <sfx2/sfxresid.hxx>
61 #include <bitmaps.hlst>
62 
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::beans;
65 using namespace ::com::sun::star::frame;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::document;
68 
69 class BrandImage final : public weld::CustomWidgetController
70 {
71 private:
72     Bitmap maBrandImage;
73     bool mbIsDark = false;
74     Size m_BmpSize;
75 
76 public:
getSize()77     const Size & getSize() { return m_BmpSize; }
78 
SetDrawingArea(weld::DrawingArea * pDrawingArea)79     virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override
80     {
81         weld::CustomWidgetController::SetDrawingArea(pDrawingArea);
82 
83         const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
84         OutputDevice& rDevice = pDrawingArea->get_ref_device();
85         rDevice.SetBackground(Wallpaper(rStyleSettings.GetWindowColor()));
86 
87         SetPointer(PointerStyle::RefHand);
88     }
89 
Resize()90     virtual void Resize() override
91     {
92         auto nWidth = GetOutputSizePixel().Width();
93         if (maBrandImage.GetSizePixel().Width() != nWidth)
94             LoadImageForWidth(nWidth);
95         weld::CustomWidgetController::Resize();
96     }
97 
LoadImageForWidth(int nWidth)98     void LoadImageForWidth(int nWidth)
99     {
100         mbIsDark = Application::GetSettings().GetStyleSettings().GetDialogColor().IsDark();
101         SfxApplication::loadBrandSvg(mbIsDark ? "shell/logo-sc_inverted" : "shell/logo-sc",
102                                     maBrandImage, nWidth);
103     }
104 
ConfigureForWidth(int nWidth)105     void ConfigureForWidth(int nWidth)
106     {
107         LoadImageForWidth(nWidth);
108         m_BmpSize = maBrandImage.GetSizePixel();
109         set_size_request(m_BmpSize.Width(), m_BmpSize.Height());
110     }
111 
StyleUpdated()112     virtual void StyleUpdated() override
113     {
114         const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
115 
116         // tdf#141857 update background to current theme
117         OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
118         rDevice.SetBackground(Wallpaper(rStyleSettings.GetWindowColor()));
119 
120         const bool bIsDark = rStyleSettings.GetDialogColor().IsDark();
121         if (bIsDark != mbIsDark)
122             LoadImageForWidth(GetOutputSizePixel().Width());
123         weld::CustomWidgetController::StyleUpdated();
124     }
125 
MouseButtonUp(const MouseEvent & rMEvt)126     virtual bool MouseButtonUp(const MouseEvent& rMEvt) override
127     {
128         if (rMEvt.IsLeft())
129         {
130             OUString sURL = officecfg::Office::Common::Menus::VolunteerURL::get();
131             localizeWebserviceURI(sURL);
132 
133             Reference<css::system::XSystemShellExecute> const xSystemShellExecute(
134                 css::system::SystemShellExecute::create(
135                     ::comphelper::getProcessComponentContext()));
136             xSystemShellExecute->execute(sURL, OUString(),
137                                          css::system::SystemShellExecuteFlags::URIS_ONLY);
138         }
139         return true;
140     }
141 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)142     virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override
143     {
144         rRenderContext.DrawBitmapEx(Point(0, 0), maBrandImage);
145     }
146 };
147 
148 // increase size of the text in the buttons on the left fMultiplier-times
149 float const g_fMultiplier = 1.2f;
150 
BackingWindow(vcl::Window * i_pParent)151 BackingWindow::BackingWindow(vcl::Window* i_pParent)
152     : InterimItemWindow(i_pParent, u"sfx/ui/startcenter.ui"_ustr, u"StartCenter"_ustr, false)
153     , mxOpenButton(m_xBuilder->weld_button(u"open_all"_ustr))
154     , mxRecentButton(m_xBuilder->weld_toggle_button(u"open_recent"_ustr))
155     , mxRemoteButton(m_xBuilder->weld_button(u"open_remote"_ustr))
156     , mxTemplateButton(m_xBuilder->weld_toggle_button(u"templates_all"_ustr))
157     , mxCreateLabel(m_xBuilder->weld_label(u"create_label"_ustr))
158     , mxAltHelpLabel(m_xBuilder->weld_label(u"althelplabel"_ustr))
159     , mxFilter(m_xBuilder->weld_combo_box(u"cbFilter"_ustr))
160     , mxActions(m_xBuilder->weld_menu_button(u"mbActions"_ustr))
161     , mxWriterAllButton(m_xBuilder->weld_button(u"writer_all"_ustr))
162     , mxCalcAllButton(m_xBuilder->weld_button(u"calc_all"_ustr))
163     , mxImpressAllButton(m_xBuilder->weld_button(u"impress_all"_ustr))
164     , mxDrawAllButton(m_xBuilder->weld_button(u"draw_all"_ustr))
165     , mxDBAllButton(m_xBuilder->weld_button(u"database_all"_ustr))
166     , mxMathAllButton(m_xBuilder->weld_button(u"math_all"_ustr))
167     , mxBrandImage(new BrandImage)
168     , mxBrandImageWeld(new weld::CustomWeld(*m_xBuilder, u"daBrand"_ustr, *mxBrandImage))
169     , mxHelpButton(m_xBuilder->weld_button(u"help"_ustr))
170     , mxExtensionsButton(m_xBuilder->weld_button(u"extensions"_ustr))
171     , mxDonateButton(m_xBuilder->weld_button(u"donate"_ustr))
172     , mxAllButtonsBox(m_xBuilder->weld_container(u"all_buttons_box"_ustr))
173     , mxButtonsBox(m_xBuilder->weld_container(u"buttons_box"_ustr))
174     , mxSmallButtonsBox(m_xBuilder->weld_container(u"small_buttons_box"_ustr))
175     , mxAllRecentThumbnails(new sfx2::RecentDocsView(m_xBuilder->weld_scrolled_window(u"scrollrecent"_ustr, true),
176                                                      m_xBuilder->weld_menu(u"recentmenu"_ustr)))
177     , mxAllRecentThumbnailsWin(new weld::CustomWeld(*m_xBuilder, u"all_recent"_ustr, *mxAllRecentThumbnails))
178     , mxLocalView(new TemplateDefaultView(m_xBuilder->weld_scrolled_window(u"scrolllocal"_ustr, true),
179                                           m_xBuilder->weld_menu(u"localmenu"_ustr)))
180     , mxLocalViewWin(new weld::CustomWeld(*m_xBuilder, u"local_view"_ustr, *mxLocalView))
181     , mbLocalViewInitialized(false)
182     , mbInitControls(false)
183 {
184     // init background, undo InterimItemWindow defaults for this widget
185     SetPaintTransparent(false);
186 
187     // square action button
188     auto nHeight = mxFilter->get_preferred_size().getHeight();
189     mxActions->set_size_request(nHeight, nHeight);
190 
191     //set an alternative help label that doesn't hotkey the H of the Help menu
192     mxHelpButton->set_label(mxAltHelpLabel->get_label());
193     mxHelpButton->connect_clicked(LINK(this, BackingWindow, ClickHelpHdl));
194 
195     // tdf#161796 replace the extension button with a donate button
196     if (officecfg::Office::Common::Misc::ShowDonation::get())
197     {
198         mxExtensionsButton->hide();
199         mxDonateButton->show();
200         mxDonateButton->set_from_icon_name(BMP_DONATE);
201         OUString sDonate(SfxResId(STR_DONATE_BUTTON));
202         if (sDonate.getLength() > 8)
203         {
204             mxDonateButton->set_tooltip_text(sDonate);
205             sDonate = OUString::Concat(sDonate.subView(0, 7)) + "...";
206         }
207         mxDonateButton->set_label(sDonate);
208     }
209 
210     mxDropTarget = mxAllRecentThumbnails->GetDropTarget();
211 
212     try
213     {
214         mxContext.set( ::comphelper::getProcessComponentContext(), uno::UNO_SET_THROW );
215     }
216     catch (const Exception&)
217     {
218         TOOLS_WARN_EXCEPTION( "fwk", "BackingWindow" );
219     }
220 
221     SetStyle( GetStyle() | WB_DIALOGCONTROL );
222 
223     // get dispatch provider
224     Reference<XDesktop2> xDesktop = Desktop::create( comphelper::getProcessComponentContext() );
225     mxDesktopDispatchProvider = xDesktop;
226 
227 }
228 
IMPL_LINK(BackingWindow,ClickHelpHdl,weld::Button &,rButton,void)229 IMPL_LINK(BackingWindow, ClickHelpHdl, weld::Button&, rButton, void)
230 {
231     if (Help* pHelp = Application::GetHelp())
232         pHelp->Start(m_xContainer->get_help_id(), &rButton);
233 }
234 
~BackingWindow()235 BackingWindow::~BackingWindow()
236 {
237     disposeOnce();
238 }
239 
dispose()240 void BackingWindow::dispose()
241 {
242     // deregister drag&drop helper
243     if (mxDropTargetListener.is())
244     {
245         if (mxDropTarget.is())
246         {
247             mxDropTarget->removeDropTargetListener(mxDropTargetListener);
248             mxDropTarget->setActive(false);
249         }
250         mxDropTargetListener.clear();
251     }
252     mxDropTarget.clear();
253     mxOpenButton.reset();
254     mxRemoteButton.reset();
255     mxRecentButton.reset();
256     mxTemplateButton.reset();
257     mxCreateLabel.reset();
258     mxAltHelpLabel.reset();
259     mxFilter.reset();
260     mxActions.reset();
261     mxWriterAllButton.reset();
262     mxCalcAllButton.reset();
263     mxImpressAllButton.reset();
264     mxDrawAllButton.reset();
265     mxDBAllButton.reset();
266     mxMathAllButton.reset();
267     mxBrandImageWeld.reset();
268     mxBrandImage.reset();
269     mxHelpButton.reset();
270     mxDonateButton.reset();
271     mxExtensionsButton.reset();
272     mxAllButtonsBox.reset();
273     mxButtonsBox.reset();
274     mxSmallButtonsBox.reset();
275     mxAllRecentThumbnailsWin.reset();
276     mxAllRecentThumbnails.reset();
277     mxLocalViewWin.reset();
278     mxLocalView.reset();
279     InterimItemWindow::dispose();
280 }
281 
initControls()282 void BackingWindow::initControls()
283 {
284     if( mbInitControls )
285         return;
286 
287     mbInitControls = true;
288 
289     // collect the URLs of the entries in the File/New menu
290     SvtModuleOptions    aModuleOptions;
291 
292     if (aModuleOptions.IsWriterInstalled())
293         mxAllRecentThumbnails->mnFileTypes |= sfx2::ApplicationType::TYPE_WRITER;
294 
295     if (aModuleOptions.IsCalcInstalled())
296         mxAllRecentThumbnails->mnFileTypes |= sfx2::ApplicationType::TYPE_CALC;
297 
298     if (aModuleOptions.IsImpressInstalled())
299         mxAllRecentThumbnails->mnFileTypes |= sfx2::ApplicationType::TYPE_IMPRESS;
300 
301     if (aModuleOptions.IsDrawInstalled())
302         mxAllRecentThumbnails->mnFileTypes |= sfx2::ApplicationType::TYPE_DRAW;
303 
304     if (aModuleOptions.IsDataBaseInstalled())
305         mxAllRecentThumbnails->mnFileTypes |= sfx2::ApplicationType::TYPE_DATABASE;
306 
307     if (aModuleOptions.IsMathInstalled())
308         mxAllRecentThumbnails->mnFileTypes |= sfx2::ApplicationType::TYPE_MATH;
309 
310     mxAllRecentThumbnails->mnFileTypes |= sfx2::ApplicationType::TYPE_OTHER;
311     mxAllRecentThumbnails->Reload();
312     mxAllRecentThumbnails->ShowTooltips( true );
313 
314     mxRecentButton->set_active(true);
315     ToggleHdl(*mxRecentButton);
316 
317     //set handlers
318     mxLocalView->setCreateContextMenuHdl(LINK(this, BackingWindow, CreateContextMenuHdl));
319     mxLocalView->setOpenTemplateHdl(LINK(this, BackingWindow, OpenTemplateHdl));
320     mxLocalView->setEditTemplateHdl(LINK(this, BackingWindow, EditTemplateHdl));
321     mxLocalView->ShowTooltips( true );
322 
323     checkInstalledModules();
324 
325     mxExtensionsButton->connect_clicked(LINK(this, BackingWindow, ExtLinkClickHdl));
326     mxDonateButton->connect_clicked(LINK(this, BackingWindow, ExtLinkClickHdl));
327 
328     mxOpenButton->connect_clicked(LINK(this, BackingWindow, ClickHdl));
329 
330     // Hide OpenRemote button on startpage if the OpenRemote uno command is not available
331     SvtCommandOptions aCmdOptions;
332     if (SvtCommandOptions().HasEntriesDisabled() && aCmdOptions.LookupDisabled(u"OpenRemote"_ustr))
333         mxRemoteButton->set_visible(false);
334     else
335         mxRemoteButton->connect_clicked(LINK(this, BackingWindow, ClickHdl));
336 
337     mxWriterAllButton->connect_clicked(LINK(this, BackingWindow, ClickHdl));
338     mxDrawAllButton->connect_clicked(LINK(this, BackingWindow, ClickHdl));
339     mxCalcAllButton->connect_clicked(LINK(this, BackingWindow, ClickHdl));
340     mxDBAllButton->connect_clicked(LINK(this, BackingWindow, ClickHdl));
341     mxImpressAllButton->connect_clicked(LINK(this, BackingWindow, ClickHdl));
342     mxMathAllButton->connect_clicked(LINK(this, BackingWindow, ClickHdl));
343 
344     mxRecentButton->connect_toggled(LINK(this, BackingWindow, ToggleHdl));
345     mxTemplateButton->connect_toggled(LINK(this, BackingWindow, ToggleHdl));
346 
347     mxFilter->connect_changed(LINK(this, BackingWindow, FilterHdl));
348     mxActions->connect_selected(LINK(this, BackingWindow, MenuSelectHdl));
349 
350     ApplyStyleSettings();
351 }
352 
DataChanged(const DataChangedEvent & rDCEvt)353 void BackingWindow::DataChanged(const DataChangedEvent& rDCEvt)
354 {
355     if ((rDCEvt.GetType() != DataChangedEventType::SETTINGS)
356         || !(rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
357     {
358         InterimItemWindow::DataChanged(rDCEvt);
359         return;
360     }
361 
362     ApplyStyleSettings();
363     Invalidate();
364 }
365 
366 template <typename WidgetClass>
setLargerFont(WidgetClass & pWidget,const vcl::Font & rFont)367 void BackingWindow::setLargerFont(WidgetClass& pWidget, const vcl::Font& rFont)
368 {
369     vcl::Font aFont(rFont);
370     aFont.SetFontSize(Size(0, aFont.GetFontSize().Height() * g_fMultiplier));
371     pWidget->set_font(aFont);
372 }
373 
ApplyStyleSettings()374 void BackingWindow::ApplyStyleSettings()
375 {
376     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
377     const Color aButtonsBackground(rStyleSettings.GetWindowColor());
378     const vcl::Font& aButtonFont(rStyleSettings.GetPushButtonFont());
379     const vcl::Font& aLabelFont(rStyleSettings.GetLabelFont());
380 
381     // setup larger fonts
382     setLargerFont(mxOpenButton, aButtonFont);
383     setLargerFont(mxRemoteButton, aButtonFont);
384     setLargerFont(mxRecentButton, aButtonFont);
385     setLargerFont(mxTemplateButton, aButtonFont);
386     setLargerFont(mxWriterAllButton, aButtonFont);
387     setLargerFont(mxDrawAllButton, aButtonFont);
388     setLargerFont(mxCalcAllButton, aButtonFont);
389     setLargerFont(mxDBAllButton, aButtonFont);
390     setLargerFont(mxImpressAllButton, aButtonFont);
391     setLargerFont(mxMathAllButton, aButtonFont);
392     setLargerFont(mxCreateLabel, aLabelFont);
393 
394     mxAllButtonsBox->set_background(aButtonsBackground);
395     mxSmallButtonsBox->set_background(aButtonsBackground);
396     SetBackground(aButtonsBackground);
397 
398     // compute the menubar height
399     sal_Int32 nMenuHeight = 0;
400     if (SystemWindow* pSystemWindow = GetSystemWindow())
401         nMenuHeight = pSystemWindow->GetMenuBarHeight();
402 
403     // fdo#34392: we do the layout dynamically, the layout depends on the font,
404     // so we should handle data changed events (font changing) of the last child
405     // control, at this point all the controls have updated settings (i.e. font).
406     Size aPrefSize(mxAllButtonsBox->get_preferred_size());
407     set_width_request(aPrefSize.Width());
408 
409     // Now set a brand image wide enough to fill this width
410     weld::DrawingArea* pDrawingArea = mxBrandImage->GetDrawingArea();
411     mxBrandImage->ConfigureForWidth(aPrefSize.Width() -
412                                     (pDrawingArea->get_margin_start() + pDrawingArea->get_margin_end()));
413     // Refetch because the brand image height to match this width is now set
414     aPrefSize = mxAllButtonsBox->get_preferred_size();
415 
416     set_height_request(nMenuHeight + aPrefSize.Height() + mxBrandImage->getSize().getHeight());
417 }
418 
initializeLocalView()419 void BackingWindow::initializeLocalView()
420 {
421     if (!mbLocalViewInitialized)
422     {
423         mbLocalViewInitialized = true;
424         mxLocalView->Populate();
425         mxLocalView->filterItems(ViewFilter_Application(FILTER_APPLICATION::NONE));
426         mxLocalView->showAllTemplates();
427     }
428 }
429 
checkInstalledModules()430 void BackingWindow::checkInstalledModules()
431 {
432     if (officecfg::Office::Common::Misc::ViewerAppMode::get())
433     {
434         mxTemplateButton->set_visible(false);
435         mxCreateLabel->set_visible(false);
436         mxWriterAllButton->set_visible(false);
437         mxCalcAllButton->set_visible(false);
438         mxImpressAllButton->set_visible(false);
439         mxDrawAllButton->set_visible(false);
440         mxMathAllButton->set_visible(false);
441         mxDBAllButton->set_visible(false);
442         return;
443     }
444 
445     SvtModuleOptions aModuleOpt;
446 
447     mxWriterAllButton->set_sensitive(aModuleOpt.IsWriterInstalled());
448     mxCalcAllButton->set_sensitive(aModuleOpt.IsCalcInstalled());
449     mxImpressAllButton->set_sensitive(aModuleOpt.IsImpressInstalled());
450     mxDrawAllButton->set_sensitive(aModuleOpt.IsDrawInstalled());
451     mxMathAllButton->set_sensitive(aModuleOpt.IsMathInstalled());
452     mxDBAllButton->set_sensitive(aModuleOpt.IsDataBaseInstalled());
453 }
454 
PreNotify(NotifyEvent & rNEvt)455 bool BackingWindow::PreNotify(NotifyEvent& rNEvt)
456 {
457     if( rNEvt.GetType() == NotifyEventType::KEYINPUT )
458     {
459         const KeyEvent* pEvt = rNEvt.GetKeyEvent();
460         const vcl::KeyCode& rKeyCode(pEvt->GetKeyCode());
461 
462         bool bThumbnailHasFocus = mxAllRecentThumbnails->HasFocus() || mxLocalView->HasFocus();
463 
464         // Subwindows of BackingWindow: Sidebar and Thumbnail view
465         if( rKeyCode.GetCode() == KEY_F6 )
466         {
467             if( rKeyCode.IsShift() ) // Shift + F6
468             {
469                 if (bThumbnailHasFocus)
470                 {
471                     mxOpenButton->grab_focus();
472                     return true;
473                 }
474             }
475             else if ( rKeyCode.IsMod1() ) // Ctrl + F6
476             {
477                 if(mxAllRecentThumbnails->IsVisible())
478                 {
479                     mxAllRecentThumbnails->GrabFocus();
480                     return true;
481                 }
482                 else if(mxLocalView->IsVisible())
483                 {
484                     mxLocalView->GrabFocus();
485                     return true;
486                 }
487             }
488             else // F6
489             {
490                 if (!bThumbnailHasFocus)
491                 {
492                     if(mxAllRecentThumbnails->IsVisible())
493                     {
494                         mxAllRecentThumbnails->GrabFocus();
495                         return true;
496                     }
497                     else if(mxLocalView->IsVisible())
498                     {
499                         mxLocalView->GrabFocus();
500                         return true;
501                     }
502                 }
503             }
504         }
505 
506         // try the 'normal' accelerators (so that eg. Ctrl+Q works)
507         if (!mpAccExec)
508         {
509             mpAccExec = svt::AcceleratorExecute::createAcceleratorHelper();
510             mpAccExec->init( comphelper::getProcessComponentContext(), mxFrame);
511         }
512 
513         const OUString aCommand = mpAccExec->findCommand(svt::AcceleratorExecute::st_VCLKey2AWTKey(rKeyCode));
514         if ((aCommand != "vnd.sun.star.findbar:FocusToFindbar") && pEvt && mpAccExec->execute(rKeyCode))
515             return true;
516     }
517     return InterimItemWindow::PreNotify( rNEvt );
518 }
519 
GetFocus()520 void BackingWindow::GetFocus()
521 {
522     GetFocusFlags nFlags = GetParent()->GetGetFocusFlags();
523     if( nFlags & GetFocusFlags::F6 )
524     {
525         if( nFlags & GetFocusFlags::Forward ) // F6
526         {
527             mxOpenButton->grab_focus();
528             return;
529         }
530         else // Shift + F6 or Ctrl + F6
531         {
532             if(mxAllRecentThumbnails->IsVisible())
533                 mxAllRecentThumbnails->GrabFocus();
534             else if(mxLocalView->IsVisible())
535                 mxLocalView->GrabFocus();
536             return;
537         }
538     }
539     InterimItemWindow::GetFocus();
540 }
541 
setOwningFrame(const css::uno::Reference<css::frame::XFrame> & xFrame)542 void BackingWindow::setOwningFrame( const css::uno::Reference< css::frame::XFrame >& xFrame )
543 {
544     mxFrame = xFrame;
545     if( ! mbInitControls )
546         initControls();
547 
548     // establish drag&drop mode
549     mxDropTargetListener.set(new OpenFileDropTargetListener(mxContext, mxFrame));
550 
551     if (mxDropTarget.is())
552     {
553         mxDropTarget->addDropTargetListener(mxDropTargetListener);
554         mxDropTarget->setActive(true);
555     }
556 
557     css::uno::Reference<XFramesSupplier> xFramesSupplier(mxDesktopDispatchProvider, UNO_QUERY);
558     if (xFramesSupplier)
559         xFramesSupplier->setActiveFrame(mxFrame);
560 }
561 
IMPL_STATIC_LINK_NOARG(BackingWindow,ExtLinkClickHdl,weld::Button &,void)562 IMPL_STATIC_LINK_NOARG(BackingWindow, ExtLinkClickHdl, weld::Button&, void)
563 {
564     try
565     {
566         OUString sURL;
567         if (officecfg::Office::Common::Misc::ShowDonation::get())
568             sURL = officecfg::Office::Common::Menus::DonationURL::get() +
569                 "?BCP47=" + LanguageTag(utl::ConfigManager::getUILocale()).getBcp47() +
570                 "&LOlang=" + LanguageTag(utl::ConfigManager::getUILocale()).getLanguage();
571         else
572             sURL = officecfg::Office::Common::Menus::ExtensionsURL::get() +
573                 "?LOvers=" + utl::ConfigManager::getProductVersion() +
574                 "&LOlocale=" + LanguageTag(utl::ConfigManager::getUILocale()).getBcp47();
575 
576         Reference<css::system::XSystemShellExecute> const
577             xSystemShellExecute(
578                 css::system::SystemShellExecute::create(
579                     ::comphelper::getProcessComponentContext()));
580         xSystemShellExecute->execute(sURL, OUString(),
581             css::system::SystemShellExecuteFlags::URIS_ONLY);
582     }
583     catch (const Exception&)
584     {
585     }
586 }
587 
applyFilter()588 void BackingWindow::applyFilter()
589 {
590     const int nFilter = mxFilter->get_active();
591     if (mxLocalView->IsVisible())
592     {
593         FILTER_APPLICATION aFilter = static_cast<FILTER_APPLICATION>(nFilter);
594         mxLocalView->filterItems(ViewFilter_Application(aFilter));
595     }
596     else
597     {
598         sfx2::ApplicationType aFilter;
599         if (nFilter == 0)
600             aFilter = sfx2::ApplicationType::TYPE_NONE;
601         else
602             aFilter = static_cast<sfx2::ApplicationType>(1 << (nFilter - 1));
603         mxAllRecentThumbnails->setFilter(aFilter);
604     }
605 }
606 
IMPL_LINK_NOARG(BackingWindow,FilterHdl,weld::ComboBox &,void)607 IMPL_LINK_NOARG( BackingWindow, FilterHdl, weld::ComboBox&, void )
608 {
609     applyFilter();
610 }
611 
IMPL_LINK(BackingWindow,ToggleHdl,weld::Toggleable &,rButton,void)612 IMPL_LINK( BackingWindow, ToggleHdl, weld::Toggleable&, rButton, void )
613 {
614     if (&rButton == mxRecentButton.get())
615     {
616         mxLocalView->Hide();
617         mxAllRecentThumbnails->Show();
618         mxAllRecentThumbnails->GrabFocus();
619         mxTemplateButton->set_active(false);
620         mxActions->show();
621     }
622     else
623     {
624         mxAllRecentThumbnails->Hide();
625         initializeLocalView();
626         mxLocalView->Show();
627         mxLocalView->reload();
628         mxLocalView->GrabFocus();
629         mxRecentButton->set_active(false);
630         mxActions->hide();
631     }
632     applyFilter();
633 }
634 
IMPL_LINK(BackingWindow,ClickHdl,weld::Button &,rButton,void)635 IMPL_LINK( BackingWindow, ClickHdl, weld::Button&, rButton, void )
636 {
637     // dispatch the appropriate URL and end the dialog
638     if( &rButton == mxWriterAllButton.get() )
639         dispatchURL( u"private:factory/swriter"_ustr );
640     else if( &rButton == mxCalcAllButton.get() )
641         dispatchURL( u"private:factory/scalc"_ustr );
642     else if( &rButton == mxImpressAllButton.get() )
643         dispatchURL( u"private:factory/simpress?slot=6686"_ustr );
644     else if( &rButton == mxDrawAllButton.get() )
645         dispatchURL( u"private:factory/sdraw"_ustr );
646     else if( &rButton == mxDBAllButton.get() )
647         dispatchURL( u"private:factory/sdatabase?Interactive"_ustr );
648     else if( &rButton == mxMathAllButton.get() )
649         dispatchURL( u"private:factory/smath"_ustr );
650     else if( &rButton == mxOpenButton.get() )
651     {
652         Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
653 
654         dispatchURL( u".uno:Open"_ustr, OUString(), xFrame, { comphelper::makePropertyValue(u"Referer"_ustr, u"private:user"_ustr) } );
655     }
656     else if( &rButton == mxRemoteButton.get() )
657     {
658         Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
659 
660         dispatchURL( u".uno:OpenRemote"_ustr, OUString(), xFrame, {} );
661     }
662 }
663 
IMPL_LINK(BackingWindow,MenuSelectHdl,const OUString &,rId,void)664 IMPL_LINK (BackingWindow, MenuSelectHdl, const OUString&, rId, void)
665 {
666     if (rId == "clear_all")
667     {
668         SvtHistoryOptions::Clear(EHistoryType::PickList, false);
669         mxAllRecentThumbnails->Reload();
670         return;
671     }
672     else if(rId == "clear_unavailable")
673     {
674         mxAllRecentThumbnails->clearUnavailableFiles();
675     }
676 }
677 
IMPL_LINK(BackingWindow,CreateContextMenuHdl,ThumbnailViewItem *,pItem,void)678 IMPL_LINK(BackingWindow, CreateContextMenuHdl, ThumbnailViewItem*, pItem, void)
679 {
680     const TemplateViewItem *pViewItem = dynamic_cast<TemplateViewItem*>(pItem);
681 
682     if (pViewItem)
683         mxLocalView->createContextMenu();
684 }
685 
IMPL_LINK(BackingWindow,OpenTemplateHdl,ThumbnailViewItem *,pItem,void)686 IMPL_LINK(BackingWindow, OpenTemplateHdl, ThumbnailViewItem*, pItem, void)
687 {
688     uno::Sequence< PropertyValue > aArgs{
689         comphelper::makePropertyValue(u"AsTemplate"_ustr, true),
690         comphelper::makePropertyValue(u"MacroExecutionMode"_ustr, MacroExecMode::USE_CONFIG),
691         comphelper::makePropertyValue(u"UpdateDocMode"_ustr, UpdateDocMode::ACCORDING_TO_CONFIG),
692         comphelper::makePropertyValue(u"InteractionHandler"_ustr, task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), nullptr ))
693     };
694 
695     TemplateViewItem *pTemplateItem = static_cast<TemplateViewItem*>(pItem);
696 
697     Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
698 
699     try
700     {
701         dispatchURL( pTemplateItem->getPath(), u"_default"_ustr, xFrame, aArgs );
702     }
703     catch( const uno::Exception& )
704     {
705     }
706 }
707 
IMPL_LINK(BackingWindow,EditTemplateHdl,ThumbnailViewItem *,pItem,void)708 IMPL_LINK(BackingWindow, EditTemplateHdl, ThumbnailViewItem*, pItem, void)
709 {
710     uno::Sequence< PropertyValue > aArgs{
711         comphelper::makePropertyValue(u"AsTemplate"_ustr, false),
712         comphelper::makePropertyValue(u"MacroExecutionMode"_ustr, MacroExecMode::USE_CONFIG),
713         comphelper::makePropertyValue(u"UpdateDocMode"_ustr, UpdateDocMode::ACCORDING_TO_CONFIG),
714     };
715 
716     TemplateViewItem *pViewItem = static_cast<TemplateViewItem*>(pItem);
717 
718     Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
719 
720     try
721     {
722         dispatchURL( pViewItem->getPath(), u"_default"_ustr, xFrame, aArgs );
723     }
724     catch( const uno::Exception& )
725     {
726     }
727 }
728 
729 namespace {
730 
731 struct ImplDelayedDispatch
732 {
733     Reference< XDispatch >      xDispatch;
734     css::util::URL   aDispatchURL;
735     Sequence< PropertyValue >   aArgs;
736 
ImplDelayedDispatch__anonb85de2ee0111::ImplDelayedDispatch737     ImplDelayedDispatch( const Reference< XDispatch >& i_xDispatch,
738                          css::util::URL i_aURL,
739                          const Sequence< PropertyValue >& i_rArgs )
740     : xDispatch( i_xDispatch ),
741       aDispatchURL(std::move( i_aURL )),
742       aArgs( i_rArgs )
743     {
744     }
745 };
746 
747 }
748 
implDispatchDelayed(void *,void * pArg)749 static void implDispatchDelayed( void*, void* pArg )
750 {
751     struct ImplDelayedDispatch* pDispatch = static_cast<ImplDelayedDispatch*>(pArg);
752     try
753     {
754         pDispatch->xDispatch->dispatch( pDispatch->aDispatchURL, pDispatch->aArgs );
755     }
756     catch (const Exception&)
757     {
758     }
759 
760     // clean up
761     delete pDispatch;
762 }
763 
dispatchURL(const OUString & i_rURL,const OUString & rTarget,const Reference<XDispatchProvider> & i_xProv,const Sequence<PropertyValue> & i_rArgs)764 void BackingWindow::dispatchURL( const OUString& i_rURL,
765                                  const OUString& rTarget,
766                                  const Reference< XDispatchProvider >& i_xProv,
767                                  const Sequence< PropertyValue >& i_rArgs )
768 {
769     // if no special dispatch provider is given, get the desktop
770     Reference< XDispatchProvider > xProvider( i_xProv.is() ? i_xProv : mxDesktopDispatchProvider );
771 
772     // check for dispatch provider
773     if( !xProvider.is())
774         return;
775 
776     // get a URL transformer to clean up the URL
777     css::util::URL aDispatchURL;
778     aDispatchURL.Complete = i_rURL;
779 
780     Reference < css::util::XURLTransformer > xURLTransformer(
781         css::util::URLTransformer::create( comphelper::getProcessComponentContext() ) );
782     try
783     {
784         // clean up the URL
785         xURLTransformer->parseStrict( aDispatchURL );
786         // get a Dispatch for the URL and target
787         Reference< XDispatch > xDispatch(
788             xProvider->queryDispatch( aDispatchURL, rTarget, 0 )
789             );
790         // dispatch the URL
791         if ( xDispatch.is() )
792         {
793             std::unique_ptr<ImplDelayedDispatch> pDisp(new ImplDelayedDispatch( xDispatch, std::move(aDispatchURL), i_rArgs ));
794             if( Application::PostUserEvent( LINK_NONMEMBER( nullptr, implDispatchDelayed ), pDisp.get() ) )
795                 pDisp.release();
796         }
797     }
798     catch (const css::uno::RuntimeException&)
799     {
800         throw;
801     }
802     catch (const css::uno::Exception&)
803     {
804     }
805 }
806 
clearRecentFileList()807 void BackingWindow::clearRecentFileList()
808 {
809     mxAllRecentThumbnails->Clear();
810     // tdf#166349 - reload recent documents to show pinned items
811     mxAllRecentThumbnails->Reload();
812 }
813 /* vim:set shiftwidth=4 softtabstop=4 expandtab:*/
814