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