File indexing completed on 2024-04-28 15:27:33
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2020 Ahmad Samir <a.samirh78@gmail.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "widgetsaskuseractionhandler.h" 0009 0010 #include <KConfig> 0011 #include <KConfigGroup> 0012 #include <KGuiItem> 0013 #include <KIO/WorkerBase> 0014 #include <KJob> 0015 #include <KJobWidgets> 0016 #include <KLocalizedString> 0017 #include <KMessageDialog> 0018 #include <KSharedConfig> 0019 #include <KSslInfoDialog> 0020 #include <KStandardGuiItem> 0021 #include <kio_widgets_debug.h> 0022 0023 #include <QApplication> 0024 #include <QDialogButtonBox> 0025 #include <QPointer> 0026 #include <QRegularExpression> 0027 #include <QUrl> 0028 0029 class KIO::WidgetsAskUserActionHandlerPrivate 0030 { 0031 public: 0032 explicit WidgetsAskUserActionHandlerPrivate(WidgetsAskUserActionHandler *qq) 0033 : q(qq) 0034 { 0035 } 0036 0037 // Creates a KSslInfoDialog or falls back to a generic Information dialog 0038 void sslMessageBox(const QString &text, const KIO::MetaData &metaData, QWidget *parent); 0039 0040 bool gotPersistentUserReply(KIO::AskUserActionInterface::MessageDialogType type, const KConfigGroup &cg, const QString &dontAskAgainName); 0041 void savePersistentUserReply(KIO::AskUserActionInterface::MessageDialogType type, KConfigGroup &cg, const QString &dontAskAgainName, int result); 0042 0043 WidgetsAskUserActionHandler *const q; 0044 QPointer<QWidget> m_parentWidget = nullptr; 0045 0046 QWidget *getParentWidget(KJob *job); 0047 QWidget *getParentWidget(QWidget *widget); 0048 }; 0049 0050 bool KIO::WidgetsAskUserActionHandlerPrivate::gotPersistentUserReply(KIO::AskUserActionInterface::MessageDialogType type, 0051 const KConfigGroup &cg, 0052 const QString &dontAskAgainName) 0053 { 0054 // storage values matching the logic of FrameworkIntegration's KMessageBoxDontAskAgainConfigStorage 0055 switch (type) { 0056 case KIO::AskUserActionInterface::QuestionTwoActions: 0057 case KIO::AskUserActionInterface::QuestionTwoActionsCancel: 0058 case KIO::AskUserActionInterface::WarningTwoActions: 0059 case KIO::AskUserActionInterface::WarningTwoActionsCancel: { 0060 // storage holds "true" if persistent reply is "Yes", "false" for persistent "No", 0061 // otherwise no persistent reply is present 0062 const QString value = cg.readEntry(dontAskAgainName, QString()); 0063 if ((value.compare(QLatin1String("yes"), Qt::CaseInsensitive) == 0) || (value.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0)) { 0064 Q_EMIT q->messageBoxResult(KIO::WorkerBase::PrimaryAction); 0065 return true; 0066 } 0067 if ((value.compare(QLatin1String("no"), Qt::CaseInsensitive) == 0) || (value.compare(QLatin1String("false"), Qt::CaseInsensitive) == 0)) { 0068 Q_EMIT q->messageBoxResult(KIO::WorkerBase::SecondaryAction); 0069 return true; 0070 } 0071 break; 0072 } 0073 case KIO::AskUserActionInterface::WarningContinueCancel: { 0074 // storage holds "false" if persistent reply is "Continue" 0075 // otherwise no persistent reply is present 0076 const bool value = cg.readEntry(dontAskAgainName, true); 0077 if (value == false) { 0078 Q_EMIT q->messageBoxResult(KIO::WorkerBase::Continue); 0079 return true; 0080 } 0081 break; 0082 } 0083 default: 0084 break; 0085 } 0086 0087 return false; 0088 } 0089 0090 void KIO::WidgetsAskUserActionHandlerPrivate::savePersistentUserReply(KIO::AskUserActionInterface::MessageDialogType type, 0091 KConfigGroup &cg, 0092 const QString &dontAskAgainName, 0093 int result) 0094 { 0095 // see gotPersistentUserReply for values stored and why 0096 switch (type) { 0097 case KIO::AskUserActionInterface::QuestionTwoActions: 0098 case KIO::AskUserActionInterface::QuestionTwoActionsCancel: 0099 case KIO::AskUserActionInterface::WarningTwoActions: 0100 case KIO::AskUserActionInterface::WarningTwoActionsCancel: 0101 cg.writeEntry(dontAskAgainName, result == KIO::WorkerBase::PrimaryAction); 0102 cg.sync(); 0103 break; 0104 case KIO::AskUserActionInterface::WarningContinueCancel: 0105 cg.writeEntry(dontAskAgainName, false); 0106 cg.sync(); 0107 break; 0108 default: 0109 break; 0110 } 0111 } 0112 0113 QWidget *KIO::WidgetsAskUserActionHandlerPrivate::getParentWidget(KJob *job) 0114 { 0115 // This needs to be in qpointer, otherwise copying process 0116 // will crash if done in background and dolphin is closed 0117 QPointer<QWidget> parentWidget = nullptr; 0118 0119 if (job) { 0120 parentWidget = KJobWidgets::window(job); 0121 } 0122 0123 return getParentWidget(parentWidget); 0124 } 0125 0126 QWidget *KIO::WidgetsAskUserActionHandlerPrivate::getParentWidget(QWidget *widget) 0127 { 0128 // This needs to be in qpointer, otherwise copying process 0129 // will crash if done in background and dolphin is closed 0130 QPointer<QWidget> parentWidget = widget; 0131 0132 if (!parentWidget) { 0133 parentWidget = this->m_parentWidget; 0134 } 0135 0136 if (!parentWidget) { 0137 parentWidget = qApp->activeWindow(); 0138 } 0139 0140 return parentWidget; 0141 } 0142 0143 KIO::WidgetsAskUserActionHandler::WidgetsAskUserActionHandler(QObject *parent) 0144 : KIO::AskUserActionInterface(parent) 0145 , d(new WidgetsAskUserActionHandlerPrivate(this)) 0146 { 0147 } 0148 0149 KIO::WidgetsAskUserActionHandler::~WidgetsAskUserActionHandler() 0150 { 0151 } 0152 0153 void KIO::WidgetsAskUserActionHandler::askUserRename(KJob *job, 0154 const QString &title, 0155 const QUrl &src, 0156 const QUrl &dest, 0157 KIO::RenameDialog_Options options, 0158 KIO::filesize_t sizeSrc, 0159 KIO::filesize_t sizeDest, 0160 const QDateTime &ctimeSrc, 0161 const QDateTime &ctimeDest, 0162 const QDateTime &mtimeSrc, 0163 const QDateTime &mtimeDest) 0164 { 0165 QMetaObject::invokeMethod(qGuiApp, [=] { 0166 auto *dlg = new KIO::RenameDialog(d->getParentWidget(job), title, src, dest, options, sizeSrc, sizeDest, ctimeSrc, ctimeDest, mtimeSrc, mtimeDest); 0167 0168 dlg->setAttribute(Qt::WA_DeleteOnClose); 0169 dlg->setWindowModality(Qt::WindowModal); 0170 0171 connect(job, &KJob::finished, dlg, &QDialog::reject); 0172 connect(dlg, &QDialog::finished, this, [this, job, dlg](const int exitCode) { 0173 KIO::RenameDialog_Result result = static_cast<RenameDialog_Result>(exitCode); 0174 const QUrl newUrl = result == Result_AutoRename ? dlg->autoDestUrl() : dlg->newDestUrl(); 0175 Q_EMIT askUserRenameResult(result, newUrl, job); 0176 }); 0177 0178 dlg->show(); 0179 }); 0180 } 0181 0182 void KIO::WidgetsAskUserActionHandler::askUserSkip(KJob *job, KIO::SkipDialog_Options options, const QString &errorText) 0183 { 0184 QMetaObject::invokeMethod(qGuiApp, [=] { 0185 auto *dlg = new KIO::SkipDialog(d->getParentWidget(job), options, errorText); 0186 dlg->setAttribute(Qt::WA_DeleteOnClose); 0187 dlg->setWindowModality(Qt::WindowModal); 0188 0189 connect(job, &KJob::finished, dlg, &QDialog::reject); 0190 connect(dlg, &QDialog::finished, this, [this, job](const int exitCode) { 0191 Q_EMIT askUserSkipResult(static_cast<KIO::SkipDialog_Result>(exitCode), job); 0192 }); 0193 0194 dlg->show(); 0195 }); 0196 } 0197 0198 struct ProcessAskDeleteResult { 0199 QStringList prettyList; 0200 KMessageDialog::Type dialogType = KMessageDialog::QuestionTwoActions; 0201 KGuiItem acceptButton; 0202 QString text; 0203 QIcon icon; 0204 QString title = i18n("Delete Permanently"); 0205 bool isSingleUrl = false; 0206 }; 0207 0208 using AskIface = KIO::AskUserActionInterface; 0209 static ProcessAskDeleteResult processAskDelete(const QList<QUrl> &urls, AskIface::DeletionType deletionType) 0210 { 0211 ProcessAskDeleteResult res; 0212 res.prettyList.reserve(urls.size()); 0213 std::transform(urls.cbegin(), urls.cend(), std::back_inserter(res.prettyList), [](const auto &url) { 0214 if (url.scheme() == QLatin1String("trash")) { 0215 QString path = url.path(); 0216 // HACK (#98983): remove "0-foo". Note that it works better than 0217 // displaying KFileItem::name(), for files under a subdir. 0218 static const QRegularExpression re(QStringLiteral("^/[0-9]+-")); 0219 path.remove(re); 0220 return path; 0221 } else { 0222 return url.toDisplayString(QUrl::PreferLocalFile); 0223 } 0224 }); 0225 0226 const int urlCount = res.prettyList.size(); 0227 res.isSingleUrl = urlCount == 1; 0228 0229 switch (deletionType) { 0230 case AskIface::Delete: { 0231 res.dialogType = KMessageDialog::QuestionTwoActions; // Using Question* so the Delete button is pre-selected. Bug 462845 0232 res.icon = QIcon::fromTheme(QStringLiteral("dialog-warning")); 0233 if (res.isSingleUrl) { 0234 res.text = xi18nc("@info", 0235 "Do you really want to permanently delete this item?<nl/><nl/>" 0236 "<filename>%1</filename><nl/><nl/>" 0237 "<emphasis strong='true'>This action cannot be undone.</emphasis>", 0238 res.prettyList.at(0)); 0239 } else { 0240 res.text = xi18ncp("@info", 0241 "Do you really want to permanently delete this %1 item?<nl/><nl/>" 0242 "<emphasis strong='true'>This action cannot be undone.</emphasis>", 0243 "Do you really want to permanently delete these %1 items?<nl/><nl/>" 0244 "<emphasis strong='true'>This action cannot be undone.</emphasis>", 0245 urlCount); 0246 } 0247 res.acceptButton = KGuiItem(i18nc("@action:button", "Delete Permanently"), QStringLiteral("edit-delete")); 0248 break; 0249 } 0250 case AskIface::DeleteInsteadOfTrash: { 0251 res.dialogType = KMessageDialog::WarningTwoActions; 0252 if (res.isSingleUrl) { 0253 res.text = xi18nc("@info", 0254 "Moving this item to Trash failed as it is too large." 0255 " Permanently delete it instead?<nl/><nl/>" 0256 "<filename>%1</filename><nl/><nl/>" 0257 "<emphasis strong='true'>This action cannot be undone.</emphasis>", 0258 res.prettyList.at(0)); 0259 } else { 0260 res.text = xi18ncp("@info", 0261 "Moving this %1 item to Trash failed as it is too large." 0262 " Permanently delete it instead?<nl/>" 0263 "<emphasis strong='true'>This action cannot be undone.</emphasis>", 0264 "Moving these %1 items to Trash failed as they are too large." 0265 " Permanently delete them instead?<nl/><nl/>" 0266 "<emphasis strong='true'>This action cannot be undone.</emphasis>", 0267 urlCount); 0268 } 0269 res.acceptButton = KGuiItem(i18nc("@action:button", "Delete Permanently"), QStringLiteral("edit-delete")); 0270 break; 0271 } 0272 case AskIface::EmptyTrash: { 0273 res.dialogType = KMessageDialog::QuestionTwoActions; // Using Question* so the Delete button is pre-selected. 0274 res.icon = QIcon::fromTheme(QStringLiteral("dialog-warning")); 0275 res.text = xi18nc("@info", 0276 "Do you want to permanently delete all items from the Trash?<nl/><nl/>" 0277 "<emphasis strong='true'>This action cannot be undone.</emphasis>"); 0278 res.acceptButton = KGuiItem(i18nc("@action:button", "Empty Trash"), QStringLiteral("user-trash")); 0279 break; 0280 } 0281 case AskIface::Trash: { 0282 if (res.isSingleUrl) { 0283 res.text = xi18nc("@info", 0284 "Do you really want to move this item to the Trash?<nl/>" 0285 "<filename>%1</filename>", 0286 res.prettyList.at(0)); 0287 } else { 0288 res.text = 0289 xi18ncp("@info", "Do you really want to move this %1 item to the Trash?", "Do you really want to move these %1 items to the Trash?", urlCount); 0290 } 0291 res.title = i18n("Move to Trash"); 0292 res.acceptButton = KGuiItem(res.title, QStringLiteral("user-trash")); 0293 break; 0294 } 0295 default: 0296 break; 0297 } 0298 return res; 0299 } 0300 0301 void KIO::WidgetsAskUserActionHandler::askUserDelete(const QList<QUrl> &urls, DeletionType deletionType, ConfirmationType confirmationType, QWidget *parent) 0302 { 0303 QString keyName; 0304 bool ask = (confirmationType == ForceConfirmation); 0305 if (!ask) { 0306 // The default value for confirmations is true for delete and false 0307 // for trash. If you change this, please also update: 0308 // dolphin/src/settings/general/confirmationssettingspage.cpp 0309 bool defaultValue = true; 0310 0311 switch (deletionType) { 0312 case DeleteInsteadOfTrash: 0313 case Delete: 0314 keyName = QStringLiteral("ConfirmDelete"); 0315 break; 0316 case Trash: 0317 keyName = QStringLiteral("ConfirmTrash"); 0318 defaultValue = false; 0319 break; 0320 case EmptyTrash: 0321 keyName = QStringLiteral("ConfirmEmptyTrash"); 0322 break; 0323 } 0324 0325 KSharedConfigPtr kioConfig = KSharedConfig::openConfig(QStringLiteral("kiorc"), KConfig::NoGlobals); 0326 ask = kioConfig->group("Confirmations").readEntry(keyName, defaultValue); 0327 } 0328 0329 if (!ask) { 0330 Q_EMIT askUserDeleteResult(true, urls, deletionType, parent); 0331 return; 0332 } 0333 0334 QMetaObject::invokeMethod(qGuiApp, [=] { 0335 const auto &[prettyList, dialogType, acceptButton, text, icon, title, singleUrl] = processAskDelete(urls, deletionType); 0336 KMessageDialog *dlg = new KMessageDialog(dialogType, text, parent); 0337 dlg->setAttribute(Qt::WA_DeleteOnClose); 0338 dlg->setCaption(title); 0339 dlg->setIcon(icon); 0340 dlg->setButtons(acceptButton, KStandardGuiItem::cancel()); 0341 if (!singleUrl) { 0342 dlg->setListWidgetItems(prettyList); 0343 } 0344 dlg->setDontAskAgainText(i18nc("@option:checkbox", "Do not ask again")); 0345 // If we get here, !ask must be false 0346 dlg->setDontAskAgainChecked(!ask); 0347 0348 connect(dlg, &QDialog::finished, this, [=](const int buttonCode) { 0349 const bool isDelete = (buttonCode == KMessageDialog::PrimaryAction); 0350 0351 Q_EMIT askUserDeleteResult(isDelete, urls, deletionType, parent); 0352 0353 if (isDelete) { 0354 KSharedConfigPtr kioConfig = KSharedConfig::openConfig(QStringLiteral("kiorc"), KConfig::NoGlobals); 0355 KConfigGroup cg = kioConfig->group("Confirmations"); 0356 cg.writeEntry(keyName, !dlg->isDontAskAgainChecked()); 0357 cg.sync(); 0358 } 0359 }); 0360 0361 dlg->setWindowModality(Qt::WindowModal); 0362 dlg->show(); 0363 }); 0364 } 0365 0366 void KIO::WidgetsAskUserActionHandler::requestUserMessageBox(MessageDialogType type, 0367 const QString &text, 0368 const QString &title, 0369 const QString &primaryActionText, 0370 const QString &secondaryActionText, 0371 const QString &primaryActionIconName, 0372 const QString &secondaryActionIconName, 0373 const QString &dontAskAgainName, 0374 const QString &details, 0375 const KIO::MetaData &metaData, 0376 QWidget *parent) 0377 { 0378 if (d->gotPersistentUserReply(type, KSharedConfig::openConfig(QStringLiteral("kioslaverc"))->group("Notification Messages"), dontAskAgainName)) { 0379 return; 0380 } 0381 0382 const KGuiItem primaryActionButton(primaryActionText, primaryActionIconName); 0383 const KGuiItem secondaryActionButton(secondaryActionText, secondaryActionIconName); 0384 0385 // It's "Do not ask again" every where except with Information 0386 QString dontAskAgainText = i18nc("@option:check", "Do not ask again"); 0387 0388 KMessageDialog::Type dlgType; 0389 bool hasCancelButton = false; 0390 0391 switch (type) { 0392 case AskUserActionInterface::QuestionTwoActions: 0393 dlgType = KMessageDialog::QuestionTwoActions; 0394 break; 0395 case AskUserActionInterface::QuestionTwoActionsCancel: 0396 dlgType = KMessageDialog::QuestionTwoActionsCancel; 0397 hasCancelButton = true; 0398 break; 0399 case AskUserActionInterface::WarningTwoActions: 0400 dlgType = KMessageDialog::WarningTwoActions; 0401 break; 0402 case AskUserActionInterface::WarningTwoActionsCancel: 0403 dlgType = KMessageDialog::WarningTwoActionsCancel; 0404 hasCancelButton = true; 0405 break; 0406 case AskUserActionInterface::WarningContinueCancel: 0407 dlgType = KMessageDialog::WarningContinueCancel; 0408 hasCancelButton = true; 0409 break; 0410 case AskUserActionInterface::SSLMessageBox: 0411 d->sslMessageBox(text, metaData, d->getParentWidget(parent)); 0412 return; 0413 case AskUserActionInterface::Information: 0414 dlgType = KMessageDialog::Information; 0415 dontAskAgainText = i18nc("@option:check", "Do not show this message again"); 0416 break; 0417 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 97) 0418 case AskUserActionInterface::Sorry: 0419 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 97) 0420 QT_WARNING_PUSH 0421 QT_WARNING_DISABLE_DEPRECATED 0422 dlgType = KMessageDialog::Sorry; 0423 QT_WARNING_POP 0424 dontAskAgainText = QString{}; // No dontAskAgain checkbox 0425 break; 0426 #else 0427 #error "Cannot build KIOCore with KIO::AskUserActionInterface::Sorry with KMessageDialog::Sorry disabled" 0428 #endif 0429 #endif 0430 case AskUserActionInterface::Error: 0431 dlgType = KMessageDialog::Error; 0432 dontAskAgainText = QString{}; // No dontAskAgain checkbox 0433 break; 0434 default: 0435 qCWarning(KIO_WIDGETS) << "Unknown message dialog type" << type; 0436 return; 0437 } 0438 0439 QMetaObject::invokeMethod(qGuiApp, [=]() { 0440 auto cancelButton = hasCancelButton ? KStandardGuiItem::cancel() : KGuiItem(); 0441 auto *dialog = new KMessageDialog(dlgType, text, d->getParentWidget(parent)); 0442 0443 dialog->setAttribute(Qt::WA_DeleteOnClose); 0444 dialog->setCaption(title); 0445 dialog->setIcon(QIcon{}); 0446 dialog->setButtons(primaryActionButton, secondaryActionButton, cancelButton); 0447 dialog->setDetails(details); 0448 dialog->setDontAskAgainText(dontAskAgainText); 0449 dialog->setDontAskAgainChecked(false); 0450 dialog->setOpenExternalLinks(true); // Allow opening external links in the text labels 0451 0452 connect(dialog, &QDialog::finished, this, [=](const int result) { 0453 KIO::WorkerBase::ButtonCode btnCode; 0454 switch (result) { 0455 case KMessageDialog::PrimaryAction: 0456 if (dlgType == KMessageDialog::WarningContinueCancel) { 0457 btnCode = KIO::WorkerBase::Continue; 0458 } else { 0459 btnCode = KIO::WorkerBase::PrimaryAction; 0460 } 0461 break; 0462 case KMessageDialog::SecondaryAction: 0463 btnCode = KIO::WorkerBase::SecondaryAction; 0464 break; 0465 case KMessageDialog::Cancel: 0466 btnCode = KIO::WorkerBase::Cancel; 0467 break; 0468 case KMessageDialog::Ok: 0469 btnCode = KIO::WorkerBase::Ok; 0470 break; 0471 default: 0472 qCWarning(KIO_WIDGETS) << "Unknown message dialog result" << result; 0473 return; 0474 } 0475 0476 Q_EMIT messageBoxResult(btnCode); 0477 0478 if ((result != KMessageDialog::Cancel) && dialog->isDontAskAgainChecked()) { 0479 KSharedConfigPtr reqMsgConfig = KSharedConfig::openConfig(QStringLiteral("kioslaverc")); 0480 KConfigGroup cg = reqMsgConfig->group("Notification Messages"); 0481 d->savePersistentUserReply(type, cg, dontAskAgainName, result); 0482 } 0483 }); 0484 0485 dialog->show(); 0486 }); 0487 } 0488 0489 void KIO::WidgetsAskUserActionHandlerPrivate::sslMessageBox(const QString &text, const KIO::MetaData &metaData, QWidget *parent) 0490 { 0491 QWidget *parentWidget = getParentWidget(parent); 0492 0493 const QStringList sslList = metaData.value(QStringLiteral("ssl_peer_chain")).split(QLatin1Char('\x01'), Qt::SkipEmptyParts); 0494 0495 QList<QSslCertificate> certChain; 0496 bool decodedOk = true; 0497 for (const QString &str : sslList) { 0498 certChain.append(QSslCertificate(str.toUtf8())); 0499 if (certChain.last().isNull()) { 0500 decodedOk = false; 0501 break; 0502 } 0503 } 0504 0505 QMetaObject::invokeMethod(qGuiApp, [=] { 0506 if (decodedOk) { // Use KSslInfoDialog 0507 KSslInfoDialog *ksslDlg = new KSslInfoDialog(parentWidget); 0508 ksslDlg->setSslInfo(certChain, 0509 metaData.value(QStringLiteral("ssl_peer_ip")), 0510 text, // The URL 0511 metaData.value(QStringLiteral("ssl_protocol_version")), 0512 metaData.value(QStringLiteral("ssl_cipher")), 0513 metaData.value(QStringLiteral("ssl_cipher_used_bits")).toInt(), 0514 metaData.value(QStringLiteral("ssl_cipher_bits")).toInt(), 0515 KSslInfoDialog::certificateErrorsFromString(metaData.value(QStringLiteral("ssl_cert_errors")))); 0516 0517 // KSslInfoDialog deletes itself by setting Qt::WA_DeleteOnClose 0518 0519 QObject::connect(ksslDlg, &QDialog::finished, q, [this]() { 0520 // KSslInfoDialog only has one button, QDialogButtonBox::Close 0521 Q_EMIT q->messageBoxResult(KIO::WorkerBase::Cancel); 0522 }); 0523 0524 ksslDlg->show(); 0525 return; 0526 } 0527 0528 // Fallback to a generic message box 0529 auto *dialog = new KMessageDialog(KMessageDialog::Information, i18n("The peer SSL certificate chain appears to be corrupt."), parentWidget); 0530 0531 dialog->setAttribute(Qt::WA_DeleteOnClose); 0532 dialog->setCaption(i18n("SSL")); 0533 // KMessageDialog will set a proper icon 0534 dialog->setIcon(QIcon{}); 0535 dialog->setButtons(KStandardGuiItem::ok()); 0536 0537 QObject::connect(dialog, &QDialog::finished, q, [this](const int result) { 0538 Q_EMIT q->messageBoxResult(result == KMessageDialog::Ok ? KIO::WorkerBase::Ok : KIO::WorkerBase::Cancel); 0539 }); 0540 0541 dialog->show(); 0542 }); 0543 } 0544 0545 void KIO::WidgetsAskUserActionHandler::setWindow(QWidget *window) 0546 { 0547 d->m_parentWidget = window; 0548 } 0549 0550 #include "moc_widgetsaskuseractionhandler.cpp"