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