1 | /* |
2 | This file is part of the KDE Libraries |
3 | SPDX-FileCopyrightText: 1999-2000 Espen Sand <espen@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | // I (espen) prefer that header files are included alphabetically |
9 | |
10 | #include "khelpmenu.h" |
11 | |
12 | #include <QAction> |
13 | #include <QApplication> |
14 | #include <QDesktopServices> |
15 | #include <QDialogButtonBox> |
16 | #include <QLabel> |
17 | #include <QMenu> |
18 | #include <QStandardPaths> |
19 | #include <QStyle> |
20 | #include <QTimer> |
21 | #include <QUrl> |
22 | #include <QWhatsThis> |
23 | #include <QWidget> |
24 | |
25 | #include "kaboutapplicationdialog.h" |
26 | #include "kaboutkdedialog_p.h" |
27 | #include "kbugreport.h" |
28 | #include "kswitchlanguagedialog_p.h" |
29 | |
30 | #include <KAboutData> |
31 | #include <KAuthorized> |
32 | #include <KLocalizedString> |
33 | #include <KStandardActions> |
34 | |
35 | #include <optional> |
36 | |
37 | using namespace KDEPrivate; |
38 | |
39 | class |
40 | { |
41 | public: |
42 | () |
43 | { |
44 | } |
45 | () |
46 | { |
47 | delete mMenu; |
48 | delete mAboutApp; |
49 | delete mAboutKDE; |
50 | delete mBugReport; |
51 | delete mSwitchApplicationLanguage; |
52 | } |
53 | |
54 | void createActions(KHelpMenu *q, bool showWhatsThis); |
55 | |
56 | QMenu * = nullptr; |
57 | QDialog * = nullptr; |
58 | KAboutKdeDialog * = nullptr; |
59 | KBugReport * = nullptr; |
60 | QAction * = nullptr; |
61 | KSwitchLanguageDialog * = nullptr; |
62 | |
63 | // TODO evaluate if we use static_cast<QWidget*>(parent()) instead of mParent to win that bit of memory |
64 | QWidget * = nullptr; |
65 | |
66 | QAction *mHandBookAction = nullptr; |
67 | QAction * = nullptr; |
68 | QAction * = nullptr; |
69 | QAction * = nullptr; |
70 | QAction * = nullptr; |
71 | QAction * = nullptr; |
72 | |
73 | std::optional<KAboutData> ; |
74 | }; |
75 | |
76 | #if KXMLGUI_BUILD_DEPRECATED_SINCE(6, 9) |
77 | KHelpMenu::(QWidget *parent, const QString &, bool showWhatsThis) |
78 | : QObject(parent) |
79 | , d(new KHelpMenuPrivate) |
80 | { |
81 | d->mParent = parent; |
82 | d->createActions(q: this, showWhatsThis); |
83 | } |
84 | #endif |
85 | |
86 | KHelpMenu::(QWidget *parent) |
87 | : QObject(parent) |
88 | , d(new KHelpMenuPrivate) |
89 | { |
90 | d->mParent = parent; |
91 | d->createActions(q: this, showWhatsThis: true); |
92 | } |
93 | |
94 | #if KXMLGUI_BUILD_DEPRECATED_SINCE(6, 9) |
95 | KHelpMenu::(QWidget *parent, const KAboutData &aboutData, bool showWhatsThis) |
96 | : QObject(parent) |
97 | , d(new KHelpMenuPrivate) |
98 | { |
99 | d->mParent = parent; |
100 | d->mAboutData = aboutData; |
101 | d->createActions(q: this, showWhatsThis); |
102 | } |
103 | #endif |
104 | |
105 | KHelpMenu::(QWidget *parent, const KAboutData &aboutData) |
106 | : QObject(parent) |
107 | , d(new KHelpMenuPrivate) |
108 | { |
109 | d->mParent = parent; |
110 | d->mAboutData = aboutData; |
111 | d->createActions(q: this, showWhatsThis: true); |
112 | } |
113 | |
114 | KHelpMenu::() |
115 | { |
116 | delete d; |
117 | } |
118 | |
119 | void KHelpMenu::(bool showWhatsThis) |
120 | { |
121 | if (!showWhatsThis) { |
122 | delete d->mWhatsThisAction; |
123 | d->mWhatsThisAction = nullptr; |
124 | } else if (KAuthorized::authorizeAction(QStringLiteral("help_whats_this" ))) { |
125 | d->mWhatsThisAction = KStandardActions::whatsThis(recvr: this, slot: &KHelpMenu::contextHelpActivated, parent: this); |
126 | } |
127 | } |
128 | |
129 | void KHelpMenuPrivate::(KHelpMenu *q, bool showWhatsThis) |
130 | { |
131 | if (KAuthorized::authorizeAction(QStringLiteral("help_contents" ))) { |
132 | mHandBookAction = KStandardActions::helpContents(recvr: q, slot: &KHelpMenu::appHelpActivated, parent: q); |
133 | } |
134 | if (showWhatsThis && KAuthorized::authorizeAction(QStringLiteral("help_whats_this" ))) { |
135 | mWhatsThisAction = KStandardActions::whatsThis(recvr: q, slot: &KHelpMenu::contextHelpActivated, parent: q); |
136 | } |
137 | |
138 | const auto bugAddress = mAboutData ? mAboutData->bugAddress() : KAboutData::applicationData().bugAddress(); |
139 | if (KAuthorized::authorizeAction(QStringLiteral("help_report_bug" )) && !bugAddress.isEmpty()) { |
140 | mReportBugAction = KStandardActions::reportBug(recvr: q, slot: &KHelpMenu::reportBug, parent: q); |
141 | } |
142 | |
143 | if (KAuthorized::authorizeAction(QStringLiteral("help_donate" )) && bugAddress == QLatin1String("submit@bugs.kde.org" )) { |
144 | mDonateAction = KStandardActions::donate(recvr: q, slot: &KHelpMenu::donate, parent: q); |
145 | } |
146 | |
147 | if (KAuthorized::authorizeAction(QStringLiteral("switch_application_language" ))) { |
148 | mSwitchApplicationLanguageAction = KStandardActions::switchApplicationLanguage(recvr: q, slot: &KHelpMenu::switchApplicationLanguage, parent: q); |
149 | } |
150 | |
151 | if (KAuthorized::authorizeAction(QStringLiteral("help_about_app" ))) { |
152 | mAboutAppAction = KStandardActions::aboutApp(recvr: q, slot: &KHelpMenu::aboutApplication, parent: q); |
153 | } |
154 | |
155 | if (KAuthorized::authorizeAction(QStringLiteral("help_about_kde" ))) { |
156 | mAboutKDEAction = KStandardActions::aboutKDE(recvr: q, slot: &KHelpMenu::aboutKDE, parent: q); |
157 | } |
158 | } |
159 | |
160 | // Used in the non-xml-gui case, like kfind or ksnapshot's help button. |
161 | QMenu *KHelpMenu::() |
162 | { |
163 | if (!d->mMenu) { |
164 | d->mMenu = new QMenu(d->mParent); |
165 | connect(sender: d->mMenu, signal: &QObject::destroyed, context: this, slot: &KHelpMenu::menuDestroyed); |
166 | |
167 | d->mMenu->setTitle(i18n("&Help" )); |
168 | |
169 | bool need_separator = false; |
170 | if (d->mHandBookAction) { |
171 | d->mMenu->addAction(action: d->mHandBookAction); |
172 | need_separator = true; |
173 | } |
174 | |
175 | if (d->mWhatsThisAction) { |
176 | d->mMenu->addAction(action: d->mWhatsThisAction); |
177 | need_separator = true; |
178 | } |
179 | |
180 | if (d->mReportBugAction) { |
181 | if (need_separator) { |
182 | d->mMenu->addSeparator(); |
183 | } |
184 | d->mMenu->addAction(action: d->mReportBugAction); |
185 | need_separator = true; |
186 | } |
187 | |
188 | if (d->mDonateAction) { |
189 | if (need_separator) { |
190 | d->mMenu->addSeparator(); |
191 | } |
192 | d->mMenu->addAction(action: d->mDonateAction); |
193 | need_separator = true; |
194 | } |
195 | |
196 | if (d->mSwitchApplicationLanguageAction) { |
197 | if (need_separator) { |
198 | d->mMenu->addSeparator(); |
199 | } |
200 | d->mMenu->addAction(action: d->mSwitchApplicationLanguageAction); |
201 | need_separator = true; |
202 | } |
203 | |
204 | if (need_separator) { |
205 | d->mMenu->addSeparator(); |
206 | } |
207 | |
208 | if (d->mAboutAppAction) { |
209 | d->mMenu->addAction(action: d->mAboutAppAction); |
210 | } |
211 | |
212 | if (d->mAboutKDEAction) { |
213 | d->mMenu->addAction(action: d->mAboutKDEAction); |
214 | } |
215 | } |
216 | |
217 | return d->mMenu; |
218 | } |
219 | |
220 | QAction *KHelpMenu::(MenuId id) const |
221 | { |
222 | switch (id) { |
223 | case menuHelpContents: |
224 | return d->mHandBookAction; |
225 | |
226 | case menuWhatsThis: |
227 | return d->mWhatsThisAction; |
228 | |
229 | case menuReportBug: |
230 | return d->mReportBugAction; |
231 | |
232 | case menuSwitchLanguage: |
233 | return d->mSwitchApplicationLanguageAction; |
234 | |
235 | case menuAboutApp: |
236 | return d->mAboutAppAction; |
237 | |
238 | case menuAboutKDE: |
239 | return d->mAboutKDEAction; |
240 | |
241 | case menuDonate: |
242 | return d->mDonateAction; |
243 | } |
244 | |
245 | return nullptr; |
246 | } |
247 | |
248 | void KHelpMenu::() |
249 | { |
250 | QDesktopServices::openUrl(url: QUrl(QStringLiteral("help:/" ))); |
251 | } |
252 | |
253 | void KHelpMenu::() |
254 | { |
255 | if (receivers(SIGNAL(showAboutApplication())) > 0) { |
256 | Q_EMIT showAboutApplication(); |
257 | } else { |
258 | if (!d->mAboutApp) { |
259 | d->mAboutApp = new KAboutApplicationDialog(d->mAboutData ? *d->mAboutData : KAboutData::applicationData(), d->mParent); |
260 | connect(sender: d->mAboutApp, signal: &QDialog::finished, context: this, slot: &KHelpMenu::dialogFinished); |
261 | } |
262 | d->mAboutApp->show(); |
263 | } |
264 | } |
265 | |
266 | void KHelpMenu::() |
267 | { |
268 | if (!d->mAboutKDE) { |
269 | d->mAboutKDE = new KAboutKdeDialog(d->mParent); |
270 | connect(sender: d->mAboutKDE, signal: &QDialog::finished, context: this, slot: &KHelpMenu::dialogFinished); |
271 | } |
272 | d->mAboutKDE->show(); |
273 | } |
274 | |
275 | void KHelpMenu::() |
276 | { |
277 | if (!d->mBugReport) { |
278 | d->mBugReport = new KBugReport(d->mAboutData ? *d->mAboutData : KAboutData::applicationData(), d->mParent); |
279 | connect(sender: d->mBugReport, signal: &QDialog::finished, context: this, slot: &KHelpMenu::dialogFinished); |
280 | } |
281 | d->mBugReport->show(); |
282 | } |
283 | |
284 | void KHelpMenu::() |
285 | { |
286 | if (!d->mSwitchApplicationLanguage) { |
287 | d->mSwitchApplicationLanguage = new KSwitchLanguageDialog(d->mParent); |
288 | connect(sender: d->mSwitchApplicationLanguage, signal: &QDialog::finished, context: this, slot: &KHelpMenu::dialogFinished); |
289 | } |
290 | d->mSwitchApplicationLanguage->show(); |
291 | } |
292 | |
293 | void KHelpMenu::() |
294 | { |
295 | const auto componentName = d->mAboutData ? d->mAboutData->componentName() : KAboutData::applicationData().componentName(); |
296 | QDesktopServices::openUrl(url: QUrl(QLatin1String("https://www.kde.org/donate?app=" ) + componentName)); |
297 | } |
298 | |
299 | void KHelpMenu::() |
300 | { |
301 | QTimer::singleShot(interval: 0, receiver: this, slot: &KHelpMenu::timerExpired); |
302 | } |
303 | |
304 | void KHelpMenu::() |
305 | { |
306 | if (d->mAboutKDE && !d->mAboutKDE->isVisible()) { |
307 | delete d->mAboutKDE; |
308 | d->mAboutKDE = nullptr; |
309 | } |
310 | |
311 | if (d->mBugReport && !d->mBugReport->isVisible()) { |
312 | delete d->mBugReport; |
313 | d->mBugReport = nullptr; |
314 | } |
315 | |
316 | if (d->mSwitchApplicationLanguage && !d->mSwitchApplicationLanguage->isVisible()) { |
317 | delete d->mSwitchApplicationLanguage; |
318 | d->mSwitchApplicationLanguage = nullptr; |
319 | } |
320 | |
321 | if (d->mAboutApp && !d->mAboutApp->isVisible()) { |
322 | delete d->mAboutApp; |
323 | d->mAboutApp = nullptr; |
324 | } |
325 | } |
326 | |
327 | void KHelpMenu::() |
328 | { |
329 | d->mMenu = nullptr; |
330 | } |
331 | |
332 | void KHelpMenu::() |
333 | { |
334 | QWhatsThis::enterWhatsThisMode(); |
335 | } |
336 | |
337 | #include "moc_khelpmenu.cpp" |
338 | |