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"
25#include "kurlnavigatorbuttonbase_p.h"
27#include <config-kiofilewidgets.h>
29#include <defaults-kfile.h>
30#include <kdiroperator.h>
31#include <kfilefiltercombo.h>
32#include <kfileitemdelegate.h>
34#include <kio/jobuidelegate.h>
35#include <kio/statjob.h>
36#include <kprotocolmanager.h>
37#include <krecentdirs.h>
38#include <krecentdocument.h>
39#include <kurlauthorized.h>
40#include <kurlcompletion.h>
43#include <KConfigGroup>
46#include <KFilePlacesModel>
49#include <KLocalizedString>
51#include <KMessageWidget>
52#include <KSharedConfig>
54#include <KStandardActions>
55#include <KToggleAction>
57#include <QAbstractProxyModel>
58#include <QApplication>
68#include <QLoggingCategory>
70#include <QMimeDatabase>
74#include <QStandardPaths>
80#include <qnamespace.h>
82Q_DECLARE_LOGGING_CATEGORY(KIO_KFILEWIDGETS_FW)
83Q_LOGGING_CATEGORY(KIO_KFILEWIDGETS_FW,
"kf.kio.kfilewidgets.kfilewidget", QtInfoMsg)
85class KFileWidgetPrivate
88 explicit KFileWidgetPrivate(KFileWidget *qq)
95 delete m_bookmarkHandler;
103 QSize screenSize()
const
105 return q->parentWidget() ? q->parentWidget()->screen()->availableGeometry().size()
109 void initDirOpWidgets();
111 void initZoomWidget();
112 void initLocationWidget();
113 void initFilterWidget();
114 void updateLocationWhatsThis();
115 void updateAutoSelectExtension();
116 void initPlacesPanel();
117 void setPlacesViewSplitterSizes();
119 void readViewConfig();
120 void writeViewConfig();
121 void setNonExtSelection();
122 void setLocationText(
const QUrl &);
123 void setLocationText(
const QList<QUrl> &);
124 void appendExtension(QUrl &url);
125 void updateLocationEditExtension(
const QString &);
126 QString findMatchingFilter(
const QString &filter,
const QString &filename)
const;
128 void updateFilterText();
135 QList<QUrl> tokenize(
const QString &line)
const;
139 void readRecentFiles();
143 void saveRecentFiles();
148 void multiSelectionChanged();
153 QUrl getCompleteUrl(
const QString &)
const;
160 bool toOverwrite(
const QUrl &);
163 void slotLocationChanged(
const QString &);
164 void urlEntered(
const QUrl &);
165 void enterUrl(
const QUrl &);
166 void enterUrl(
const QString &);
167 void locationAccepted(
const QString &);
168 void slotFilterChanged();
169 void fileHighlighted(
const KFileItem &);
170 void fileSelected(
const KFileItem &);
171 void slotLoadingFinished();
172 void togglePlacesPanel(
bool show, QObject *sender =
nullptr);
173 void toggleBookmarks(
bool);
174 void slotAutoSelectExtClicked();
175 void placesViewSplitterMoved(
int,
int);
176 void activateUrlNavigator();
182 void changeIconsSize(ZoomState zoom);
183 void slotDirOpIconSizeChanged(
int size);
184 void slotIconSizeSliderMoved(
int);
185 void slotIconSizeChanged(
int);
186 void slotViewDoubleClicked(
const QModelIndex &);
187 void slotViewKeyEnterReturnPressed();
189 void addToRecentDocuments();
191 QString locationEditCurrentText()
const;
198 QUrl mostLocalUrl(
const QUrl &url);
200 void setInlinePreviewShown(
bool show);
202 KFileWidget *
const q;
209 QBoxLayout *m_boxLayout =
nullptr;
210 QFormLayout *m_lafBox =
nullptr;
212 QLabel *m_locationLabel =
nullptr;
213 QWidget *m_opsWidget =
nullptr;
214 QVBoxLayout *m_opsWidgetLayout =
nullptr;
216 QLabel *m_filterLabel =
nullptr;
217 KUrlNavigator *m_urlNavigator =
nullptr;
218 KMessageWidget *m_messageWidget =
nullptr;
219 QPushButton *m_okButton =
nullptr;
220 QPushButton *m_cancelButton =
nullptr;
221 QDockWidget *m_placesDock =
nullptr;
222 KFilePlacesView *m_placesView =
nullptr;
223 QSplitter *m_placesViewSplitter =
nullptr;
227 int m_placesViewWidth = -1;
229 QWidget *m_labeledCustomWidget =
nullptr;
230 QWidget *m_bottomCustomWidget =
nullptr;
233 QCheckBox *m_autoSelectExtCheckBox =
nullptr;
236 QList<QUrl> m_urlList;
243 KFileBookmarkHandler *m_bookmarkHandler =
nullptr;
245 KActionMenu *m_bookmarkButton =
nullptr;
247 QToolBar *m_toolbar =
nullptr;
248 KUrlComboBox *m_locationEdit =
nullptr;
249 KDirOperator *m_ops =
nullptr;
250 KFileFilterCombo *m_filterWidget =
nullptr;
251 QTimer m_filterDelayTimer;
253 KFilePlacesModel *m_model =
nullptr;
256 bool m_autoSelectExtChecked =
false;
260 bool m_keepLocation =
false;
264 bool m_hasView =
false;
266 bool m_hasDefaultFilter =
false;
267 bool m_inAccept =
false;
268 bool m_confirmOverwrite =
false;
269 bool m_differentHierarchyLevelItemsEntered =
false;
271 const std::array<short, 8> m_stdIconSizes = {
282 QSlider *m_iconSizeSlider =
nullptr;
283 QAction *m_zoomOutAction =
nullptr;
284 QAction *m_zoomInAction =
nullptr;
289 KConfigGroup m_configGroup;
290 KConfigGroup m_stateConfigGroup;
292 KToggleAction *m_toggleBookmarksAction =
nullptr;
293 KToggleAction *m_togglePlacesPanelAction =
nullptr;
296Q_GLOBAL_STATIC(
QUrl, lastDirectory)
299static bool containsProtocolSection(
const QString &
string)
301 int len =
string.length();
302 static const char prot[] =
":/";
303 for (
int i = 0; i < len;) {
309 for (; j >= 0; j--) {
310 const QChar &ch(
string[j]);
311 if (ch.toLatin1() == 0 || !ch.isLetter()) {
314 if (ch.isSpace() && (i - j - 1) >= 2) {
318 if (j < 0 && i >= 2) {
330 if (Utils::isAbsoluteLocalPath(str)) {
334 if (url.isRelative()) {
343 , d(new KFileWidgetPrivate(this))
345 QUrl startDir(_startDir);
351 d->m_okButton->setDefault(
true);
355 d->m_okButton->hide();
356 d->m_cancelButton->hide();
358 d->initDirOpWidgets();
362 d->m_url =
getStartUrl(startDir, d->m_fileClass, filename);
365 const auto operatorActions = d->m_ops->allActions();
366 for (
QAction *action : operatorActions) {
373 d->activateUrlNavigator();
391 d->initLocationWidget();
394 d->initFilterWidget();
398 d->m_autoSelectExtCheckBox =
new QCheckBox(
this);
400 d->slotAutoSelectExtClicked();
407 config->reparseConfiguration();
413 if (d->m_configGroup.hasKey(RecentURLs)) {
414 d->m_stateConfigGroup.writeEntry(RecentURLs, d->m_configGroup.readEntry(RecentURLs));
415 d->m_configGroup.revertToDefault(RecentURLs);
418 if (d->m_configGroup.hasKey(RecentFiles)) {
419 d->m_stateConfigGroup.writeEntry(RecentFiles, d->m_configGroup.readEntry(RecentFiles));
420 d->m_configGroup.revertToDefault(RecentFiles);
424 d->readRecentFiles();
426 d->m_ops->action(KDirOperator::ShowPreview)->setChecked(d->m_ops->isInlinePreviewShown());
427 d->slotDirOpIconSizeChanged(d->m_ops->iconSize());
431 d->m_ops->action(KDirOperator::ShowPreview)->setChecked(pg->isPreviewShown());
441 bool statRes =
false;
445 statRes = statJob->
exec();
454 d->m_ops->setUrl(startDir,
true);
455 d->m_urlNavigator->setLocationUrl(startDir);
456 if (d->m_placesView) {
457 d->m_placesView->setUrl(startDir);
463 QLineEdit *lineEdit = d->m_locationEdit->lineEdit();
466 d->setLocationText(
QUrl(filename));
475 d->m_locationEdit->setFocus();
478 Q_ASSERT(showHiddenAction);
479 d->m_urlNavigator->setShowHiddenFolders(showHiddenAction->
isChecked());
481 d->m_urlNavigator->setShowHiddenFolders(checked);
485 Q_ASSERT(hiddenFilesLastAction);
486 d->m_urlNavigator->setSortHiddenFoldersLast(hiddenFilesLastAction->isChecked());
488 d->m_urlNavigator->setSortHiddenFoldersLast(checked);
496 d->m_ops->removeEventFilter(
this);
497 d->m_locationEdit->removeEventFilter(
this);
502 d->m_locationLabel->setText(text);
507 d->m_ops->clearFilter();
508 d->m_filterWidget->setFilters(filters, activeFilter);
509 d->m_ops->updateDir();
510 d->m_hasDefaultFilter =
false;
511 d->m_filterWidget->setEditable(
true);
512 d->updateFilterText();
514 d->updateAutoSelectExtension();
519 return d->m_filterWidget->currentFilter();
525 d->m_ops->clearFilter();
526 d->m_hasDefaultFilter =
false;
527 d->m_filterWidget->setEditable(
true);
529 d->updateAutoSelectExtension();
534 d->m_ops->setPreviewWidget(w);
535 d->m_ops->clearHistory();
539QUrl KFileWidgetPrivate::getCompleteUrl(
const QString &_url)
const
546 if (Utils::isAbsoluteLocalPath(url)) {
549 QUrl relativeUrlTest(m_ops->url());
550 relativeUrlTest.setPath(Utils::concatPaths(relativeUrlTest.path(), url));
570 const QSize goodSize(48 * fontSize, 30 * fontSize);
571 const QSize scrnSize = d->screenSize();
572 const QSize minSize(scrnSize / 2);
573 const QSize maxSize(scrnSize * qreal(0.9));
595 QList<QUrl> locationEditCurrentTextList(d->tokenize(locationEditCurrentText));
599 if (!((
mode & KFile::File) || (
mode & KFile::Directory) || (
mode & KFile::Files))) {
604 const bool directoryMode = (
mode & KFile::Directory);
605 const bool onlyDirectoryMode = directoryMode && !(
mode & KFile::File) && !(
mode & KFile::Files);
608 d->m_urlList.clear();
612 if (locationEditCurrentTextList.
isEmpty() && !onlyDirectoryMode) {
618 if (locationEditCurrentTextList.
count() > 1) {
619 if (
mode & KFile::File) {
644 if (!d->m_differentHierarchyLevelItemsEntered) {
654 while (!res &&
start < locationEditCurrentTextList.
count()) {
655 topMostUrl = locationEditCurrentTextList.
at(
start);
658 res = statJob->
exec();
672 for (
int i =
start; i < locationEditCurrentTextList.
count(); ++i) {
673 QUrl currUrl = locationEditCurrentTextList.
at(i);
676 int res = statJob->
exec();
692 stringList.
reserve(locationEditCurrentTextList.
count());
693 for (
int i = 0; i < locationEditCurrentTextList.
count(); ++i) {
694 Q_ASSERT(topMostUrl.
isParentOf(locationEditCurrentTextList[i]));
695 QString relativePath = relativePathOrUrl(topMostUrl, locationEditCurrentTextList[i]);
696 stringList << escapeDoubleQuotes(std::move(relativePath));
699 d->m_ops->setUrl(topMostUrl,
true);
700 const bool signalsBlocked = d->m_locationEdit->lineEdit()->blockSignals(
true);
701 d->m_locationEdit->lineEdit()->setText(QStringLiteral(
"\"%1\"").arg(stringList.
join(QStringLiteral(
"\" \""))));
704 d->m_differentHierarchyLevelItemsEntered =
true;
711 }
else if (!locationEditCurrentTextList.
isEmpty()) {
720 if (!locationEditCurrentText.
isEmpty() && !onlyDirectoryMode
721 && (Utils::isAbsoluteLocalPath(locationEditCurrentText) || containsProtocolSection(locationEditCurrentText))) {
722 QUrl url = urlFromString(locationEditCurrentText);
725 if (d->m_operationMode == Opening) {
728 int res = statJob->
exec();
734 Utils::appendSlashToPath(url);
742 int res = statJob->
exec();
751 d->m_ops->setUrl(url,
true);
752 const bool signalsBlocked = d->m_locationEdit->lineEdit()->blockSignals(
true);
753 d->m_locationEdit->lineEdit()->setText(fileName);
758 locationEditCurrentTextList = {url};
764 d->m_differentHierarchyLevelItemsEntered =
false;
770 bool filesInList =
false;
771 while (it != locationEditCurrentTextList.
constEnd()) {
774 if (d->m_operationMode == Saving && !directoryMode) {
775 d->appendExtension(url);
781 int res = statJob->
exec();
790 if ((
mode & KFile::LocalOnly) && !d->mostLocalUrl(d->m_url).isLocalFile()) {
798 i18np(
"The selected URL uses an unsupported scheme. "
799 "Please use the following scheme: %2",
800 "The selected URL uses an unsupported scheme. "
801 "Please use one of the following schemes: %2",
804 i18n(
"Unsupported URL scheme"));
813 while (it != locationEditCurrentTextList.
constEnd()) {
817 bool res = checkStatJob->
exec();
820 i18n(
"More than one folder has been selected and this dialog does not accept folders, so it is not possible to decide "
821 "which one to enter. Please select only one folder to list it."),
822 i18n(
"More than one folder provided"));
832 i18n(
"At least one folder and one file has been selected. Selected files will be ignored and the selected folder will be listed"),
833 i18n(
"Files and folders selected"));
835 d->m_ops->setUrl(url,
true);
836 const bool signalsBlocked = d->m_locationEdit->lineEdit()->blockSignals(
true);
837 d->m_locationEdit->lineEdit()->setText(
QString());
840 }
else if (res && onlyDirectoryMode && !statJob->
statResult().
isDir()) {
843 }
else if (!(
mode & KFile::ExistingOnly) || res) {
855 if ((d->m_operationMode == Saving) && d->m_confirmOverwrite && !d->toOverwrite(url)) {
867void KFileWidget::accept()
869 d->m_inAccept =
true;
871 *lastDirectory() = d->m_ops->url();
872 if (!d->m_fileClass.isEmpty()) {
877 d->m_locationEdit->setItemText(0, QString());
880 int atmost = d->m_locationEdit->maxItems();
881 for (
const auto &url : list) {
892 for (
int i = 1; i < d->m_locationEdit->count(); ++i) {
893 if (d->m_locationEdit->itemText(i) == file) {
894 d->m_locationEdit->removeItem(i--);
901 d->m_locationEdit->insertItem(1, file);
904 d->writeViewConfig();
905 d->saveRecentFiles();
907 d->addToRecentDocuments();
909 if (!(
mode() & KFile::Files)) {
916void KFileWidgetPrivate::fileHighlighted(
const KFileItem &i)
918 if ((m_locationEdit->hasFocus() && !m_locationEdit->currentText().isEmpty())) {
922 if (!i.
isNull() && i.isDir() && !(m_ops->mode() & KFile::Directory)) {
926 const bool modified = m_locationEdit->lineEdit()->isModified();
928 if (!(m_ops->mode() & KFile::Files)) {
931 setLocationText(QUrl());
938 if (!m_locationEdit->hasFocus()) {
939 setLocationText(m_url);
942 Q_EMIT q->fileHighlighted(m_url);
944 multiSelectionChanged();
945 Q_EMIT q->selectionChanged();
948 m_locationEdit->lineEdit()->setModified(
false);
955 if (m_operationMode == KFileWidget::Saving) {
956 m_locationEdit->setFocus();
960void KFileWidgetPrivate::fileSelected(
const KFileItem &i)
962 if (!i.
isNull() && i.isDir()) {
966 if (!(m_ops->mode() & KFile::Files)) {
968 setLocationText(QUrl());
971 setLocationText(i.targetUrl());
973 multiSelectionChanged();
974 Q_EMIT q->selectionChanged();
978 if (m_operationMode == KFileWidget::Saving) {
979 m_locationEdit->setFocus();
987void KFileWidgetPrivate::multiSelectionChanged()
989 if (m_locationEdit->hasFocus() && !m_locationEdit->currentText().isEmpty()) {
993 const KFileItemList
list = m_ops->selectedItems();
996 setLocationText(QUrl());
1000 setLocationText(
list.targetUrlList());
1003void KFileWidgetPrivate::setLocationText(
const QUrl &url)
1008 if ((url.
isEmpty() && m_locationEdit->lineEdit()->text().isEmpty()) || m_locationEdit->lineEdit()->text() == escapeDoubleQuotes(url.
fileName())) {
1014 const QSignalBlocker blocker(m_locationEdit);
1020 q->setUrl(directory,
false);
1022 q->setUrl(url,
false);
1025 m_locationEdit->lineEdit()->selectAll();
1026 m_locationEdit->lineEdit()->insert(escapeDoubleQuotes(url.
fileName()));
1027 }
else if (!m_locationEdit->lineEdit()->text().isEmpty()) {
1028 m_locationEdit->clearEditText();
1031 if (m_operationMode == KFileWidget::Saving) {
1032 setNonExtSelection();
1041 relPath.remove(0, basePath.length());
1043 relPath.remove(0, 1);
1054 path.
replace(QStringLiteral(
"\\"), QStringLiteral(
"\\\\"));
1056 path.
replace(QStringLiteral(
"\""), QStringLiteral(
"\\\""));
1060void KFileWidgetPrivate::initDirOpWidgets()
1062 m_opsWidget =
new QWidget(q);
1063 m_opsWidgetLayout =
new QVBoxLayout(m_opsWidget);
1064 m_opsWidgetLayout->setContentsMargins(0, 0, 0, 0);
1065 m_opsWidgetLayout->setSpacing(0);
1067 m_model =
new KFilePlacesModel(q);
1075 m_urlNavigator =
new KUrlNavigator(m_model, QUrl(), m_opsWidget);
1076 m_urlNavigator->setPlacesSelectorVisible(
false);
1083 m_messageWidget =
new KMessageWidget(q);
1085 m_messageWidget->setWordWrap(
true);
1086 m_messageWidget->hide();
1088 auto topSeparator =
new QFrame(q);
1091 m_ops =
new KDirOperator(QUrl(), m_opsWidget);
1092 m_ops->installEventFilter(q);
1093 m_ops->setObjectName(QStringLiteral(
"KFileWidget::ops"));
1094 m_ops->setIsSaving(m_operationMode == KFileWidget::Saving);
1095 m_ops->setNewFileMenuSelectDirWhenAlreadyExist(
true);
1096 m_ops->showOpenWithActions(
true);
1099 auto bottomSparator =
new QFrame(q);
1102 q->connect(m_ops, &KDirOperator::urlEntered, q, [
this](
const QUrl &url) {
1106 fileHighlighted(item);
1108 q->connect(m_ops, &KDirOperator::fileSelected, q, [
this](
const KFileItem &item) {
1111 q->connect(m_ops, &KDirOperator::finishedLoading, q, [
this]() {
1112 slotLoadingFinished();
1115 slotViewKeyEnterReturnPressed();
1119 q->setSelectedUrls(urls);
1126 m_ops->dirLister()->setAutoErrorHandlingEnabled(
false);
1128 m_messageWidget->setText(job->errorString());
1129 m_messageWidget->animatedShow();
1132 m_ops->setupMenu(KDirOperator::SortActions | KDirOperator::FileActions | KDirOperator::ViewActions);
1136 m_opsWidgetLayout->addWidget(m_toolbar);
1137 m_opsWidgetLayout->addWidget(m_urlNavigator);
1138 m_opsWidgetLayout->addWidget(m_messageWidget);
1139 m_opsWidgetLayout->addWidget(topSeparator);
1140 m_opsWidgetLayout->addWidget(m_ops);
1141 m_opsWidgetLayout->addWidget(bottomSparator);
1144void KFileWidgetPrivate::initZoomWidget()
1146 m_iconSizeSlider =
new QSlider(q);
1148 m_iconSizeSlider->setMinimumWidth(40);
1150 m_iconSizeSlider->setMinimum(0);
1151 m_iconSizeSlider->setMaximum(m_stdIconSizes.size() - 1);
1152 m_iconSizeSlider->setSingleStep(1);
1153 m_iconSizeSlider->setPageStep(1);
1157 slotIconSizeChanged(m_stdIconSizes[step]);
1161 slotIconSizeSliderMoved(m_stdIconSizes[step]);
1165 slotDirOpIconSizeChanged(iconSize);
1172 changeIconsSize(ZoomOut);
1176 q->addAction(m_zoomOutAction);
1182 changeIconsSize(ZoomIn);
1186 q->addAction(m_zoomInAction);
1189void KFileWidgetPrivate::initToolbar()
1191 m_toolbar =
new QToolBar(m_opsWidget);
1192 m_toolbar->setObjectName(QStringLiteral(
"KFileWidget::toolbar"));
1193 m_toolbar->setMovable(
false);
1204 ->setWhatsThis(
i18n(
"<qt>Click this button to enter the parent folder.<br /><br />"
1205 "For instance, if the current location is file:/home/konqi clicking this "
1206 "button will take you to file:/home.</qt>"));
1208 m_ops->action(
KDirOperator::Back)->setWhatsThis(
i18n(
"Click this button to move backwards one step in the browsing history."));
1209 m_ops->action(
KDirOperator::Forward)->setWhatsThis(
i18n(
"Click this button to move forward one step in the browsing history."));
1211 m_ops->action(
KDirOperator::Reload)->setWhatsThis(
i18n(
"Click this button to reload the contents of the current location."));
1215 m_togglePlacesPanelAction =
new KToggleAction(
i18n(
"Show Places Panel"), q);
1216 q->addAction(m_togglePlacesPanelAction);
1217 m_togglePlacesPanelAction->setShortcut(QKeySequence(
Qt::Key_F9));
1218 q->connect(m_togglePlacesPanelAction, &
QAction::toggled, q, [
this](
bool show) {
1219 togglePlacesPanel(show);
1222 m_toggleBookmarksAction =
new KToggleAction(
i18n(
"Show Bookmarks Button"), q);
1223 q->addAction(m_toggleBookmarksAction);
1224 q->connect(m_toggleBookmarksAction, &
QAction::toggled, q, [
this](
bool show) {
1225 toggleBookmarks(show);
1229 KActionMenu *menu =
new KActionMenu(
QIcon::fromTheme(QStringLiteral(
"configure")),
i18n(
"Options"), q);
1232 i18n(
"<qt>This is the preferences menu for the file dialog. "
1233 "Various options can be accessed from this menu including: <ul>"
1234 "<li>how files are sorted in the list</li>"
1235 "<li>types of view, including icon and list</li>"
1236 "<li>showing of hidden files</li>"
1237 "<li>the Places panel</li>"
1238 "<li>file previews</li>"
1239 "<li>separating folders from files</li></ul></qt>"));
1241 menu->
addAction(m_ops->action(KDirOperator::AllowExpansionInDetailsView));
1242 menu->addSeparator();
1244 menu->
addAction(m_togglePlacesPanelAction);
1245 menu->
addAction(m_toggleBookmarksAction);
1251 m_bookmarkButton =
new KActionMenu(
QIcon::fromTheme(QStringLiteral(
"bookmarks")),
i18n(
"Bookmarks"), q);
1253 q->addAction(m_bookmarkButton);
1254 m_bookmarkButton->setWhatsThis(
1255 i18n(
"<qt>This button allows you to bookmark specific locations. "
1256 "Click on this button to open the bookmark menu where you may add, "
1257 "edit or select a bookmark.<br /><br />"
1258 "These bookmarks are specific to the file dialog, but otherwise operate "
1259 "like bookmarks elsewhere in KDE.</qt>"));
1261 QWidget *midSpacer =
new QWidget(q);
1268 m_toolbar->addSeparator();
1269 m_toolbar->addAction(m_ops->action(KDirOperator::ViewIconsView));
1270 m_toolbar->addAction(m_ops->action(KDirOperator::ViewCompactView));
1271 m_toolbar->addAction(m_ops->action(KDirOperator::ViewDetailsView));
1272 m_toolbar->addSeparator();
1273 m_toolbar->addAction(m_ops->action(KDirOperator::ShowPreview));
1275 m_toolbar->addAction(m_bookmarkButton);
1277 m_toolbar->addWidget(midSpacer);
1280 m_toolbar->addAction(m_zoomOutAction);
1281 m_toolbar->addWidget(m_iconSizeSlider);
1282 m_toolbar->addAction(m_zoomInAction);
1283 m_toolbar->addSeparator();
1286 m_toolbar->addAction(menu);
1289 m_toolbar->setMovable(
false);
1292void KFileWidgetPrivate::initLocationWidget()
1294 m_locationLabel =
new QLabel(
i18n(
"&Name:"), q);
1295 m_locationEdit =
new KUrlComboBox(KUrlComboBox::Files,
true, q);
1296 m_locationEdit->installEventFilter(q);
1302 slotLocationChanged(text);
1306 m_locationEdit->lineEdit()->setClearButtonEnabled(
false);
1308 QAction *clearAction =
new QAction(
QIcon::fromTheme(QStringLiteral(
"edit-clear")), {}, m_locationEdit->lineEdit());
1313 clearAction->setVisible(m_locationEdit->lineEdit()->text().length() > 0);
1316 QAction *undoAction =
new QAction(
QIcon::fromTheme(QStringLiteral(
"edit-undo")),
i18nc(
"@info:tooltip",
"Undo filename change"), m_locationEdit->lineEdit());
1321 undoAction->setVisible(m_locationEdit->lineEdit()->isUndoAvailable());
1324 updateLocationWhatsThis();
1325 m_locationLabel->setBuddy(m_locationEdit);
1327 KUrlCompletion *fileCompletionObj =
new KUrlCompletion(KUrlCompletion::FileCompletion);
1328 m_locationEdit->setCompletionObject(fileCompletionObj);
1329 m_locationEdit->setAutoDeleteCompletionObject(
true);
1332 locationAccepted(text);
1336void KFileWidgetPrivate::initFilterWidget()
1338 m_filterLabel =
new QLabel(q);
1339 m_filterWidget =
new KFileFilterCombo(q);
1346 m_filterLabel->setBuddy(m_filterWidget);
1348 slotFilterChanged();
1351 m_filterDelayTimer.setSingleShot(
true);
1352 m_filterDelayTimer.setInterval(300);
1355 slotFilterChanged();
1359void KFileWidgetPrivate::setLocationText(
const QList<QUrl> &urlList)
1364 const QSignalBlocker blocker(m_locationEdit);
1366 const QUrl baseUrl = m_ops->
url();
1368 if (urlList.
count() > 1) {
1370 for (
const QUrl &url : urlList) {
1371 urls += QStringLiteral(
"\"%1\" ").
arg(escapeDoubleQuotes(relativePathOrUrl(baseUrl, url)));
1375 m_locationEdit->lineEdit()->selectAll();
1376 m_locationEdit->lineEdit()->insert(urls);
1377 }
else if (urlList.count() == 1) {
1378 const auto url = urlList[0];
1379 m_locationEdit->lineEdit()->selectAll();
1380 m_locationEdit->lineEdit()->insert(escapeDoubleQuotes(relativePathOrUrl(baseUrl, url)));
1381 }
else if (!m_locationEdit->lineEdit()->text().isEmpty()) {
1382 m_locationEdit->clearEditText();
1385 if (m_operationMode == KFileWidget::Saving) {
1386 setNonExtSelection();
1390void KFileWidgetPrivate::updateLocationWhatsThis()
1392 const QString autocompletionWhatsThisText =
i18n(
1393 "<qt>While typing in the text area, you may be presented "
1394 "with possible matches. "
1395 "This feature can be controlled by clicking with the right mouse button "
1396 "and selecting a preferred mode from the <b>Text Completion</b> menu.</qt>");
1398 QString whatsThisText;
1399 if (m_operationMode == KFileWidget::Saving) {
1400 whatsThisText = QLatin1String(
"<qt>") +
i18n(
"This is the name to save the file as.") + autocompletionWhatsThisText;
1401 }
else if (m_ops->mode() & KFile::Files) {
1402 whatsThisText = QLatin1String(
"<qt>")
1403 +
i18n(
"This is the list of files to open. More than "
1404 "one file can be specified by listing several "
1405 "files, separated by spaces.")
1406 + autocompletionWhatsThisText;
1408 whatsThisText = QLatin1String(
"<qt>") +
i18n(
"This is the name of the file to open.") + autocompletionWhatsThisText;
1411 m_locationLabel->setWhatsThis(whatsThisText);
1412 m_locationEdit->setWhatsThis(whatsThisText);
1415void KFileWidgetPrivate::initPlacesPanel()
1421 m_placesDock =
new QDockWidget(
i18nc(
"@title:window",
"Places"), q);
1423 m_placesDock->setTitleBarWidget(
new KDEPrivate::KFileWidgetDockTitleBar(m_placesDock));
1425 m_placesView =
new KFilePlacesView(m_placesDock);
1426 m_placesView->setModel(m_model);
1429 m_placesView->setObjectName(QStringLiteral(
"url bar"));
1430 QObject::connect(m_placesView, &KFilePlacesView::urlChanged, q, [
this](
const QUrl &url) {
1435 m_messageWidget->setText(errorMessage);
1436 m_messageWidget->animatedShow();
1443 m_placesView->setUrl(m_url);
1445 m_placesDock->setWidget(m_placesView);
1446 m_placesViewSplitter->insertWidget(0, m_placesDock);
1449 m_placesViewWidth = m_configGroup.readEntry(SpeedbarWidth, m_placesView->sizeHint().width());
1452 setPlacesViewSplitterSizes();
1455 togglePlacesPanel(visible, m_placesDock);
1459void KFileWidgetPrivate::setPlacesViewSplitterSizes()
1461 if (m_placesViewWidth > 0) {
1462 QList<int> sizes = m_placesViewSplitter->sizes();
1463 sizes[0] = m_placesViewWidth;
1464 sizes[1] = q->width() - m_placesViewWidth - m_placesViewSplitter->handleWidth();
1465 m_placesViewSplitter->setSizes(sizes);
1469void KFileWidgetPrivate::initGUI()
1473 m_boxLayout =
new QVBoxLayout(q);
1474 m_boxLayout->setContentsMargins(0, 0, 0, 0);
1476 m_placesViewSplitter =
new QSplitter(q);
1478 m_placesViewSplitter->setChildrenCollapsible(
false);
1479 m_boxLayout->addWidget(m_placesViewSplitter);
1482 placesViewSplitterMoved(pos, index);
1484 m_placesViewSplitter->insertWidget(0, m_opsWidget);
1486 m_lafBox =
new QFormLayout();
1493 m_lafBox->addRow(m_locationLabel, m_locationEdit);
1494 m_lafBox->addRow(m_filterLabel, m_filterWidget);
1496 m_lafBox->addWidget(m_autoSelectExtCheckBox);
1498 m_opsWidgetLayout->addLayout(m_lafBox);
1500 auto hbox =
new QHBoxLayout();
1507 hbox->addStretch(2);
1508 hbox->addWidget(m_okButton);
1509 hbox->addWidget(m_cancelButton);
1511 m_opsWidgetLayout->addLayout(hbox);
1513 auto updateTabOrder = [
this]() {
1515 q->setTabOrder(m_urlNavigator, m_ops);
1517 q->setTabOrder(m_ops, m_autoSelectExtCheckBox);
1518 q->setTabOrder(m_autoSelectExtCheckBox, m_locationEdit);
1519 q->setTabOrder(m_locationEdit, m_filterWidget);
1520 q->setTabOrder(m_filterWidget, m_okButton);
1521 q->setTabOrder(m_okButton, m_cancelButton);
1522 q->setTabOrder(m_cancelButton, m_placesView);
1525 const auto toolbarChildren = m_toolbar->children();
1526 QList<QWidget *> toolbarButtons;
1527 for (QObject *obj : std::as_const(toolbarChildren)) {
1528 if (
auto *button = qobject_cast<QToolButton *>(obj)) {
1531 toolbarButtons << button;
1532 }
else if (
auto *slider = qobject_cast<QSlider *>(obj)) {
1533 toolbarButtons << slider;
1537 q->setTabOrder(m_placesView, toolbarButtons.
first());
1541 while (nextIt != toolbarButtons.
constEnd()) {
1542 q->setTabOrder(*it, *nextIt);
1552void KFileWidgetPrivate::slotFilterChanged()
1554 m_filterDelayTimer.stop();
1556 KFileFilter
filter = m_filterWidget->currentFilter();
1558 m_ops->clearFilter();
1560 if (!
filter.mimePatterns().isEmpty()) {
1561 QStringList types =
filter.mimePatterns();
1562 types.
prepend(QStringLiteral(
"inode/directory"));
1563 m_ops->setMimeFilter(types);
1566 const auto filePatterns =
filter.filePatterns();
1567 const bool hasRegExSyntax = std::any_of(filePatterns.constBegin(), filePatterns.constEnd(), [](
const QString &filter) {
1568 return filter.contains(QLatin1Char(
'*')) || filter.contains(QLatin1Char(
'?')) || filter.contains(QLatin1Char(
'['));
1571 if (hasRegExSyntax) {
1572 m_ops->setNameFilter(
filter.filePatterns().join(QLatin1Char(
' ')));
1574 m_ops->setNameFilter(QLatin1Char(
'*') + filePatterns.join(QLatin1Char(
'*')) + QLatin1Char(
'*'));
1577 updateAutoSelectExtension();
1581 Q_EMIT q->filterChanged(filter);
1588 d->m_ops->setUrl(url, clearforward);
1592void KFileWidgetPrivate::urlEntered(
const QUrl &url)
1597 if (pathCombo->
count() != 0) {
1602 if (m_keepLocation) {
1603 const QUrl currentUrl = urlFromString(locationEditCurrentText());
1607 m_locationEdit->lineEdit()->setModified(
true);
1610 m_locationEdit->blockSignals(blocked);
1612 m_urlNavigator->setLocationUrl(url);
1615 KUrlCompletion *
completion =
dynamic_cast<KUrlCompletion *
>(m_locationEdit->completionObject());
1621 m_placesView->setUrl(url);
1624 m_messageWidget->hide();
1627void KFileWidgetPrivate::locationAccepted(
const QString &url)
1634void KFileWidgetPrivate::enterUrl(
const QUrl &url)
1641 Utils::appendSlashToPath(u);
1648 if (q->window()->focusWidget() != m_locationEdit) {
1653void KFileWidgetPrivate::enterUrl(
const QString &url)
1660bool KFileWidgetPrivate::toOverwrite(
const QUrl &url)
1666 bool res = statJob->
exec();
1670 i18n(
"The file \"%1\" already exists. Do you wish to overwrite it?", url.
fileName()),
1671 i18n(
"Overwrite File?"),
1678 m_locationEdit->setFocus();
1679 setNonExtSelection();
1695 d->setLocationText(url);
1708 d->setLocationText(urls);
1711void KFileWidgetPrivate::slotLoadingFinished()
1718 m_ops->blockSignals(
true);
1719 QUrl u(m_ops->url());
1720 if (currentText.
startsWith(QLatin1Char(
'/'))) {
1723 u.
setPath(Utils::concatPaths(m_ops->url().path(), currentText));
1725 m_ops->setCurrentItem(u);
1726 m_ops->blockSignals(
false);
1729void KFileWidgetPrivate::slotLocationChanged(
const QString &text)
1733 m_locationEdit->lineEdit()->setModified(
true);
1735 if (text.
isEmpty() && m_ops->view()) {
1736 m_ops->view()->clearSelection();
1739 if (!m_locationEdit->lineEdit()->text().isEmpty()) {
1740 const QList<QUrl> urlList(tokenize(text));
1741 m_ops->setCurrentItems(urlList);
1751 if (d->m_inAccept) {
1763 if (d->m_inAccept) {
1764 if (d->m_ops->mode() & KFile::Files) {
1765 list = d->m_urlList;
1775 qCDebug(KIO_KFILEWIDGETS_FW) <<
"Tokenizing:" << line;
1779 Utils::appendSlashToPath(baseUrl);
1783 auto addUrl = [baseUrl, &urls](
const QString &partial_name) {
1784 if (partial_name.trimmed().isEmpty()) {
1789 QUrl partial_url(partial_name);
1790 if (!partial_url.isValid()
1791 || partial_url.isRelative()
1793 || (!partial_url.scheme().isEmpty() && (!partial_name.contains(QStringLiteral(
"://")) || !
KProtocolInfo::isKnownProtocol(partial_url.scheme())))) {
1796 partial_url.clear();
1797 partial_url.setPath(partial_name);
1802 if (partial_url.isRelative() || baseUrl.
isParentOf(partial_url)) {
1803 partial_url = baseUrl.
resolved(partial_url);
1806 if (partial_url.isValid()) {
1807 urls.
append(partial_url);
1810 qCDebug(KIO_KFILEWIDGETS_FW) <<
"Discarding Invalid" << partial_url;
1817 QString partial_name;
1818 bool escape =
false;
1819 for (
int i = 0; i < line.
length(); i++) {
1820 const QChar ch = line[i];
1838 addUrl(partial_name);
1839 partial_name.
clear();
1850 if (!partial_name.
isEmpty()) {
1851 addUrl(partial_name);
1852 partial_name.
clear();
1862 if (d->m_inAccept) {
1863 const QUrl url = d->mostLocalUrl(d->m_url);
1879 if (d->m_inAccept) {
1880 if (d->m_ops->mode() & KFile::Files) {
1882 for (
const auto &u : urls) {
1883 const QUrl url = d->mostLocalUrl(u);
1891 if (d->m_url.isLocalFile()) {
1892 list.
append(d->m_url.toLocalFile());
1902 return d->m_ops->
url();
1909 if (d->m_placesDock) {
1912 d->setPlacesViewSplitterSizes();
1916void KFileWidget::showEvent(
QShowEvent *event)
1918 if (!d->m_hasView) {
1921 d->m_ops->setViewMode(KFile::Default);
1922 d->m_hasView =
true;
1925 d->slotViewDoubleClicked(index);
1928 d->m_ops->clearHistory();
1933bool KFileWidget::eventFilter(
QObject *watched,
QEvent *event)
1942 const auto type =
event->type();
1959 d->m_ops->setMode(m);
1960 if (d->m_ops->dirOnlyMode()) {
1961 d->m_filterWidget->setDefaultFilter(
KFileFilter(
i18n(
"All Folders"), {QStringLiteral(
"*")}, {}));
1963 d->m_filterWidget->setDefaultFilter(
KFileFilter(
i18n(
"All Files"), {QStringLiteral(
"*")}, {}));
1966 d->updateAutoSelectExtension();
1971 return d->m_ops->mode();
1974void KFileWidgetPrivate::readViewConfig()
1988 m_locationEdit->setCompletionMode(cm);
1992 togglePlacesPanel(m_configGroup.readEntry(ShowSpeedbar,
true));
1995 toggleBookmarks(m_configGroup.readEntry(ShowBookmarks,
false));
1998 m_autoSelectExtChecked = m_configGroup.readEntry(AutoSelectExtChecked, DefaultAutoSelectExtChecked);
1999 updateAutoSelectExtension();
2002 m_urlNavigator->setUrlEditable(!m_configGroup.readEntry(BreadcrumbNavigation,
true));
2005 m_urlNavigator->setShowFullPath(m_configGroup.readEntry(ShowFullPath,
false));
2007 int w1 = q->minimumSize().width();
2008 int w2 = m_toolbar->sizeHint().width();
2010 q->setMinimumWidth(w2);
2014void KFileWidgetPrivate::writeViewConfig()
2022 KConfigGroup tmpGroup(&tmp, ConfigGroup);
2024 KUrlComboBox *pathCombo = m_urlNavigator->editor();
2026 tmpGroup.writeEntry(PathComboCompletionMode,
static_cast<int>(pathCombo->
completionMode()));
2027 tmpGroup.writeEntry(LocationComboCompletionMode,
static_cast<int>(m_locationEdit->completionMode()));
2029 const bool showPlacesPanel = m_placesDock && !m_placesDock->
isHidden();
2030 tmpGroup.writeEntry(ShowSpeedbar, showPlacesPanel);
2031 if (m_placesViewWidth > 0) {
2032 tmpGroup.writeEntry(SpeedbarWidth, m_placesViewWidth);
2035 tmpGroup.writeEntry(ShowBookmarks, m_bookmarkHandler !=
nullptr);
2036 tmpGroup.writeEntry(AutoSelectExtChecked, m_autoSelectExtChecked);
2037 tmpGroup.writeEntry(BreadcrumbNavigation, !m_urlNavigator->isUrlEditable());
2038 tmpGroup.writeEntry(ShowFullPath, m_urlNavigator->showFullPath());
2040 m_ops->writeConfig(tmpGroup);
2046void KFileWidgetPrivate::readRecentFiles()
2050 const bool oldState = m_locationEdit->blockSignals(
true);
2051 m_locationEdit->setMaxItems(m_configGroup.readEntry(RecentFilesNumber, DefaultRecentURLsNumber));
2052 m_locationEdit->setUrls(m_stateConfigGroup.readPathEntry(RecentFiles, QStringList()), KUrlComboBox::RemoveBottom);
2053 m_locationEdit->setCurrentIndex(-1);
2054 m_locationEdit->blockSignals(oldState);
2056 KUrlComboBox *combo = m_urlNavigator->editor();
2057 combo->
setUrls(m_stateConfigGroup.readPathEntry(RecentURLs, QStringList()), KUrlComboBox::RemoveTop);
2058 combo->
setMaxItems(m_configGroup.readEntry(RecentURLsNumber, DefaultRecentURLsNumber));
2059 combo->
setUrl(m_ops->url());
2062 KUrlCompletion *
completion =
dynamic_cast<KUrlCompletion *
>(m_locationEdit->completionObject());
2068void KFileWidgetPrivate::saveRecentFiles()
2071 m_stateConfigGroup.writePathEntry(RecentFiles, m_locationEdit->urls());
2073 KUrlComboBox *pathCombo = m_urlNavigator->editor();
2074 m_stateConfigGroup.writePathEntry(RecentURLs, pathCombo->urls());
2079 return d->m_okButton;
2084 return d->m_cancelButton;
2088void KFileWidget::slotCancel()
2090 d->writeViewConfig();
2096 d->m_keepLocation = keep;
2101 return d->m_keepLocation;
2108 d->m_operationMode =
mode;
2109 d->m_keepLocation = (
mode == Saving);
2110 d->m_filterWidget->setEditable(!d->m_hasDefaultFilter ||
mode != Saving);
2111 if (
mode == Opening) {
2113 d->m_okButton->setText(
i18n(
"&Open"));
2118 }
else if (
mode == Saving) {
2120 d->setNonExtSelection();
2124 d->updateLocationWhatsThis();
2125 d->updateAutoSelectExtension();
2128 d->m_ops->setIsSaving(
mode == Saving);
2130 d->updateFilterText();
2135 return d->m_operationMode;
2138void KFileWidgetPrivate::slotAutoSelectExtClicked()
2144 m_autoSelectExtChecked = m_autoSelectExtCheckBox->
isChecked();
2147 updateLocationEditExtension(m_extension );
2150void KFileWidgetPrivate::placesViewSplitterMoved(
int pos,
int index)
2156 if (m_placesDock && index == 1) {
2157 m_placesViewWidth = pos;
2162void KFileWidgetPrivate::activateUrlNavigator()
2166 QLineEdit *lineEdit = m_urlNavigator->editor()->lineEdit();
2171 m_urlNavigator->setUrlEditable(
false);
2173 m_urlNavigator->setUrlEditable(
true);
2174 m_urlNavigator->setFocus();
2179void KFileWidgetPrivate::slotDirOpIconSizeChanged(
int size)
2181 auto beginIt = m_stdIconSizes.cbegin();
2182 auto endIt = m_stdIconSizes.cend();
2183 auto it = std::lower_bound(beginIt, endIt, size);
2184 const int sliderStep = it != endIt ? it - beginIt : 0;
2185 m_iconSizeSlider->setValue(sliderStep);
2186 m_zoomOutAction->setDisabled(it == beginIt);
2187 m_zoomInAction->setDisabled(it == (endIt - 1));
2190void KFileWidgetPrivate::changeIconsSize(ZoomState zoom)
2192 int step = m_iconSizeSlider->value();
2194 if (zoom == ZoomOut) {
2200 if (step ==
static_cast<int>(m_stdIconSizes.size() - 1)) {
2206 m_iconSizeSlider->setValue(step);
2207 slotIconSizeSliderMoved(m_stdIconSizes[step]);
2210void KFileWidgetPrivate::slotIconSizeChanged(
int _value)
2212 m_ops->setIconSize(_value);
2213 m_iconSizeSlider->setToolTip(
i18n(
"Icon size: %1 pixels", _value));
2216void KFileWidgetPrivate::slotIconSizeSliderMoved(
int size)
2220 slotIconSizeChanged(size);
2222 QPoint global(m_iconSizeSlider->rect().topLeft());
2223 global.ry() += m_iconSizeSlider->height() / 2;
2224 QHelpEvent toolTipEvent(
QEvent::ToolTip, QPoint(0, 0), m_iconSizeSlider->mapToGlobal(global));
2228void KFileWidgetPrivate::slotViewDoubleClicked(
const QModelIndex &index)
2231 if (m_operationMode == KFileWidget::Saving && index.
isValid() && m_ops->selectedItems().constFirst().isFile()) {
2236void KFileWidgetPrivate::slotViewKeyEnterReturnPressed()
2240 if (m_operationMode == KFileWidget::Saving && (m_ops->mode() & KFile::File) && m_ops->selectedItems().isEmpty()) {
2289void KFileWidgetPrivate::updateAutoSelectExtension()
2291 if (!m_autoSelectExtCheckBox) {
2304 QString lastExtension = m_extension;
2305 m_extension.
clear();
2308 if ((m_operationMode == KFileWidget::Saving) && (m_ops->mode() & KFile::File)) {
2313 KFileFilter fileFilter = m_filterWidget->currentFilter();
2319 if (currentExtension.
isEmpty()) {
2320 currentExtension = locationEditCurrentText().
section(QLatin1Char(
'.'), -1, -1);
2324 QString defaultExtension;
2325 QStringList extensionList;
2330 defaultExtension = getExtensionFromPatternList(extensionList);
2338 if (!defaultExtension.
isEmpty()) {
2339 defaultExtension.
prepend(QLatin1Char(
'.'));
2344 if ((!currentExtension.
isEmpty() && extensionList.
contains(QLatin1String(
"*.") + currentExtension))
2346 m_extension = QLatin1Char(
'.') + currentExtension;
2348 m_extension = defaultExtension;
2358 QString whatsThisExtension;
2359 if (!m_extension.isEmpty()) {
2361 m_autoSelectExtCheckBox->setText(
i18n(
"Automatically select filename e&xtension (%1)", m_extension));
2362 whatsThisExtension =
i18n(
"the extension <b>%1</b>", m_extension);
2364 m_autoSelectExtCheckBox->setEnabled(
true);
2365 m_autoSelectExtCheckBox->setChecked(m_autoSelectExtChecked);
2368 m_autoSelectExtCheckBox->setText(
i18n(
"Automatically select filename e&xtension"));
2369 whatsThisExtension =
i18n(
"a suitable extension");
2371 m_autoSelectExtCheckBox->setChecked(
false);
2372 m_autoSelectExtCheckBox->setEnabled(
false);
2375 const QString locationLabelText = stripUndisplayable(m_locationLabel->text());
2376 m_autoSelectExtCheckBox->setWhatsThis(QLatin1String(
"<qt>")
2377 +
i18n(
"This option enables some convenient features for "
2378 "saving files with extensions:<br />"
2380 "<li>Any extension specified in the <b>%1</b> text "
2381 "area will be updated if you change the file type "
2384 "<li>If no extension is specified in the <b>%2</b> "
2385 "text area when you click "
2386 "<b>Save</b>, %3 will be added to the end of the "
2387 "filename (if the filename does not already exist). "
2388 "This extension is based on the file type that you "
2389 "have chosen to save in.<br />"
2391 "If you do not want KDE to supply an extension for the "
2392 "filename, you can either turn this option off or you "
2393 "can suppress it by adding a period (.) to the end of "
2394 "the filename (the period will be automatically "
2398 "If unsure, keep this option enabled as it makes your "
2399 "files more manageable.",
2403 + QLatin1String(
"</qt>"));
2405 m_autoSelectExtCheckBox->show();
2408 updateLocationEditExtension(lastExtension);
2412 m_autoSelectExtCheckBox->setChecked(
false);
2413 m_autoSelectExtCheckBox->hide();
2420void KFileWidgetPrivate::updateLocationEditExtension(
const QString &lastExtension)
2422 if (!m_autoSelectExtCheckBox->isChecked() || m_extension.isEmpty()) {
2426 const QString urlStr = locationEditCurrentText();
2431 const int fileNameOffset = urlStr.
lastIndexOf(QLatin1Char(
'/')) + 1;
2432 QStringView fileName = QStringView(urlStr).mid(fileNameOffset);
2434 const int dot = fileName.
lastIndexOf(QLatin1Char(
'.'));
2435 const int len = fileName.
length();
2440 const QUrl url = getCompleteUrl(urlStr);
2445 bool result = statJob->
exec();
2464 }
else if (!m_extension.isEmpty() && fileName.
endsWith(m_extension)) {
2465 fileName.
chop(m_extension.length());
2471 const QString newText = QStringView(urlStr).left(fileNameOffset) + fileName + m_extension;
2472 if (newText != locationEditCurrentText()) {
2473 const int idx = m_locationEdit->currentIndex();
2475 m_locationEdit->lineEdit()->selectAll();
2476 m_locationEdit->lineEdit()->insert(newText);
2478 m_locationEdit->setItemText(idx, newText);
2480 m_locationEdit->lineEdit()->setModified(
true);
2490 QRegularExpression rx;
2491 for (
const QString &p : patterns) {
2502void KFileWidgetPrivate::updateFilter()
2504 if ((m_operationMode == KFileWidget::Saving) && (m_ops->mode() & KFile::File)) {
2505 QString urlStr = locationEditCurrentText();
2513 bool matchesCurrentFilter = [
this, urlMimeType, urlStr] {
2514 const KFileFilter
filter = m_filterWidget->currentFilter();
2515 if (
filter.mimePatterns().contains(urlMimeType.
name())) {
2519 QString filename = urlStr.
mid(urlStr.
lastIndexOf(QLatin1Char(
'/')) + 1);
2521 const auto filePatterns =
filter.filePatterns();
2522 const bool hasMatch = std::any_of(filePatterns.cbegin(), filePatterns.cend(), [filename](
const QString &pattern) {
2523 QRegularExpression rx(QRegularExpression::wildcardToRegularExpression(pattern));
2525 return rx.match(filename).hasMatch();
2530 if (matchesCurrentFilter) {
2534 const auto filters = m_filterWidget->filters();
2536 auto filterIt = std::find_if(filters.cbegin(), filters.cend(), [urlStr, urlMimeType](
const KFileFilter &filter) {
2537 if (filter.mimePatterns().contains(urlMimeType.name())) {
2541 QString filename = urlStr.
mid(urlStr.
lastIndexOf(QLatin1Char(
'/')) + 1);
2544 const auto filePatterns =
filter.filePatterns();
2545 const bool hasMatch = std::any_of(filePatterns.cbegin(), filePatterns.cend(), [filename](
const QString &pattern) {
2547 if (pattern == QLatin1String(
"*")) {
2553 return rx.
match(filename).hasMatch();
2559 if (filterIt != filters.cend()) {
2560 m_filterWidget->setCurrentFilter(*filterIt);
2566void KFileWidgetPrivate::appendExtension(
QUrl &url)
2570 if (!m_autoSelectExtCheckBox->isChecked() || m_extension.isEmpty()) {
2581 const int len = fileName.
length();
2582 const int dot = fileName.
lastIndexOf(QLatin1Char(
'.'));
2584 const bool suppressExtension = (dot == len - 1);
2585 const bool unspecifiedExtension = !fileName.
endsWith(m_extension);
2588 if (!(suppressExtension || unspecifiedExtension)) {
2595 bool res = statJob->
exec();
2602 if (suppressExtension) {
2619 else if (unspecifiedExtension) {
2628void KFileWidgetPrivate::addToRecentDocuments()
2630 int m = m_ops->mode();
2634 if (m & KFile::LocalOnly) {
2635 const QStringList files = q->selectedFiles();
2637 for (; it != files.
end() && atmost > 0; ++it) {
2644 const QList<QUrl> urls = q->selectedUrls();
2646 for (; it != urls.
end() && atmost > 0; ++it) {
2647 if ((*it).isValid()) {
2657 return d->m_locationEdit;
2662 return d->m_filterWidget;
2665void KFileWidgetPrivate::togglePlacesPanel(
bool show,
QObject *sender)
2669 m_placesDock->
show();
2675 for (
int rowIndex = 0; rowIndex < model->
rowCount(); rowIndex++) {
2685 if (sender == m_placesDock && m_placesDock && m_placesDock->isVisibleTo(q)) {
2692 m_placesDock->hide();
2697 if (!m_toolbar->actions().contains(homeAction)) {
2698 m_toolbar->insertAction(reloadAction, homeAction);
2702 m_togglePlacesPanelAction->setChecked(show);
2705 m_urlNavigator->setPlacesSelectorVisible(!show);
2708void KFileWidgetPrivate::toggleBookmarks(
bool show)
2711 if (m_bookmarkHandler) {
2714 m_bookmarkHandler =
new KFileBookmarkHandler(q);
2715 q->connect(m_bookmarkHandler, &KFileBookmarkHandler::openUrl, q, [
this](
const QString &path) {
2718 m_bookmarkButton->setMenu(m_bookmarkHandler->menu());
2719 }
else if (m_bookmarkHandler) {
2720 m_bookmarkButton->setMenu(
nullptr);
2721 delete m_bookmarkHandler;
2722 m_bookmarkHandler =
nullptr;
2725 if (m_bookmarkButton) {
2726 m_bookmarkButton->setVisible(show);
2729 m_toggleBookmarksAction->setChecked(show);
2736 return getStartUrl(startDir, recentDirClass, fileName);
2742 recentDirClass.
clear();
2746 bool useDefaultStartDir = startDir.
isEmpty();
2747 if (!useDefaultStartDir) {
2765 keyword = urlDir.
mid(1);
2770 recentDirClass = query.arg(keyword);
2786 useDefaultStartDir =
true;
2791 useDefaultStartDir =
true;
2796 if (useDefaultStartDir) {
2797 if (lastDirectory()->isEmpty()) {
2806 || !
QDir(lastDirectory()->toLocalFile()).exists()) {
2810 ret = *lastDirectory();
2820 *lastDirectory() = directory;
2824void KFileWidgetPrivate::setNonExtSelection()
2827 QString filename = locationEditCurrentText();
2834 int lastDot = filename.
lastIndexOf(QLatin1Char(
'.'));
2836 m_locationEdit->lineEdit()->setSelection(0, lastDot);
2838 m_locationEdit->lineEdit()->selectAll();
2845void KFileWidgetPrivate::updateFilterText()
2848 QString whatsThisText;
2850 if (m_operationMode == KFileWidget::Saving && !m_filterWidget->currentFilter().mimePatterns().isEmpty()) {
2852 whatsThisText =
i18n(
"<qt>This is the file type selector. It is used to select the format that the file will be saved as.</qt>");
2855 whatsThisText =
i18n(
2856 "<qt>This is the filter to apply to the file list. "
2857 "File names that do not match the filter will not be shown.<p>"
2858 "You may select from one of the preset filters in the "
2859 "drop down menu, or you may enter a custom filter "
2860 "directly into the text area.</p><p>"
2861 "Wildcards such as * and ? are allowed.</p></qt>");
2864 if (m_filterLabel) {
2865 m_filterLabel->setText(label);
2866 m_filterLabel->setWhatsThis(whatsThisText);
2868 if (m_filterWidget) {
2869 m_filterWidget->setWhatsThis(whatsThisText);
2875 delete d->m_bottomCustomWidget;
2876 d->m_bottomCustomWidget = widget;
2881 d->m_bottomCustomWidget->
setParent(
this);
2883 d->m_opsWidgetLayout->addWidget(d->m_bottomCustomWidget);
2890 setTabOrder(d->m_cancelButton, d->m_bottomCustomWidget);
2891 setTabOrder(d->m_bottomCustomWidget, d->m_urlNavigator);
2896 delete d->m_labeledCustomWidget;
2897 d->m_labeledCustomWidget = widget;
2901 d->m_lafBox->addRow(label, widget);
2909#if KIOFILEWIDGETS_BUILD_DEPRECATED_SINCE(6, 3)
2912 d->m_configGroup = group;
2913 d->readViewConfig();
2914 d->readRecentFiles();
2918QString KFileWidgetPrivate::locationEditCurrentText()
const
2923QUrl KFileWidgetPrivate::mostLocalUrl(
const QUrl &url)
2931 bool res = statJob->
exec();
2947void KFileWidgetPrivate::setInlinePreviewShown(
bool show)
2949 m_ops->setInlinePreviewShown(show);
2954 d->m_confirmOverwrite = enable;
2959 d->setInlinePreviewShown(
show);
2965 QSize goodSize(48 * fontSize, 30 * fontSize);
2966 const QSize scrnSize = d->screenSize();
2967 QSize minSize(scrnSize / 2);
2968 QSize maxSize(scrnSize * qreal(0.9));
2974 d->m_ops->setViewMode(
mode);
2975 d->m_hasView =
true;
2980 d->m_model->setSupportedSchemes(schemes);
2981 d->m_ops->setSupportedSchemes(schemes);
2982 d->m_urlNavigator->setSupportedSchemes(schemes);
2987 return d->m_model->supportedSchemes();
2990#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 layoutChanged()
The internal layout and graphical representation of components has changed, either after an url chang...
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 textEdited(const QString &text)
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)