bump product version to 7.6.3.2-android
[LibreOffice.git] / vcl / unx / gtk3_kde5 / kde5_filepicker.cxx
blobb3382b33d1093ed075de6bb8c677dc64f67f9376
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/svapp.hxx>
22 #include "kde5_filepicker.hxx"
24 #include <KWindowSystem>
25 #include <KFileWidget>
27 #include <QtCore/QDebug>
28 #include <QtCore/QUrl>
29 #include <QtWidgets/QCheckBox>
30 #include <QtWidgets/QFileDialog>
31 #include <QtWidgets/QGridLayout>
32 #include <QtWidgets/QWidget>
33 #include <QtWidgets/QApplication>
35 // KDE5FilePicker
37 KDE5FilePicker::KDE5FilePicker(QObject* parent)
38 : QObject(parent)
39 , _dialog(new QFileDialog(nullptr, {}, QDir::homePath()))
40 , _extraControls(new QWidget)
41 , _layout(new QGridLayout(_extraControls))
42 , _winId(0)
44 _dialog->setSupportedSchemes({
45 QStringLiteral("file"), QStringLiteral("ftp"), QStringLiteral("http"),
46 QStringLiteral("https"), QStringLiteral("webdav"), QStringLiteral("webdavs"),
47 QStringLiteral("smb"),
48 QStringLiteral(""), // this makes removable devices shown
49 });
51 setMultiSelectionMode(false);
53 connect(_dialog, &QFileDialog::filterSelected, this, &KDE5FilePicker::filterChanged);
54 connect(_dialog, &QFileDialog::fileSelected, this, &KDE5FilePicker::selectionChanged);
56 setupCustomWidgets();
59 void KDE5FilePicker::enableFolderMode()
61 _dialog->setOption(QFileDialog::ShowDirsOnly, true);
62 // Workaround for https://bugs.kde.org/show_bug.cgi?id=406464 :
63 // Don't set file mode to QFileDialog::Directory when native KDE Plasma 5
64 // file dialog is used, since clicking on directory "bar" inside directory "foo"
65 // and then confirming would return "foo" rather than "foo/bar";
66 // on the other hand, non-native file dialog needs 'QFileDialog::Directory'
67 // and doesn't allow folder selection otherwise
68 if (Application::GetDesktopEnvironment() != "PLASMA5")
70 _dialog->setFileMode(QFileDialog::Directory);
74 KDE5FilePicker::~KDE5FilePicker()
76 delete _extraControls;
77 delete _dialog;
80 void KDE5FilePicker::setTitle(const QString& title) { _dialog->setWindowTitle(title); }
82 bool KDE5FilePicker::execute()
84 if (!_filters.isEmpty())
85 _dialog->setNameFilters(_filters);
86 if (!_currentFilter.isEmpty())
87 _dialog->selectNameFilter(_currentFilter);
89 _dialog->show();
90 //block and wait for user input
91 return _dialog->exec() == QFileDialog::Accepted;
94 void KDE5FilePicker::setMultiSelectionMode(bool multiSelect)
96 if (_dialog->acceptMode() == QFileDialog::AcceptSave)
97 return;
99 _dialog->setFileMode(multiSelect ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
102 void KDE5FilePicker::setDefaultName(const QString& name) { _dialog->selectFile(name); }
104 void KDE5FilePicker::setDisplayDirectory(const QString& dir)
106 _dialog->setDirectoryUrl(QUrl(dir));
109 QString KDE5FilePicker::getDisplayDirectory() const { return _dialog->directoryUrl().url(); }
111 QList<QUrl> KDE5FilePicker::getSelectedFiles() const { return _dialog->selectedUrls(); }
113 void KDE5FilePicker::appendFilter(const QString& title, const QString& filter)
115 QString t = title;
116 QString f = filter;
117 // '/' need to be escaped else they are assumed to be mime types by kfiledialog
118 //see the docs
119 t.replace("/", "\\/");
121 // openoffice gives us filters separated by ';' qt dialogs just want space separated
122 f.replace(";", " ");
124 // make sure "*.*" is not used as "all files"
125 f.replace("*.*", "*");
127 _filters << QStringLiteral("%1 (%2)").arg(t, f);
128 _titleToFilters[t] = _filters.constLast();
131 void KDE5FilePicker::setCurrentFilter(const QString& title)
133 _currentFilter = _titleToFilters.value(title);
136 QString KDE5FilePicker::getCurrentFilter() const
138 QString filter = _titleToFilters.key(_dialog->selectedNameFilter());
140 //default if not found
141 if (filter.isEmpty())
142 filter = "ODF Text Document (.odt)";
144 return filter;
147 void KDE5FilePicker::setValue(sal_Int16 controlId, sal_Int16 /*nControlAction*/, bool value)
149 if (_customWidgets.contains(controlId))
151 QCheckBox* cb = dynamic_cast<QCheckBox*>(_customWidgets.value(controlId));
152 if (cb)
153 cb->setChecked(value);
155 else
156 qWarning() << "set value on unknown control" << controlId;
159 bool KDE5FilePicker::getValue(sal_Int16 controlId, sal_Int16 /*nControlAction*/) const
161 bool ret = false;
162 if (_customWidgets.contains(controlId))
164 QCheckBox* cb = dynamic_cast<QCheckBox*>(_customWidgets.value(controlId));
165 if (cb)
166 ret = cb->isChecked();
168 else
169 qWarning() << "get value on unknown control" << controlId;
171 return ret;
174 void KDE5FilePicker::enableControl(sal_Int16 controlId, bool enable)
176 if (_customWidgets.contains(controlId))
177 _customWidgets.value(controlId)->setEnabled(enable);
178 else
179 qWarning() << "enable on unknown control" << controlId;
182 void KDE5FilePicker::setLabel(sal_Int16 controlId, const QString& label)
184 if (_customWidgets.contains(controlId))
186 QCheckBox* cb = dynamic_cast<QCheckBox*>(_customWidgets.value(controlId));
187 if (cb)
188 cb->setText(label);
190 else
191 qWarning() << "set label on unknown control" << controlId;
194 QString KDE5FilePicker::getLabel(sal_Int16 controlId) const
196 QString label;
197 if (_customWidgets.contains(controlId))
199 QCheckBox* cb = dynamic_cast<QCheckBox*>(_customWidgets.value(controlId));
200 if (cb)
201 label = cb->text();
203 else
204 qWarning() << "get label on unknown control" << controlId;
206 return label;
209 void KDE5FilePicker::addCheckBox(sal_Int16 controlId, const QString& label, bool hidden)
211 auto resString = label;
212 resString.replace('~', '&');
214 auto widget = new QCheckBox(resString, _extraControls);
215 widget->setHidden(hidden);
216 if (!hidden)
218 _layout->addWidget(widget);
220 _customWidgets.insert(controlId, widget);
223 void KDE5FilePicker::initialize(bool saveDialog)
225 //default is opening
226 QFileDialog::AcceptMode operationMode
227 = saveDialog ? QFileDialog::AcceptSave : QFileDialog::AcceptOpen;
229 _dialog->setAcceptMode(operationMode);
231 if (saveDialog)
232 _dialog->setFileMode(QFileDialog::AnyFile);
235 void KDE5FilePicker::setWinId(sal_uInt64 winId) { _winId = winId; }
237 void KDE5FilePicker::setupCustomWidgets()
239 // When using the platform-native Plasma/KDE5 file picker, we currently rely on KFileWidget
240 // being present to add the custom controls visible (s. 'eventFilter' method).
241 // Since this doesn't work for other desktop environments, use a non-native
242 // dialog there in order not to lose the custom controls and insert the custom
243 // widget in the layout returned by QFileDialog::layout()
244 // (which returns nullptr for native file dialogs)
245 if (Application::GetDesktopEnvironment() == "PLASMA5")
247 qApp->installEventFilter(this);
249 else
251 _dialog->setOption(QFileDialog::DontUseNativeDialog);
252 QGridLayout* pLayout = static_cast<QGridLayout*>(_dialog->layout());
253 assert(pLayout);
254 const int row = pLayout->rowCount();
255 pLayout->addWidget(_extraControls, row, 1);
259 bool KDE5FilePicker::eventFilter(QObject* o, QEvent* e)
261 if (e->type() == QEvent::Show && o->isWidgetType())
263 auto* w = static_cast<QWidget*>(o);
264 if (!w->parentWidget() && w->isModal())
267 To replace when baseline will include kwindowsystem >= 5.62 with:
268 w->setAttribute(Qt::WA_NativeWindow, true);
269 KWindowSystem::setMainWindow(w->windowHandle(), _winId);
271 SAL_WNODEPRECATED_DECLARATIONS_PUSH
272 KWindowSystem::setMainWindow(w, _winId);
273 SAL_WNODEPRECATED_DECLARATIONS_POP
274 if (auto* fileWidget = w->findChild<KFileWidget*>({}, Qt::FindDirectChildrenOnly))
276 fileWidget->setCustomWidget(_extraControls);
277 // remove event filter again; the only purpose was to set the custom widget here
278 qApp->removeEventFilter(this);
282 return QObject::eventFilter(o, e);
285 #include <kde5_filepicker.moc>
287 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */