File indexing completed on 2025-04-27 13:10:40
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1999, 2000, 2001 Carsten Pfeiffer <pfeiffer@kde.org> 0004 SPDX-FileCopyrightText: 2013 Teo Mrnjavac <teo@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #include "kurlrequester.h" 0010 #include "../utils_p.h" 0011 #include "kio_widgets_debug.h" 0012 0013 #include <KComboBox> 0014 #include <KDragWidgetDecorator> 0015 #include <KLineEdit> 0016 #include <KLocalizedString> 0017 #include <kprotocolmanager.h> 0018 #include <kurlcompletion.h> 0019 0020 #include <QAction> 0021 #include <QApplication> 0022 #include <QDrag> 0023 #include <QEvent> 0024 #include <QHBoxLayout> 0025 #include <QKeySequence> 0026 #include <QMenu> 0027 #include <QMimeData> 0028 0029 class KUrlDragPushButton : public QPushButton 0030 { 0031 Q_OBJECT 0032 public: 0033 explicit KUrlDragPushButton(QWidget *parent) 0034 : QPushButton(parent) 0035 { 0036 new DragDecorator(this); 0037 } 0038 ~KUrlDragPushButton() override 0039 { 0040 } 0041 0042 void setURL(const QUrl &url) 0043 { 0044 m_urls.clear(); 0045 m_urls.append(url); 0046 } 0047 0048 private: 0049 class DragDecorator : public KDragWidgetDecoratorBase 0050 { 0051 public: 0052 explicit DragDecorator(KUrlDragPushButton *button) 0053 : KDragWidgetDecoratorBase(button) 0054 , m_button(button) 0055 { 0056 } 0057 0058 protected: 0059 QDrag *dragObject() override 0060 { 0061 if (m_button->m_urls.isEmpty()) { 0062 return nullptr; 0063 } 0064 0065 QDrag *drag = new QDrag(m_button); 0066 QMimeData *mimeData = new QMimeData; 0067 mimeData->setUrls(m_button->m_urls); 0068 drag->setMimeData(mimeData); 0069 return drag; 0070 } 0071 0072 private: 0073 KUrlDragPushButton *m_button; 0074 }; 0075 0076 QList<QUrl> m_urls; 0077 }; 0078 0079 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 108) 0080 // regular expression string copied from QPlatformFileDialogHelper 0081 static const QString filterRegExpString = QStringLiteral("^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"); 0082 #endif 0083 0084 class Q_DECL_HIDDEN KUrlRequester::KUrlRequesterPrivate 0085 { 0086 public: 0087 explicit KUrlRequesterPrivate(KUrlRequester *parent) 0088 : m_fileDialogModeWasDirAndFile(false) 0089 , m_parent(parent) 0090 , edit(nullptr) 0091 , combo(nullptr) 0092 , fileDialogMode(KFile::File | KFile::ExistingOnly | KFile::LocalOnly) 0093 , fileDialogAcceptMode(QFileDialog::AcceptOpen) 0094 { 0095 } 0096 0097 ~KUrlRequesterPrivate() 0098 { 0099 delete myCompletion; 0100 delete myFileDialog; 0101 } 0102 0103 void init(); 0104 0105 void setText(const QString &text) 0106 { 0107 if (combo) { 0108 if (combo->isEditable()) { 0109 combo->setEditText(text); 0110 } else { 0111 int i = combo->findText(text); 0112 if (i == -1) { 0113 combo->addItem(text); 0114 combo->setCurrentIndex(combo->count() - 1); 0115 } else { 0116 combo->setCurrentIndex(i); 0117 } 0118 } 0119 } else { 0120 edit->setText(text); 0121 } 0122 } 0123 0124 void connectSignals(KUrlRequester *receiver) 0125 { 0126 if (combo) { 0127 connect(combo, &QComboBox::currentTextChanged, receiver, &KUrlRequester::textChanged); 0128 connect(combo, &QComboBox::editTextChanged, receiver, &KUrlRequester::textEdited); 0129 0130 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 80) 0131 connect(combo, qOverload<const QString &>(&KComboBox::returnPressed), receiver, qOverload<>(&KUrlRequester::returnPressed)); 0132 #endif 0133 connect(combo, qOverload<const QString &>(&KComboBox::returnPressed), receiver, qOverload<const QString &>(&KUrlRequester::returnPressed)); 0134 } else if (edit) { 0135 connect(edit, &QLineEdit::textChanged, receiver, &KUrlRequester::textChanged); 0136 connect(edit, &QLineEdit::textEdited, receiver, &KUrlRequester::textEdited); 0137 0138 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 80) 0139 connect(edit, qOverload<>(&QLineEdit::returnPressed), receiver, qOverload<>(&KUrlRequester::returnPressed)); 0140 #else 0141 connect(edit, qOverload<>(&QLineEdit::returnPressed), receiver, [this]() { 0142 m_parent->Q_EMIT returnPressed(QString{}); 0143 }); 0144 #endif 0145 if (auto kline = qobject_cast<KLineEdit *>(edit)) { 0146 connect(kline, &KLineEdit::returnKeyPressed, receiver, qOverload<const QString &>(&KUrlRequester::returnPressed)); 0147 } 0148 } 0149 } 0150 0151 void setCompletionObject(KCompletion *comp) 0152 { 0153 if (combo) { 0154 combo->setCompletionObject(comp); 0155 } else { 0156 edit->setCompletionObject(comp); 0157 } 0158 } 0159 0160 void updateCompletionStartDir(const QUrl &newStartDir) 0161 { 0162 myCompletion->setDir(newStartDir); 0163 } 0164 0165 QString text() const 0166 { 0167 return combo ? combo->currentText() : edit->text(); 0168 } 0169 0170 /** 0171 * replaces ~user or $FOO, if necessary 0172 * if text() is a relative path, make it absolute using startDir() 0173 */ 0174 QUrl url() const 0175 { 0176 const QString txt = text(); 0177 KUrlCompletion *comp; 0178 if (combo) { 0179 comp = qobject_cast<KUrlCompletion *>(combo->completionObject()); 0180 } else { 0181 comp = qobject_cast<KUrlCompletion *>(edit->completionObject()); 0182 } 0183 0184 QString enteredPath; 0185 if (comp) { 0186 enteredPath = comp->replacedPath(txt); 0187 } else { 0188 enteredPath = txt; 0189 } 0190 0191 if (Utils::isAbsoluteLocalPath(enteredPath)) { 0192 return QUrl::fromLocalFile(enteredPath); 0193 } 0194 0195 const QUrl enteredUrl = QUrl(enteredPath); // absolute or relative 0196 if (enteredUrl.isRelative() && !txt.isEmpty()) { 0197 QUrl finalUrl(m_startDir); 0198 finalUrl.setPath(Utils::concatPaths(finalUrl.path(), enteredPath)); 0199 return finalUrl; 0200 } else { 0201 return enteredUrl; 0202 } 0203 } 0204 0205 static void applyFileMode(QFileDialog *dlg, KFile::Modes m, QFileDialog::AcceptMode acceptMode) 0206 { 0207 QFileDialog::FileMode fileMode; 0208 bool dirsOnly = false; 0209 if (m & KFile::Directory) { 0210 fileMode = QFileDialog::Directory; 0211 if ((m & KFile::File) == 0 && (m & KFile::Files) == 0) { 0212 dirsOnly = true; 0213 } 0214 } else if (m & KFile::Files && m & KFile::ExistingOnly) { 0215 fileMode = QFileDialog::ExistingFiles; 0216 } else if (m & KFile::File && m & KFile::ExistingOnly) { 0217 fileMode = QFileDialog::ExistingFile; 0218 } else { 0219 fileMode = QFileDialog::AnyFile; 0220 } 0221 0222 dlg->setFileMode(fileMode); 0223 dlg->setAcceptMode(acceptMode); 0224 dlg->setOption(QFileDialog::ShowDirsOnly, dirsOnly); 0225 } 0226 0227 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 108) 0228 // Converts from "*.foo *.bar|Comment" to "Comment (*.foo *.bar)" 0229 QStringList kToQFilters(const QString &filters) const 0230 { 0231 QStringList qFilters = filters.split(QLatin1Char('\n'), Qt::SkipEmptyParts); 0232 0233 for (QString &qFilter : qFilters) { 0234 int sep = qFilter.indexOf(QLatin1Char('|')); 0235 if (sep != -1) { 0236 const QStringView fView(qFilter); 0237 const auto globs = fView.left(sep).trimmed(); 0238 const auto desc = fView.mid(sep + 1).trimmed(); 0239 qFilter = desc + QLatin1String(" (") + globs + QLatin1Char(')'); 0240 } 0241 } 0242 0243 return qFilters; 0244 } 0245 0246 // Converts from "Comment (*.foo *.bar)" to "*.foo *.bar|Comment" 0247 static QString qToKFilter(const QStringList &filters) 0248 { 0249 const QRegularExpression regexp(filterRegExpString); 0250 QStringList result; 0251 for (const QString &filter : filters) { 0252 QRegularExpressionMatch match; 0253 filter.indexOf(regexp, 0, &match); 0254 if (match.hasMatch()) { 0255 result.append(match.capturedView(2).trimmed() + QLatin1Char('|') + match.capturedView(1).trimmed()); 0256 } else { 0257 result.append(filter); 0258 } 0259 } 0260 return result.join(QLatin1Char('\n')); 0261 } 0262 0263 // Provides work-around for older Plasma Qt Platform Theme integration versions 0264 // only processing filters with explicit names (bug 470893), 0265 // use the filter expressions as name as fallback if no name is given 0266 // TODO: find a way to test if the current theme is a broken Plasma one, otherwise skip 0267 static QStringList ensureNamedFilter(const QStringList &filters) 0268 { 0269 QStringList namedFilters(filters); 0270 const QRegularExpression regexp(filterRegExpString); 0271 for (QString &filter : namedFilters) { 0272 QRegularExpressionMatch match; 0273 filter.indexOf(regexp, 0, &match); 0274 if (!match.hasMatch()) { 0275 filter = filter + QLatin1String(" (") + filter + QLatin1Char(')'); 0276 } 0277 } 0278 return namedFilters; 0279 } 0280 #endif 0281 0282 QUrl getDirFromFileDialog(const QUrl &openUrl) const 0283 { 0284 return QFileDialog::getExistingDirectoryUrl(m_parent, QString(), openUrl, QFileDialog::ShowDirsOnly); 0285 } 0286 0287 void createFileDialog() 0288 { 0289 // Creates the fileDialog if it doesn't exist yet 0290 QFileDialog *dlg = m_parent->fileDialog(); 0291 0292 if (!url().isEmpty() && !url().isRelative()) { 0293 QUrl u(url()); 0294 // If we won't be able to list it (e.g. http), then don't try :) 0295 if (KProtocolManager::supportsListing(u)) { 0296 dlg->selectUrl(u); 0297 } 0298 } else { 0299 dlg->setDirectoryUrl(m_startDir); 0300 } 0301 0302 dlg->setAcceptMode(fileDialogAcceptMode); 0303 0304 // Update the file dialog window modality 0305 if (dlg->windowModality() != fileDialogModality) { 0306 dlg->setWindowModality(fileDialogModality); 0307 } 0308 0309 if (fileDialogModality == Qt::NonModal) { 0310 dlg->show(); 0311 } else { 0312 dlg->exec(); 0313 } 0314 } 0315 0316 // slots 0317 void slotUpdateUrl(); 0318 void slotOpenDialog(); 0319 void slotFileDialogAccepted(); 0320 0321 QUrl m_startDir; 0322 bool m_startDirCustomized; 0323 bool m_fileDialogModeWasDirAndFile; 0324 KUrlRequester *const m_parent; // TODO: rename to 'q' 0325 KLineEdit *edit; 0326 KComboBox *combo; 0327 KFile::Modes fileDialogMode; 0328 QFileDialog::AcceptMode fileDialogAcceptMode; 0329 QStringList nameFilters; 0330 QStringList mimeTypeFilters; 0331 KEditListWidget::CustomEditor editor; 0332 KUrlDragPushButton *myButton; 0333 QFileDialog *myFileDialog; 0334 KUrlCompletion *myCompletion; 0335 Qt::WindowModality fileDialogModality; 0336 }; 0337 0338 KUrlRequester::KUrlRequester(QWidget *editWidget, QWidget *parent) 0339 : QWidget(parent) 0340 , d(new KUrlRequesterPrivate(this)) 0341 { 0342 // must have this as parent 0343 editWidget->setParent(this); 0344 d->combo = qobject_cast<KComboBox *>(editWidget); 0345 d->edit = qobject_cast<KLineEdit *>(editWidget); 0346 if (d->edit) { 0347 d->edit->setClearButtonEnabled(true); 0348 } 0349 0350 d->init(); 0351 } 0352 0353 KUrlRequester::KUrlRequester(QWidget *parent) 0354 : QWidget(parent) 0355 , d(new KUrlRequesterPrivate(this)) 0356 { 0357 d->init(); 0358 } 0359 0360 KUrlRequester::KUrlRequester(const QUrl &url, QWidget *parent) 0361 : QWidget(parent) 0362 , d(new KUrlRequesterPrivate(this)) 0363 { 0364 d->init(); 0365 setUrl(url); 0366 } 0367 0368 KUrlRequester::~KUrlRequester() 0369 { 0370 QWidget *widget = d->combo ? static_cast<QWidget *>(d->combo) : static_cast<QWidget *>(d->edit); 0371 widget->removeEventFilter(this); 0372 } 0373 0374 void KUrlRequester::KUrlRequesterPrivate::init() 0375 { 0376 myFileDialog = nullptr; 0377 fileDialogModality = Qt::ApplicationModal; 0378 0379 if (!combo && !edit) { 0380 edit = new KLineEdit(m_parent); 0381 edit->setClearButtonEnabled(true); 0382 } 0383 0384 QWidget *widget = combo ? static_cast<QWidget *>(combo) : static_cast<QWidget *>(edit); 0385 0386 QHBoxLayout *topLayout = new QHBoxLayout(m_parent); 0387 topLayout->setContentsMargins(0, 0, 0, 0); 0388 topLayout->setSpacing(-1); // use default spacing 0389 topLayout->addWidget(widget); 0390 0391 myButton = new KUrlDragPushButton(m_parent); 0392 myButton->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); 0393 int buttonSize = myButton->sizeHint().expandedTo(widget->sizeHint()).height(); 0394 myButton->setFixedSize(buttonSize, buttonSize); 0395 myButton->setToolTip(i18n("Open file dialog")); 0396 0397 connect(myButton, &KUrlDragPushButton::pressed, m_parent, [this]() { 0398 slotUpdateUrl(); 0399 }); 0400 0401 widget->installEventFilter(m_parent); 0402 m_parent->setFocusProxy(widget); 0403 m_parent->setFocusPolicy(Qt::StrongFocus); 0404 topLayout->addWidget(myButton); 0405 0406 connectSignals(m_parent); 0407 connect(myButton, &KUrlDragPushButton::clicked, m_parent, [this]() { 0408 slotOpenDialog(); 0409 }); 0410 0411 m_startDir = QUrl::fromLocalFile(QDir::currentPath()); 0412 m_startDirCustomized = false; 0413 0414 myCompletion = new KUrlCompletion(); 0415 updateCompletionStartDir(m_startDir); 0416 0417 setCompletionObject(myCompletion); 0418 0419 QAction *openAction = new QAction(m_parent); 0420 openAction->setShortcut(QKeySequence::Open); 0421 m_parent->connect(openAction, &QAction::triggered, m_parent, [this]() { 0422 slotOpenDialog(); 0423 }); 0424 } 0425 0426 void KUrlRequester::setUrl(const QUrl &url) 0427 { 0428 d->setText(url.toDisplayString(QUrl::PreferLocalFile)); 0429 } 0430 0431 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(4, 3) 0432 void KUrlRequester::setPath(const QString &path) 0433 { 0434 d->setText(path); 0435 } 0436 #endif 0437 0438 void KUrlRequester::setText(const QString &text) 0439 { 0440 d->setText(text); 0441 } 0442 0443 void KUrlRequester::setStartDir(const QUrl &startDir) 0444 { 0445 d->m_startDir = startDir; 0446 d->m_startDirCustomized = true; 0447 d->updateCompletionStartDir(startDir); 0448 } 0449 0450 void KUrlRequester::changeEvent(QEvent *e) 0451 { 0452 if (e->type() == QEvent::WindowTitleChange) { 0453 if (d->myFileDialog) { 0454 d->myFileDialog->setWindowTitle(windowTitle()); 0455 } 0456 } 0457 QWidget::changeEvent(e); 0458 } 0459 0460 QUrl KUrlRequester::url() const 0461 { 0462 return d->url(); 0463 } 0464 0465 QUrl KUrlRequester::startDir() const 0466 { 0467 return d->m_startDir; 0468 } 0469 0470 QString KUrlRequester::text() const 0471 { 0472 return d->text(); 0473 } 0474 0475 void KUrlRequester::KUrlRequesterPrivate::slotOpenDialog() 0476 { 0477 if (myFileDialog) { 0478 if (myFileDialog->isVisible()) { 0479 // The file dialog is already being shown, raise it and exit 0480 myFileDialog->raise(); 0481 myFileDialog->activateWindow(); 0482 return; 0483 } 0484 } 0485 0486 if (!m_fileDialogModeWasDirAndFile 0487 && (((fileDialogMode & KFile::Directory) && !(fileDialogMode & KFile::File)) || 0488 /* catch possible fileDialog()->setMode( KFile::Directory ) changes */ 0489 (myFileDialog && (myFileDialog->fileMode() == QFileDialog::Directory && myFileDialog->testOption(QFileDialog::ShowDirsOnly))))) { 0490 const QUrl openUrl = (!m_parent->url().isEmpty() && !m_parent->url().isRelative()) ? m_parent->url() : m_startDir; 0491 0492 /* FIXME We need a new abstract interface for using KDirSelectDialog in a non-modal way */ 0493 0494 QUrl newUrl; 0495 if (fileDialogMode & KFile::LocalOnly) { 0496 newUrl = QFileDialog::getExistingDirectoryUrl(m_parent, QString(), openUrl, QFileDialog::ShowDirsOnly, QStringList() << QStringLiteral("file")); 0497 } else { 0498 newUrl = getDirFromFileDialog(openUrl); 0499 } 0500 0501 if (newUrl.isValid()) { 0502 m_parent->setUrl(newUrl); 0503 Q_EMIT m_parent->urlSelected(url()); 0504 } 0505 } else { 0506 Q_EMIT m_parent->openFileDialog(m_parent); 0507 0508 if (((fileDialogMode & KFile::Directory) && (fileDialogMode & KFile::File)) || m_fileDialogModeWasDirAndFile) { 0509 QMenu *dirOrFileMenu = new QMenu(); 0510 QAction *fileAction = new QAction(QIcon::fromTheme(QStringLiteral("document-new")), i18n("File")); 0511 QAction *dirAction = new QAction(QIcon::fromTheme(QStringLiteral("folder-new")), i18n("Directory")); 0512 dirOrFileMenu->addAction(fileAction); 0513 dirOrFileMenu->addAction(dirAction); 0514 0515 connect(fileAction, &QAction::triggered, [this]() { 0516 fileDialogMode = KFile::File; 0517 applyFileMode(m_parent->fileDialog(), fileDialogMode, fileDialogAcceptMode); 0518 m_fileDialogModeWasDirAndFile = true; 0519 createFileDialog(); 0520 }); 0521 0522 connect(dirAction, &QAction::triggered, [this]() { 0523 fileDialogMode = KFile::Directory; 0524 applyFileMode(m_parent->fileDialog(), fileDialogMode, fileDialogAcceptMode); 0525 m_fileDialogModeWasDirAndFile = true; 0526 createFileDialog(); 0527 }); 0528 0529 dirOrFileMenu->exec(m_parent->mapToGlobal(QPoint(m_parent->width(), m_parent->height()))); 0530 0531 return; 0532 } 0533 0534 createFileDialog(); 0535 } 0536 } 0537 0538 void KUrlRequester::KUrlRequesterPrivate::slotFileDialogAccepted() 0539 { 0540 if (!myFileDialog) { 0541 return; 0542 } 0543 0544 const QUrl newUrl = myFileDialog->selectedUrls().constFirst(); 0545 if (newUrl.isValid()) { 0546 m_parent->setUrl(newUrl); 0547 Q_EMIT m_parent->urlSelected(url()); 0548 // remember url as defaultStartDir and update startdir for autocompletion 0549 if (newUrl.isLocalFile() && !m_startDirCustomized) { 0550 m_startDir = newUrl.adjusted(QUrl::RemoveFilename); 0551 updateCompletionStartDir(m_startDir); 0552 } 0553 } 0554 } 0555 0556 void KUrlRequester::setMode(KFile::Modes mode) 0557 { 0558 Q_ASSERT((mode & KFile::Files) == 0); 0559 d->fileDialogMode = mode; 0560 if ((mode & KFile::Directory) && !(mode & KFile::File)) { 0561 d->myCompletion->setMode(KUrlCompletion::DirCompletion); 0562 } 0563 0564 if (d->myFileDialog) { 0565 d->applyFileMode(d->myFileDialog, mode, d->fileDialogAcceptMode); 0566 } 0567 } 0568 0569 KFile::Modes KUrlRequester::mode() const 0570 { 0571 return d->fileDialogMode; 0572 } 0573 0574 void KUrlRequester::setAcceptMode(QFileDialog::AcceptMode mode) 0575 { 0576 d->fileDialogAcceptMode = mode; 0577 0578 if (d->myFileDialog) { 0579 d->applyFileMode(d->myFileDialog, d->fileDialogMode, mode); 0580 } 0581 } 0582 0583 QFileDialog::AcceptMode KUrlRequester::acceptMode() const 0584 { 0585 return d->fileDialogAcceptMode; 0586 } 0587 0588 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 108) 0589 void KUrlRequester::setFilter(const QString &filter) 0590 { 0591 d->nameFilters = d->kToQFilters(filter); 0592 0593 if (d->myFileDialog) { 0594 d->myFileDialog->setNameFilters(d->ensureNamedFilter(d->nameFilters)); 0595 } 0596 } 0597 #endif 0598 0599 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 108) 0600 QString KUrlRequester::filter() const 0601 { 0602 return d->qToKFilter(d->nameFilters); 0603 } 0604 #endif 0605 0606 QStringList KUrlRequester::nameFilters() const 0607 { 0608 return d->nameFilters; 0609 } 0610 0611 void KUrlRequester::setNameFilters(const QStringList &filters) 0612 { 0613 d->nameFilters = filters; 0614 0615 if (d->myFileDialog) { 0616 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 108) 0617 d->myFileDialog->setNameFilters(d->ensureNamedFilter(d->nameFilters)); 0618 #else 0619 d->myFileDialog->setNameFilters(d->nameFilters); 0620 #endif 0621 } 0622 } 0623 0624 void KUrlRequester::setNameFilter(const QString &filter) 0625 { 0626 if (filter.isEmpty()) { 0627 setNameFilters(QStringList()); 0628 return; 0629 } 0630 0631 // by default use ";;" as separator 0632 // if not present, support alternatively "\n" (matching QFileDialog behaviour) 0633 // if also not present split() will simply return the string passed in 0634 QString separator = QStringLiteral(";;"); 0635 if (!filter.contains(separator)) { 0636 separator = QStringLiteral("\n"); 0637 } 0638 setNameFilters(filter.split(separator)); 0639 } 0640 0641 void KUrlRequester::setMimeTypeFilters(const QStringList &mimeTypes) 0642 { 0643 d->mimeTypeFilters = mimeTypes; 0644 0645 if (d->myFileDialog) { 0646 d->myFileDialog->setMimeTypeFilters(d->mimeTypeFilters); 0647 } 0648 d->myCompletion->setMimeTypeFilters(d->mimeTypeFilters); 0649 } 0650 0651 QStringList KUrlRequester::mimeTypeFilters() const 0652 { 0653 return d->mimeTypeFilters; 0654 } 0655 0656 QFileDialog *KUrlRequester::fileDialog() const 0657 { 0658 if (d->myFileDialog 0659 && ((d->myFileDialog->fileMode() == QFileDialog::Directory && !(d->fileDialogMode & KFile::Directory)) 0660 || (d->myFileDialog->fileMode() != QFileDialog::Directory && (d->fileDialogMode & KFile::Directory)))) { 0661 delete d->myFileDialog; 0662 d->myFileDialog = nullptr; 0663 } 0664 0665 if (!d->myFileDialog) { 0666 d->myFileDialog = new QFileDialog(window(), windowTitle()); 0667 if (!d->mimeTypeFilters.isEmpty()) { 0668 d->myFileDialog->setMimeTypeFilters(d->mimeTypeFilters); 0669 } else { 0670 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 108) 0671 d->myFileDialog->setNameFilters(d->ensureNamedFilter(d->nameFilters)); 0672 #else 0673 d->myFileDialog->setNameFilters(d->nameFilters); 0674 #endif 0675 } 0676 0677 d->applyFileMode(d->myFileDialog, d->fileDialogMode, d->fileDialogAcceptMode); 0678 0679 d->myFileDialog->setWindowModality(d->fileDialogModality); 0680 connect(d->myFileDialog, &QFileDialog::accepted, this, [this]() { 0681 d->slotFileDialogAccepted(); 0682 }); 0683 } 0684 0685 return d->myFileDialog; 0686 } 0687 0688 void KUrlRequester::clear() 0689 { 0690 d->setText(QString()); 0691 } 0692 0693 KLineEdit *KUrlRequester::lineEdit() const 0694 { 0695 return d->edit; 0696 } 0697 0698 KComboBox *KUrlRequester::comboBox() const 0699 { 0700 return d->combo; 0701 } 0702 0703 void KUrlRequester::KUrlRequesterPrivate::slotUpdateUrl() 0704 { 0705 const QUrl visibleUrl = url(); 0706 QUrl u = visibleUrl; 0707 if (visibleUrl.isRelative()) { 0708 u = QUrl::fromLocalFile(QDir::currentPath() + QLatin1Char('/')).resolved(visibleUrl); 0709 } 0710 myButton->setURL(u); 0711 } 0712 0713 bool KUrlRequester::eventFilter(QObject *obj, QEvent *ev) 0714 { 0715 if ((d->edit == obj) || (d->combo == obj)) { 0716 if ((ev->type() == QEvent::FocusIn) || (ev->type() == QEvent::FocusOut)) 0717 // Forward focusin/focusout events to the urlrequester; needed by file form element in khtml 0718 { 0719 QApplication::sendEvent(this, ev); 0720 } 0721 } 0722 return QWidget::eventFilter(obj, ev); 0723 } 0724 0725 QPushButton *KUrlRequester::button() const 0726 { 0727 return d->myButton; 0728 } 0729 0730 KUrlCompletion *KUrlRequester::completionObject() const 0731 { 0732 return d->myCompletion; 0733 } 0734 0735 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 0) 0736 void KUrlRequester::setClickMessage(const QString &msg) 0737 { 0738 setPlaceholderText(msg); 0739 } 0740 #endif 0741 0742 void KUrlRequester::setPlaceholderText(const QString &msg) 0743 { 0744 if (d->edit) { 0745 d->edit->setPlaceholderText(msg); 0746 } 0747 } 0748 0749 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 0) 0750 QString KUrlRequester::clickMessage() const 0751 { 0752 return placeholderText(); 0753 } 0754 #endif 0755 0756 QString KUrlRequester::placeholderText() const 0757 { 0758 if (d->edit) { 0759 return d->edit->placeholderText(); 0760 } else { 0761 return QString(); 0762 } 0763 } 0764 0765 Qt::WindowModality KUrlRequester::fileDialogModality() const 0766 { 0767 return d->fileDialogModality; 0768 } 0769 0770 void KUrlRequester::setFileDialogModality(Qt::WindowModality modality) 0771 { 0772 d->fileDialogModality = modality; 0773 } 0774 0775 const KEditListWidget::CustomEditor &KUrlRequester::customEditor() 0776 { 0777 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); 0778 0779 KLineEdit *edit = d->edit; 0780 if (!edit && d->combo) { 0781 edit = qobject_cast<KLineEdit *>(d->combo->lineEdit()); 0782 } 0783 0784 #ifndef NDEBUG 0785 if (!edit) { 0786 qCWarning(KIO_WIDGETS) << "KUrlRequester's lineedit is not a KLineEdit!??\n"; 0787 } 0788 #endif 0789 0790 d->editor.setRepresentationWidget(this); 0791 d->editor.setLineEdit(edit); 0792 return d->editor; 0793 } 0794 0795 KUrlComboRequester::KUrlComboRequester(QWidget *parent) 0796 : KUrlRequester(new KComboBox(false), parent) 0797 , d(nullptr) 0798 { 0799 } 0800 0801 #include "kurlrequester.moc" 0802 #include "moc_kurlrequester.cpp"