LibreOffice Module cui (master) 1
tipofthedaydlg.cxx
Go to the documentation of this file.
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 <sal/config.h>
21#include <tipofthedaydlg.hxx>
22#include <tipoftheday.hrc>
23
24#include <sfx2/viewfrm.hxx>
26#include <vcl/graphicfilter.hxx>
27#include <vcl/help.hxx>
28#include <vcl/window.hxx>
29
30#include <com/sun/star/frame/XDispatch.hpp>
31#include <com/sun/star/frame/XDispatchProvider.hpp>
32#include <com/sun/star/util/URL.hpp>
33#include <com/sun/star/util/URLTransformer.hpp>
34
36#include <dialmgr.hxx>
38#include <officecfg/Office/Common.hxx>
39#include <osl/file.hxx>
40#include <rtl/bootstrap.hxx>
42#include <unotools/resmgr.hxx>
44#include <com/sun/star/beans/PropertyValue.hpp>
45
46//size of preview
47const Size ThumbSize(150, 150);
48
50 : GenericDialogController(pParent, "cui/ui/tipofthedaydialog.ui", "TipOfTheDayDialog")
51 , m_pParent(pParent)
52 , m_pText(m_xBuilder->weld_label("lbText"))
53 , m_pShowTip(m_xBuilder->weld_check_button("cbShowTip"))
54 , m_pNext(m_xBuilder->weld_button("btnNext"))
55 , m_pLink(m_xBuilder->weld_link_button("btnLink"))
56 , m_pPreview(new weld::CustomWeld(*m_xBuilder, "imPreview", m_aPreview))
57{
58 m_pShowTip->set_active(officecfg::Office::Common::Misc::ShowTipOfTheDay::get());
59 m_pNext->connect_clicked(LINK(this, TipOfTheDayDialog, OnNextClick));
60 m_nCurrentTip = officecfg::Office::Common::Misc::LastTipOfTheDayID::get();
61 m_pPreview->set_size_request(ThumbSize.Width(), ThumbSize.Height());
62
63 if (pParent != nullptr)
64 {
65 css::uno::Reference<css::awt::XWindow> xWindow = pParent->GetXWindow();
66 if (xWindow.is())
67 {
69 if (xVclWin != nullptr)
70 xVclWin->AddEventListener(LINK(this, TipOfTheDayDialog, Terminated));
71 }
72 }
73
74 const auto t0 = std::chrono::system_clock::now().time_since_epoch();
75 sal_Int32 nDay = std::chrono::duration_cast<std::chrono::hours>(t0).count() / 24;
76 //show next tip after one day
77 if (nDay > officecfg::Office::Common::Misc::LastTipOfTheDayShown::get())
79
80 // save this time to the config now instead of in the dtor otherwise we
81 // end up with multiple copies of this dialog every time we open a new
82 // document if the first one isn't closed
83 std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
85 officecfg::Office::Common::Misc::LastTipOfTheDayShown::set(nDay, xChanges);
86 xChanges->commit();
87
88 UpdateTip();
89}
90
91IMPL_LINK(TipOfTheDayDialog, Terminated, VclWindowEvent&, rEvent, void)
92{
93 if (rEvent.GetId() == VclEventId::ObjectDying)
95}
96
98{
99 std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
101 officecfg::Office::Common::Misc::LastTipOfTheDayID::set(m_nCurrentTip, xChanges);
102 officecfg::Office::Common::Misc::ShowTipOfTheDay::set(m_pShowTip->get_active(), xChanges);
103 xChanges->commit();
104
105 if (m_pParent != nullptr)
106 {
107 css::uno::Reference<css::awt::XWindow> xWindow = m_pParent->GetXWindow();
108 if (xWindow.is())
109 {
111 if (xVclWin != nullptr)
112 xVclWin->RemoveEventListener(LINK(this, TipOfTheDayDialog, Terminated));
113 }
114 }
115}
116
117static bool file_exists(const OUString& fileName)
118{
119 ::osl::File aFile(fileName);
120 return aFile.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None;
121}
122
124{
125 constexpr sal_Int32 nNumberOfTips = std::size(TIPOFTHEDAY_STRINGARRAY);
126
127 if ((m_nCurrentTip >= nNumberOfTips) || (m_nCurrentTip < 0))
128 m_nCurrentTip = 0;
129
130 //title
131 m_xDialog->set_title(CuiResId(STR_TITLE)
132 .replaceFirst("%CURRENT", OUString::number(m_nCurrentTip + 1))
133 .replaceFirst("%TOTAL", OUString::number(nNumberOfTips)));
134
135 auto[sTip, sLink, sImage] = TIPOFTHEDAY_STRINGARRAY[m_nCurrentTip];
136
137 // text
138//replace MOD1 & MOD2 shortcuts depending on platform
139#ifdef MACOSX
140 const OUString aMOD1 = CuiResId(STR_CMD);
141 const OUString aMOD2 = CuiResId(STR_Option);
142#else
143 const OUString aMOD1 = CuiResId(STR_CTRL);
144 const OUString aMOD2 = CuiResId(STR_Alt);
145#endif
146 m_pText->set_label(CuiResId(sTip).replaceAll("%MOD1", aMOD1).replaceAll("%MOD2", aMOD2));
147
148 // hyperlink
149 if (sLink.isEmpty())
150 {
151 m_pLink->set_visible(false);
152 }
153 else if (sLink.startsWith(".uno:"))
154 {
155 m_pLink->set_visible(false);
156 //show the link only if the UNO command is available in the current module
157 SfxViewFrame* pViewFrame = SfxViewFrame::Current();
158 if (pViewFrame)
159 {
160 const auto xFrame = pViewFrame->GetFrame().GetFrameInterface();
161 const css::uno::Reference<css::frame::XDispatchProvider> xDispatchProvider(
162 xFrame, css::uno::UNO_QUERY);
163 if (xDispatchProvider.is())
164 {
165 css::util::URL aCommandURL;
166 aCommandURL.Complete = sLink;
167 const css::uno::Reference<css::uno::XComponentContext> xContext
169 const css::uno::Reference<css::util::XURLTransformer> xParser
170 = css::util::URLTransformer::create(xContext);
171 xParser->parseStrict(aCommandURL);
172 const css::uno::Reference<css::frame::XDispatch> xDisp
173 = xDispatchProvider->queryDispatch(aCommandURL, OUString(), 0);
174 if (xDisp.is())
175 {
176 m_pLink->set_label(CuiResId(STR_UNO_LINK));
177 m_pLink->set_uri(sLink);
178
179 const OUString aModuleName(
181 const auto aProperties
183 m_pLink->set_tooltip_text(
185
186 m_pLink->set_visible(true);
187 m_pLink->connect_activate_link(LINK(this, TipOfTheDayDialog, OnLinkClick));
188 }
189 }
190 }
191 }
192 else if (sLink.startsWith("http"))
193 {
194 // Links may have some %PRODUCTVERSION which need to be expanded
195 OUString aText = Translate::ExpandVariables(sLink);
197 if (aLang == "en" || aLang == "pt" || aLang == "zh") //en-US/GB, pt-BR, zh-CH/TW
199 m_pLink->set_uri(aText.replaceFirst("%LANGUAGENAME", aLang));
200 m_pLink->set_label(CuiResId(STR_MORE_LINK));
201 m_pLink->set_visible(true);
202 m_pLink->connect_activate_link(Link<weld::LinkButton&, bool>());
203 }
204 else
205 {
206 m_pLink->set_uri(sLink);
207 m_pLink->set_label(CuiResId(STR_HELP_LINK));
208 m_pLink->set_visible(true);
209 m_pLink->connect_activate_link(LINK(this, TipOfTheDayDialog, OnLinkClick));
210 }
211 // image
212 OUString aURL("$BRAND_BASE_DIR/$BRAND_SHARE_SUBDIR/tipoftheday/");
213 rtl::Bootstrap::expandMacros(aURL);
214 OUString aImageName = sImage;
215 // use default image if none is available with the number
216 if (aImageName.isEmpty() || !file_exists(aURL + aImageName))
217 aImageName = "tipoftheday.png";
218 Graphic aGraphic;
219 GraphicFilter::LoadGraphic(aURL + aImageName, OUString(), aGraphic);
220
221 if (!aGraphic.IsAnimated())
222 {
223 BitmapEx aBmpEx(aGraphic.GetBitmapEx());
224 if (aBmpEx.Scale(ThumbSize))
225 aGraphic = aBmpEx;
226 }
227 m_aPreview.SetPreview(aGraphic);
228}
229
230IMPL_LINK(TipOfTheDayDialog, OnLinkClick, weld::LinkButton&, rButton, bool)
231{
232 const OUString sLink = rButton.get_uri();
233 if (sLink.startsWith(".uno:"))
234 {
237 }
238 else
239 {
240 Application::GetHelp()->Start(sLink, static_cast<weld::Widget*>(nullptr));
241 }
242 return true;
243}
244
246{
247 m_nCurrentTip++; //zeroed at updatetip when out of range
248 UpdateTip();
249}
250
251/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
static Help * GetHelp()
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
void SetPreview(const Graphic &rGraphic)
Definition: cuigrfflt.cxx:71
static ErrCode LoadGraphic(const OUString &rPath, const OUString &rFilter, Graphic &rGraphic, GraphicFilter *pFilter=nullptr, sal_uInt16 *pDeterminedFormat=nullptr)
bool IsAnimated() const
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
virtual bool Start(const OUString &rHelpId, weld::Widget *pWidget=nullptr)
OUString getLanguage() const
const OUString & getBcp47(bool bResolveSystem=true) const
const css::uno::Reference< css::frame::XFrame > & GetFrameInterface() const
static SfxViewFrame * Current()
SfxFrame & GetFrame() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
CuiGraphicPreviewWindow m_aPreview
std::unique_ptr< weld::Label > m_pText
weld::Window * m_pParent
TipOfTheDayDialog(weld::Window *pWindow)
std::unique_ptr< weld::LinkButton > m_pLink
std::unique_ptr< weld::CustomWeld > m_pPreview
std::unique_ptr< weld::Button > m_pNext
std::unique_ptr< weld::CheckButton > m_pShowTip
virtual ~TipOfTheDayDialog() override
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
static std::shared_ptr< ConfigurationChanges > create()
static OUString getUILocale()
void response(int nResponse)
std::shared_ptr< weld::Dialog > m_xDialog
virtual css::uno::Reference< css::awt::XWindow > GetXWindow()=0
OUString CuiResId(TranslateId aKey)
Definition: cuiresmgr.cxx:23
URL aURL
OUString ExpandVariables(const OUString &rString)
bool dispatchCommand(const OUString &rCommand, const uno::Reference< css::frame::XFrame > &rFrame, const css::uno::Sequence< css::beans::PropertyValue > &rArguments, const uno::Reference< css::frame::XDispatchResultListener > &rListener)
Reference< XComponentContext > getProcessComponentContext()
Sequence< beans::PropertyValue > GetCommandProperties(const OUString &rsCommandName, const OUString &rsModuleName)
OUString GetTooltipForCommand(const OUString &rsCommandName, const css::uno::Sequence< css::beans::PropertyValue > &rProperties, const Reference< frame::XFrame > &rxFrame)
OUString GetModuleIdentifier(const Reference< frame::XFrame > &rxFrame)
Reference< XFrame > xFrame
IMPL_LINK_NOARG(TipOfTheDayDialog, OnNextClick, weld::Button &, void)
IMPL_LINK(TipOfTheDayDialog, Terminated, VclWindowEvent &, rEvent, void)
const Size ThumbSize(150, 150)
static bool file_exists(const OUString &fileName)
RET_OK