15#include "kfilewidget.h"
17#include "../utils_p.h"
18#include "kfilebookmarkhandler_p.h"
19#include "kfileplacesmodel.h"
20#include "kfileplacesview.h"
21#include "kfilepreviewgenerator.h"
22#include "kfilewidgetdocktitlebar_p.h"
23#include "kurlcombobox.h"
24#include "kurlnavigator.h"
26#include <config-kiofilewidgets.h>
28#include <defaults-kfile.h>
29#include <kdiroperator.h>
30#include <kfilefiltercombo.h>
31#include <kfileitemdelegate.h>
33#include <kio/jobuidelegate.h>
34#include <kio/statjob.h>
35#include <kprotocolmanager.h>
36#include <krecentdirs.h>
37#include <krecentdocument.h>
38#include <kurlauthorized.h>
39#include <kurlcompletion.h>
42#include <KConfigGroup>
45#include <KFilePlacesModel>
48#include <KLocalizedString>
50#include <KMessageWidget>
51#include <KSharedConfig>
53#include <KStandardActions>
54#include <KToggleAction>
56#include <QAbstractProxyModel>
57#include <QApplication>
67#include <QLoggingCategory>
69#include <QMimeDatabase>
73#include <QStandardPaths>
80Q_DECLARE_LOGGING_CATEGORY(KIO_KFILEWIDGETS_FW)
81Q_LOGGING_CATEGORY(KIO_KFILEWIDGETS_FW,
"kf.kio.kfilewidgets.kfilewidget", QtInfoMsg)
83class KFileWidgetPrivate
86 explicit KFileWidgetPrivate(KFileWidget *qq)
93 delete m_bookmarkHandler;
101 QSize screenSize()
const
103 return q->parentWidget() ? q->parentWidget()->screen()->availableGeometry().size()
107 void initDirOpWidgets();
109 void initZoomWidget();
110 void initLocationWidget();
111 void initFilterWidget();
112 void updateLocationWhatsThis();
113 void updateAutoSelectExtension();
114 void initPlacesPanel();
115 void setPlacesViewSplitterSizes();
117 void readViewConfig();
118 void writeViewConfig();
119 void setNonExtSelection();
120 void setLocationText(
const QUrl &);
121 void setLocationText(
const QList<QUrl> &);
122 void appendExtension(QUrl &url);
123 void updateLocationEditExtension(
const QString &);
124 QString findMatchingFilter(
const QString &filter,
const QString &filename)
const;
126 void updateFilterText();
133 QList<QUrl> tokenize(
const QString &line)
const;
137 void readRecentFiles();
141 void saveRecentFiles();
146 void multiSelectionChanged();
151 QUrl getCompleteUrl(
const QString &)
const;
158 bool toOverwrite(
const QUrl &);
161 void slotLocationChanged(
const QString &);
162 void urlEntered(
const QUrl &);
163 void enterUrl(
const QUrl &);
164 void enterUrl(
const QString &);
165 void locationAccepted(
const QString &);
166 void slotFilterChanged();
167 void fileHighlighted(
const KFileItem &);
168 void fileSelected(
const KFileItem &);
169 void slotLoadingFinished();
170 void togglePlacesPanel(
bool show, QObject *sender =
nullptr);
171 void toggleBookmarks(
bool);
172 void slotAutoSelectExtClicked();
173 void placesViewSplitterMoved(
int,
int);
174 void activateUrlNavigator();
180 void changeIconsSize(ZoomState zoom);
181 void slotDirOpIconSizeChanged(
int size);
182 void slotIconSizeSliderMoved(
int);
183 void slotIconSizeChanged(
int);
184 void slotViewDoubleClicked(
const QModelIndex &);
185 void slotViewKeyEnterReturnPressed();
187 void addToRecentDocuments();
189 QString locationEditCurrentText()
const;
196 QUrl mostLocalUrl(
const QUrl &url);
198 void setInlinePreviewShown(
bool show);
200 KFileWidget *
const q;
207 QBoxLayout *m_boxLayout =
nullptr;
208 QFormLayout *m_lafBox =
nullptr;
210 QLabel *m_locationLabel =
nullptr;
211 QWidget *m_opsWidget =
nullptr;
212 QVBoxLayout *m_opsWidgetLayout =
nullptr;
214 QLabel *m_filterLabel =
nullptr;
215 KUrlNavigator *m_urlNavigator =
nullptr;
216 KMessageWidget *m_messageWidget =
nullptr;
217 QPushButton *m_okButton =
nullptr;
218 QPushButton *m_cancelButton =
nullptr;
219 QDockWidget *m_placesDock =
nullptr;
220 KFilePlacesView *m_placesView =
nullptr;
221 QSplitter *m_placesViewSplitter =
nullptr;
225 int m_placesViewWidth = -1;
227 QWidget *m_labeledCustomWidget =
nullptr;
228 QWidget *m_bottomCustomWidget =
nullptr;
231 QCheckBox *m_autoSelectExtCheckBox =
nullptr;
234 QList<QUrl> m_urlList;
241 KFileBookmarkHandler *m_bookmarkHandler =
nullptr;
243 KActionMenu *m_bookmarkButton =
nullptr;
245 QToolBar *m_toolbar =
nullptr;
246 KUrlComboBox *m_locationEdit =
nullptr;
247 KDirOperator *m_ops =
nullptr;
248 KFileFilterCombo *m_filterWidget =
nullptr;
249 QTimer m_filterDelayTimer;
251 KFilePlacesModel *m_model =
nullptr;
254 bool m_autoSelectExtChecked =
false;
258 bool m_keepLocation =
false;
262 bool m_hasView =
false;
264 bool m_hasDefaultFilter =
false;
265 bool m_inAccept =
false;
266 bool m_confirmOverwrite =
false;
267 bool m_differentHierarchyLevelItemsEntered =
false;
269 const std::array<short, 8> m_stdIconSizes = {
280 QSlider *m_iconSizeSlider =
nullptr;
281 QAction *m_zoomOutAction =
nullptr;
282 QAction *m_zoomInAction =
nullptr;
287 KConfigGroup m_configGroup;
288 KConfigGroup m_stateConfigGroup;
290 KToggleAction *m_toggleBookmarksAction =
nullptr;
291 KToggleAction *m_togglePlacesPanelAction =
nullptr;
294Q_GLOBAL_STATIC(
QUrl, lastDirectory)
297static bool containsProtocolSection(
const QString &
string)
299 int len =
string.length();
300 static const char prot[] =
":/";
301 for (
int i = 0; i < len;) {
307 for (; j >= 0; j--) {
308 const QChar &ch(
string[j]);
309 if (ch.toLatin1() == 0 || !ch.isLetter()) {
312 if (ch.isSpace() && (i - j - 1) >= 2) {
316 if (j < 0 && i >= 2) {
328 if (Utils::isAbsoluteLocalPath(str)) {
332 if (url.isRelative()) {
341 , d(new KFileWidgetPrivate(this))
343 QUrl startDir(_startDir);
349 d->m_okButton->setDefault(
true);
353 d->m_okButton->hide();
354 d->m_cancelButton->hide();
356 d->initDirOpWidgets();
360 d->m_url =
getStartUrl(startDir, d->m_fileClass, filename);
363 const auto operatorActions = d->m_ops->allActions();
364 for (
QAction *action : operatorActions) {
371 d->activateUrlNavigator();
389 d->initLocationWidget();
392 d->initFilterWidget();
396 d->m_autoSelectExtCheckBox =
new QCheckBox(
this);
398 d->slotAutoSelectExtClicked();
405 config->reparseConfiguration();
411 if (d->m_configGroup.hasKey(RecentURLs)) {
412 d->m_stateConfigGroup.writeEntry(RecentURLs, d->m_configGroup.readEntry(RecentURLs));
413 d->m_configGroup.revertToDefault(RecentURLs);
416 if (d->m_configGroup.hasKey(RecentFiles)) {
417 d->m_stateConfigGroup.writeEntry(RecentFiles, d->m_configGroup.readEntry(RecentFiles));
418 d->m_configGroup.revertToDefault(RecentFiles);
422 d->readRecentFiles();
424 d->m_ops->action(KDirOperator::ShowPreview)->setChecked(d->m_ops->isInlinePreviewShown());
425 d->slotDirOpIconSizeChanged(d->m_ops->iconSize());
429 d->m_ops->action(KDirOperator::ShowPreview)->setChecked(pg->isPreviewShown());
439 bool statRes =
false;
443 statRes = statJob->
exec();
452 d->m_ops->setUrl(startDir,
true);
453 d->m_urlNavigator->setLocationUrl(startDir);
454 if (d->m_placesView) {
455 d->m_placesView->setUrl(startDir);
461 QLineEdit *lineEdit = d->m_locationEdit->lineEdit();
464 d->setLocationText(
QUrl(filename));
473 d->m_locationEdit->setFocus();
476 Q_ASSERT(showHiddenAction);
477 d->m_urlNavigator->setShowHiddenFolders(showHiddenAction->
isChecked());
479 d->m_urlNavigator->setShowHiddenFolders(checked);
483 Q_ASSERT(hiddenFilesLastAction);
484 d->m_urlNavigator->setSortHiddenFoldersLast(hiddenFilesLastAction->isChecked());
486 d->m_urlNavigator->setSortHiddenFoldersLast(checked);
494 d->m_ops->removeEventFilter(
this);
495 d->m_locationEdit->removeEventFilter(
this);
500 d->m_locationLabel->setText(text);
505 d->m_ops->clearFilter();
506 d->m_filterWidget->setFilters(filters, activeFilter);
507 d->m_ops->updateDir();
508 d->m_hasDefaultFilter =
false;
509 d->m_filterWidget->setEditable(
true);
510 d->updateFilterText();
512 d->updateAutoSelectExtension();
517 return d->m_filterWidget->currentFilter();
523 d->m_ops->clearFilter();
524 d->m_hasDefaultFilter =
false;
525 d->m_filterWidget->setEditable(
true);
527 d->updateAutoSelectExtension();
532 d->m_ops->setPreviewWidget(w);
533 d->m_ops->clearHistory();
537QUrl KFileWidgetPrivate::getCompleteUrl(
const QString &_url)
const
544 if (Utils::isAbsoluteLocalPath(url)) {
547 QUrl relativeUrlTest(m_ops->url());
548 relativeUrlTest.setPath(Utils::concatPaths(relativeUrlTest.path(), url));
568 const QSize goodSize(48 * fontSize, 30 * fontSize);
569 const QSize scrnSize = d->screenSize();
570 const QSize minSize(scrnSize / 2);
571 const QSize maxSize(scrnSize * qreal(0.9));
593 QList<QUrl> locationEditCurrentTextList(d->tokenize(locationEditCurrentText));
597 if (!((
mode & KFile::File) || (
mode & KFile::Directory) || (
mode & KFile::Files))) {
602 const bool directoryMode = (
mode & KFile::Directory);
603 const bool onlyDirectoryMode = directoryMode && !(
mode & KFile::File) && !(
mode & KFile::Files);
606 d->m_urlList.clear();
610 if (locationEditCurrentTextList.
isEmpty() && !onlyDirectoryMode) {
616 if (locationEditCurrentTextList.
count() > 1) {
617 if (
mode & KFile::File) {
642 if (!d->m_differentHierarchyLevelItemsEntered) {
652 while (!res &&
start < locationEditCurrentTextList.
count()) {
653 topMostUrl = locationEditCurrentTextList.
at(
start);
656 res = statJob->
exec();
670 for (
int i =
start; i < locationEditCurrentTextList.
count(); ++i) {
671 QUrl currUrl = locationEditCurrentTextList.
at(i);
674 int res = statJob->
exec();
690 stringList.
reserve(locationEditCurrentTextList.
count());
691 for (
int i = 0; i < locationEditCurrentTextList.
count(); ++i) {
692 Q_ASSERT(topMostUrl.
isParentOf(locationEditCurrentTextList[i]));
693 QString relativePath = relativePathOrUrl(topMostUrl, locationEditCurrentTextList[i]);
694 stringList << escapeDoubleQuotes(std::move(relativePath));
697 d->m_ops->setUrl(topMostUrl,
true);
698 const bool signalsBlocked = d->m_locationEdit->lineEdit()->blockSignals(
true);
699 d->m_locationEdit->lineEdit()->setText(QStringLiteral(
"\"%1\"").arg(stringList.
join(QStringLiteral(
"\" \""))));
702 d->m_differentHierarchyLevelItemsEntered =
true;
709 }
else if (!locationEditCurrentTextList.
isEmpty()) {
718 if (!locationEditCurrentText.
isEmpty() && !onlyDirectoryMode
719 && (Utils::isAbsoluteLocalPath(locationEditCurrentText) || containsProtocolSection(locationEditCurrentText))) {
720 QUrl url = urlFromString(locationEditCurrentText);
723 if (d->m_operationMode == Opening) {
726 int res = statJob->
exec();
732 Utils::appendSlashToPath(url);
740 int res = statJob->
exec();
749 d->m_ops->setUrl(url,
true);
750 const bool signalsBlocked = d->m_locationEdit->lineEdit()->blockSignals(
true);
751 d->m_locationEdit->lineEdit()->setText(fileName);
756 locationEditCurrentTextList = {url};
762 d->m_differentHierarchyLevelItemsEntered =
false;
768 bool filesInList =
false;
769 while (it != locationEditCurrentTextList.
constEnd()) {
772 if (d->m_operationMode == Saving && !directoryMode) {
773 d->appendExtension(url);
779 int res = statJob->
exec();
788 if ((
mode & KFile::LocalOnly) && !d->mostLocalUrl(d->m_url).isLocalFile()) {
796 i18np(
"The selected URL uses an unsupported scheme. "
797 "Please use the following scheme: %2",
798 "The selected URL uses an unsupported scheme. "
799 "Please use one of the following schemes: %2",
802 i18n(
"Unsupported URL scheme"));
811 while (it != locationEditCurrentTextList.
constEnd()) {
815 bool res = checkStatJob->
exec();
818 i18n(
"More than one folder has been selected and this dialog does not accept folders, so it is not possible to decide "
819 "which one to enter. Please select only one folder to list it."),
820 i18n(
"More than one folder provided"));
830 i18n(
"At least one folder and one file has been selected. Selected files will be ignored and the selected folder will be listed"),
831 i18n(
"Files and folders selected"));
833 d->m_ops->setUrl(url,
true);
834 const bool signalsBlocked = d->m_locationEdit->lineEdit()->blockSignals(
true);
835 d->m_locationEdit->lineEdit()->setText(
QString());
838 }
else if (res && onlyDirectoryMode && !statJob->
statResult().
isDir()) {
841 }
else if (!(
mode & KFile::ExistingOnly) || res) {
853 if ((d->m_operationMode == Saving) && d->m_confirmOverwrite && !d->toOverwrite(url)) {
865void KFileWidget::accept()
867 d->m_inAccept =
true;
869 *lastDirectory() = d->m_ops->url();
870 if (!d->m_fileClass.isEmpty()) {
875 d->m_locationEdit->setItemText(0, QString());
878 int atmost = d->m_locationEdit->maxItems();
879 for (
const auto &url : list) {
890 for (
int i = 1; i < d->m_locationEdit->count(); ++i) {
891 if (d->m_locationEdit->itemText(i) == file) {
892 d->m_locationEdit->removeItem(i--);
899 d->m_locationEdit->insertItem(1, file);
902 d->writeViewConfig();
903 d->saveRecentFiles();
905 d->addToRecentDocuments();
907 if (!(
mode() & KFile::Files)) {
914void KFileWidgetPrivate::fileHighlighted(
const KFileItem &i)
916 if ((m_locationEdit->hasFocus() && !m_locationEdit->currentText().isEmpty())) {
920 if (!i.
isNull() && i.isDir() && !(m_ops->mode() & KFile::Directory)) {
924 const bool modified = m_locationEdit->lineEdit()->isModified();
926 if (!(m_ops->mode() & KFile::Files)) {
929 setLocationText(QUrl());
936 if (!m_locationEdit->hasFocus()) {
937 setLocationText(m_url);
940 Q_EMIT q->fileHighlighted(m_url);
942 multiSelectionChanged();
943 Q_EMIT q->selectionChanged();
946 m_locationEdit->lineEdit()->setModified(
false);
953 if (m_operationMode == KFileWidget::Saving) {
954 m_locationEdit->setFocus();
958void KFileWidgetPrivate::fileSelected(
const KFileItem &i)
960 if (!i.
isNull() && i.isDir()) {
964 if (!(m_ops->mode() & KFile::Files)) {
966 setLocationText(QUrl());
969 setLocationText(i.targetUrl());
971 multiSelectionChanged();
972 Q_EMIT q->selectionChanged();
976 if (m_operationMode == KFileWidget::Saving) {
977 m_locationEdit->setFocus();
985void KFileWidgetPrivate::multiSelectionChanged()
987 if (m_locationEdit->hasFocus() && !m_locationEdit->currentText().isEmpty()) {
991 const KFileItemList
list = m_ops->selectedItems();
994 setLocationText(QUrl());
998 setLocationText(
list.targetUrlList());
1001void KFileWidgetPrivate::setLocationText(
const QUrl &url)
1006 const QSignalBlocker blocker(m_locationEdit);
1012 q->setUrl(directory,
false);
1014 q->setUrl(url,
false);
1017 m_locationEdit->setEditText(escapeDoubleQuotes(url.
fileName()));
1018 }
else if (!m_locationEdit->lineEdit()->text().isEmpty()) {
1019 m_locationEdit->clearEditText();
1022 if (m_operationMode == KFileWidget::Saving) {
1023 setNonExtSelection();
1032 relPath.remove(0, basePath.length());
1034 relPath.remove(0, 1);
1045 path.
replace(QStringLiteral(
"\\"), QStringLiteral(
"\\\\"));
1047 path.
replace(QStringLiteral(
"\""), QStringLiteral(
"\\\""));
1051void KFileWidgetPrivate::initDirOpWidgets()
1053 m_opsWidget =
new QWidget(q);
1054 m_opsWidgetLayout =
new QVBoxLayout(m_opsWidget);
1055 m_opsWidgetLayout->setContentsMargins(0, 0, 0, 0);
1056 m_opsWidgetLayout->setSpacing(0);
1058 m_model =
new KFilePlacesModel(q);
1066 m_urlNavigator =
new KUrlNavigator(m_model, QUrl(), m_opsWidget);
1067 m_urlNavigator->setPlacesSelectorVisible(
false);
1074 m_messageWidget =
new KMessageWidget(q);
1076 m_messageWidget->setWordWrap(
true);
1077 m_messageWidget->hide();
1079 auto topSeparator =
new QFrame(q);
1082 m_ops =
new KDirOperator(QUrl(), m_opsWidget);
1083 m_ops->installEventFilter(q);
1084 m_ops->setObjectName(QStringLiteral(
"KFileWidget::ops"));
1085 m_ops->setIsSaving(m_operationMode == KFileWidget::Saving);
1086 m_ops->setNewFileMenuSelectDirWhenAlreadyExist(
true);
1087 m_ops->showOpenWithActions(
true);
1090 auto bottomSparator =
new QFrame(q);
1093 q->connect(m_ops, &KDirOperator::urlEntered, q, [
this](
const QUrl &url) {
1097 fileHighlighted(item);
1099 q->connect(m_ops, &KDirOperator::fileSelected, q, [
this](
const KFileItem &item) {
1102 q->connect(m_ops, &KDirOperator::finishedLoading, q, [
this]() {
1103 slotLoadingFinished();
1106 slotViewKeyEnterReturnPressed();
1110 q->setSelectedUrls(urls);
1117 m_ops->dirLister()->setAutoErrorHandlingEnabled(
false);
1119 m_messageWidget->setText(job->errorString());
1120 m_messageWidget->animatedShow();
1123 m_ops->setupMenu(KDirOperator::SortActions | KDirOperator::FileActions | KDirOperator::ViewActions);
1127 m_opsWidgetLayout->addWidget(m_toolbar);
1128 m_opsWidgetLayout->addWidget(m_urlNavigator);
1129 m_opsWidgetLayout->addWidget(m_messageWidget);
1130 m_opsWidgetLayout->addWidget(topSeparator);
1131 m_opsWidgetLayout->addWidget(m_ops);
1132 m_opsWidgetLayout->addWidget(bottomSparator);
1135void KFileWidgetPrivate::initZoomWidget()
1137 m_iconSizeSlider =
new QSlider(q);
1139 m_iconSizeSlider->setMinimumWidth(40);
1141 m_iconSizeSlider->setMinimum(0);
1142 m_iconSizeSlider->setMaximum(m_stdIconSizes.size() - 1);
1143 m_iconSizeSlider->setSingleStep(1);
1144 m_iconSizeSlider->setPageStep(1);
1148 slotIconSizeChanged(m_stdIconSizes[step]);
1152 slotIconSizeSliderMoved(m_stdIconSizes[step]);
1156 slotDirOpIconSizeChanged(iconSize);
1163 changeIconsSize(ZoomOut);
1167 q->addAction(m_zoomOutAction);
1173 changeIconsSize(ZoomIn);
1177 q->addAction(m_zoomInAction);
1180void KFileWidgetPrivate::initToolbar()
1182 m_toolbar =
new QToolBar(m_opsWidget);
1183 m_toolbar->setObjectName(QStringLiteral(
"KFileWidget::toolbar"));
1184 m_toolbar->setMovable(
false);
1195 ->setWhatsThis(
i18n(
"<qt>Click this button to enter the parent folder.<br /><br />"
1196 "For instance, if the current location is file:/home/konqi clicking this "
1197 "button will take you to file:/home.</qt>"));
1199 m_ops->action(
KDirOperator::Back)->setWhatsThis(
i18n(
"Click this button to move backwards one step in the browsing history."));
1200 m_ops->action(
KDirOperator::Forward)->setWhatsThis(
i18n(
"Click this button to move forward one step in the browsing history."));
1202 m_ops->action(
KDirOperator::Reload)->setWhatsThis(
i18n(
"Click this button to reload the contents of the current location."));
1206 m_togglePlacesPanelAction =
new KToggleAction(
i18n(
"Show Places Panel"), q);
1207 q->addAction(m_togglePlacesPanelAction);
1208 m_togglePlacesPanelAction->setShortcut(QKeySequence(
Qt::Key_F9));
1209 q->connect(m_togglePlacesPanelAction, &
QAction::toggled, q, [
this](
bool show) {
1210 togglePlacesPanel(show);
1213 m_toggleBookmarksAction =
new KToggleAction(
i18n(
"Show Bookmarks Button"), q);
1214 q->addAction(m_toggleBookmarksAction);
1215 q->connect(m_toggleBookmarksAction, &
QAction::toggled, q, [
this](
bool show) {
1216 toggleBookmarks(show);
1220 KActionMenu *menu =
new KActionMenu(
QIcon::fromTheme(QStringLiteral(
"configure")),
i18n(
"Options"), q);
1223 i18n(
"<qt>This is the preferences menu for the file dialog. "
1224 "Various options can be accessed from this menu including: <ul>"
1225 "<li>how files are sorted in the list</li>"
1226 "<li>types of view, including icon and list</li>"
1227 "<li>showing of hidden files</li>"
1228 "<li>the Places panel</li>"
1229 "<li>file previews</li>"
1230 "<li>separating folders from files</li></ul></qt>"));
1232 menu->
addAction(m_ops->action(KDirOperator::AllowExpansionInDetailsView));
1233 menu->addSeparator();
1235 menu->
addAction(m_togglePlacesPanelAction);
1236 menu->
addAction(m_toggleBookmarksAction);
1242 m_bookmarkButton =
new KActionMenu(
QIcon::fromTheme(QStringLiteral(
"bookmarks")),
i18n(
"Bookmarks"), q);
1244 q->addAction(m_bookmarkButton);
1245 m_bookmarkButton->setWhatsThis(
1246 i18n(
"<qt>This button allows you to bookmark specific locations. "
1247 "Click on this button to open the bookmark menu where you may add, "
1248 "edit or select a bookmark.<br /><br />"
1249 "These bookmarks are specific to the file dialog, but otherwise operate "
1250 "like bookmarks elsewhere in KDE.</qt>"));
1252 QWidget *midSpacer =
new QWidget(q);
1259 m_toolbar->addSeparator();
1260 m_toolbar->addAction(m_ops->action(KDirOperator::ViewIconsView));
1261 m_toolbar->addAction(m_ops->action(KDirOperator::ViewCompactView));
1262 m_toolbar->addAction(m_ops->action(KDirOperator::ViewDetailsView));
1263 m_toolbar->addSeparator();
1264 m_toolbar->addAction(m_ops->action(KDirOperator::ShowPreview));
1266 m_toolbar->addAction(m_bookmarkButton);
1268 m_toolbar->addWidget(midSpacer);
1271 m_toolbar->addAction(m_zoomOutAction);
1272 m_toolbar->addWidget(m_iconSizeSlider);
1273 m_toolbar->addAction(m_zoomInAction);
1274 m_toolbar->addSeparator();
1277 m_toolbar->addAction(menu);
1280 m_toolbar->setMovable(
false);
1283void KFileWidgetPrivate::initLocationWidget()
1285 m_locationLabel =
new QLabel(
i18n(
"&Name:"), q);
1286 m_locationEdit =
new KUrlComboBox(KUrlComboBox::Files,
true, q);
1287 m_locationEdit->installEventFilter(q);
1293 slotLocationChanged(text);
1296 updateLocationWhatsThis();
1297 m_locationLabel->setBuddy(m_locationEdit);
1299 KUrlCompletion *fileCompletionObj =
new KUrlCompletion(KUrlCompletion::FileCompletion);
1300 m_locationEdit->setCompletionObject(fileCompletionObj);
1301 m_locationEdit->setAutoDeleteCompletionObject(
true);
1304 locationAccepted(text);
1308void KFileWidgetPrivate::initFilterWidget()
1310 m_filterLabel =
new QLabel(q);
1311 m_filterWidget =
new KFileFilterCombo(q);
1318 m_filterLabel->setBuddy(m_filterWidget);
1320 slotFilterChanged();
1323 m_filterDelayTimer.setSingleShot(
true);
1324 m_filterDelayTimer.setInterval(300);
1327 slotFilterChanged();
1331void KFileWidgetPrivate::setLocationText(
const QList<QUrl> &urlList)
1336 const QSignalBlocker blocker(m_locationEdit);
1338 const QUrl baseUrl = m_ops->
url();
1340 if (urlList.
count() > 1) {
1342 for (
const QUrl &url : urlList) {
1343 urls += QStringLiteral(
"\"%1\" ").
arg(escapeDoubleQuotes(relativePathOrUrl(baseUrl, url)));
1346 m_locationEdit->setEditText(urls);
1347 }
else if (urlList.count() == 1) {
1348 const auto url = urlList[0];
1349 m_locationEdit->setEditText(escapeDoubleQuotes(relativePathOrUrl(baseUrl, url)));
1350 }
else if (!m_locationEdit->lineEdit()->text().isEmpty()) {
1351 m_locationEdit->clearEditText();
1354 if (m_operationMode == KFileWidget::Saving) {
1355 setNonExtSelection();
1359void KFileWidgetPrivate::updateLocationWhatsThis()
1361 const QString autocompletionWhatsThisText =
i18n(
1362 "<qt>While typing in the text area, you may be presented "
1363 "with possible matches. "
1364 "This feature can be controlled by clicking with the right mouse button "
1365 "and selecting a preferred mode from the <b>Text Completion</b> menu.</qt>");
1367 QString whatsThisText;
1368 if (m_operationMode == KFileWidget::Saving) {
1369 whatsThisText = QLatin1String(
"<qt>") +
i18n(
"This is the name to save the file as.") + autocompletionWhatsThisText;
1370 }
else if (m_ops->mode() & KFile::Files) {
1371 whatsThisText = QLatin1String(
"<qt>")
1372 +
i18n(
"This is the list of files to open. More than "
1373 "one file can be specified by listing several "
1374 "files, separated by spaces.")
1375 + autocompletionWhatsThisText;
1377 whatsThisText = QLatin1String(
"<qt>") +
i18n(
"This is the name of the file to open.") + autocompletionWhatsThisText;
1380 m_locationLabel->setWhatsThis(whatsThisText);
1381 m_locationEdit->setWhatsThis(whatsThisText);
1384void KFileWidgetPrivate::initPlacesPanel()
1390 m_placesDock =
new QDockWidget(
i18nc(
"@title:window",
"Places"), q);
1392 m_placesDock->setTitleBarWidget(
new KDEPrivate::KFileWidgetDockTitleBar(m_placesDock));
1394 m_placesView =
new KFilePlacesView(m_placesDock);
1395 m_placesView->setModel(m_model);
1398 m_placesView->setObjectName(QStringLiteral(
"url bar"));
1399 QObject::connect(m_placesView, &KFilePlacesView::urlChanged, q, [
this](
const QUrl &url) {
1404 m_messageWidget->setText(errorMessage);
1405 m_messageWidget->animatedShow();
1412 m_placesView->setUrl(m_url);
1414 m_placesDock->setWidget(m_placesView);
1415 m_placesViewSplitter->insertWidget(0, m_placesDock);
1418 m_placesViewWidth = m_configGroup.readEntry(SpeedbarWidth, m_placesView->sizeHint().width());
1421 setPlacesViewSplitterSizes();
1424 togglePlacesPanel(visible, m_placesDock);
1428void KFileWidgetPrivate::setPlacesViewSplitterSizes()
1430 if (m_placesViewWidth > 0) {
1431 QList<int> sizes = m_placesViewSplitter->sizes();
1432 sizes[0] = m_placesViewWidth;
1433 sizes[1] = q->width() - m_placesViewWidth - m_placesViewSplitter->handleWidth();
1434 m_placesViewSplitter->setSizes(sizes);
1438void KFileWidgetPrivate::initGUI()
1442 m_boxLayout =
new QVBoxLayout(q);
1443 m_boxLayout->setContentsMargins(0, 0, 0, 0);
1445 m_placesViewSplitter =
new QSplitter(q);
1447 m_placesViewSplitter->setChildrenCollapsible(
false);
1448 m_boxLayout->addWidget(m_placesViewSplitter);
1451 placesViewSplitterMoved(pos, index);
1453 m_placesViewSplitter->insertWidget(0, m_opsWidget);
1455 m_lafBox =
new QFormLayout();
1462 m_lafBox->addRow(m_locationLabel, m_locationEdit);
1463 m_lafBox->addRow(m_filterLabel, m_filterWidget);
1465 m_lafBox->addWidget(m_autoSelectExtCheckBox);
1467 m_opsWidgetLayout->addLayout(m_lafBox);
1469 auto hbox =
new QHBoxLayout();
1476 hbox->addStretch(2);
1477 hbox->addWidget(m_okButton);
1478 hbox->addWidget(m_cancelButton);
1480 m_opsWidgetLayout->addLayout(hbox);
1482 q->setTabOrder(m_ops, m_autoSelectExtCheckBox);
1483 q->setTabOrder(m_autoSelectExtCheckBox, m_locationEdit);
1484 q->setTabOrder(m_locationEdit, m_filterWidget);
1485 q->setTabOrder(m_filterWidget, m_okButton);
1486 q->setTabOrder(m_okButton, m_cancelButton);
1487 q->setTabOrder(m_cancelButton, m_urlNavigator);
1488 q->setTabOrder(m_urlNavigator, m_ops);
1491void KFileWidgetPrivate::slotFilterChanged()
1493 m_filterDelayTimer.stop();
1495 KFileFilter
filter = m_filterWidget->currentFilter();
1497 m_ops->clearFilter();
1499 if (!
filter.mimePatterns().isEmpty()) {
1500 QStringList types =
filter.mimePatterns();
1501 types.
prepend(QStringLiteral(
"inode/directory"));
1502 m_ops->setMimeFilter(types);
1505 const auto filePatterns =
filter.filePatterns();
1506 const bool hasRegExSyntax = std::any_of(filePatterns.constBegin(), filePatterns.constEnd(), [](
const QString &filter) {
1507 return filter.contains(QLatin1Char(
'*')) || filter.contains(QLatin1Char(
'?')) || filter.contains(QLatin1Char(
'['));
1510 if (hasRegExSyntax) {
1511 m_ops->setNameFilter(
filter.filePatterns().join(QLatin1Char(
' ')));
1513 m_ops->setNameFilter(QLatin1Char(
'*') + filePatterns.join(QLatin1Char(
'*')) + QLatin1Char(
'*'));
1516 updateAutoSelectExtension();
1520 Q_EMIT q->filterChanged(filter);
1527 d->m_ops->setUrl(url, clearforward);
1531void KFileWidgetPrivate::urlEntered(
const QUrl &url)
1536 if (pathCombo->
count() != 0) {
1541 if (m_keepLocation) {
1542 const QUrl currentUrl = urlFromString(locationEditCurrentText());
1546 m_locationEdit->lineEdit()->setModified(
true);
1549 m_locationEdit->blockSignals(blocked);
1551 m_urlNavigator->setLocationUrl(url);
1554 KUrlCompletion *
completion =
dynamic_cast<KUrlCompletion *
>(m_locationEdit->completionObject());
1560 m_placesView->setUrl(url);
1563 m_messageWidget->hide();
1566void KFileWidgetPrivate::locationAccepted(
const QString &url)
1573void KFileWidgetPrivate::enterUrl(
const QUrl &url)
1580 Utils::appendSlashToPath(u);
1587 if (q->window()->focusWidget() != m_locationEdit) {
1592void KFileWidgetPrivate::enterUrl(
const QString &url)
1599bool KFileWidgetPrivate::toOverwrite(
const QUrl &url)
1605 bool res = statJob->
exec();
1609 i18n(
"The file \"%1\" already exists. Do you wish to overwrite it?", url.
fileName()),
1610 i18n(
"Overwrite File?"),
1617 m_locationEdit->setFocus();
1618 setNonExtSelection();
1634 d->setLocationText(url);
1647 d->setLocationText(urls);
1650void KFileWidgetPrivate::slotLoadingFinished()
1657 m_ops->blockSignals(
true);
1658 QUrl u(m_ops->url());
1659 if (currentText.
startsWith(QLatin1Char(
'/'))) {
1662 u.
setPath(Utils::concatPaths(m_ops->url().path(), currentText));
1664 m_ops->setCurrentItem(u);
1665 m_ops->blockSignals(
false);
1668void KFileWidgetPrivate::slotLocationChanged(
const QString &text)
1672 m_locationEdit->lineEdit()->setModified(
true);
1674 if (text.
isEmpty() && m_ops->view()) {
1675 m_ops->view()->clearSelection();
1678 if (!m_locationEdit->lineEdit()->text().isEmpty()) {
1679 const QList<QUrl> urlList(tokenize(text));
1680 m_ops->setCurrentItems(urlList);
1690 if (d->m_inAccept) {
1702 if (d->m_inAccept) {
1703 if (d->m_ops->mode() & KFile::Files) {
1704 list = d->m_urlList;
1714 qCDebug(KIO_KFILEWIDGETS_FW) <<
"Tokenizing:" << line;
1718 Utils::appendSlashToPath(baseUrl);
1722 auto addUrl = [baseUrl, &urls](
const QString &partial_name) {
1723 if (partial_name.trimmed().isEmpty()) {
1728 QUrl partial_url(partial_name);
1729 if (!partial_url.isValid()
1730 || partial_url.isRelative()
1732 || (!partial_url.scheme().isEmpty() && (!partial_name.contains(QStringLiteral(
"://")) || !
KProtocolInfo::isKnownProtocol(partial_url.scheme())))) {
1735 partial_url.clear();
1736 partial_url.setPath(partial_name);
1741 if (partial_url.isRelative() || baseUrl.
isParentOf(partial_url)) {
1742 partial_url = baseUrl.
resolved(partial_url);
1745 if (partial_url.isValid()) {
1746 urls.
append(partial_url);
1749 qCDebug(KIO_KFILEWIDGETS_FW) <<
"Discarding Invalid" << partial_url;
1756 QString partial_name;
1757 bool escape =
false;
1758 for (
int i = 0; i < line.
length(); i++) {
1759 const QChar ch = line[i];
1777 addUrl(partial_name);
1778 partial_name.
clear();
1789 if (!partial_name.
isEmpty()) {
1790 addUrl(partial_name);
1791 partial_name.
clear();
1801 if (d->m_inAccept) {
1802 const QUrl url = d->mostLocalUrl(d->m_url);
1818 if (d->m_inAccept) {
1819 if (d->m_ops->mode() & KFile::Files) {
1821 for (
const auto &u : urls) {
1822 const QUrl url = d->mostLocalUrl(u);
1830 if (d->m_url.isLocalFile()) {
1831 list.
append(d->m_url.toLocalFile());
1841 return d->m_ops->
url();
1848 if (d->m_placesDock) {
1851 d->setPlacesViewSplitterSizes();
1855void KFileWidget::showEvent(
QShowEvent *event)
1857 if (!d->m_hasView) {
1860 d->m_ops->setViewMode(KFile::Default);
1861 d->m_hasView =
true;
1864 d->slotViewDoubleClicked(index);
1867 d->m_ops->clearHistory();
1872bool KFileWidget::eventFilter(
QObject *watched,
QEvent *event)
1881 const auto type =
event->type();
1898 d->m_ops->setMode(m);
1899 if (d->m_ops->dirOnlyMode()) {
1900 d->m_filterWidget->setDefaultFilter(
KFileFilter(
i18n(
"All Folders"), {QStringLiteral(
"*")}, {}));
1902 d->m_filterWidget->setDefaultFilter(
KFileFilter(
i18n(
"All Files"), {QStringLiteral(
"*")}, {}));
1905 d->updateAutoSelectExtension();
1910 return d->m_ops->mode();
1913void KFileWidgetPrivate::readViewConfig()
1927 m_locationEdit->setCompletionMode(cm);
1931 togglePlacesPanel(m_configGroup.readEntry(ShowSpeedbar,
true));
1934 toggleBookmarks(m_configGroup.readEntry(ShowBookmarks,
false));
1937 m_autoSelectExtChecked = m_configGroup.readEntry(AutoSelectExtChecked, DefaultAutoSelectExtChecked);
1938 updateAutoSelectExtension();
1941 m_urlNavigator->setUrlEditable(!m_configGroup.readEntry(BreadcrumbNavigation,
true));
1944 m_urlNavigator->setShowFullPath(m_configGroup.readEntry(ShowFullPath,
false));
1946 int w1 = q->minimumSize().width();
1947 int w2 = m_toolbar->sizeHint().width();
1949 q->setMinimumWidth(w2);
1953void KFileWidgetPrivate::writeViewConfig()
1961 KConfigGroup tmpGroup(&tmp, ConfigGroup);
1963 KUrlComboBox *pathCombo = m_urlNavigator->editor();
1965 tmpGroup.writeEntry(PathComboCompletionMode,
static_cast<int>(pathCombo->
completionMode()));
1966 tmpGroup.writeEntry(LocationComboCompletionMode,
static_cast<int>(m_locationEdit->completionMode()));
1968 const bool showPlacesPanel = m_placesDock && !m_placesDock->
isHidden();
1969 tmpGroup.writeEntry(ShowSpeedbar, showPlacesPanel);
1970 if (m_placesViewWidth > 0) {
1971 tmpGroup.writeEntry(SpeedbarWidth, m_placesViewWidth);
1974 tmpGroup.writeEntry(ShowBookmarks, m_bookmarkHandler !=
nullptr);
1975 tmpGroup.writeEntry(AutoSelectExtChecked, m_autoSelectExtChecked);
1976 tmpGroup.writeEntry(BreadcrumbNavigation, !m_urlNavigator->isUrlEditable());
1977 tmpGroup.writeEntry(ShowFullPath, m_urlNavigator->showFullPath());
1979 m_ops->writeConfig(tmpGroup);
1985void KFileWidgetPrivate::readRecentFiles()
1989 const bool oldState = m_locationEdit->blockSignals(
true);
1990 m_locationEdit->setMaxItems(m_configGroup.readEntry(RecentFilesNumber, DefaultRecentURLsNumber));
1991 m_locationEdit->setUrls(m_stateConfigGroup.readPathEntry(RecentFiles, QStringList()), KUrlComboBox::RemoveBottom);
1992 m_locationEdit->setCurrentIndex(-1);
1993 m_locationEdit->blockSignals(oldState);
1995 KUrlComboBox *combo = m_urlNavigator->editor();
1996 combo->
setUrls(m_stateConfigGroup.readPathEntry(RecentURLs, QStringList()), KUrlComboBox::RemoveTop);
1997 combo->
setMaxItems(m_configGroup.readEntry(RecentURLsNumber, DefaultRecentURLsNumber));
1998 combo->
setUrl(m_ops->url());
2001 KUrlCompletion *
completion =
dynamic_cast<KUrlCompletion *
>(m_locationEdit->completionObject());
2007void KFileWidgetPrivate::saveRecentFiles()
2010 m_stateConfigGroup.writePathEntry(RecentFiles, m_locationEdit->urls());
2012 KUrlComboBox *pathCombo = m_urlNavigator->editor();
2013 m_stateConfigGroup.writePathEntry(RecentURLs, pathCombo->urls());
2018 return d->m_okButton;
2023 return d->m_cancelButton;
2027void KFileWidget::slotCancel()
2029 d->writeViewConfig();
2035 d->m_keepLocation = keep;
2040 return d->m_keepLocation;
2047 d->m_operationMode =
mode;
2048 d->m_keepLocation = (
mode == Saving);
2049 d->m_filterWidget->setEditable(!d->m_hasDefaultFilter ||
mode != Saving);
2050 if (
mode == Opening) {
2052 d->m_okButton->setText(
i18n(
"&Open"));
2057 }
else if (
mode == Saving) {
2059 d->setNonExtSelection();
2063 d->updateLocationWhatsThis();
2064 d->updateAutoSelectExtension();
2067 d->m_ops->setIsSaving(
mode == Saving);
2069 d->updateFilterText();
2074 return d->m_operationMode;
2077void KFileWidgetPrivate::slotAutoSelectExtClicked()
2083 m_autoSelectExtChecked = m_autoSelectExtCheckBox->
isChecked();
2086 updateLocationEditExtension(m_extension );
2089void KFileWidgetPrivate::placesViewSplitterMoved(
int pos,
int index)
2095 if (m_placesDock && index == 1) {
2096 m_placesViewWidth = pos;
2101void KFileWidgetPrivate::activateUrlNavigator()
2105 QLineEdit *lineEdit = m_urlNavigator->editor()->lineEdit();
2110 m_urlNavigator->setUrlEditable(
false);
2112 m_urlNavigator->setUrlEditable(
true);
2113 m_urlNavigator->setFocus();
2118void KFileWidgetPrivate::slotDirOpIconSizeChanged(
int size)
2120 auto beginIt = m_stdIconSizes.cbegin();
2121 auto endIt = m_stdIconSizes.cend();
2122 auto it = std::lower_bound(beginIt, endIt, size);
2123 const int sliderStep = it != endIt ? it - beginIt : 0;
2124 m_iconSizeSlider->setValue(sliderStep);
2125 m_zoomOutAction->setDisabled(it == beginIt);
2126 m_zoomInAction->setDisabled(it == (endIt - 1));
2129void KFileWidgetPrivate::changeIconsSize(ZoomState zoom)
2131 int step = m_iconSizeSlider->value();
2133 if (zoom == ZoomOut) {
2139 if (step ==
static_cast<int>(m_stdIconSizes.size() - 1)) {
2145 m_iconSizeSlider->setValue(step);
2146 slotIconSizeSliderMoved(m_stdIconSizes[step]);
2149void KFileWidgetPrivate::slotIconSizeChanged(
int _value)
2151 m_ops->setIconSize(_value);
2152 m_iconSizeSlider->setToolTip(
i18n(
"Icon size: %1 pixels", _value));
2155void KFileWidgetPrivate::slotIconSizeSliderMoved(
int size)
2159 slotIconSizeChanged(size);
2161 QPoint global(m_iconSizeSlider->rect().topLeft());
2162 global.ry() += m_iconSizeSlider->height() / 2;
2163 QHelpEvent toolTipEvent(
QEvent::ToolTip, QPoint(0, 0), m_iconSizeSlider->mapToGlobal(global));
2167void KFileWidgetPrivate::slotViewDoubleClicked(
const QModelIndex &index)
2170 if (m_operationMode == KFileWidget::Saving && index.
isValid() && m_ops->selectedItems().constFirst().isFile()) {
2175void KFileWidgetPrivate::slotViewKeyEnterReturnPressed()
2179 if (m_operationMode == KFileWidget::Saving && (m_ops->mode() & KFile::File) && m_ops->selectedItems().isEmpty()) {
2228void KFileWidgetPrivate::updateAutoSelectExtension()
2230 if (!m_autoSelectExtCheckBox) {
2243 QString lastExtension = m_extension;
2244 m_extension.
clear();
2247 if ((m_operationMode == KFileWidget::Saving) && (m_ops->mode() & KFile::File)) {
2252 KFileFilter fileFilter = m_filterWidget->currentFilter();
2258 if (currentExtension.
isEmpty()) {
2259 currentExtension = locationEditCurrentText().
section(QLatin1Char(
'.'), -1, -1);
2263 QString defaultExtension;
2264 QStringList extensionList;
2269 defaultExtension = getExtensionFromPatternList(extensionList);
2277 if (!defaultExtension.
isEmpty()) {
2278 defaultExtension.
prepend(QLatin1Char(
'.'));
2283 if ((!currentExtension.
isEmpty() && extensionList.
contains(QLatin1String(
"*.") + currentExtension))
2285 m_extension = QLatin1Char(
'.') + currentExtension;
2287 m_extension = defaultExtension;
2297 QString whatsThisExtension;
2298 if (!m_extension.isEmpty()) {
2300 m_autoSelectExtCheckBox->setText(
i18n(
"Automatically select filename e&xtension (%1)", m_extension));
2301 whatsThisExtension =
i18n(
"the extension <b>%1</b>", m_extension);
2303 m_autoSelectExtCheckBox->setEnabled(
true);
2304 m_autoSelectExtCheckBox->setChecked(m_autoSelectExtChecked);
2307 m_autoSelectExtCheckBox->setText(
i18n(
"Automatically select filename e&xtension"));
2308 whatsThisExtension =
i18n(
"a suitable extension");
2310 m_autoSelectExtCheckBox->setChecked(
false);
2311 m_autoSelectExtCheckBox->setEnabled(
false);
2314 const QString locationLabelText = stripUndisplayable(m_locationLabel->text());
2315 m_autoSelectExtCheckBox->setWhatsThis(QLatin1String(
"<qt>")
2316 +
i18n(
"This option enables some convenient features for "
2317 "saving files with extensions:<br />"
2319 "<li>Any extension specified in the <b>%1</b> text "
2320 "area will be updated if you change the file type "
2323 "<li>If no extension is specified in the <b>%2</b> "
2324 "text area when you click "
2325 "<b>Save</b>, %3 will be added to the end of the "
2326 "filename (if the filename does not already exist). "
2327 "This extension is based on the file type that you "
2328 "have chosen to save in.<br />"
2330 "If you do not want KDE to supply an extension for the "
2331 "filename, you can either turn this option off or you "
2332 "can suppress it by adding a period (.) to the end of "
2333 "the filename (the period will be automatically "
2337 "If unsure, keep this option enabled as it makes your "
2338 "files more manageable.",
2342 + QLatin1String(
"</qt>"));
2344 m_autoSelectExtCheckBox->show();
2347 updateLocationEditExtension(lastExtension);
2351 m_autoSelectExtCheckBox->setChecked(
false);
2352 m_autoSelectExtCheckBox->hide();
2359void KFileWidgetPrivate::updateLocationEditExtension(
const QString &lastExtension)
2361 if (!m_autoSelectExtCheckBox->isChecked() || m_extension.isEmpty()) {
2365 const QString urlStr = locationEditCurrentText();
2370 const int fileNameOffset = urlStr.
lastIndexOf(QLatin1Char(
'/')) + 1;
2371 QStringView fileName = QStringView(urlStr).mid(fileNameOffset);
2373 const int dot = fileName.
lastIndexOf(QLatin1Char(
'.'));
2374 const int len = fileName.
length();
2379 const QUrl url = getCompleteUrl(urlStr);
2384 bool result = statJob->
exec();
2403 }
else if (!m_extension.isEmpty() && fileName.
endsWith(m_extension)) {
2404 fileName.
chop(m_extension.length());
2410 const QString newText = QStringView(urlStr).left(fileNameOffset) + fileName + m_extension;
2411 if (newText != locationEditCurrentText()) {
2412 const int idx = m_locationEdit->currentIndex();
2414 m_locationEdit->setEditText(newText);
2416 m_locationEdit->setItemText(idx, newText);
2418 m_locationEdit->lineEdit()->setModified(
true);
2428 QRegularExpression rx;
2429 for (
const QString &p : patterns) {
2440void KFileWidgetPrivate::updateFilter()
2442 if ((m_operationMode == KFileWidget::Saving) && (m_ops->mode() & KFile::File)) {
2443 QString urlStr = locationEditCurrentText();
2451 bool matchesCurrentFilter = [
this, urlMimeType, urlStr] {
2452 const KFileFilter
filter = m_filterWidget->currentFilter();
2453 if (
filter.mimePatterns().contains(urlMimeType.
name())) {
2457 QString filename = urlStr.
mid(urlStr.
lastIndexOf(QLatin1Char(
'/')) + 1);
2459 const auto filePatterns =
filter.filePatterns();
2460 const bool hasMatch = std::any_of(filePatterns.cbegin(), filePatterns.cend(), [filename](
const QString &pattern) {
2461 QRegularExpression rx(QRegularExpression::wildcardToRegularExpression(pattern));
2463 return rx.match(filename).hasMatch();
2468 if (matchesCurrentFilter) {
2472 const auto filters = m_filterWidget->filters();
2474 auto filterIt = std::find_if(filters.cbegin(), filters.cend(), [urlStr, urlMimeType](
const KFileFilter &filter) {
2475 if (filter.mimePatterns().contains(urlMimeType.name())) {
2479 QString filename = urlStr.
mid(urlStr.
lastIndexOf(QLatin1Char(
'/')) + 1);
2482 const auto filePatterns =
filter.filePatterns();
2483 const bool hasMatch = std::any_of(filePatterns.cbegin(), filePatterns.cend(), [filename](
const QString &pattern) {
2485 if (pattern == QLatin1String(
"*")) {
2491 return rx.
match(filename).hasMatch();
2497 if (filterIt != filters.cend()) {
2498 m_filterWidget->setCurrentFilter(*filterIt);
2504void KFileWidgetPrivate::appendExtension(
QUrl &url)
2508 if (!m_autoSelectExtCheckBox->isChecked() || m_extension.isEmpty()) {
2519 const int len = fileName.
length();
2520 const int dot = fileName.
lastIndexOf(QLatin1Char(
'.'));
2522 const bool suppressExtension = (dot == len - 1);
2523 const bool unspecifiedExtension = !fileName.
endsWith(m_extension);
2526 if (!(suppressExtension || unspecifiedExtension)) {
2533 bool res = statJob->
exec();
2540 if (suppressExtension) {
2557 else if (unspecifiedExtension) {
2566void KFileWidgetPrivate::addToRecentDocuments()
2568 int m = m_ops->mode();
2572 if (m & KFile::LocalOnly) {
2573 const QStringList files = q->selectedFiles();
2575 for (; it != files.
end() && atmost > 0; ++it) {
2582 const QList<QUrl> urls = q->selectedUrls();
2584 for (; it != urls.
end() && atmost > 0; ++it) {
2585 if ((*it).isValid()) {
2595 return d->m_locationEdit;
2600 return d->m_filterWidget;
2603void KFileWidgetPrivate::togglePlacesPanel(
bool show,
QObject *sender)
2607 m_placesDock->
show();
2613 for (
int rowIndex = 0; rowIndex < model->
rowCount(); rowIndex++) {
2623 if (sender == m_placesDock && m_placesDock && m_placesDock->isVisibleTo(q)) {
2630 m_placesDock->hide();
2635 if (!m_toolbar->actions().contains(homeAction)) {
2636 m_toolbar->insertAction(reloadAction, homeAction);
2640 m_togglePlacesPanelAction->setChecked(show);
2643 m_urlNavigator->setPlacesSelectorVisible(!show);
2646void KFileWidgetPrivate::toggleBookmarks(
bool show)
2649 if (m_bookmarkHandler) {
2652 m_bookmarkHandler =
new KFileBookmarkHandler(q);
2653 q->connect(m_bookmarkHandler, &KFileBookmarkHandler::openUrl, q, [
this](
const QString &path) {
2656 m_bookmarkButton->setMenu(m_bookmarkHandler->menu());
2657 }
else if (m_bookmarkHandler) {
2658 m_bookmarkButton->setMenu(
nullptr);
2659 delete m_bookmarkHandler;
2660 m_bookmarkHandler =
nullptr;
2663 if (m_bookmarkButton) {
2664 m_bookmarkButton->setVisible(show);
2667 m_toggleBookmarksAction->setChecked(show);
2674 return getStartUrl(startDir, recentDirClass, fileName);
2680 recentDirClass.
clear();
2684 bool useDefaultStartDir = startDir.
isEmpty();
2685 if (!useDefaultStartDir) {
2703 keyword = urlDir.
mid(1);
2708 recentDirClass = query.arg(keyword);
2724 useDefaultStartDir =
true;
2729 useDefaultStartDir =
true;
2734 if (useDefaultStartDir) {
2735 if (lastDirectory()->isEmpty()) {
2744 || !
QDir(lastDirectory()->toLocalFile()).exists()) {
2748 ret = *lastDirectory();
2758 *lastDirectory() = directory;
2762void KFileWidgetPrivate::setNonExtSelection()
2765 QString filename = locationEditCurrentText();
2772 int lastDot = filename.
lastIndexOf(QLatin1Char(
'.'));
2774 m_locationEdit->lineEdit()->setSelection(0, lastDot);
2776 m_locationEdit->lineEdit()->selectAll();
2783void KFileWidgetPrivate::updateFilterText()
2786 QString whatsThisText;
2788 if (m_operationMode == KFileWidget::Saving && !m_filterWidget->currentFilter().mimePatterns().isEmpty()) {
2790 whatsThisText =
i18n(
"<qt>This is the file type selector. It is used to select the format that the file will be saved as.</qt>");
2793 whatsThisText =
i18n(
2794 "<qt>This is the filter to apply to the file list. "
2795 "File names that do not match the filter will not be shown.<p>"
2796 "You may select from one of the preset filters in the "
2797 "drop down menu, or you may enter a custom filter "
2798 "directly into the text area.</p><p>"
2799 "Wildcards such as * and ? are allowed.</p></qt>");
2802 if (m_filterLabel) {
2803 m_filterLabel->setText(label);
2804 m_filterLabel->setWhatsThis(whatsThisText);
2806 if (m_filterWidget) {
2807 m_filterWidget->setWhatsThis(whatsThisText);
2813 delete d->m_bottomCustomWidget;
2814 d->m_bottomCustomWidget = widget;
2819 d->m_bottomCustomWidget->
setParent(
this);
2821 d->m_opsWidgetLayout->addWidget(d->m_bottomCustomWidget);
2828 setTabOrder(d->m_cancelButton, d->m_bottomCustomWidget);
2829 setTabOrder(d->m_bottomCustomWidget, d->m_urlNavigator);
2834 delete d->m_labeledCustomWidget;
2835 d->m_labeledCustomWidget = widget;
2839 d->m_lafBox->addRow(label, widget);
2847#if KIOFILEWIDGETS_BUILD_DEPRECATED_SINCE(6, 3)
2850 d->m_configGroup = group;
2851 d->readViewConfig();
2852 d->readRecentFiles();
2856QString KFileWidgetPrivate::locationEditCurrentText()
const
2861QUrl KFileWidgetPrivate::mostLocalUrl(
const QUrl &url)
2869 bool res = statJob->
exec();
2885void KFileWidgetPrivate::setInlinePreviewShown(
bool show)
2887 m_ops->setInlinePreviewShown(show);
2892 d->m_confirmOverwrite = enable;
2897 d->setInlinePreviewShown(
show);
2903 QSize goodSize(48 * fontSize, 30 * fontSize);
2904 const QSize scrnSize = d->screenSize();
2905 QSize minSize(scrnSize / 2);
2906 QSize maxSize(scrnSize * qreal(0.9));
2912 d->m_ops->setViewMode(
mode);
2913 d->m_hasView =
true;
2918 d->m_model->setSupportedSchemes(schemes);
2919 d->m_ops->setSupportedSchemes(schemes);
2920 d->m_urlNavigator->setSupportedSchemes(schemes);
2925 return d->m_model->supportedSchemes();
2928#include "moc_kfilewidget.cpp"
void returnPressed(const QString &text)
virtual void setCompletionMode(KCompletion::CompletionMode mode)
void setAutoDeleteCompletionObject(bool autoDelete)
KCompletion::CompletionMode completionMode() const
QString readEntry(const char *key, const char *aDefault=nullptr) const
void jobError(KIO::Job *job)
Emitted if listing a directory fails with an error.
This widget works as a network transparent filebrowser.
void keyEnterReturnPressed()
Triggered when the user hit Enter/Return.
void renamingFinished(const QList< QUrl > &urls)
Emitted when renaming selected files has finished.
void updateSelectionDependentActions()
Enables/disables actions that are selection dependent.
virtual void readConfig(const KConfigGroup &configGroup)
Reads the default settings for a view, i.e. the default KFile::FileView.
@ Up
Changes to the parent directory.
@ Home
Changes to the user's home directory.
@ ShowHiddenFiles
shows hidden files
@ ShowPreviewPanel
shows a preview next to the fileview
@ Forward
Goes forward in the history.
@ NewFolder
Opens a dialog box to create a directory.
@ SortMenu
An ActionMenu containing all sort-options.
@ SortHiddenFilesLast
Sorts hidden files last.
@ Reload
Reloads the current directory.
@ Back
Goes back to the previous directory.
void fileHighlighted(const KFileItem &item)
Emitted when a file is highlighted or generally the selection changes in multiselection mode.
void viewChanged(QAbstractItemView *newView)
Emitted whenever the current fileview is changed, either by an explicit call to setView() or by the u...
QAction * action(KDirOperator::Action action) const
Obtain a given action from the KDirOperator's set of actions.
void currentIconSizeChanged(int size)
Will notify that the icon size has changed.
virtual void setViewConfig(KConfigGroup &configGroup)
Sets the config object and the to be used group in KDirOperator.
void filterChanged()
This signal is emitted whenever the filter has been changed.
Encapsulates rules to filter a list of files.
QStringList filePatterns() const
List of file name patterns that are included by this filter.
bool isEmpty() const
Whether the filer is empty, i.e. matches all files.
QStringList mimePatterns() const
List of MIME types that are included by this filter;.
A KFileItem is a generic class to handle a file, local or remote.
bool isNull() const
Return true if default-constructed.
This class is a list view model.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Get the children model index for the given row and column.
Q_INVOKABLE QUrl url(const QModelIndex &index) const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Get the number of rows for a model index.
void errorMessage(const QString &message)
message An error message explaining what went wrong.
Generates previews for files of an item view.
QFlags< Mode > Modes
Stores a combination of Mode values.
static void assign(QPushButton *button, const KGuiItem &item)
A KIO job that retrieves information about a file or directory.
const UDSEntry & statResult() const
Result of the stat operation.
QString stringValue(uint field) const
@ UDS_LOCAL_PATH
A local file path if the KIO worker display files sitting on the local filesystem (but in another hie...
static QString removeAcceleratorMarker(const QString &label)
static bool isKnownProtocol(const QUrl &url)
Returns whether a protocol is installed that is able to handle url.
static bool supportsListing(const QUrl &url)
Returns whether the protocol can list files/objects.
static int maximumItems()
Returns the maximum amount of recent document entries allowed.
static void add(const QUrl &url)
Add a new item to the Recent Document menu.
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
static KSharedConfig::Ptr openStateConfig(const QString &fileName=QString())
This combobox shows a number of recent URLs/directories, as well as some default directories.
void setUrls(const QStringList &urls)
Inserts urls into the combobox below the "default urls" (see addDefaultUrl).
void setUrl(const QUrl &url)
Sets the current url.
void setCompletionObject(KCompletion *compObj, bool hsig=true) override
Reimplemented from KComboBox (from KCompletion)
void setMaxItems(int)
Sets how many items should be handled and displayed by the combobox.
This class does completion of URLs including user directories (~user) and environment variables.
QString replacedPath(const QString &text) const
Replaces username and/or environment variables, depending on the current settings and returns the fil...
KUrlComboBox * editor() const
void returnPressed()
This signal is emitted when the Return or Enter key is pressed.
void urlChanged(const QUrl &url)
Is emitted, if the location URL has been changed e.
Q_SCRIPTABLE QString start(QString train="")
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KIOCORE_EXPORT QString iconNameForUrl(const QUrl &url)
Return the icon name for a URL.
KIOCORE_EXPORT StatJob * stat(const QUrl &url, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
KIOCORE_EXPORT QString buildErrorString(int errorCode, const QString &errorText)
Returns a translated error message for errorCode using the additional error information provided by e...
KIOCORE_EXPORT QUrl upUrl(const QUrl &url)
This function is useful to implement the "Up" button in a file manager for example.
@ HideProgressInfo
Hide progress information dialog, i.e. don't show a GUI.
QString path(const QString &relativePath)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
void information(QWidget *parent, const QString &text, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
KIOCORE_EXPORT QString dir(const QString &fileClass)
Returns the most recently used directory associated with this file-class.
KIOCORE_EXPORT QStringList list(const QString &fileClass)
Returns a list of directories associated with this file-class.
KIOCORE_EXPORT void add(const QString &fileClass, const QString &directory)
Associates directory with fileClass.
KCOREADDONS_EXPORT QString tildeExpand(const QString &path)
QAction * create(StandardAction id, const Receiver *recvr, Func slot, QObject *parent, std::optional< Qt::ConnectionType > connectionType=std::nullopt)
QString label(StandardShortcut id)
const QList< QKeySequence > & completion()
const QList< QKeySequence > & createFolder()
bool authorizeUrlAction(const QString &action, const QUrl &baseURL, const QUrl &destURL)
Returns whether a certain URL related action is authorized.
void doubleClicked(const QModelIndex &index)
QAbstractItemModel * model() const const
void sliderMoved(int value)
void valueChanged(int value)
bool isChecked() const const
void setShortcut(const QKeySequence &shortcut)
void toggled(bool checked)
void triggered(bool checked)
void setWhatsThis(const QString &what)
char toLatin1() const const
AdjustToContentsOnFirstShow
void editTextChanged(const QString &text)
QLineEdit * lineEdit() const const
bool sendEvent(QObject *receiver, QEvent *event)
QString cleanPath(const QString &path)
QString fromNativeSeparators(const QString &pathName)
QIcon fromTheme(const QString &name)
void setSelection(int start, int length)
void setText(const QString &)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
bool isEmpty() const const
void prepend(parameter_type value)
void reserve(qsizetype size)
QMimeType mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode) const const
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
QString suffixForFileName(const QString &fileName) const const
bool isValid() const const
bool isValid() const const
bool blockSignals(bool block)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
virtual bool eventFilter(QObject *watched, QEvent *event)
QObject * parent() const const
bool setProperty(const char *name, QVariant &&value)
bool signalsBlocked() const const
QRegularExpressionMatch match(QStringView subjectView, qsizetype offset, MatchType matchType, MatchOptions matchOptions) const const
void setPattern(const QString &pattern)
QString wildcardToRegularExpression(QStringView pattern, WildcardConversionOptions options)
bool hasMatch() const const
QSize boundedTo(const QSize &otherSize) const const
QSize expandedTo(const QSize &otherSize) const const
void splitterMoved(int pos, int index)
QString writableLocation(StandardLocation type)
QString arg(Args &&... args) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & prepend(QChar ch)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QString section(QChar sep, qsizetype start, qsizetype end, SectionFlags flags) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QString join(QChar separator) const const
void chop(qsizetype length)
bool endsWith(QChar ch) const const
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs) const const
qsizetype length() const const
void truncate(qsizetype length)
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
void keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay)
QUrl adjusted(FormattingOptions options) const const
QString fileName(ComponentFormattingOptions options) const const
QUrl fromLocalFile(const QString &localFile)
bool isEmpty() const const
bool isLocalFile() const const
bool isParentOf(const QUrl &childUrl) const const
bool isRelative() const const
bool isValid() const const
bool matches(const QUrl &url, FormattingOptions options) const const
QString path(ComponentFormattingOptions options) const const
QUrl resolved(const QUrl &relative) const const
QString scheme() const const
void setPath(const QString &path, ParsingMode mode)
QString toDisplayString(FormattingOptions options) const const
QString toLocalFile() const const
QString url(FormattingOptions options) const const
QVariant fromValue(T &&value)