1 /*
2     This file is part of the KDE libraries
3     SPDX-FileCopyrightText: 1999, 2000, 2001 Carsten Pfeiffer <pfeiffer@kde.org>
4     SPDX-FileCopyrightText: 2013 Teo Mrnjavac <teo@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-only
7 */
8 
9 #ifndef KURLREQUESTER_H
10 #define KURLREQUESTER_H
11 
12 #include "kiowidgets_export.h"
13 
14 #include <KEditListWidget>
15 #include <kfile.h>
16 
17 #include <QFileDialog>
18 #include <QPushButton>
19 #include <QUrl>
20 
21 class KComboBox;
22 class KLineEdit;
23 class KUrlCompletion;
24 
25 class QEvent;
26 class QString;
27 
28 /**
29  * @class KUrlRequester kurlrequester.h <KUrlRequester>
30  *
31  * This class is a widget showing a lineedit and a button, which invokes a
32  * filedialog. File name completion is available in the lineedit.
33  *
34  * The defaults for the filedialog are to ask for one existing local file.
35  * The default filter is "*", i.e. show all files, and the start directory is
36  * the current working directory, or the last directory where a file has been
37  * selected.
38  *
39  * You can change this behavior by using setMode(), setFilter() and setStartDir().
40  *
41  * The default window modality for the file dialog is Qt::ApplicationModal
42  *
43  * \image html kurlrequester.png "KUrlRequester"
44  *
45  * @short A widget to request a filename/url from the user
46  * @author Carsten Pfeiffer <pfeiffer@kde.org>
47  */
48 class KIOWIDGETS_EXPORT KUrlRequester : public QWidget
49 {
50     Q_OBJECT
51     Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY textChanged USER true)
52     Q_PROPERTY(QString filter READ filter WRITE setFilter)
53     Q_PROPERTY(KFile::Modes mode READ mode WRITE setMode)
54     Q_PROPERTY(QFileDialog::AcceptMode acceptMode READ acceptMode WRITE setAcceptMode)
55 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 0)
56     /// @deprecated Since 5.0, use placeholderText
57     Q_PROPERTY(QString clickMessage READ clickMessage WRITE setClickMessage)
58 #endif
59     Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText)
60     Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
61     Q_PROPERTY(Qt::WindowModality fileDialogModality READ fileDialogModality WRITE setFileDialogModality)
62 
63 public:
64     /**
65      * Constructs a KUrlRequester widget.
66      */
67     explicit KUrlRequester(QWidget *parent = nullptr);
68 
69     /**
70      * Constructs a KUrlRequester widget with the initial URL @p url.
71      */
72     explicit KUrlRequester(const QUrl &url, QWidget *parent = nullptr);
73 
74     /**
75      * Special constructor, which creates a KUrlRequester widget with a custom
76      * edit-widget. The edit-widget can be either a KComboBox or a KLineEdit
77      * (or inherited thereof). Note: for geometry management reasons, the
78      * edit-widget is reparented to have the KUrlRequester as parent.
79      */
80     KUrlRequester(QWidget *editWidget, QWidget *parent);
81     /**
82      * Destructs the KUrlRequester.
83      */
84     ~KUrlRequester() override;
85 
86     /**
87      * @returns the current url in the lineedit. May be malformed, if the user
88      * entered something weird. For local files, ~user or environment variables
89      * are substituted, relative paths will be resolved against startDir()
90      */
91     QUrl url() const;
92 
93     /**
94      * @returns the current start dir
95      * @since 4.3
96      */
97     QUrl startDir() const;
98 
99     /**
100      * @returns the current text in the lineedit or combobox.
101      * This does not do the URL expansion that url() does, it's only provided
102      * for cases where KUrlRequester is used to enter URL-or-something-else,
103      * like KOpenWithDialog where you can type a full command with arguments.
104      *
105      * @since 4.2
106      */
107     QString text() const;
108 
109     /**
110      * Sets the mode of the file dialog.
111      * Note: you can only select one file with the filedialog,
112      * so KFile::Files doesn't make much sense.
113      *
114      * The default is KFile::File | KFile::ExistingOnly | KFile::LocalOnly.
115      *
116      * @see QFileDialog::setFileMode()
117      */
118     void setMode(KFile::Modes m);
119 
120     /**
121      * Returns the current mode
122      * @see QFileDialog::fileMode()
123      */
124     KFile::Modes mode() const;
125 
126     /**
127      * Sets the open / save mode of the file dialog.
128      *
129      * The default is QFileDialog::AcceptOpen.
130      *
131      * @see QFileDialog::setAcceptMode()
132      * @since 5.33
133      */
134     void setAcceptMode(QFileDialog::AcceptMode m);
135 
136     /**
137      * Returns the current open / save mode
138      * @see QFileDialog::acceptMode()
139      * @since 5.33
140      */
141     QFileDialog::AcceptMode acceptMode() const;
142 
143     /**
144      * Sets the filters for the file dialog, separated by \\n.
145      * @see QFileDialog::setNameFilters()
146      */
147     void setFilter(const QString &filter);
148 
149     /**
150      * Returns the filters for the file dialog, separated by \\n.
151      * @see QFileDialog::nameFilters()
152      */
153     QString filter() const;
154 
155     /**
156      * Sets the MIME type filters for the file dialog.
157      * @see QFileDialog::setMimeTypeFilters()
158      * @since 5.31
159      */
160     void setMimeTypeFilters(const QStringList &mimeTypes);
161     /**
162      * Returns the MIME type filters for the file dialog.
163      * @see QFileDialog::mimeTypeFilters()
164      * @since 5.31
165      */
166     QStringList mimeTypeFilters() const;
167 
168     /**
169      * @returns a pointer to the filedialog.
170      * You can use this to customize the dialog, e.g. to call setLocationLabel
171      * or other things which are not accessible in the KUrlRequester API.
172      *
173      * Never returns 0. This method creates the file dialog on demand.
174      *
175      * @deprecated since 5.0. The dialog will be created anyway when the user
176      * requests it, and will behave according to the properties of KUrlRequester.
177      */
178     KIOWIDGETS_DEPRECATED_VERSION(5, 0, "See API docs")
179     virtual QFileDialog *fileDialog() const;
180 
181     /**
182      * @returns a pointer to the lineedit, either the default one, or the
183      * special one, if you used the special constructor.
184      *
185      * It is provided so that you can e.g. set an own completion object
186      * (e.g. KShellCompletion) into it.
187      */
188     KLineEdit *lineEdit() const;
189 
190     /**
191      * @returns a pointer to the combobox, in case you have set one using the
192      * special constructor. Returns 0L otherwise.
193      */
194     KComboBox *comboBox() const;
195 
196     /**
197      * @returns a pointer to the pushbutton. It is provided so that you can
198      * specify an own pixmap or a text, if you really need to.
199      */
200     QPushButton *button() const;
201 
202     /**
203      * @returns the KUrlCompletion object used in the lineedit/combobox.
204      */
205     KUrlCompletion *completionObject() const;
206 
207     /**
208      * @returns an object, suitable for use with KEditListWidget. It allows you
209      * to put this KUrlRequester into a KEditListWidget.
210      * Basically, do it like this:
211      * \code
212      * KUrlRequester *req = new KUrlRequester( someWidget );
213      * [...]
214      * KEditListWidget *editListWidget = new KEditListWidget( req->customEditor(), someWidget );
215      * \endcode
216      */
217     const KEditListWidget::CustomEditor &customEditor();
218 
219 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 0)
220     /**
221      * @returns the message set with setClickMessage
222      * @since 4.2
223      * @deprecated Since 5.0, use KUrlRequester::placeholderText instead.
224      */
225     KIOWIDGETS_DEPRECATED_VERSION(5, 0, "Use KUrlRequester::placeholderText()")
226     QString clickMessage() const;
227 #endif
228 
229 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 0)
230     /**
231      * Set a click message @p msg
232      * @since 4.2
233      * @deprecated Since 5.0, use KUrlRequester::setPlaceholderText instead.
234      */
235     KIOWIDGETS_DEPRECATED_VERSION(5, 0, "Use KUrlRequester::setPlaceholderText(const QString&)")
236     void setClickMessage(const QString &msg);
237 #endif
238 
239     /**
240      * @return the message set with setPlaceholderText
241      * @since 5.0
242      */
243     QString placeholderText() const;
244 
245     /**
246      * This makes the KUrlRequester line edit display a grayed-out hinting text as long as
247      * the user didn't enter any text. It is often used as indication about
248      * the purpose of the line edit.
249      * @since 5.0
250      */
251     void setPlaceholderText(const QString &msg);
252 
253     /**
254      * @returns the window modality of the file dialog set with setFileDialogModality
255      * @since 4.4
256      */
257     Qt::WindowModality fileDialogModality() const;
258 
259     /**
260      * Set the window modality for the file dialog to @p modality
261      * Directory selection dialogs are always modal
262      *
263      * The default is Qt::ApplicationModal.
264      *
265      * @since 4.4
266      */
267     void setFileDialogModality(Qt::WindowModality modality);
268 
269 public Q_SLOTS:
270     /**
271      * Sets the url in the lineedit to @p url.
272      */
273     void setUrl(const QUrl &url);
274 
275     /**
276      * Sets the start dir @p startDir.
277      * The start dir is only used when the URL isn't set.
278      * @since 4.3
279      */
280     void setStartDir(const QUrl &startDir);
281 
282 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(4, 3)
283     /**
284      * Sets the url in the lineedit to @p QUrl::fromLocalFile(path).
285      * This is only for local paths; do not pass a url here.
286      * This method is mostly for "local paths only" url requesters,
287      * for instance those set up with setMode(KFile::File|KFile::ExistingOnly|KFile::LocalOnly)
288      *
289      * @deprecated Since 4.3. Use setUrl(QUrl::fromLocalFile(path)) instead.
290      */
291     KIOWIDGETS_DEPRECATED_VERSION(4, 3, "Use KUrlRequester::setUrl(QUrl::fromLocalFile(path))")
292     void setPath(const QString &path);
293 #endif
294 
295     /**
296      * Sets the current text in the lineedit or combobox.
297      * This is used for cases where KUrlRequester is used to
298      * enter URL-or-something-else, like KOpenWithDialog where you
299      * can type a full command with arguments.
300      *
301      * @see text
302      * @since 4.3
303      */
304     void setText(const QString &text);
305 
306     /**
307      * Clears the lineedit/combobox.
308      */
309     void clear();
310 
311 Q_SIGNALS:
312     // forwards from LineEdit
313     /**
314      * Emitted when the text in the lineedit changes.
315      * The parameter contains the contents of the lineedit.
316      */
317     void textChanged(const QString &);
318 
319     /**
320      * Emitted when the text in the lineedit was modified by the user.
321      * Unlike textChanged(), this signal is not emitted when the text is changed programmatically, for example, by calling setText().
322      * @since 5.21
323      */
324     void textEdited(const QString &);
325 
326 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 80)
327     /**
328      * Emitted when return or enter was pressed in the lineedit.
329      *
330      * @deprecated since 5.80, use KUrlRequester::returnPressed(const QString &) signal
331      */
332     KIOWIDGETS_DEPRECATED_VERSION(5, 80, "Use KUrlRequester::returnPressed(const QString &) signal")
333     void returnPressed(); // clazy:exclude=overloaded-signal
334 #endif
335 
336     /**
337      * Emitted when return or enter was pressed in the lineedit.
338      * The parameter contains the contents of the lineedit.
339      */
340     void returnPressed(const QString &text); // clazy:exclude=overloaded-signal
341 
342     /**
343      * Emitted before the filedialog is going to open. Connect
344      * to this signal to "configure" the filedialog, e.g. set the
345      * filefilter, the mode, a preview-widget, etc. It's usually
346      * not necessary to set a URL for the filedialog, as it will
347      * get set properly from the editfield contents.
348      *
349      * If you use multiple KUrlRequesters, you can connect all of them
350      * to the same slot and use the given KUrlRequester pointer to know
351      * which one is going to open.
352      */
353     void openFileDialog(KUrlRequester *);
354 
355     /**
356      * Emitted when the user changed the URL via the file dialog.
357      * The parameter contains the contents of the lineedit.
358      */
359     void urlSelected(const QUrl &);
360 
361 protected:
362     void changeEvent(QEvent *e) override;
363     bool eventFilter(QObject *obj, QEvent *ev) override;
364 
365 private:
366     class KUrlRequesterPrivate;
367     KUrlRequesterPrivate *const d;
368 
369     Q_DISABLE_COPY(KUrlRequester)
370 
371     Q_PRIVATE_SLOT(d, void _k_slotUpdateUrl())
372     Q_PRIVATE_SLOT(d, void _k_slotOpenDialog())
373     Q_PRIVATE_SLOT(d, void _k_slotFileDialogAccepted())
374 };
375 
376 class KIOWIDGETS_EXPORT KUrlComboRequester : public KUrlRequester // krazy:exclude=dpointer (For use in Qt Designer)
377 {
378     Q_OBJECT
379 public:
380     /**
381      * Constructs a KUrlRequester widget with a combobox.
382      */
383     explicit KUrlComboRequester(QWidget *parent = nullptr);
384 
385 private:
386     class Private;
387     Private *const d;
388 };
389 
390 #endif // KURLREQUESTER_H
391