office-gobmx/vcl/unx/gtk3_kde5/kde5_filepicker.cxx
Michael Stahl d343a2b639 tdf#146386 deprecate, remove usage of Inet::Settings::ooInetFTPProxyName
* officecfg: deprecate Inet::Settings::ooInetFTPProxyName/Port
* ucbhelper: stop handling these settings
* sfx2: remove SID_INET_FTP_PROXY_NAME and SID_INET_FTP_PROXY_PORT
  and usage from SfxApplication::GetOptions()
* shell: remove proxy config code from backends
* stoc: the JavaVM would have its "ftp.proxyHost" properties set based
  on officecfg values; remove that
* sysui,vcl: remove protocol from KDE desktop files and file picker

Change-Id: Iba02676cf6e519e2fa60ba925209436d38e75f49
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159500
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
2023-11-16 19:15:26 +01:00

286 lines
8.9 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <vcl/svapp.hxx>
#include "kde5_filepicker.hxx"
#include <KWindowSystem>
#include <KFileWidget>
#include <QtCore/QDebug>
#include <QtCore/QUrl>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QWidget>
#include <QtWidgets/QApplication>
// KDE5FilePicker
KDE5FilePicker::KDE5FilePicker(QObject* parent)
: QObject(parent)
, _dialog(new QFileDialog(nullptr, {}, QDir::homePath()))
, _extraControls(new QWidget)
, _layout(new QGridLayout(_extraControls))
, _winId(0)
{
_dialog->setSupportedSchemes({
QStringLiteral("file"), QStringLiteral("http"), QStringLiteral("https"),
QStringLiteral("webdav"), QStringLiteral("webdavs"), QStringLiteral("smb"),
QStringLiteral(""), // this makes removable devices shown
});
setMultiSelectionMode(false);
connect(_dialog, &QFileDialog::filterSelected, this, &KDE5FilePicker::filterChanged);
connect(_dialog, &QFileDialog::fileSelected, this, &KDE5FilePicker::selectionChanged);
setupCustomWidgets();
}
void KDE5FilePicker::enableFolderMode()
{
_dialog->setOption(QFileDialog::ShowDirsOnly, true);
// Workaround for https://bugs.kde.org/show_bug.cgi?id=406464 :
// Don't set file mode to QFileDialog::Directory when native KDE Plasma 5
// file dialog is used, since clicking on directory "bar" inside directory "foo"
// and then confirming would return "foo" rather than "foo/bar";
// on the other hand, non-native file dialog needs 'QFileDialog::Directory'
// and doesn't allow folder selection otherwise
if (Application::GetDesktopEnvironment() != "PLASMA5")
{
_dialog->setFileMode(QFileDialog::Directory);
}
}
KDE5FilePicker::~KDE5FilePicker()
{
delete _extraControls;
delete _dialog;
}
void KDE5FilePicker::setTitle(const QString& title) { _dialog->setWindowTitle(title); }
bool KDE5FilePicker::execute()
{
if (!_filters.isEmpty())
_dialog->setNameFilters(_filters);
if (!_currentFilter.isEmpty())
_dialog->selectNameFilter(_currentFilter);
_dialog->show();
//block and wait for user input
return _dialog->exec() == QFileDialog::Accepted;
}
void KDE5FilePicker::setMultiSelectionMode(bool multiSelect)
{
if (_dialog->acceptMode() == QFileDialog::AcceptSave)
return;
_dialog->setFileMode(multiSelect ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
}
void KDE5FilePicker::setDefaultName(const QString& name) { _dialog->selectFile(name); }
void KDE5FilePicker::setDisplayDirectory(const QString& dir)
{
_dialog->setDirectoryUrl(QUrl(dir));
}
QString KDE5FilePicker::getDisplayDirectory() const { return _dialog->directoryUrl().url(); }
QList<QUrl> KDE5FilePicker::getSelectedFiles() const { return _dialog->selectedUrls(); }
void KDE5FilePicker::appendFilter(const QString& title, const QString& filter)
{
QString t = title;
QString f = filter;
// '/' need to be escaped else they are assumed to be mime types by kfiledialog
//see the docs
t.replace("/", "\\/");
// openoffice gives us filters separated by ';' qt dialogs just want space separated
f.replace(";", " ");
// make sure "*.*" is not used as "all files"
f.replace("*.*", "*");
_filters << QStringLiteral("%1 (%2)").arg(t, f);
_titleToFilters[t] = _filters.constLast();
}
void KDE5FilePicker::setCurrentFilter(const QString& title)
{
_currentFilter = _titleToFilters.value(title);
}
QString KDE5FilePicker::getCurrentFilter() const
{
QString filter = _titleToFilters.key(_dialog->selectedNameFilter());
//default if not found
if (filter.isEmpty())
filter = "ODF Text Document (.odt)";
return filter;
}
void KDE5FilePicker::setValue(sal_Int16 controlId, sal_Int16 /*nControlAction*/, bool value)
{
if (_customWidgets.contains(controlId))
{
QCheckBox* cb = dynamic_cast<QCheckBox*>(_customWidgets.value(controlId));
if (cb)
cb->setChecked(value);
}
else
qWarning() << "set value on unknown control" << controlId;
}
bool KDE5FilePicker::getValue(sal_Int16 controlId, sal_Int16 /*nControlAction*/) const
{
bool ret = false;
if (_customWidgets.contains(controlId))
{
QCheckBox* cb = dynamic_cast<QCheckBox*>(_customWidgets.value(controlId));
if (cb)
ret = cb->isChecked();
}
else
qWarning() << "get value on unknown control" << controlId;
return ret;
}
void KDE5FilePicker::enableControl(sal_Int16 controlId, bool enable)
{
if (_customWidgets.contains(controlId))
_customWidgets.value(controlId)->setEnabled(enable);
else
qWarning() << "enable on unknown control" << controlId;
}
void KDE5FilePicker::setLabel(sal_Int16 controlId, const QString& label)
{
if (_customWidgets.contains(controlId))
{
QCheckBox* cb = dynamic_cast<QCheckBox*>(_customWidgets.value(controlId));
if (cb)
cb->setText(label);
}
else
qWarning() << "set label on unknown control" << controlId;
}
QString KDE5FilePicker::getLabel(sal_Int16 controlId) const
{
QString label;
if (_customWidgets.contains(controlId))
{
QCheckBox* cb = dynamic_cast<QCheckBox*>(_customWidgets.value(controlId));
if (cb)
label = cb->text();
}
else
qWarning() << "get label on unknown control" << controlId;
return label;
}
void KDE5FilePicker::addCheckBox(sal_Int16 controlId, const QString& label, bool hidden)
{
auto resString = label;
resString.replace('~', '&');
auto widget = new QCheckBox(resString, _extraControls);
widget->setHidden(hidden);
if (!hidden)
{
_layout->addWidget(widget);
}
_customWidgets.insert(controlId, widget);
}
void KDE5FilePicker::initialize(bool saveDialog)
{
//default is opening
QFileDialog::AcceptMode operationMode
= saveDialog ? QFileDialog::AcceptSave : QFileDialog::AcceptOpen;
_dialog->setAcceptMode(operationMode);
if (saveDialog)
_dialog->setFileMode(QFileDialog::AnyFile);
}
void KDE5FilePicker::setWinId(sal_uInt64 winId) { _winId = winId; }
void KDE5FilePicker::setupCustomWidgets()
{
// When using the platform-native Plasma/KDE5 file picker, we currently rely on KFileWidget
// being present to add the custom controls visible (s. 'eventFilter' method).
// Since this doesn't work for other desktop environments, use a non-native
// dialog there in order not to lose the custom controls and insert the custom
// widget in the layout returned by QFileDialog::layout()
// (which returns nullptr for native file dialogs)
if (Application::GetDesktopEnvironment() == "PLASMA5")
{
qApp->installEventFilter(this);
}
else
{
_dialog->setOption(QFileDialog::DontUseNativeDialog);
QGridLayout* pLayout = static_cast<QGridLayout*>(_dialog->layout());
assert(pLayout);
const int row = pLayout->rowCount();
pLayout->addWidget(_extraControls, row, 1);
}
}
bool KDE5FilePicker::eventFilter(QObject* o, QEvent* e)
{
if (e->type() == QEvent::Show && o->isWidgetType())
{
auto* w = static_cast<QWidget*>(o);
if (!w->parentWidget() && w->isModal())
{
/*
To replace when baseline will include kwindowsystem >= 5.62 with:
w->setAttribute(Qt::WA_NativeWindow, true);
KWindowSystem::setMainWindow(w->windowHandle(), _winId);
*/
SAL_WNODEPRECATED_DECLARATIONS_PUSH
KWindowSystem::setMainWindow(w, _winId);
SAL_WNODEPRECATED_DECLARATIONS_POP
if (auto* fileWidget = w->findChild<KFileWidget*>({}, Qt::FindDirectChildrenOnly))
{
fileWidget->setCustomWidget(_extraControls);
// remove event filter again; the only purpose was to set the custom widget here
qApp->removeEventFilter(this);
}
}
}
return QObject::eventFilter(o, e);
}
#include <kde5_filepicker.moc>
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */