diff --git a/src/platformtheme/kdeplatformfiledialoghelper.cpp b/src/platformtheme/kdeplatformfiledialoghelper.cpp index 0a4f89f..44eca19 100644 --- a/src/platformtheme/kdeplatformfiledialoghelper.cpp +++ b/src/platformtheme/kdeplatformfiledialoghelper.cpp @@ -1,320 +1,347 @@ /* 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 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.begin()), end(list.end()); bool first = true; for (; it != end; ++it) { int ob = it->lastIndexOf('('), cb = it->lastIndexOf(')'); 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.begin()), end(list.end()); int pos; QString sel; for (; it != end; ++it) { if (-1 != (pos = it->indexOf(kde)) && pos > 0 && ('(' == (*it)[pos - 1] || ' ' == (*it)[pos - 1]) && it->length() >= kde.length() + pos && (')' == (*it)[pos + kde.length()] || ' ' == (*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.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); 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::selectedNameFilter() { return m_fileWidget->filterWidget()->currentFilter(); } void KDEPlatformFileDialog::selectNameFilter(const QString &filter) { m_fileWidget->filterWidget()->setCurrentFilter(filter); } void KDEPlatformFileDialog::setDirectory(const QUrl &directory) { 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)) { KDirSelectDialog *dialog = new KDirSelectDialog(m_dialog->directory()); delete m_dialog; m_dialog = dialog; connect(m_dialog, SIGNAL(accepted()), SIGNAL(accept())); connect(m_dialog, SIGNAL(rejected()), SIGNAL(reject())); } 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 ? i18n("Opening...") : i18n("Saving...")); } else { dialog->setWindowTitle(options()->windowTitle()); } setDirectory(options()->initialDirectory()); dialog->setViewMode(options()->viewMode()); 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)); + } + + // MIME filters QStringList filters = options()->mimeTypeFilters(); if (!filters.isEmpty()) { dialog->m_fileWidget->setMimeFilter(filters); } + // name filters QStringList nameFilters = options()->nameFilters(); 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); + } } } void KDEPlatformFileDialogHelper::exec() { 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()); m_dialog->exec(); } void KDEPlatformFileDialogHelper::hide() { m_dialog->hide(); } void KDEPlatformFileDialogHelper::saveSize() { KSharedConfig::Ptr conf = KSharedConfig::openConfig(); KConfigGroup group = conf->group("FileDialogSize"); KWindowConfig::saveWindowSize(m_dialog->windowHandle(), group); } bool KDEPlatformFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) { initializeDialog(); m_dialog->setWindowFlags(windowFlags); m_dialog->setModal(windowModality != Qt::NonModal); if (windowModality == Qt::NonModal) { m_dialog->show(); KSharedConfig::Ptr conf = KSharedConfig::openConfig(); KWindowConfig::restoreWindowSize(m_dialog->windowHandle(), conf->group("FileDialogSize")); } return true; } QList KDEPlatformFileDialogHelper::selectedFiles() const { return m_dialog->selectedFiles(); } 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); } void KDEPlatformFileDialogHelper::setDirectory(const QUrl &directory) { 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/kdeplatformfiledialoghelper.h b/src/platformtheme/kdeplatformfiledialoghelper.h index 682b9e6..05f70fd 100644 --- a/src/platformtheme/kdeplatformfiledialoghelper.h +++ b/src/platformtheme/kdeplatformfiledialoghelper.h @@ -1,79 +1,80 @@ /* This file is part of the KDE libraries * Copyright 2013 Aleix Pol Gonzalez * * 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. */ #ifndef KDEPLATFORMFILEDIALOGHELPER_H #define KDEPLATFORMFILEDIALOGHELPER_H #include #include "kdeplatformfiledialogbase_p.h" class KFileWidget; class QDialogButtonBox; class KDEPlatformFileDialog : public KDEPlatformFileDialogBase { Q_OBJECT public: friend class KDEPlatformFileDialogHelper; explicit KDEPlatformFileDialog(); QUrl directory() Q_DECL_OVERRIDE; void selectNameFilter(const QString &filter) Q_DECL_OVERRIDE; void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; void selectFile(const QUrl &filename) Q_DECL_OVERRIDE; void setViewMode(QFileDialogOptions::ViewMode view); void setFileMode(QFileDialogOptions::FileMode mode); + void setCustomLabel(QFileDialogOptions::DialogLabel label, const QString & text); QString selectedNameFilter() Q_DECL_OVERRIDE; QList selectedFiles() Q_DECL_OVERRIDE; protected: KFileWidget *m_fileWidget; }; class KDEPlatformFileDialogHelper : public QPlatformFileDialogHelper { Q_OBJECT public: KDEPlatformFileDialogHelper(); virtual ~KDEPlatformFileDialogHelper(); void initializeDialog(); virtual bool defaultNameFilterDisables() const Q_DECL_OVERRIDE; virtual QUrl directory() const Q_DECL_OVERRIDE; virtual QList selectedFiles() const Q_DECL_OVERRIDE; virtual QString selectedNameFilter() const Q_DECL_OVERRIDE; virtual void selectNameFilter(const QString &filter) Q_DECL_OVERRIDE; virtual void selectFile(const QUrl &filename) Q_DECL_OVERRIDE; virtual void setFilter() Q_DECL_OVERRIDE; virtual void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; virtual bool isSupportedUrl(const QUrl& url) const Q_DECL_OVERRIDE; virtual void exec() Q_DECL_OVERRIDE; virtual void hide() Q_DECL_OVERRIDE; virtual bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE; private Q_SLOTS: void saveSize(); private: KDEPlatformFileDialogBase *m_dialog; }; #endif // KDEPLATFORMFILEDIALOGHELPER_H diff --git a/src/platformtheme/kfiletreeview.cpp b/src/platformtheme/kfiletreeview.cpp index 16a427e..77b128d 100644 --- a/src/platformtheme/kfiletreeview.cpp +++ b/src/platformtheme/kfiletreeview.cpp @@ -1,212 +1,212 @@ /* This file is part of the KDE project Copyright (C) 2007 Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) 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 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 "kfiletreeview_p.h" -#include +#include #include #include #include #include #include #include #include #include #include class KFileTreeView::Private { public: Private(KFileTreeView *parent) : q(parent) { } QUrl urlForProxyIndex(const QModelIndex &index) const; void _k_activated(const QModelIndex &); void _k_currentChanged(const QModelIndex &, const QModelIndex &); void _k_expanded(const QModelIndex &); KFileTreeView *q; KDirModel *mSourceModel; KDirSortFilterProxyModel *mProxyModel; }; QUrl KFileTreeView::Private::urlForProxyIndex(const QModelIndex &index) const { const KFileItem item = mSourceModel->itemForIndex(mProxyModel->mapToSource(index)); return !item.isNull() ? item.url() : QUrl(); } void KFileTreeView::Private::_k_activated(const QModelIndex &index) { const QUrl url = urlForProxyIndex(index); if (url.isValid()) { emit q->activated(url); } } void KFileTreeView::Private::_k_currentChanged(const QModelIndex ¤tIndex, const QModelIndex &) { const QUrl url = urlForProxyIndex(currentIndex); if (url.isValid()) { emit q->currentChanged(url); } } void KFileTreeView::Private::_k_expanded(const QModelIndex &baseIndex) { QModelIndex index = mProxyModel->mapFromSource(baseIndex); q->selectionModel()->clearSelection(); q->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent); q->scrollTo(index); } KFileTreeView::KFileTreeView(QWidget *parent) : QTreeView(parent), d(new Private(this)) { d->mSourceModel = new KDirModel(this); d->mProxyModel = new KDirSortFilterProxyModel(this); d->mProxyModel->setSourceModel(d->mSourceModel); setModel(d->mProxyModel); setItemDelegate(new KFileItemDelegate(this)); setLayoutDirection(Qt::LeftToRight); d->mSourceModel->dirLister()->openUrl(QUrl::fromLocalFile(QDir::root().absolutePath()), KDirLister::Keep); connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(_k_activated(QModelIndex))); connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(_k_currentChanged(QModelIndex,QModelIndex))); connect(d->mSourceModel, SIGNAL(expand(QModelIndex)), this, SLOT(_k_expanded(QModelIndex))); } KFileTreeView::~KFileTreeView() { delete d; } QUrl KFileTreeView::currentUrl() const { return d->urlForProxyIndex(currentIndex()); } QUrl KFileTreeView::selectedUrl() const { if (!selectionModel()->hasSelection()) { return QUrl(); } const QItemSelection selection = selectionModel()->selection(); const QModelIndex firstIndex = selection.indexes().first(); return d->urlForProxyIndex(firstIndex); } QList KFileTreeView::selectedUrls() const { QList urls; if (!selectionModel()->hasSelection()) { return urls; } const QModelIndexList indexes = selectionModel()->selection().indexes(); foreach (const QModelIndex &index, indexes) { const QUrl url = d->urlForProxyIndex(index); if (url.isValid()) { urls.append(url); } } return urls; } QUrl KFileTreeView::rootUrl() const { return d->mSourceModel->dirLister()->url(); } void KFileTreeView::setDirOnlyMode(bool enabled) { d->mSourceModel->dirLister()->setDirOnlyMode(enabled); d->mSourceModel->dirLister()->openUrl(d->mSourceModel->dirLister()->url()); } void KFileTreeView::setShowHiddenFiles(bool enabled) { QUrl url = currentUrl(); d->mSourceModel->dirLister()->setShowingDotFiles(enabled); d->mSourceModel->dirLister()->openUrl(d->mSourceModel->dirLister()->url()); setCurrentUrl(url); } void KFileTreeView::setCurrentUrl(const QUrl &url) { QModelIndex baseIndex = d->mSourceModel->indexForUrl(url); if (!baseIndex.isValid()) { d->mSourceModel->expandToUrl(url); return; } QModelIndex proxyIndex = d->mProxyModel->mapFromSource(baseIndex); selectionModel()->clearSelection(); selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::SelectCurrent); scrollTo(proxyIndex); } void KFileTreeView::setRootUrl(const QUrl &url) { d->mSourceModel->dirLister()->openUrl(url); } void KFileTreeView::contextMenuEvent(QContextMenuEvent *event) { QMenu menu; KToggleAction *showHiddenAction = new KToggleAction(i18n("Show Hidden Folders"), &menu); showHiddenAction->setChecked(d->mSourceModel->dirLister()->showingDotFiles()); connect(showHiddenAction, SIGNAL(toggled(bool)), this, SLOT(setShowHiddenFiles(bool))); menu.addAction(showHiddenAction); menu.exec(event->globalPos()); } bool KFileTreeView::showHiddenFiles() const { return d->mSourceModel->dirLister()->showingDotFiles(); } QSize KFileTreeView::sizeHint() const { // This size makes KDirSelectDialog pop up just under 800x600 by default :-) return QSize(680, 500); } #include "moc_kfiletreeview_p.cpp"