File indexing completed on 2024-05-12 05:46:42

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