Krita Source Code Documentation
Loading...
Searching...
No Matches
kcheckaccelerators.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 SPDX-FileCopyrightText: 1997 Matthias Kalle Dalheimer (kalle@kde.org)
3 SPDX-FileCopyrightText: 1998, 1999, 2000 KDE Team
4 SPDX-FileCopyrightText: 2008 Nick Shaforostoff <shaforostoff@kde.ru>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8
10
11#include <QApplication>
12#include <QCheckBox>
13#include <QDialog>
14#include <QShortcutEvent>
15#include <QMouseEvent>
16#include <QLayout>
17#include <QMenuBar>
18#include <QTabBar>
19#include <QTextBrowser>
20#include <QChar>
21#include <QLabel>
22#include <QComboBox>
23#include <QGroupBox>
24#include <QClipboard>
25#include <QProcess>
26#include <QDialogButtonBox>
27#include <QFile>
28
29#include <kconfig.h>
30#include <kconfiggroup.h>
31#include <ksharedconfig.h>
32#include <klocalizedstring.h>
33#include <kacceleratormanager.h>
34
36{
37 Q_OBJECT
38public:
39 explicit KisKCheckAcceleratorsInitializer(QObject *parent = 0)
40 : QObject(parent)
41 {
42 }
43
44public Q_SLOTS:
46 {
47 KConfigGroup cg(KSharedConfig::openConfig(), "Development");
48 QString sKey = cg.readEntry("CheckAccelerators").trimmed();
49 int key = 0;
50 if (!sKey.isEmpty()) {
51 QList<QKeySequence> cuts = QKeySequence::listFromString(sKey);
52 if (!cuts.isEmpty()) {
53 key = cuts.first()[0];
54 }
55 }
56 const bool autoCheck = cg.readEntry("AutoCheckAccelerators", true);
57 const bool copyWidgetText = cg.readEntry("CopyWidgetText", false);
58 if (!copyWidgetText && key == 0 && !autoCheck) {
59 deleteLater();
60 return;
61 }
62
63 new KisKCheckAccelerators(qApp, key, autoCheck, copyWidgetText);
64 deleteLater();
65 }
66};
67
68static void startupFunc()
69{
70 // Call initiateIfNeeded once we're in the event loop
71 // This is to prevent using KSharedConfig before main() can set the app name
72 QCoreApplication *app = QCoreApplication::instance();
74 QMetaObject::invokeMethod(initializer, "initiateIfNeeded", Qt::QueuedConnection);
75}
76
77Q_COREAPP_STARTUP_FUNCTION(startupFunc)
78
79KisKCheckAccelerators::KisKCheckAccelerators(QObject *parent, int key_, bool autoCheck_, bool copyWidgetText_)
80 : QObject(parent)
81 , key(key_)
82 , autoCheck(autoCheck_)
83 , copyWidgetText(copyWidgetText_)
84 , drklash(nullptr)
85{
86 setObjectName(QStringLiteral("kapp_accel_filter"));
87
88 KConfigGroup cg(KSharedConfig::openConfig(), "Development");
89 alwaysShow = cg.readEntry("AlwaysShowCheckAccelerators", false);
90 copyWidgetTextCommand = cg.readEntry("CopyWidgetTextCommand", QString());
91
92 parent->installEventFilter(this);
93 connect(&autoCheckTimer, SIGNAL(timeout()), SLOT(autoCheckSlot()));
94}
95
96bool KisKCheckAccelerators::eventFilter(QObject *obj, QEvent *e)
97{
98 if (block) {
99 return false;
100 }
101
102 switch (e->type()) { // just simplify debugging
103 case QEvent::ShortcutOverride:
104 if (key && (static_cast<QKeyEvent *>(e)->key() == key)) {
105 block = true;
106 checkAccelerators(false);
107 block = false;
108 e->accept();
109 return true;
110 }
111 break;
112 case QEvent::ChildAdded:
113 case QEvent::ChildRemoved:
114 // Only care about widgets; this also avoids starting the timer in other threads
115 if (!static_cast<QChildEvent *>(e)->child()->isWidgetType()) {
116 break;
117 }
118 Q_FALLTHROUGH();
119 case QEvent::Resize:
120 case QEvent::LayoutRequest:
121 case QEvent::WindowActivate:
122 case QEvent::WindowDeactivate:
123 if (autoCheck) {
124 autoCheckTimer.setSingleShot(true);
125 autoCheckTimer.start(20); // 20 ms
126 }
127 break;
128 //case QEvent::MouseButtonDblClick:
129 case QEvent::MouseButtonPress:
130 if (copyWidgetText && static_cast<QMouseEvent *>(e)->button() == Qt::MiddleButton) {
131 //kWarning()<<"obj"<<obj;
132 QWidget *w = static_cast<QWidget *>(obj)->childAt(static_cast<QMouseEvent *>(e)->pos());
133 if (!w) {
134 w = static_cast<QWidget *>(obj);
135 }
136 if (!w) {
137 return false;
138 }
139 //kWarning()<<"MouseButtonDblClick"<<w;
140 QString text;
141 if (qobject_cast<QLabel *>(w)) {
142 text = static_cast<QLabel *>(w)->text();
143 } else if (qobject_cast<QAbstractButton *>(w)) {
144 text = static_cast<QAbstractButton *>(w)->text();
145 } else if (qobject_cast<QComboBox *>(w)) {
146 text = static_cast<QComboBox *>(w)->currentText();
147 } else if (qobject_cast<QTabBar *>(w)) {
148 text = static_cast<QTabBar *>(w)->tabText(static_cast<QTabBar *>(w)->tabAt(static_cast<QMouseEvent *>(e)->pos()));
149 } else if (qobject_cast<QGroupBox *>(w)) {
150 text = static_cast<QGroupBox *>(w)->title();
151 } else if (qobject_cast<QMenu *>(obj)) {
152 QAction *a = static_cast<QMenu *>(obj)->actionAt(static_cast<QMouseEvent *>(e)->pos());
153 if (!a) {
154 return false;
155 }
156 text = a->text();
157 if (text.isEmpty()) {
158 text = a->iconText();
159 }
160 }
161 if (text.isEmpty()) {
162 return false;
163 }
164
165 if (static_cast<QMouseEvent *>(e)->modifiers() == Qt::ControlModifier) {
166 text.remove(QChar::fromLatin1('&'));
167 }
168
169 //kWarning()<<KGlobal::activeComponent().catalogName()<<text;
170 if (copyWidgetTextCommand.isEmpty()) {
171 QClipboard *clipboard = QApplication::clipboard();
172 clipboard->setText(text);
173 } else {
174 QProcess *script = new QProcess(this);
175 script->start(copyWidgetTextCommand.arg(text, QFile::decodeName(KLocalizedString::applicationDomain())), QStringList());
176 connect(script, SIGNAL(finished(int,QProcess::ExitStatus)), script, SLOT(deleteLater()));
177 }
178 e->accept();
179 return true;
180
181 //kWarning()<<"MouseButtonDblClick"<<static_cast<QWidget*>(obj)->childAt(static_cast<QMouseEvent*>(e)->globalPos());
182 }
183 return false;
184 case QEvent::Timer:
185 case QEvent::MouseMove:
186 case QEvent::Paint:
187 return false;
188 default:
189 // qDebug() << "KisKCheckAccelerators::eventFilter " << e->type() << " " << autoCheck;
190 break;
191 }
192 return false;
193}
194
196{
197 if (block) {
198 autoCheckTimer.setSingleShot(true);
199 autoCheckTimer.start(20);
200 return;
201 }
202 block = true;
204 block = false;
205}
206
207void KisKCheckAccelerators::createDialog(QWidget *actWin, bool automatic)
208{
209 if (drklash) {
210 return;
211 }
212
213 drklash = new QDialog(actWin);
214 drklash->setAttribute(Qt::WA_DeleteOnClose);
215 drklash->setObjectName(QStringLiteral("kapp_accel_check_dlg"));
216 drklash->setWindowTitle(i18nc("@title:window", "Dr. Klash' Accelerator Diagnosis"));
217 drklash->resize(500, 460);
218 QVBoxLayout *layout = new QVBoxLayout(drklash);
219 drklash_view = new QTextBrowser(drklash);
220 layout->addWidget(drklash_view);
221 QCheckBox *disableAutoCheck = 0;
222 if (automatic) {
223 disableAutoCheck = new QCheckBox(i18nc("@option:check", "Disable automatic checking"), drklash);
224 connect(disableAutoCheck, SIGNAL(toggled(bool)), SLOT(slotDisableCheck(bool)));
225 layout->addWidget(disableAutoCheck);
226 }
227 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, drklash);
228 layout->addWidget(buttonBox);
229 connect(buttonBox, SIGNAL(rejected()), drklash, SLOT(close()));
230 if (disableAutoCheck) {
231 disableAutoCheck->setFocus();
232 } else {
233 drklash_view->setFocus();
234 }
235}
236
238{
239 autoCheck = !on;
240 if (!on) {
242 }
243}
244
246{
247 QWidget *actWin = qApp->activeWindow();
248 if (!actWin) {
249 return;
250 }
251
252 KAcceleratorManager::manage(actWin);
253 QString a, c, r;
254 KAcceleratorManager::last_manage(a, c, r);
255
256 if (automatic) { // for now we only show dialogs on F12 checks
257 return;
258 }
259
260 if (c.isEmpty() && r.isEmpty() && (automatic || a.isEmpty())) {
261 return;
262 }
263
264 QString s;
265
266 if (! c.isEmpty()) {
267 s += i18n("<h2>Accelerators changed</h2>");
268 s += QStringLiteral("<table border><tr><th><b>");
269 s += i18n("Old Text");
270 s += QStringLiteral("</b></th><th><b>");
271 s += i18n("New Text");
272 s += QStringLiteral("</b></th></tr>");
273 s += c;
274 s += QStringLiteral("</table>");
275 }
276
277 if (! r.isEmpty()) {
278 s += i18n("<h2>Accelerators removed</h2>");
279 s += QStringLiteral("<table border><tr><th><b>");
280 s += i18n("Old Text");
281 s += QStringLiteral("</b></th></tr>");
282 s += r;
283 s += QStringLiteral("</table>");
284 }
285
286 if (! a.isEmpty()) {
287 s += i18n("<h2>Accelerators added (just for your info)</h2>");
288 s += QStringLiteral("<table border><tr><th><b>");
289 s += i18n("New Text");
290 s += QStringLiteral("</b></th></tr>");
291 s += a;
292 s += QStringLiteral("</table>");
293 }
294
295 createDialog(actWin, automatic);
296 drklash_view->setHtml(s);
297 drklash->show();
298 drklash->raise();
299
300 // dlg will be destroyed before returning
301}
302
303#include "kcheckaccelerators.moc"
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KisKCheckAcceleratorsInitializer(QObject *parent=0)
bool eventFilter(QObject *, QEvent *e) override
void checkAccelerators(bool automatic)
QPointer< QDialog > drklash
void createDialog(QWidget *parent, bool automatic)
static void startupFunc()
QString button(const QWheelEvent &ev)