KXmlGui

kbugreport.cpp
1 /*
2  This file is part of the KDE project
3  SPDX-FileCopyrightText: 1999 David Faure <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "kbugreport.h"
9 
10 #include <QProcess>
11 #include <QDialogButtonBox>
12 #include <QPushButton>
13 #include <QRadioButton>
14 #include <QGroupBox>
15 #include <QLocale>
16 #include <QCloseEvent>
17 #include <QLabel>
18 #include <QUrl>
19 #include <QUrlQuery>
20 #include <QDesktopServices>
21 #include <QComboBox>
22 #include <QLineEdit>
23 #include <QStandardPaths>
24 #include <QTextEdit>
25 #include <QHBoxLayout>
26 #include <QGridLayout>
27 
28 #include <kaboutdata.h>
29 #include <kconfig.h>
30 #include <kconfiggroup.h>
31 #include <kemailsettings.h>
32 #include <klocalizedstring.h>
33 #include <kmessagebox.h>
34 #include <ktitlewidget.h>
35 
36 #include "debug.h"
37 #include "../kxmlgui_version.h"
38 #include "systeminformation_p.h"
39 #include "config-xmlgui.h"
40 
41 #include <array>
42 
43 class KBugReportPrivate
44 {
45 public:
46  KBugReportPrivate(KBugReport *q): q(q), m_aboutData(KAboutData::applicationData()) {}
47 
48  enum BugDestination
49  {
50  BugsKdeOrg,
51  CustomEmail,
52  CustomUrl
53  };
54 
55  void _k_slotConfigureEmail();
56  void _k_slotSetFrom();
57  void _k_updateUrl();
58 
59  KBugReport *q;
60  QProcess *m_process;
61  KAboutData m_aboutData;
62 
63  QTextEdit *m_lineedit;
64  QLineEdit *m_subject;
65  QLabel *m_from;
66  QLabel *m_version;
67  QString m_strVersion;
68  QGroupBox *m_bgSeverity;
69  QPushButton *m_configureEmail;
70 
71  QString lastError;
72  QString kde_version;
73  QString appname;
74  QString os;
75  QUrl url;
76  QList<QRadioButton *> severityButtons;
77  int currentSeverity()
78  {
79  for (int i = 0; i < severityButtons.count(); i++)
80  if (severityButtons[i]->isChecked()) {
81  return i;
82  }
83  return -1;
84  }
85  BugDestination bugDestination;
86 };
87 
88 KBugReport::KBugReport(const KAboutData &aboutData, QWidget *_parent)
89  : QDialog(_parent), d(new KBugReportPrivate(this))
90 {
91  setWindowTitle(i18nc("@title:window", "Submit Bug Report"));
92 
93  QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
97 
98  d->m_aboutData = aboutData;
99  d->m_process = nullptr;
100  d->bugDestination = KBugReportPrivate::CustomEmail;
101 
102  const QString bugAddress = d->m_aboutData.bugAddress();
103  if (bugAddress == QLatin1String("[email protected]")) {
104  // This is a core KDE application -> redirect to the web form
105  d->bugDestination = KBugReportPrivate::BugsKdeOrg;
106  } else if (!QUrl(bugAddress).scheme().isEmpty()) {
107  // The bug reporting address is a URL -> redirect to that
108  d->bugDestination = KBugReportPrivate::CustomUrl;
109  }
110 
111  if (d->bugDestination != KBugReportPrivate::CustomEmail) {
112  KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::close());
113  }
114 
115  QLabel *tmpLabel;
116  QVBoxLayout *lay = new QVBoxLayout;
117  setLayout(lay);
118 
119  KTitleWidget *title = new KTitleWidget(this);
120  title->setText(i18n("Submit Bug Report"));
121  title->setIconSize(QSize(32, 32));
122  title->setIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug")));
123  lay->addWidget(title);
124 
125  QGridLayout *glay = new QGridLayout();
126  lay->addLayout(glay);
127 
128  int row = 0;
129 
130  if (d->bugDestination == KBugReportPrivate::CustomEmail) {
131  // From
132  QString qwtstr = i18n("Your email address. If incorrect, use the Configure Email button to change it");
133  tmpLabel = new QLabel(i18nc("Email sender address", "From:"), this);
134  glay->addWidget(tmpLabel, row, 0);
135  tmpLabel->setWhatsThis(qwtstr);
136  d->m_from = new QLabel(this);
137  glay->addWidget(d->m_from, row, 1);
138  d->m_from->setWhatsThis(qwtstr);
139 
140  // Configure email button
141  d->m_configureEmail = new QPushButton(i18nc("@action:button", "Configure Email..."), this);
142  connect(d->m_configureEmail, SIGNAL(clicked()), this,
143  SLOT(_k_slotConfigureEmail()));
144  glay->addWidget(d->m_configureEmail, 0, 2, 3, 1, Qt::AlignTop | Qt::AlignRight);
145 
146  // To
147  qwtstr = i18n("The email address this bug report is sent to.");
148  tmpLabel = new QLabel(i18nc("Email receiver address", "To:"), this);
149  glay->addWidget(tmpLabel, ++row, 0);
150  tmpLabel->setWhatsThis(qwtstr);
151  tmpLabel = new QLabel(d->m_aboutData.bugAddress(), this);
153  glay->addWidget(tmpLabel, row, 1);
154  tmpLabel->setWhatsThis(qwtstr);
155 
156  KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok),
157  KGuiItem(i18nc("@action:button", "&Send"), QStringLiteral("mail-send"),
158  i18nc("@info:tooltip", "Send bug report."),
159  i18nc("@info:whatsthis", "Send this bug report to %1.", d->m_aboutData.bugAddress())));
160  row++;
161  } else {
162  d->m_configureEmail = nullptr;
163  d->m_from = nullptr;
164  }
165 
166  // Program name
167  QString qwtstr = i18n("The application for which you wish to submit a bug report - if incorrect, please use the Report Bug menu item of the correct application");
168  tmpLabel = new QLabel(i18n("Application: "), this);
169  glay->addWidget(tmpLabel, row, 0);
170  tmpLabel->setWhatsThis(qwtstr);
171  QLabel *appLabel = new QLabel(this);
172  d->appname = d->m_aboutData.productName();
173  appLabel->setText(d->appname);
174  glay->addWidget(appLabel, row, 1);
175  tmpLabel->setWhatsThis(qwtstr);
176 
177  // Version
178  qwtstr = i18n("The version of this application - please make sure that no newer version is available before sending a bug report");
179  tmpLabel = new QLabel(i18n("Version:"), this);
180  glay->addWidget(tmpLabel, ++row, 0);
181  tmpLabel->setWhatsThis(qwtstr);
182  d->m_strVersion = d->m_aboutData.version();
183  if (d->m_strVersion.isEmpty()) {
184  d->m_strVersion = i18n("no version set (programmer error)");
185  }
186  d->kde_version = QStringLiteral(KXMLGUI_VERSION_STRING) + QLatin1String(", ") + QStringLiteral(XMLGUI_DISTRIBUTION_TEXT);
187  if (d->bugDestination != KBugReportPrivate::BugsKdeOrg) {
188  d->m_strVersion += QLatin1Char(' ') + d->kde_version;
189  }
190  d->m_version = new QLabel(d->m_strVersion, this);
191  d->m_version->setTextInteractionFlags(Qt::TextBrowserInteraction);
192  //glay->addWidget( d->m_version, row, 1 );
193  glay->addWidget(d->m_version, row, 1, 1, 2);
194  d->m_version->setWhatsThis(qwtstr);
195 
196  tmpLabel = new QLabel(i18n("OS:"), this);
197  glay->addWidget(tmpLabel, ++row, 0);
198  d->os = SystemInformation::operatingSystemVersion();
199 
200  tmpLabel = new QLabel(d->os, this);
201  tmpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
202  glay->addWidget(tmpLabel, row, 1, 1, 2);
203 
204  if (d->bugDestination == KBugReportPrivate::CustomEmail) {
205  // Severity
206  d->m_bgSeverity = new QGroupBox(i18nc("@title:group", "Se&verity"), this);
207 
208  struct SeverityData { QString name; QString text; };
209  const std::array<SeverityData, 5> severityData = { {
210  { QStringLiteral("critical"), i18nc("bug severity", "Critical") },
211  { QStringLiteral("grave"), i18nc("bug severity", "Grave") },
212  { QStringLiteral("normal"), i18nc("bug severity", "Normal") },
213  { QStringLiteral("wishlist"), i18nc("bug severity", "Wishlist") },
214  { QStringLiteral("i18n"), i18nc("bug severity", "Translation") },
215  } };
216 
217  QHBoxLayout *severityLayout = new QHBoxLayout(d->m_bgSeverity);
218  for (auto& severityDatum : severityData) {
219  // Store the severity string as the name
220  QRadioButton *rb = new QRadioButton(severityDatum.text, d->m_bgSeverity);
221  rb->setObjectName(severityDatum.name);
222  d->severityButtons.append(rb);
223  severityLayout->addWidget(rb);
224  }
225  d->severityButtons[2]->setChecked(true); // default : "normal"
226 
227  lay->addWidget(d->m_bgSeverity);
228 
229  // Subject
230  QHBoxLayout *hlay = new QHBoxLayout();
231  lay->addItem(hlay);
232  tmpLabel = new QLabel(i18n("S&ubject: "), this);
233  hlay->addWidget(tmpLabel);
234  d->m_subject = new QLineEdit(this);
235  d->m_subject->setClearButtonEnabled(true);
236  d->m_subject->setFocus();
237  tmpLabel->setBuddy(d->m_subject);
238  hlay->addWidget(d->m_subject);
239 
240  QString text = i18n("Enter the text (in English if possible) that you wish to submit for the "
241  "bug report.\n"
242  "If you press \"Send\", a mail message will be sent to the maintainer of "
243  "this program.\n");
244  QLabel *label = new QLabel(this);
245 
246  label->setText(text);
247  lay->addWidget(label);
248 
249  // The multiline-edit
250  d->m_lineedit = new QTextEdit(this);
251  d->m_lineedit->setMinimumHeight(180); // make it big
252  d->m_lineedit->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
253  d->m_lineedit->setLineWrapMode(QTextEdit::WidgetWidth);
254  lay->addWidget(d->m_lineedit, 10 /*stretch*/);
255 
256  d->_k_slotSetFrom();
257  } else {
258  // Point to the web form
259 
260  QString text;
261  if (d->bugDestination == KBugReportPrivate::BugsKdeOrg) {
262  text = i18n("<qt>To submit a bug report, click on the button below. This will open a web browser "
263  "window on <a href=\"https://bugs.kde.org\">https://bugs.kde.org</a> where you will find "
264  "a form to fill in. The information displayed above will be transferred to that server.</qt>");
265  d->_k_updateUrl();
266  } else {
267  text = i18n("<qt>To submit a bug report, click on the button below. This will open a web browser "
268  "window on <a href=\"%1\">%2</a>.</qt>", bugAddress, bugAddress);
269  d->url = QUrl(bugAddress);
270  }
271 
272  lay->addSpacing(10);
273  QLabel *label = new QLabel(text, this);
274  label->setOpenExternalLinks(true);
276  label->setWordWrap(true);
277  lay->addWidget(label);
278  lay->addSpacing(10);
279 
280 
281  QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
282  if (d->bugDestination == KBugReportPrivate::BugsKdeOrg) {
283  okButton->setText(i18nc("@action:button", "&Launch Bug Report Wizard"));
284  } else {
285  okButton->setText(i18nc("@action:button", "&Submit Bug Report"));
286  }
287  okButton->setIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug")));
288  }
289 
290  lay->addWidget(buttonBox);
291  setMinimumHeight(sizeHint().height() + 20); // WORKAROUND: prevent "cropped" qcombobox
292 }
293 
295 {
296  delete d;
297 }
298 
300 {
301  if (d->bugDestination == KBugReportPrivate::CustomEmail) {
302  return d->m_lineedit->toPlainText();
303  } else {
304  return QString();
305  }
306 }
307 
309 {
310  if (d->bugDestination == KBugReportPrivate::CustomEmail) {
311  d->m_lineedit->setPlainText(messageBody);
312  }
313 }
314 
315 void KBugReportPrivate::_k_updateUrl()
316 {
317  url = QUrl(QStringLiteral("https://bugs.kde.org/enter_bug.cgi"));
318  QUrlQuery query;
319  query.addQueryItem(QStringLiteral("format"), QStringLiteral("guided")); // use the guided form
320 
321  // the string format is product/component, where component is optional
322  QStringList list = appname.split(QLatin1Char('/'));
323  query.addQueryItem(QStringLiteral("product"), list[0]);
324  if (list.size() == 2) {
325  query.addQueryItem(QStringLiteral("component"), list[1]);
326  }
327 
328  query.addQueryItem(QStringLiteral("version"), m_strVersion);
329  url.setQuery(query);
330 
331  // TODO: guess and fill OS(sys_os) and Platform(rep_platform) fields
332 }
333 
334 void KBugReportPrivate::_k_slotConfigureEmail()
335 {
336  if (m_process) {
337  return;
338  }
339  m_process = new QProcess;
340  QObject::connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), q, SLOT(_k_slotSetFrom()));
341  m_process->start(QStringLiteral("kcmshell5"), QStringList() << QStringLiteral("kcm_users"));
342  if (!m_process->waitForStarted()) {
343  //qCDebug(DEBUG_KXMLGUI) << "Couldn't start kcmshell5..";
344  delete m_process;
345  m_process = nullptr;
346  return;
347  }
348  m_configureEmail->setEnabled(false);
349 }
350 
351 void KBugReportPrivate::_k_slotSetFrom()
352 {
353  delete m_process;
354  m_process = nullptr;
355  m_configureEmail->setEnabled(true);
356 
357  KEMailSettings emailSettings;
358  QString fromaddr = emailSettings.getSetting(KEMailSettings::EmailAddress);
359  if (fromaddr.isEmpty()) {
360  fromaddr = SystemInformation::userName();
361  } else {
362  QString name = emailSettings.getSetting(KEMailSettings::RealName);
363  if (!name.isEmpty()) {
364  fromaddr = name + QLatin1String(" <") + fromaddr + QLatin1Char('>');
365  }
366  }
367  m_from->setText(fromaddr);
368 }
369 
371 {
372  if (d->bugDestination != KBugReportPrivate::CustomEmail) {
374  return;
375  }
376 
377  if (d->m_lineedit->toPlainText().isEmpty() ||
378  d->m_subject->text().isEmpty()) {
379  QString msg = i18n("You must specify both a subject and a description "
380  "before the report can be sent.");
381  KMessageBox::error(this, msg);
382  return;
383  }
384 
385  switch (d->currentSeverity()) {
386  case 0: // critical
388  "<p>You chose the severity <b>Critical</b>. "
389  "Please note that this severity is intended only for bugs that:</p>"
390  "<ul><li>break unrelated software on the system (or the whole system)</li>"
391  "<li>cause serious data loss</li>"
392  "<li>introduce a security hole on the system where the affected package is installed</li></ul>\n"
393  "<p>Does the bug you are reporting cause any of the above damage? "
394  "If it does not, please select a lower severity. Thank you.</p>"), QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel()) == KMessageBox::No) {
395  return;
396  }
397  break;
398  case 1: // grave
400  "<p>You chose the severity <b>Grave</b>. "
401  "Please note that this severity is intended only for bugs that:</p>"
402  "<ul><li>make the package in question unusable or mostly so</li>"
403  "<li>cause data loss</li>"
404  "<li>introduce a security hole allowing access to the accounts of users who use the affected package</li></ul>\n"
405  "<p>Does the bug you are reporting cause any of the above damage? "
406  "If it does not, please select a lower severity. Thank you.</p>"), QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel()) == KMessageBox::No) {
407  return;
408  }
409  break;
410  default:
411  break;
412  }
413  if (!sendBugReport()) {
414  QString msg = i18n("Unable to send the bug report.\n"
415  "Please submit a bug report manually....\n"
416  "See https://bugs.kde.org/ for instructions.");
417  KMessageBox::error(this, msg + QLatin1String("\n\n") + d->lastError);
418  return;
419  }
420 
422  i18n("Bug report sent, thank you for your input."));
423  QDialog::accept();
424 }
425 
426 void KBugReport::closeEvent(QCloseEvent *e)
427 {
428  if (d->bugDestination == KBugReportPrivate::CustomEmail &&
429  ((d->m_lineedit->toPlainText().length() > 0) || d->m_subject->isModified())) {
430  int rc = KMessageBox::warningYesNo(this,
431  i18n("Close and discard\nedited message?"),
432  i18nc("@title:window", "Close Message"),
434  if (rc == KMessageBox::No) {
435  e->ignore();
436  return;
437  }
438  }
440 }
441 
443 {
444  //qCDebug(DEBUG_KXMLGUI) << d->severityButtons[d->currentSeverity()]->objectName();
445  // Prepend the pseudo-headers to the contents of the mail
446  QString severity = d->severityButtons[d->currentSeverity()]->objectName();
447  QString appname = d->appname;
448  QString os = QStringLiteral("OS: %1 (%2)\n").
449  arg(QStringLiteral(XMLGUI_COMPILING_OS),
450  QStringLiteral(XMLGUI_DISTRIBUTION_TEXT));
451  QString bodyText;
452  /* for(int i = 0; i < m_lineedit->numLines(); i++)
453  {
454  QString line = m_lineedit->textLine(i);
455  if (!line.endsWith("\n"))
456  line += '\n';
457  bodyText += line;
458  }
459  */
460  bodyText = d->m_lineedit->toPlainText();
461  if (bodyText.length() > 0)
462  if (bodyText[bodyText.length() - 1] != QLatin1Char('\n')) {
463  bodyText += QLatin1Char('\n');
464  }
465  if (severity == QLatin1String("i18n") && QLocale().language() != QLocale::system().language()) {
466  // Case 1 : i18n bug
467  QString package = QLatin1String("i18n_") + QLocale::languageToString(QLocale().language());
468  package.replace(QLatin1Char('_'), QLatin1Char('-'));
469  return QLatin1String("Package: ") + package +
470  QLatin1String("\nApplication: ") + appname +
471  QLatin1String("\nVersion: ") + d->m_strVersion +
472  // not really i18n's version, so better here IMHO
473  QLatin1Char('\n') + os +
474  QLatin1Char('\n') + bodyText;
475  } else {
476  appname.replace(QLatin1Char('_'), QLatin1Char('-'));
477  // Case 2 : normal bug
478  return QLatin1String("Package: ") + appname +
479  QLatin1String("\nVersion: ") + d->m_strVersion +
480  QLatin1String("\nSeverity: ") + severity +
481  QLatin1Char('\n') + os +
482  QLatin1Char('\n') + bodyText;
483  }
484 }
485 
487 {
488  QString recipient = d->m_aboutData.bugAddress();
489  if (recipient.isEmpty()) {
490  recipient = QStringLiteral("[email protected]");
491  }
492 
493  QString command = QStandardPaths::findExecutable(QStringLiteral("ksendbugmail"));
494  if (command.isEmpty()) {
495  command = QFile::decodeName(CMAKE_INSTALL_PREFIX "/" KF5_LIBEXEC_INSTALL_DIR "/ksendbugmail");
496  }
497 
498  QProcess proc;
499  QStringList args;
500  args << QStringLiteral("--subject") << d->m_subject->text() << QStringLiteral("--recipient") << recipient;
501  proc.start(command, args);
502  //qCDebug(DEBUG_KXMLGUI) << command << args;
503  if (!proc.waitForStarted()) {
504  qCCritical(DEBUG_KXMLGUI) << "Unable to open a pipe to " << command;
505  return false;
506  }
507  proc.write(text().toUtf8());
508  proc.closeWriteChannel();
509 
510  proc.waitForFinished();
511  //qCDebug(DEBUG_KXMLGUI) << "kbugreport: sendbugmail exit, status " << proc.exitStatus() << " code " << proc.exitCode();
512 
513  QByteArray line;
514  if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() != 0) {
515  // XXX not stderr?
516  while (!proc.atEnd()) {
517  line = proc.readLine();
518  }
519  d->lastError = QString::fromUtf8(line);
520  return false;
521  }
522  return true;
523 }
524 
525 #include "moc_kbugreport.cpp"
virtual bool atEnd() const const override
void accept() override
OK has been clicked.
Definition: kbugreport.cpp:370
QString messageBody() const
The message body of the bug report.
Definition: kbugreport.cpp:299
virtual void closeEvent(QCloseEvent *e) override
virtual void reject()
KGuiItem close()
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
void setMessageBody(const QString &messageBody)
Sets the message body of the bug report.
Definition: kbugreport.cpp:308
QString findExecutable(const QString &executableName, const QStringList &paths)
KGuiItem cont()
void addSpacing(int size)
KGuiItem cancel()
void setIcon(const QIcon &icon)
AlignTop
int size() const const
QLocale system()
A dialog box for sending bug reports.
Definition: kbugreport.h:32
void finished(int result)
void addQueryItem(const QString &key, const QString &value)
void setEnabled(bool)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
int count(const T &value) const const
QString fromUtf8(const char *str, int size)
void ignore()
void setLayout(QLayout *layout)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
virtual void addItem(QLayoutItem *item) override
void setObjectName(const QString &name)
bool isEmpty() const const
void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
void setText(const QString &)
virtual QSize sizeHint() const const override
TextBrowserInteraction
virtual void accept()
ButtonCode questionYesNo(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const QString &dontAskAgainName=QString(), Options options=Notify)
KGuiItem discard()
void setIconSize(const QSize &iconSize)
~KBugReport() override
Destructor.
Definition: kbugreport.cpp:294
bool waitForStarted(int msecs)
QString i18n(const char *text, const TYPE &arg...)
QString & replace(int position, int n, QChar after)
void setTextInteractionFlags(Qt::TextInteractionFlags flags)
WrapAtWordBoundaryOrAnywhere
void setStandardButtons(QDialogButtonBox::StandardButtons buttons)
QString text() const
"Configure email" has been clicked - this calls kcmshell5 System/email
Definition: kbugreport.cpp:442
void setWindowTitle(const QString &)
bool sendBugReport()
Attempt to e-mail the bug report.
Definition: kbugreport.cpp:486
int length() const const
void setMinimumHeight(int minh)
void setQuery(const QString &query, QUrl::ParsingMode mode)
void setText(const QString &text)
qint64 write(const char *data, qint64 maxSize)
QPushButton * button(QDialogButtonBox::StandardButton which) const const
QIcon fromTheme(const QString &name)
QString getSetting(KEMailSettings::Setting s) const
KBugReport(const KAboutData &aboutData, QWidget *parent=nullptr)
Creates a bug-report dialog.
Definition: kbugreport.cpp:88
void setText(const QString &text, Qt::Alignment alignment=Qt::AlignLeft|Qt::AlignVCenter)
void information(QWidget *parent, const QString &text, const QString &caption=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
void setIcon(const QIcon &icon, ImageAlignment alignment=ImageRight)
bool openUrl(const QUrl &url)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void closeWriteChannel()
QProcess::ExitStatus exitStatus() const const
int exitCode() const const
void setWordWrap(bool on)
void start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode)
int height() const const
QString decodeName(const QByteArray &localFileName)
void addLayout(QLayout *layout, int stretch)
qint64 readLine(char *data, qint64 maxSize)
ButtonCode warningYesNo(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const QString &dontAskAgainName=QString(), Options options=Options(Notify|Dangerous))
bool waitForFinished(int msecs)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Aug 12 2020 22:50:46 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.