diff --git a/src/platformtheme/kdeplatformfiledialoghelper.cpp b/src/platformtheme/kdeplatformfiledialoghelper.cpp index 8fe3aa6..fe9ac4d 100644 --- a/src/platformtheme/kdeplatformfiledialoghelper.cpp +++ b/src/platformtheme/kdeplatformfiledialoghelper.cpp @@ -1,427 +1,427 @@ /* This file is part of the KDE libraries * Copyright 2013 Aleix Pol Gonzalez * Copyright 2014 Martin Klapetek * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License or ( at * your option ) version 3 or, at the discretion of KDE e.V. ( which shall * act as a proxy as in section 14 of the GPLv3 ), any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kdeplatformfiledialoghelper.h" #include "kdeplatformfiledialogbase_p.h" #include "kdirselectdialog_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { /* * Map a Qt filter string into a KDE one. */ static QString qt2KdeFilter(const QStringList &f) { QString filter; QTextStream str(&filter, QIODevice::WriteOnly); QStringList list(f); list.replaceInStrings(QStringLiteral("/"), QStringLiteral("\\/")); QStringList::const_iterator it(list.constBegin()), end(list.constEnd()); bool first = true; for (; it != end; ++it) { int ob = it->lastIndexOf(QLatin1Char('(')), cb = it->lastIndexOf(QLatin1Char(')')); if (-1 != cb && ob < cb) { if (first) { first = false; } else { str << '\n'; } str << it->mid(ob + 1, (cb - ob) - 1) << '|' << it->mid(0, ob); } } return filter; } /* * Map a KDE filter string into a Qt one. */ static QString kde2QtFilter(const QStringList &list, const QString &kde) { QStringList::const_iterator it(list.constBegin()), end(list.constEnd()); int pos; for (; it != end; ++it) { if (-1 != (pos = it->indexOf(kde)) && pos > 0 && (QLatin1Char('(') == (*it)[pos - 1] || QLatin1Char(' ') == (*it)[pos - 1]) && it->length() >= kde.length() + pos && (QLatin1Char(')') == (*it)[pos + kde.length()] || QLatin1Char(' ') == (*it)[pos + kde.length()])) { return *it; } } return QString(); } } KDEPlatformFileDialog::KDEPlatformFileDialog() : KDEPlatformFileDialogBase() , m_fileWidget(new KFileWidget(QUrl(), this)) { setLayout(new QVBoxLayout); connect(m_fileWidget, SIGNAL(filterChanged(QString)), SIGNAL(filterSelected(QString))); layout()->addWidget(m_fileWidget); m_buttons = new QDialogButtonBox(this); m_buttons->addButton(m_fileWidget->okButton(), QDialogButtonBox::AcceptRole); m_buttons->addButton(m_fileWidget->cancelButton(), QDialogButtonBox::RejectRole); connect(m_buttons, SIGNAL(rejected()), m_fileWidget, SLOT(slotCancel())); connect(m_fileWidget->okButton(), SIGNAL(clicked(bool)), m_fileWidget, SLOT(slotOk())); connect(m_fileWidget, SIGNAL(accepted()), m_fileWidget, SLOT(accept())); connect(m_fileWidget, SIGNAL(accepted()), SLOT(accept())); connect(m_fileWidget->cancelButton(), SIGNAL(clicked(bool)), SLOT(reject())); layout()->addWidget(m_buttons); } QUrl KDEPlatformFileDialog::directory() { return m_fileWidget->baseUrl(); } QList KDEPlatformFileDialog::selectedFiles() { return m_fileWidget->selectedUrls(); } void KDEPlatformFileDialog::selectFile(const QUrl &filename) { QUrl dirUrl = filename.adjusted(QUrl::RemoveFilename); m_fileWidget->setUrl(dirUrl); - m_fileWidget->setSelection(filename.toString()); + m_fileWidget->setSelectedUrl(filename); } void KDEPlatformFileDialog::setViewMode(QFileDialogOptions::ViewMode view) { switch (view) { case QFileDialogOptions::ViewMode::Detail: m_fileWidget->setViewMode(KFile::FileView::Detail); break; case QFileDialogOptions::ViewMode::List: m_fileWidget->setViewMode(KFile::FileView::Simple); break; default: m_fileWidget->setViewMode(KFile::FileView::Default); break; } } void KDEPlatformFileDialog::setFileMode(QFileDialogOptions::FileMode mode) { switch (mode) { case QFileDialogOptions::FileMode::AnyFile: m_fileWidget->setMode(KFile::File); break; case QFileDialogOptions::FileMode::ExistingFile: m_fileWidget->setMode(KFile::Mode::File | KFile::Mode::ExistingOnly); break; case QFileDialogOptions::FileMode::Directory: m_fileWidget->setMode(KFile::Mode::Directory | KFile::Mode::ExistingOnly); break; case QFileDialogOptions::FileMode::ExistingFiles: m_fileWidget->setMode(KFile::Mode::Files | KFile::Mode::ExistingOnly); break; default: m_fileWidget->setMode(KFile::File); break; } } void KDEPlatformFileDialog::setCustomLabel(QFileDialogOptions::DialogLabel label, const QString &text) { if (label == QFileDialogOptions::Accept) { // OK button m_fileWidget->okButton()->setText(text); } else if (label == QFileDialogOptions::Reject) { // Cancel button m_fileWidget->cancelButton()->setText(text); } else if (label == QFileDialogOptions::LookIn) { // Location label m_fileWidget->setLocationLabel(text); } } QString KDEPlatformFileDialog::selectedMimeTypeFilter() { if (m_fileWidget->filterWidget()->isMimeFilter()) { const auto mimeTypeFromFilter = QMimeDatabase().mimeTypeForName(m_fileWidget->filterWidget()->currentFilter()); // If one does not call selectMimeTypeFilter(), KFileFilterCombo::currentFilter() returns invalid mimeTypes, // such as "application/json application/zip". if (mimeTypeFromFilter.isValid()) { return mimeTypeFromFilter.name(); } } if (selectedFiles().isEmpty()) { return QString(); } // Works for both KFile::File and KFile::Files modes. return QMimeDatabase().mimeTypeForUrl(selectedFiles().at(0)).name(); } QString KDEPlatformFileDialog::selectedNameFilter() { return m_fileWidget->filterWidget()->currentFilter(); } void KDEPlatformFileDialog::selectMimeTypeFilter(const QString &filter) { m_fileWidget->filterWidget()->setCurrentFilter(filter); } void KDEPlatformFileDialog::selectNameFilter(const QString &filter) { m_fileWidget->filterWidget()->setCurrentFilter(filter); } void KDEPlatformFileDialog::setDirectory(const QUrl &directory) { if (!directory.isLocalFile()) { // Qt can not determine if the remote URL points to a file or a // directory, that is why options()->initialDirectory() always returns // the full URL. KIO::StatJob *job = KIO::stat(directory); KJobWidgets::setWindow(job, this); if (job->exec()) { KIO::UDSEntry entry = job->statResult(); if (!entry.isDir()) { // this is probably a file remove the file part m_fileWidget->setUrl(directory.adjusted(QUrl::RemoveFilename)); - m_fileWidget->setSelection(directory.fileName()); + m_fileWidget->setSelectedUrl(directory); } else { m_fileWidget->setUrl(directory); } } } else { m_fileWidget->setUrl(directory); } } bool KDEPlatformFileDialogHelper::isSupportedUrl(const QUrl& url) const { return KProtocolInfo::protocols().contains(url.scheme()); } //////////////////////////////////////////////// KDEPlatformFileDialogHelper::KDEPlatformFileDialogHelper() : QPlatformFileDialogHelper() , m_dialog(new KDEPlatformFileDialog) { connect(m_dialog, SIGNAL(closed()), SLOT(saveSize())); connect(m_dialog, SIGNAL(finished(int)), SLOT(saveSize())); connect(m_dialog, SIGNAL(currentChanged(QUrl)), SIGNAL(currentChanged(QUrl))); connect(m_dialog, SIGNAL(directoryEntered(QUrl)), SIGNAL(directoryEntered(QUrl))); connect(m_dialog, SIGNAL(fileSelected(QUrl)), SIGNAL(fileSelected(QUrl))); connect(m_dialog, SIGNAL(filesSelected(QList)), SIGNAL(filesSelected(QList))); connect(m_dialog, SIGNAL(filterSelected(QString)), SIGNAL(filterSelected(QString))); connect(m_dialog, SIGNAL(accepted()), SIGNAL(accept())); connect(m_dialog, SIGNAL(rejected()), SIGNAL(reject())); } KDEPlatformFileDialogHelper::~KDEPlatformFileDialogHelper() { saveSize(); delete m_dialog; } void KDEPlatformFileDialogHelper::initializeDialog() { if (options()->testOption(QFileDialogOptions::ShowDirsOnly)) { m_dialog->deleteLater(); m_dialog = new KDirSelectDialog(options()->initialDirectory()); connect(m_dialog, SIGNAL(accepted()), SIGNAL(accept())); connect(m_dialog, SIGNAL(rejected()), SIGNAL(reject())); if (!options()->windowTitle().isEmpty()) m_dialog->setWindowTitle(options()->windowTitle()); } else { // needed for accessing m_fileWidget KDEPlatformFileDialog *dialog = qobject_cast(m_dialog); dialog->m_fileWidget->setOperationMode(options()->acceptMode() == QFileDialogOptions::AcceptOpen ? KFileWidget::Opening : KFileWidget::Saving); if (options()->windowTitle().isEmpty()) { dialog->setWindowTitle(options()->acceptMode() == QFileDialogOptions::AcceptOpen ? i18nc("@title:window", "Open File") : i18nc("@title:window", "Save File")); } else { dialog->setWindowTitle(options()->windowTitle()); } setDirectory(options()->initialDirectory()); //dialog->setViewMode(options()->viewMode()); // don't override our options, fixes remembering the chosen view mode and sizes! dialog->setFileMode(options()->fileMode()); // custom labels if (options()->isLabelExplicitlySet(QFileDialogOptions::Accept)) { // OK button dialog->setCustomLabel(QFileDialogOptions::Accept, options()->labelText(QFileDialogOptions::Accept)); } else if (options()->isLabelExplicitlySet(QFileDialogOptions::Reject)) { // Cancel button dialog->setCustomLabel(QFileDialogOptions::Reject, options()->labelText(QFileDialogOptions::Reject)); } else if (options()->isLabelExplicitlySet(QFileDialogOptions::LookIn)) { // Location label dialog->setCustomLabel(QFileDialogOptions::LookIn, options()->labelText(QFileDialogOptions::LookIn)); } const QStringList mimeFilters = options()->mimeTypeFilters(); const QStringList nameFilters = options()->nameFilters(); if (!mimeFilters.isEmpty()) { dialog->m_fileWidget->setMimeFilter(mimeFilters); if ( mimeFilters.contains( QStringLiteral("inode/directory") ) ) dialog->m_fileWidget->setMode( dialog->m_fileWidget->mode() | KFile::Directory ); } else if (!nameFilters.isEmpty()) { dialog->m_fileWidget->setFilter(qt2KdeFilter(nameFilters)); } if (!options()->initiallySelectedNameFilter().isEmpty()) { selectNameFilter(options()->initiallySelectedNameFilter()); } // overwrite option if (options()->testOption(QFileDialogOptions::FileDialogOption::DontConfirmOverwrite)) { dialog->m_fileWidget->setConfirmOverwrite(false); } else if (options()->acceptMode() == QFileDialogOptions::AcceptSave) { dialog->m_fileWidget->setConfirmOverwrite(true); } } } void KDEPlatformFileDialogHelper::exec() { restoreSize(); // KDEPlatformFileDialog::show() will always be called during QFileDialog::exec() // discard the delayed show() it and use exec() and it will call show() for us. // We can't hide and show it here because of https://bugreports.qt.io/browse/QTBUG-48248 m_dialog->discardDelayedShow(); m_dialog->exec(); } void KDEPlatformFileDialogHelper::hide() { m_dialog->discardDelayedShow(); m_dialog->hide(); } void KDEPlatformFileDialogHelper::saveSize() { KSharedConfig::Ptr conf = KSharedConfig::openConfig(); KConfigGroup group = conf->group("FileDialogSize"); KWindowConfig::saveWindowSize(m_dialog->windowHandle(), group); } void KDEPlatformFileDialogHelper::restoreSize() { m_dialog->winId(); // ensure there's a window created KSharedConfig::Ptr conf = KSharedConfig::openConfig(); KWindowConfig::restoreWindowSize(m_dialog->windowHandle(), conf->group("FileDialogSize")); // NOTICE: QWindow::setGeometry() does NOT impact the backing QWidget geometry even if the platform // window was created -> QTBUG-40584. We therefore copy the size here. // TODO: remove once this was resolved in QWidget QPA m_dialog->resize(m_dialog->windowHandle()->size()); } bool KDEPlatformFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) { initializeDialog(); m_dialog->setWindowFlags(windowFlags); m_dialog->setWindowModality(windowModality); restoreSize(); m_dialog->windowHandle()->setTransientParent(parent); // Use a delayed show here to delay show() after the internal Qt invisible QDialog. // The delayed call shouldn't matter, because for other "real" native QPlatformDialog // implementation like Mac and Windows, the native dialog is not necessarily // show up immediately. m_dialog->delayedShow(); return true; } QList KDEPlatformFileDialogHelper::selectedFiles() const { return m_dialog->selectedFiles(); } #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) QString KDEPlatformFileDialogHelper::selectedMimeTypeFilter() const { return m_dialog->selectedMimeTypeFilter(); } void KDEPlatformFileDialogHelper::selectMimeTypeFilter(const QString &filter) { m_dialog->selectMimeTypeFilter(filter); } #endif QString KDEPlatformFileDialogHelper::selectedNameFilter() const { return kde2QtFilter(options()->nameFilters(), m_dialog->selectedNameFilter()); } QUrl KDEPlatformFileDialogHelper::directory() const { return m_dialog->directory(); } void KDEPlatformFileDialogHelper::selectFile(const QUrl &filename) { m_dialog->selectFile(filename); // Qt 5 at least <= 5.8.0 does not derive the directory from the passed url // and set the initialDirectory option accordingly, also not for known schemes // like file://, so we have to do it ourselves options()->setInitialDirectory(m_dialog->directory()); } void KDEPlatformFileDialogHelper::setDirectory(const QUrl &directory) { if (!directory.isEmpty()) { m_dialog->setDirectory(directory); } } void KDEPlatformFileDialogHelper::selectNameFilter(const QString &filter) { m_dialog->selectNameFilter(qt2KdeFilter(QStringList(filter))); } void KDEPlatformFileDialogHelper::setFilter() { } bool KDEPlatformFileDialogHelper::defaultNameFilterDisables() const { return false; } diff --git a/src/platformtheme/kdirselectdialog.cpp b/src/platformtheme/kdirselectdialog.cpp index 07e8b03..9d13ec4 100644 --- a/src/platformtheme/kdirselectdialog.cpp +++ b/src/platformtheme/kdirselectdialog.cpp @@ -1,588 +1,588 @@ /* Copyright (C) 2001,2002 Carsten Pfeiffer Copyright (C) 2001 Michael Jarrett Copyright (C) 2009 Shaun Reich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kdirselectdialog_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kfiletreeview_p.h" #include #include // ### add mutator for treeview! class KDirSelectDialog::Private { public: Private(bool localOnly, KDirSelectDialog *parent) : m_parent(parent), m_localOnly(localOnly), m_comboLocked(false), m_urlCombo(0) { } void readConfig(const KSharedConfigPtr &config, const QString &group); void saveConfig(KSharedConfigPtr config, const QString &group); void slotMkdir(); void slotCurrentChanged(); void slotExpand(const QModelIndex &); void slotUrlActivated(const QString &); void slotComboTextChanged(const QString &); void slotContextMenuRequested(const QPoint &); void slotNewFolder(); void slotMoveToTrash(); void slotDelete(); void slotProperties(); KDirSelectDialog *m_parent; bool m_localOnly : 1; bool m_comboLocked : 1; QUrl m_rootUrl; QUrl m_startDir; KFileTreeView *m_treeView; QMenu *m_contextMenu; KActionCollection *m_actions; KFilePlacesView *m_placesView; KHistoryComboBox *m_urlCombo; QString m_recentDirClass; QUrl m_startURL; QAction *moveToTrash; QAction *deleteAction; QAction *showHiddenFoldersAction; }; void KDirSelectDialog::Private::readConfig(const KSharedConfig::Ptr &config, const QString &group) { m_urlCombo->clear(); KConfigGroup conf(config, group); m_urlCombo->setHistoryItems(conf.readPathEntry("History Items", QStringList())); const QSize size = conf.readEntry("DirSelectDialog Size", QSize()); if (size.isValid()) { m_parent->resize(size); } } void KDirSelectDialog::Private::saveConfig(KSharedConfig::Ptr config, const QString &group) { KConfigGroup conf(config, group); KConfigGroup::WriteConfigFlags flags(KConfigGroup::Persistent | KConfigGroup::Global); conf.writePathEntry("History Items", m_urlCombo->historyItems(), flags); conf.writeEntry("DirSelectDialog Size", m_parent->size(), flags); config->sync(); } void KDirSelectDialog::Private::slotMkdir() { bool ok; QString where = m_parent->url().toDisplayString(QUrl::PreferLocalFile); QString name = i18nc("folder name", "New Folder"); if (m_parent->url().isLocalFile() && QFileInfo::exists(m_parent->url().toLocalFile() + QLatin1Char('/') + name)) { name = KIO::suggestName(m_parent->url(), name); } QString directory = KIO::encodeFileName(QInputDialog::getText(m_parent, i18nc("@title:window", "New Folder"), i18nc("@label:textbox", "Create new folder in:\n%1", where), QLineEdit::Normal, name, &ok)); if (!ok) { return; } bool selectDirectory = true; bool writeOk = false; bool exists = false; QUrl folderurl(m_parent->url()); const QStringList dirs = directory.split(QLatin1Char('/'), QString::SkipEmptyParts); QStringList::ConstIterator it = dirs.begin(); for (; it != dirs.end(); ++it) { folderurl.setPath(folderurl.path() + QLatin1Char('/') + *it); KIO::StatJob *job = KIO::stat(folderurl); KJobWidgets::setWindow(job, m_parent); job->setDetails(0); //We only want to know if it exists, 0 == that. job->setSide(KIO::StatJob::DestinationSide); exists = job->exec(); if (!exists) { KIO::MkdirJob *job = KIO::mkdir(folderurl); KJobWidgets::setWindow(job, m_parent); writeOk = job->exec(); } } if (exists) { // url was already existent QString which = folderurl.toDisplayString(QUrl::PreferLocalFile); KMessageBox::sorry(m_parent, i18n("A file or folder named %1 already exists.", which)); selectDirectory = false; } else if (!writeOk) { KMessageBox::sorry(m_parent, i18n("You do not have permission to create that folder.")); } else if (selectDirectory) { m_parent->setCurrentUrl(folderurl); } } void KDirSelectDialog::Private::slotCurrentChanged() { if (m_comboLocked) { return; } const QUrl u = m_treeView->currentUrl(); if (u.isValid()) { m_urlCombo->setEditText(u.toDisplayString(QUrl::PreferLocalFile)); } else { m_urlCombo->setEditText(QString()); } } void KDirSelectDialog::Private::slotUrlActivated(const QString &text) { if (text.isEmpty()) { return; } const QUrl url = QUrl::fromUserInput(text); m_urlCombo->addToHistory(url.toDisplayString()); if (m_parent->localOnly() && !url.isLocalFile()) { return; //FIXME: messagebox for the user } QUrl oldUrl = m_treeView->currentUrl(); if (oldUrl.isEmpty()) { oldUrl = m_startDir; } m_parent->setCurrentUrl(oldUrl); } void KDirSelectDialog::Private::slotComboTextChanged(const QString &text) { m_treeView->blockSignals(true); QUrl url = QUrl::fromUserInput(text); #ifdef Q_OS_WIN QUrl rootUrl(m_treeView->rootUrl()); if (url.isLocalFile() && !rootUrl.isParentOf(url) && !rootUrl.matches(url, QUrl::StripTrailingSlash)) { QUrl tmp = KIO::upUrl(url); while (tmp.path().length() > 1) { url = tmp; tmp = KIO::upUrl(url); } m_treeView->setRootUrl(url); } #endif m_treeView->setCurrentUrl(url); m_treeView->blockSignals(false); } void KDirSelectDialog::Private::slotContextMenuRequested(const QPoint &pos) { m_contextMenu->popup(m_treeView->viewport()->mapToGlobal(pos)); } void KDirSelectDialog::Private::slotExpand(const QModelIndex &index) { m_treeView->setExpanded(index, !m_treeView->isExpanded(index)); } void KDirSelectDialog::Private::slotNewFolder() { slotMkdir(); } void KDirSelectDialog::Private::slotMoveToTrash() { const QUrl url = m_treeView->selectedUrl(); KIO::JobUiDelegate job; if (job.askDeleteConfirmation(QList() << url, KIO::JobUiDelegate::Trash, KIO::JobUiDelegate::DefaultConfirmation)) { KIO::CopyJob *copyJob = KIO::trash(url); KJobWidgets::setWindow(copyJob, m_parent); - copyJob->ui()->setAutoErrorHandlingEnabled(true); + copyJob->uiDelegate()->setAutoErrorHandlingEnabled(true); } } void KDirSelectDialog::Private::slotDelete() { const QUrl url = m_treeView->selectedUrl(); KIO::JobUiDelegate job; if (job.askDeleteConfirmation(QList() << url, KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::DefaultConfirmation)) { KIO::DeleteJob *deleteJob = KIO::del(url); KJobWidgets::setWindow(deleteJob, m_parent); - deleteJob->ui()->setAutoErrorHandlingEnabled(true); + deleteJob->uiDelegate()->setAutoErrorHandlingEnabled(true); } } void KDirSelectDialog::Private::slotProperties() { KPropertiesDialog *dialog = 0; dialog = new KPropertiesDialog(m_treeView->selectedUrl(), this->m_parent); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); } KDirSelectDialog::KDirSelectDialog(const QUrl &startDir, bool localOnly, QWidget *parent) // #ifdef Q_OS_WIN // : QDialog(parent, Qt::WindowMinMaxButtonsHint), // #else // : QDialog(parent), // #endif : d(new Private(localOnly, this)) { setWindowTitle(i18nc("@title:window", "Select Folder")); QVBoxLayout *topLayout = new QVBoxLayout; setLayout(topLayout); QFrame *page = new QFrame(this); topLayout->addWidget(page); QPushButton *folderButton = new QPushButton; KGuiItem::assign(folderButton, KGuiItem(i18nc("@action:button", "New Folder..."), QStringLiteral("folder-new"))); connect(folderButton, SIGNAL(clicked()), this, SLOT(slotNewFolder())); m_buttons = new QDialogButtonBox(this); m_buttons->addButton(folderButton, QDialogButtonBox::ActionRole); m_buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(m_buttons, SIGNAL(accepted()), this, SLOT(accept())); connect(m_buttons, SIGNAL(rejected()), this, SLOT(reject())); topLayout->addWidget(m_buttons); QHBoxLayout *hlay = new QHBoxLayout(page); hlay->setMargin(0); QVBoxLayout *mainLayout = new QVBoxLayout(); d->m_actions = new KActionCollection(this); d->m_actions->addAssociatedWidget(this); d->m_placesView = new KFilePlacesView(page); d->m_placesView->setModel(new KFilePlacesModel(d->m_placesView)); d->m_placesView->setObjectName(QStringLiteral("speedbar")); d->m_placesView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); d->m_placesView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); connect(d->m_placesView, SIGNAL(urlChanged(QUrl)), SLOT(setCurrentUrl(QUrl))); hlay->addWidget(d->m_placesView); hlay->addLayout(mainLayout); d->m_treeView = new KFileTreeView(page); d->m_treeView->setDirOnlyMode(true); d->m_treeView->setContextMenuPolicy(Qt::CustomContextMenu); for (int i = 1; i < d->m_treeView->model()->columnCount(); ++i) { d->m_treeView->hideColumn(i); } d->m_urlCombo = new KHistoryComboBox(page); d->m_urlCombo->setLayoutDirection(Qt::LeftToRight); d->m_urlCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); d->m_urlCombo->setTrapReturnKey(true); d->m_urlCombo->setPixmapProvider(new KUrlPixmapProvider()); KUrlCompletion *comp = new KUrlCompletion(); comp->setMode(KUrlCompletion::DirCompletion); d->m_urlCombo->setCompletionObject(comp, true); d->m_urlCombo->setAutoDeleteCompletionObject(true); d->m_urlCombo->setDuplicatesEnabled(false); d->m_contextMenu = new QMenu(this); QAction *newFolder = new QAction(i18nc("@action:inmenu", "New Folder..."), this); d->m_actions->addAction(newFolder->objectName(), newFolder); newFolder->setIcon(QIcon::fromTheme(QStringLiteral("folder-new"))); newFolder->setShortcut(Qt::Key_F10); connect(newFolder, SIGNAL(triggered(bool)), this, SLOT(slotNewFolder())); d->m_contextMenu->addAction(newFolder); d->moveToTrash = new QAction(i18nc("@action:inmenu", "Move to Trash"), this); d->m_actions->addAction(d->moveToTrash->objectName(), d->moveToTrash); d->moveToTrash->setIcon(QIcon::fromTheme(QStringLiteral("user-trash"))); d->moveToTrash->setShortcut(Qt::Key_Delete); connect(d->moveToTrash, SIGNAL(triggered(bool)), this, SLOT(slotMoveToTrash())); d->m_contextMenu->addAction(d->moveToTrash); d->deleteAction = new QAction(i18nc("@action:inmenu", "Delete"), this); d->m_actions->addAction(d->deleteAction->objectName(), d->deleteAction); d->deleteAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); d->deleteAction->setShortcut(Qt::SHIFT + Qt::Key_Delete); connect(d->deleteAction, SIGNAL(triggered(bool)), this, SLOT(slotDelete())); d->m_contextMenu->addAction(d->deleteAction); d->m_contextMenu->addSeparator(); d->showHiddenFoldersAction = new KToggleAction(i18nc("@option:check", "Show Hidden Folders"), this); d->m_actions->addAction(d->showHiddenFoldersAction->objectName(), d->showHiddenFoldersAction); d->showHiddenFoldersAction->setShortcut(Qt::Key_F8); connect(d->showHiddenFoldersAction, SIGNAL(triggered(bool)), d->m_treeView, SLOT(setShowHiddenFiles(bool))); d->m_contextMenu->addAction(d->showHiddenFoldersAction); d->m_contextMenu->addSeparator(); QAction *propertiesAction = new QAction(i18nc("@action:inmenu", "Properties"), this); d->m_actions->addAction(propertiesAction->objectName(), propertiesAction); propertiesAction->setIcon(QIcon::fromTheme(QStringLiteral("document-properties"))); propertiesAction->setShortcut(Qt::ALT + Qt::Key_Return); connect(propertiesAction, SIGNAL(triggered(bool)), this, SLOT(slotProperties())); d->m_contextMenu->addAction(propertiesAction); d->m_startURL = KFileWidget::getStartUrl(startDir, d->m_recentDirClass); if (localOnly && !d->m_startURL.isLocalFile()) { QString docPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); if (QDir(docPath).exists()) { d->m_startURL = QUrl::fromLocalFile(docPath); } else { d->m_startURL = QUrl::fromLocalFile(QDir::homePath()); } } d->m_startDir = d->m_startURL; d->m_rootUrl = d->m_treeView->rootUrl(); d->readConfig(KSharedConfig::openConfig(), QStringLiteral("DirSelect Dialog")); mainLayout->addWidget(d->m_treeView, 1); mainLayout->addWidget(d->m_urlCombo, 0); connect(d->m_treeView, SIGNAL(currentChanged(QUrl)), SLOT(slotCurrentChanged())); connect(d->m_treeView, SIGNAL(activated(QModelIndex)), SLOT(slotExpand(QModelIndex))); connect(d->m_treeView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(slotContextMenuRequested(QPoint))); connect(d->m_urlCombo, SIGNAL(editTextChanged(QString)), SLOT(slotComboTextChanged(QString))); connect(d->m_urlCombo, SIGNAL(activated(QString)), SLOT(slotUrlActivated(QString))); connect(d->m_urlCombo, SIGNAL(returnPressed(QString)), SLOT(slotUrlActivated(QString))); setCurrentUrl(d->m_startURL); } KDirSelectDialog::~KDirSelectDialog() { delete d; } QUrl KDirSelectDialog::url() const { QUrl comboUrl = QUrl::fromUserInput(d->m_urlCombo->currentText()); if (comboUrl.isValid()) { KIO::StatJob *statJob = KIO::stat(comboUrl, KIO::HideProgressInfo); KJobWidgets::setWindow(statJob, d->m_parent); const bool ok = statJob->exec(); if (ok && statJob->statResult().isDir()) { return comboUrl; } } // qDebug() << comboUrl.path() << " is not an accessible directory"; return d->m_treeView->currentUrl(); } QUrl KDirSelectDialog::rootUrl() const { return d->m_rootUrl; } QAbstractItemView *KDirSelectDialog::view() const { return d->m_treeView; } bool KDirSelectDialog::localOnly() const { return d->m_localOnly; } QUrl KDirSelectDialog::startDir() const { return d->m_startDir; } void KDirSelectDialog::setCurrentUrl(const QUrl &url) { if (!url.isValid()) { return; } if (url.scheme() != d->m_rootUrl.scheme()) { QUrl u(url); //We need the url to end with / because some code ahead (kdirmodel) is expecting //to find the / separator. It can happen that a valid url like smb: does not have //one so we should add it. if (!u.toString().endsWith(QLatin1Char('/'))) { u.setPath(QStringLiteral("/")); } d->m_treeView->setRootUrl(u); d->m_rootUrl = u; } //Check if url represents a hidden folder and enable showing them QString fileName = url.fileName(); //TODO a better hidden file check? bool isHidden = fileName.length() > 1 && fileName[0] == QLatin1Char('.') && (fileName.length() > 2 ? fileName[1] != QLatin1Char('.') : true); bool showHiddenFiles = isHidden && !d->m_treeView->showHiddenFiles(); if (showHiddenFiles) { d->showHiddenFoldersAction->setChecked(true); d->m_treeView->setShowHiddenFiles(true); } d->m_treeView->setCurrentUrl(url); } void KDirSelectDialog::accept() { QUrl selectedUrl = url(); if (!selectedUrl.isValid()) { return; } if (!d->m_recentDirClass.isEmpty()) { KRecentDirs::add(d->m_recentDirClass, selectedUrl.toString()); } d->m_urlCombo->addToHistory(selectedUrl.toDisplayString()); KFileWidget::setStartDir(url()); QDialog::accept(); } void KDirSelectDialog::hideEvent(QHideEvent *event) { d->saveConfig(KSharedConfig::openConfig(), QStringLiteral("DirSelect Dialog")); QDialog::hideEvent(event); } // static QUrl KDirSelectDialog::selectDirectory(const QUrl &startDir, bool localOnly, QWidget *parent, const QString &caption) { KDirSelectDialog myDialog(startDir, localOnly, parent); if (!caption.isNull()) { myDialog.setWindowTitle(caption); } if (myDialog.exec() == QDialog::Accepted) { QUrl url = myDialog.url(); //Returning the most local url if (url.isLocalFile()) { return url; } KIO::StatJob *job = KIO::stat(url); KJobWidgets::setWindow(job, parent); if (!job->exec()) { return url; } KIO::UDSEntry entry = job->statResult(); const QString path = entry.stringValue(KIO::UDSEntry::UDS_LOCAL_PATH); return path.isEmpty() ? url : QUrl::fromLocalFile(path); } else { return QUrl(); } } QUrl KDirSelectDialog::directory() { return url(); } QList KDirSelectDialog::selectedFiles() { return QList() << url(); } void KDirSelectDialog::setDirectory(const QUrl &directory) { setCurrentUrl(directory); } QString KDirSelectDialog::selectedMimeTypeFilter() { return QString(); } QString KDirSelectDialog::selectedNameFilter() { return QString(); } void KDirSelectDialog::selectFile(const QUrl &filename) { Q_UNUSED(filename) } void KDirSelectDialog::selectMimeTypeFilter(const QString &filter) { Q_UNUSED(filter) } void KDirSelectDialog::selectNameFilter(const QString &filter) { Q_UNUSED(filter) } #include "moc_kdirselectdialog_p.cpp"