KSane

ksanewidget.cpp
1/*
2 * SPDX-FileCopyrightText: 2007-2010 Kare Sars <kare dot sars at iki dot fi>
3 * SPDX-FileCopyrightText: 2009 Matthias Nagl <matthias at nagl dot info>
4 * SPDX-FileCopyrightText: 2009 Grzegorz Kurtyka <grzegorz dot kurtyka at gmail dot com>
5 * SPDX-FileCopyrightText: 2007-2008 Gilles Caulier <caulier dot gilles at gmail dot com>
6 * SPDX-FileCopyrightText: 2014 Gregor Mitsch : port to KDE5 frameworks
7 * SPDX-FileCopyrightText: 2021 Alexander Stippich <a.stippich@gmx.net>
8 *
9 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
10 */
11
12#include "ksanewidget.h"
13#include "ksanewidget_p.h"
14
15#include <unistd.h>
16
17#include <QApplication>
18#include <QList>
19#include <QLabel>
20#include <QSplitter>
21#include <QPointer>
22#include <QIcon>
23#include <QShortcut>
24
25#include <KPasswordDialog>
26#ifdef HAVE_KWALLET
27#include <KWallet>
28#endif
29
30#include <KLocalizedString>
31
32#include "ksanedevicedialog.h"
33#include <ksane_debug.h>
34
35namespace KSaneIface
36{
37
39 : QWidget(parent), d(new KSaneWidgetPrivate(this))
40{
41 d->m_ksaneCoreInterface = new KSaneCore::Interface();
42
43 connect(d->m_ksaneCoreInterface, &KSaneCore::Interface::scannedImageReady, d, &KSaneWidgetPrivate::imageReady);
44 connect(d->m_ksaneCoreInterface, &KSaneCore::Interface::scanFinished, d, &KSaneWidgetPrivate::scanDone);
45 connect(d->m_ksaneCoreInterface, &KSaneCore::Interface::userMessage, d, &KSaneWidgetPrivate::alertUser);
46 connect(d->m_ksaneCoreInterface, &KSaneCore::Interface::scanProgress, d, &KSaneWidgetPrivate::updateProgress);
47 connect(d->m_ksaneCoreInterface, &KSaneCore::Interface::batchModeCountDown, d, &KSaneWidgetPrivate::updateCountDown);
48 connect(d->m_ksaneCoreInterface, &KSaneCore::Interface::availableDevices, d, &KSaneWidgetPrivate::signalDevListUpdate);
50
51 // Create the static UI
52 // create the preview
53 d->m_previewViewer = new KSaneViewer(&(d->m_previewImg), this);
54 connect(d->m_previewViewer, &KSaneViewer::newSelection,
55 d, &KSaneWidgetPrivate::handleSelection);
56
57 d->m_warmingUp = new QLabel;
58 d->m_warmingUp->setText(i18n("Waiting for the scan to start."));
59 d->m_warmingUp->setAlignment(Qt::AlignCenter);
60 d->m_warmingUp->hide();
61
62 d->m_countDown = new QLabel;
63 d->m_countDown->setAlignment(Qt::AlignCenter);
64 d->m_countDown->hide();
65
66 d->m_progressBar = new QProgressBar;
67 d->m_progressBar->setMaximum(100);
68
69 d->m_cancelBtn = new QPushButton;
70 d->m_cancelBtn->setIcon(QIcon::fromTheme(QStringLiteral("process-stop")));
71 d->m_cancelBtn->setToolTip(i18n("Cancel current scan operation"));
73
74 d->m_activityFrame = new QWidget;
75 QHBoxLayout *progress_lay = new QHBoxLayout(d->m_activityFrame);
76 progress_lay->setContentsMargins(0, 0, 0, 0);
77 progress_lay->addWidget(d->m_progressBar, 100);
78 progress_lay->addWidget(d->m_warmingUp, 100);
79 progress_lay->addWidget(d->m_countDown, 100);
80 progress_lay->addWidget(d->m_cancelBtn, 0);
81 d->m_activityFrame->hide();
82
83 d->m_zInBtn = new QToolButton(this);
84 d->m_zInBtn->setAutoRaise(true);
85 d->m_zInBtn->setIcon(QIcon::fromTheme(QStringLiteral("zoom-in")));
86 d->m_zInBtn->setToolTip(i18n("Zoom In"));
87 connect(d->m_zInBtn, &QToolButton::clicked, d->m_previewViewer, &KSaneViewer::zoomIn);
88
89 d->m_zOutBtn = new QToolButton(this);
90 d->m_zOutBtn->setAutoRaise(true);
91 d->m_zOutBtn->setIcon(QIcon::fromTheme(QStringLiteral("zoom-out")));
92 d->m_zOutBtn->setToolTip(i18n("Zoom Out"));
93 connect(d->m_zOutBtn, &QToolButton::clicked, d->m_previewViewer, &KSaneViewer::zoomOut);
94
95 d->m_zSelBtn = new QToolButton(this);
96 d->m_zSelBtn->setAutoRaise(true);
97 d->m_zSelBtn->setIcon(QIcon::fromTheme(QStringLiteral("zoom-fit-best")));
98 d->m_zSelBtn->setToolTip(i18n("Zoom to Selection"));
99 connect(d->m_zSelBtn, &QToolButton::clicked, d->m_previewViewer, &KSaneViewer::zoomSel);
100
101 d->m_zFitBtn = new QToolButton(this);
102 d->m_zFitBtn->setAutoRaise(true);
103 d->m_zFitBtn->setIcon(QIcon::fromTheme(QStringLiteral("document-preview")));
104 d->m_zFitBtn->setToolTip(i18n("Zoom to Fit"));
105 connect(d->m_zFitBtn, &QToolButton::clicked, d->m_previewViewer, &KSaneViewer::zoom2Fit);
106
107 d->m_clearSelBtn = new QToolButton(this);
108 d->m_clearSelBtn->setAutoRaise(true);
109 d->m_clearSelBtn->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear")));
110 d->m_clearSelBtn->setToolTip(i18n("Clear Selections"));
111 connect(d->m_clearSelBtn, &QToolButton::clicked, d->m_previewViewer, &KSaneViewer::clearSelections);
112
113 QShortcut *prevShortcut = new QShortcut(QKeySequence(QStringLiteral("Ctrl+P")), this);
114 connect(prevShortcut, &QShortcut::activated, d, &KSaneWidgetPrivate::startPreviewScan);
115
116 QShortcut *scanShortcut = new QShortcut(QKeySequence(QStringLiteral("Ctrl+S")), this);
117 connect(scanShortcut, &QShortcut::activated, d, &KSaneWidgetPrivate::startFinalScan);
118
119 d->m_prevBtn = new QPushButton(this);
120 d->m_prevBtn->setIcon(QIcon::fromTheme(QStringLiteral("document-import")));
121 d->m_prevBtn->setToolTip(i18n("Scan Preview Image (%1)", prevShortcut->key().toString(QKeySequence::NativeText)));
122 d->m_prevBtn->setText(i18nc("Preview button text", "Preview"));
123 connect(d->m_prevBtn, &QToolButton::clicked, d, &KSaneWidgetPrivate::startPreviewScan);
124
125 d->m_scanBtn = new QPushButton(this);
126 d->m_scanBtn->setIcon(QIcon::fromTheme(QStringLiteral("document-save")));
127 d->m_scanBtn->setToolTip(i18n("Scan Final Image (%1)", scanShortcut->key().toString(QKeySequence::NativeText)));
128 d->m_scanBtn->setText(i18nc("Final scan button text", "Scan"));
129 d->m_scanBtn->setFocus(Qt::OtherFocusReason);
130 setFocusProxy(d->m_scanBtn);
131 connect(d->m_scanBtn, &QToolButton::clicked, d, &KSaneWidgetPrivate::startFinalScan);
132
133 d->m_btnFrame = new QWidget;
134 QHBoxLayout *btn_lay = new QHBoxLayout(d->m_btnFrame);
135 btn_lay->setContentsMargins(0, 0, 0, 0);
136 btn_lay->addWidget(d->m_zInBtn);
137 btn_lay->addWidget(d->m_zOutBtn);
138 btn_lay->addWidget(d->m_zSelBtn);
139 btn_lay->addWidget(d->m_zFitBtn);
140 btn_lay->addWidget(d->m_clearSelBtn);
141 btn_lay->addStretch(100);
142 btn_lay->addWidget(d->m_prevBtn);
143 btn_lay->addWidget(d->m_scanBtn);
144
145 // calculate the height of the waiting/scanning/buttons frames to avoid jumpiness.
146 int minHeight = d->m_btnFrame->sizeHint().height();
147 if (d->m_activityFrame->sizeHint().height() > minHeight) {
148 minHeight = d->m_activityFrame->sizeHint().height();
149 }
150 d->m_btnFrame->setMinimumHeight(minHeight);
151 d->m_activityFrame->setMinimumHeight(minHeight);
152 d->m_warmingUp->setMinimumHeight(minHeight);
153 d->m_countDown->setMinimumHeight(minHeight);
154
155 d->m_previewFrame = new QWidget;
156 QVBoxLayout *preview_layout = new QVBoxLayout(d->m_previewFrame);
157 preview_layout->setContentsMargins(0, 0, 0, 0);
158 preview_layout->addWidget(d->m_previewViewer, 100);
159 preview_layout->addWidget(d->m_activityFrame, 0);
160 preview_layout->addWidget(d->m_btnFrame, 0);
161
162 // Create Options Widget
163 d->m_optsTabWidget = new QTabWidget();
164
165 // Add the basic options tab
166 d->m_basicScrollA = new QScrollArea();
167 d->m_basicScrollA->setWidgetResizable(true);
168 d->m_basicScrollA->setFrameShape(QFrame::NoFrame);
169 d->m_optsTabWidget->addTab(d->m_basicScrollA, i18n("Basic Options"));
170
171 // Add the advanced options tab
172 d->m_advancedScrollA = new QScrollArea();
173 d->m_advancedScrollA->setWidgetResizable(true);
174 d->m_advancedScrollA->setFrameShape(QFrame::NoFrame);
175 d->m_optsTabWidget->addTab(d->m_advancedScrollA, i18n("Advanced Options"));
176
177 // Add the other options tab
178 d->m_otherScrollA = new QScrollArea;
179 d->m_otherScrollA->setWidgetResizable(true);
180 d->m_otherScrollA->setFrameShape(QFrame::NoFrame);
181 d->m_optsTabWidget->addTab(d->m_otherScrollA, i18n("Scanner Specific Options"));
182
183 d->m_splitter = new QSplitter(this);
184 d->m_splitter->addWidget(d->m_optsTabWidget);
185 d->m_splitter->setStretchFactor(0, 0);
186 d->m_splitter->addWidget(d->m_previewFrame);
187 d->m_splitter->setStretchFactor(1, 100);
188
189 d->m_optionsCollapser = new SplitterCollapser(d->m_splitter, d->m_optsTabWidget);
190
191 QHBoxLayout *base_layout = new QHBoxLayout(this);
192 base_layout->addWidget(d->m_splitter);
193 base_layout->setContentsMargins(0, 0, 0, 0);
194
195 // disable the interface in case no device is opened.
196 d->m_optsTabWidget->setDisabled(true);
197 d->m_previewViewer->setDisabled(true);
198 d->m_btnFrame->setDisabled(true);
199
200}
201
203{
204 delete d->m_ksaneCoreInterface;
205 delete d;
206}
207
209{
210 return d->m_ksaneCoreInterface->deviceName();
211}
212
214{
215 return d->m_ksaneCoreInterface->deviceVendor();
216}
217
219{
220 return d->m_ksaneCoreInterface->deviceModel();
221}
222
224{
225 QString selected_name;
226 QPointer<KSaneDeviceDialog> sel = new KSaneDeviceDialog(parent);
227 connect(d->m_ksaneCoreInterface, &KSaneCore::Interface::availableDevices, sel, &KSaneDeviceDialog::updateDevicesList);
228 connect(sel, &KSaneDeviceDialog::requestReloadList, d->m_ksaneCoreInterface, &KSaneCore::Interface::reloadDevicesList);
229
230 d->m_ksaneCoreInterface->reloadDevicesList();
231
232 if (sel->exec() == QDialog::Accepted) {
233 selected_name = sel->getSelectedName();
234 }
235
236 delete sel;
237 return selected_name;
238}
239
240bool KSaneWidget::openDevice(const QString &deviceName)
241{
242 KPasswordDialog *dlg;
243#ifdef HAVE_KWALLET
244 KWallet::Wallet *saneWallet;
245#endif
246 QString myFolderName = QStringLiteral("ksane");
247 QMap<QString, QString> wallet_entry;
248
249 KSaneCore::Interface::OpenStatus status = d->m_ksaneCoreInterface->openDevice(deviceName);
250 if (status == KSaneCore::Interface::OpeningFailed) {
251 return false;
252 }
253
254 bool password_dialog_ok = true;
255
256 // prepare wallet for authentication and create password dialog
257 if (status == KSaneCore::Interface::OpeningDenied) {
258#ifdef HAVE_KWALLET
260
261 if (saneWallet) {
263 if (!saneWallet->hasFolder(myFolderName)) {
264 saneWallet->createFolder(myFolderName);
265 }
266 saneWallet->setFolder(myFolderName);
267 saneWallet->readMap(deviceName, wallet_entry);
268 if (!wallet_entry.empty() || true) {
269 dlg->setUsername(wallet_entry[QStringLiteral("username")]);
270 dlg->setPassword(wallet_entry[QStringLiteral("password")]);
271 dlg->setKeepPassword(true);
272 }
273 } else
274#endif
275 {
277 }
278 dlg->setPrompt(i18n("Authentication required for resource: %1", deviceName));
279
280 }
281
282 // sane_open failed due to insufficient authorization
283 // retry opening device with user provided data assisted with kwallet records
284 while (status == KSaneCore::Interface::OpeningDenied) {
285
286 password_dialog_ok = dlg->exec();
287 if (!password_dialog_ok) {
288 delete dlg;
289 return false; //the user canceled
290 }
291
292 // add/update the device user-name and password for authentication
293 status = d->m_ksaneCoreInterface->openRestrictedDevice(deviceName, dlg->username(), dlg->password());
294
295#ifdef HAVE_KWALLET
296 // store password in wallet on successful authentication
297 if (dlg->keepPassword() && status != KSaneCore::Interface::OpeningDenied) {
299 entry[QStringLiteral("username")] = dlg->username();
300 entry[QStringLiteral("password")] = dlg->password();
301 if (saneWallet) {
302 saneWallet->writeMap(deviceName, entry);
303 }
304 }
305#endif
306 }
307
308 // Create the options interface
309 d->createOptInterface();
310
311 // Enable the interface
312 d->m_optsTabWidget->setDisabled(false);
313 d->m_previewViewer->setDisabled(false);
314 d->m_btnFrame->setDisabled(false);
315
316 // estimate the preview size and create an empty image
317 // this is done so that you can select scan area without
318 // having to scan a preview.
319 d->updatePreviewSize();
320 QTimer::singleShot(1000, d->m_previewViewer, &KSaneViewer::zoom2Fit);
321 return true;
322}
323
325{
326 bool result = d->m_ksaneCoreInterface->closeDevice();
327 if (!result) {
328 return false;
329 }
330 d->clearDeviceOptions();
331 // disable the interface until a new device is opened.
332 d->m_optsTabWidget->setDisabled(true);
333 d->m_previewViewer->setDisabled(true);
334 d->m_btnFrame->setDisabled(true);
335
336 return true;
337}
338
340{
341 if (d->m_btnFrame->isEnabled()) {
342 d->m_cancelMultiScan = false;
343 d->startFinalScan();
344 } else {
345 // if the button frame is disabled, there is no open device to scan from
347 }
348}
349
351{
352 if (d->m_btnFrame->isEnabled()) {
353 d->m_cancelMultiScan = false;
354 d->startPreviewScan();
355 } else {
356 // if the button frame is disabled, there is no open device to scan from
358 }
359}
360
362{
363 d->m_cancelMultiScan = true;
364 d->m_ksaneCoreInterface->stopScan();
365}
366
368{
369 d->m_previewDPI = dpi;
370}
371
372void KSaneWidget::getOptionValues(QMap <QString, QString> &opts)
373{
374 opts.clear();
375 opts = d->m_ksaneCoreInterface->getOptionsMap();
376}
377
378bool KSaneWidget::getOptionValue(const QString &option, QString &value)
379{
380 const auto optionsMap = d->m_ksaneCoreInterface->getOptionsMap();
381 auto it = optionsMap.constBegin();
382 while (it != optionsMap.constEnd()) {
383 if(it.key() == option) {
384 value = it.value();
385 return !value.isEmpty();
386 }
387 it++;
388 }
389 return false;
390}
391
392int KSaneWidget::setOptionValues(const QMap <QString, QString> &options)
393{
394 int ret = 0;
395
396 ret = d->m_ksaneCoreInterface->setOptionsMap(options);
397
398 if ((d->m_splitGamChB) &&
399 (d->m_optGamR) &&
400 (d->m_optGamG) &&
401 (d->m_optGamB)) {
402 // check if the current gamma values are identical. if they are identical,
403 // uncheck the "Separate color intensity tables" checkbox
404 QVariant redGamma = d->m_optGamR->value();
405 QVariant greenGamma = d->m_optGamG->value();
406 QVariant blueGamma = d->m_optGamB->value();
407
408 if ((redGamma == greenGamma) && (greenGamma == blueGamma)) {
409 d->m_splitGamChB->setChecked(false);
410 // set the values to the common gamma widget
411 d->m_commonGamma->setValues(redGamma);
412 } else {
413 d->m_splitGamChB->setChecked(true);
414 }
415 }
416 return ret;
417}
418
419bool KSaneWidget::setOptionValue(const QString &option, const QString &value)
420{
421 if (d->m_scanOngoing) {
422 return false;
423 }
424
425 const auto optionsList = d->m_ksaneCoreInterface->getOptionsList();
426 for (auto &writeOption : optionsList) {
427 if (writeOption->name() == option) {
428 if (writeOption->setValue(value)) {
429 if ((d->m_splitGamChB) &&
430 (d->m_optGamR) &&
431 (d->m_optGamG) &&
432 (d->m_optGamB) &&
433 ((writeOption == d->m_optGamR) ||
434 (writeOption == d->m_optGamG) ||
435 (writeOption == d->m_optGamB))) {
436 // check if the current gamma values are identical. if they are identical,
437 // uncheck the "Separate color intensity tables" checkbox
438 QVariant redGamma = d->m_optGamR->value();
439 QVariant greenGamma = d->m_optGamG->value();
440 QVariant blueGamma = d->m_optGamB->value();
441 if ((redGamma == greenGamma) && (greenGamma == blueGamma)) {
442 d->m_splitGamChB->setChecked(false);
443 // set the values to the common gamma widget
444 d->m_commonGamma->setValues(redGamma);
445 } else {
446 d->m_splitGamChB->setChecked(true);
447 }
448 }
449 return true;
450 }
451 }
452 }
453 return false;
454}
455
457{
458 d->m_autoSelect = enable;
459}
460
462{
463 float result = 0.0;
464 if (d->m_optBrX) {
465 if (d->m_optBrX->valueUnit() == KSaneCore::Option::UnitPixel) {
466 result = d->m_optBrX->maximumValue().toFloat();
467 float dpi = 0;
468 if (d->m_optRes) {
469 dpi = d->m_optRes->value().toFloat();
470 }
471 if (dpi < 1) {
472 qCDebug(KSANE_LOG) << "Broken DPI value";
473 dpi = 1.0;
474 }
475 result = result / dpi / 25.4;
476 } else if (d->m_optBrX->valueUnit() == KSaneCore::Option::UnitMilliMeter) {
477 result = d->m_optBrX->maximumValue().toFloat();
478 }
479 }
480 return result;
481}
482
484{
485 float result = 0.0;
486 if (d->m_optBrY) {
487 if (d->m_optBrY->valueUnit() == KSaneCore::Option::UnitPixel) {
488 result = d->m_optBrY->maximumValue().toFloat();
489 float dpi = 0;
490 if (d->m_optRes) {
491 dpi = d->m_optRes->value().toFloat();
492 }
493 if (dpi < 1) {
494 qCDebug(KSANE_LOG) << "Broken DPI value";
495 dpi = 1.0;
496 }
497 result = result / dpi / 25.4;
498 } else if (d->m_optBrY->valueUnit() == KSaneCore::Option::UnitMilliMeter) {
499 result = d->m_optBrY->maximumValue().toFloat();
500 }
501 }
502 return result;
503}
504
505void KSaneWidget::setSelection(QPointF topLeft, QPointF bottomRight)
506{
507 if (!d->m_optBrX || !d->m_optBrY || !d->m_optTlX || !d->m_optTlY) {
508 return;
509 }
510 if (topLeft.x() < 0.0 || topLeft.y() < 0.0 || bottomRight.x() < 0.0 || bottomRight.y() < 0.0) {
511 d->m_previewViewer->clearActiveSelection();
512 return;
513 }
514
515 float tlxRatio = d->scanAreaToRatioX(topLeft.x());
516 float tlyRatio = d->scanAreaToRatioY(topLeft.y());
517 float brxRatio = d->scanAreaToRatioX(bottomRight.x());
518 float bryRatio = d->scanAreaToRatioX(bottomRight.y());
519
520 d->m_previewViewer->setSelection(tlxRatio, tlyRatio, brxRatio, bryRatio);
521}
522
523} // NameSpace KSaneIface
524
525#include "moc_ksanewidget.cpp"
void setKeepPassword(bool b)
QString password() const
void setUsername(const QString &)
void setPrompt(const QString &prompt)
void setPassword(const QString &password)
bool keepPassword() const
QString username() const
bool reloadDevicesList(DeviceType type=AllDevices)
void scannedImageReady(const QImage &scannedImage)
void availableDevices(const QList< DeviceInformation * > &deviceList)
void scanFinished(KSaneCore::Interface::ScanStatus status, const QString &strStatus)
void batchModeCountDown(int remainingSeconds)
void userMessage(KSaneCore::Interface::ScanStatus status, const QString &strStatus)
void scanProgress(int percent)
void buttonPressed(const QString &optionName, const QString &optionLabel, bool pressed)
bool openDevice(const QString &device_name)
This method opens the specified scanner device and adds the scan options to the KSane widget.
bool getOptionValue(const QString &option, QString &value)
This function reads one parameter value into a string.
@ ErrorGeneral
The error string should contain an error message.
Definition ksanewidget.h:39
void cancelScan()
This method can be used to cancel a scan or prevent an automatic new scan.
void scanDone(int status, const QString &strStatus)
This signal is emitted when the scanning has ended.
bool closeDevice()
This method closes the currently open scanner device.
bool setOptionValue(const QString &option, const QString &value)
This function writes one parameter value into a string.
QString selectDevice(QWidget *parent=nullptr)
This helper method displays a dialog for selecting a scanner.
void getOptionValues(QMap< QString, QString > &options)
This method reads the available parameters and their values and returns them in a QMap (Name,...
QString deviceVendor() const
This method returns the vendor name of the currently opened scanner.
int setOptionValues(const QMap< QString, QString > &options)
This method can be used to write many parameter values at once.
void startPreviewScan()
This method can be used to start a preview scan.
void setPreviewResolution(float dpi)
This function is used to set the preferred resolution for scanning the preview.
QString deviceName() const
This method returns the internal device name of the currently opened scanner.
KSaneWidget(QWidget *parent=nullptr)
This constructor initializes the private class variables, but the widget is left empty.
void startScan()
This method can be used to start a scan (if no GUI is needed).
float scanAreaWidth()
This method returns the scan area's width in mm.
void enableAutoSelect(bool enable)
This function can be used to enable/disable automatic selections on previews.
float scanAreaHeight()
This method returns the scan area's height in mm.
void setSelection(QPointF topLeft, QPointF bottomRight)
This method sets the selection according to the given points.
QString deviceModel() const
This method returns the model of the currently opened scanner.
void buttonPressed(const QString &optionName, const QString &optionLabel, bool pressed)
This Signal is emitted when a hardware button is pressed.
~KSaneWidget() override
Standard destructor.
A button which appears on the side of a splitter handle and allows easy collapsing of the widget on t...
virtual bool createFolder(const QString &f)
virtual bool hasFolder(const QString &f)
virtual int readMap(const QString &key, QMap< QString, QString > &value)
static const QString LocalWallet()
static Wallet * openWallet(const QString &name, WId w, OpenType ot=Synchronous)
virtual bool setFolder(const QString &f)
virtual int writeMap(const QString &key, const QMap< QString, QString > &value)
Q_SCRIPTABLE CaptureState status()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
void clicked(bool checked)
void addStretch(int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
virtual int exec()
QIcon fromTheme(const QString &name)
void setContentsMargins(const QMargins &margins)
void clear()
bool empty() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
qreal x() const const
qreal y() const const
void activated()
bool isEmpty() const const
AlignCenter
OtherFocusReason
QWidget(QWidget *parent, Qt::WindowFlags f)
void setFocusProxy(QWidget *w)
WId winId() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 24 2024 12:00:24 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.