1
#include "lxqtfiledialoghelper.h"
3
#include <libfm-qt/libfmqt.h>
4
#include <libfm-qt/filedialog.h>
13
static std::unique_ptr<Fm::LibFmQt> libfmQtContext_;
15
LXQtFileDialogHelper::LXQtFileDialogHelper() {
16
if(!libfmQtContext_) {
17
// initialize libfm-qt only once
18
libfmQtContext_ = std::unique_ptr<Fm::LibFmQt>{new Fm::LibFmQt()};
21
// can only be used after libfm-qt initialization
22
dlg_ = std::unique_ptr<Fm::FileDialog>(new Fm::FileDialog());
23
connect(dlg_.get(), &Fm::FileDialog::accepted, [this]() {
27
connect(dlg_.get(), &Fm::FileDialog::rejected, [this]() {
32
connect(dlg_.get(), &Fm::FileDialog::fileSelected, this, &LXQtFileDialogHelper::fileSelected);
33
connect(dlg_.get(), &Fm::FileDialog::filesSelected, this, &LXQtFileDialogHelper::filesSelected);
34
connect(dlg_.get(), &Fm::FileDialog::currentChanged, this, &LXQtFileDialogHelper::currentChanged);
35
connect(dlg_.get(), &Fm::FileDialog::directoryEntered, this, &LXQtFileDialogHelper::directoryEntered);
36
connect(dlg_.get(), &Fm::FileDialog::filterSelected, this, &LXQtFileDialogHelper::filterSelected);
39
LXQtFileDialogHelper::~LXQtFileDialogHelper() {
42
void LXQtFileDialogHelper::exec() {
46
bool LXQtFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow* parent) {
47
dlg_->setAttribute(Qt::WA_NativeWindow, true); // without this, sometimes windowHandle() will return nullptr
49
dlg_->setWindowFlags(windowFlags);
50
dlg_->setWindowModality(windowModality);
52
// Reference: KDE implementation
53
// https://github.com/KDE/plasma-integration/blob/master/src/platformtheme/kdeplatformfiledialoghelper.cpp
54
dlg_->windowHandle()->setTransientParent(parent);
57
// central positioning with respect to the parent window
58
if(parent && parent->isVisible()) {
59
dlg_->move(parent->x() + (parent->width() - dlg_->width()) / 2,
60
parent->y() + (parent->height() - dlg_->height()) / 2);
65
// NOTE: the timer here is required as a workaround borrowed from KDE. Without this, the dialog UI will be blocked.
66
// QFileDialog calls our platform plugin to show our own native file dialog instead of showing its widget.
67
// However, it still creates a hidden dialog internally, and then make it modal.
68
// So user input from all other windows that are not the children of the QFileDialog widget will be blocked.
69
// This includes our own dialog. After the return of this show() method, QFileDialog creates its own window and
70
// then make it modal, which blocks our UI. The timer schedule a delayed popup of our file dialog, so we can
71
// show again after QFileDialog and override the modal state. Then our UI can be unblocked.
72
QTimer::singleShot(0, dlg_.get(), &QDialog::show);
77
void LXQtFileDialogHelper::hide() {
81
bool LXQtFileDialogHelper::defaultNameFilterDisables() const {
85
void LXQtFileDialogHelper::setDirectory(const QUrl& directory) {
86
dlg_->setDirectory(directory);
89
QUrl LXQtFileDialogHelper::directory() const {
90
return dlg_->directory();
93
void LXQtFileDialogHelper::selectFile(const QUrl& filename) {
94
dlg_->selectFile(filename);
97
QList<QUrl> LXQtFileDialogHelper::selectedFiles() const {
98
return dlg_->selectedFiles();
101
void LXQtFileDialogHelper::setFilter() {
102
// FIXME: what's this?
103
// The gtk+ 3 file dialog helper in Qt5 update options in this method.
107
void LXQtFileDialogHelper::selectNameFilter(const QString& filter) {
108
dlg_->selectNameFilter(filter);
111
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
112
QString LXQtFileDialogHelper::selectedMimeTypeFilter() const {
113
return dlg_->selectedMimeTypeFilter();
116
void LXQtFileDialogHelper::selectMimeTypeFilter(const QString& filter) {
117
dlg_->selectMimeTypeFilter(filter);
121
QString LXQtFileDialogHelper::selectedNameFilter() const {
122
return dlg_->selectedNameFilter();
125
bool LXQtFileDialogHelper::isSupportedUrl(const QUrl& url) const {
126
return dlg_->isSupportedUrl(url);
129
void LXQtFileDialogHelper::applyOptions() {
130
auto& opt = options();
133
if(opt->windowTitle().isEmpty()) {
134
dlg_->setWindowTitle(opt->acceptMode() == QFileDialogOptions::AcceptOpen ? tr("Open File")
138
dlg_->setWindowTitle(opt->windowTitle());
141
dlg_->setFilter(opt->filter());
142
dlg_->setViewMode(opt->viewMode() == QFileDialogOptions::Detail ? Fm::FolderView::DetailedListMode
143
: Fm::FolderView::CompactMode);
144
dlg_->setFileMode(QFileDialog::FileMode(opt->fileMode()));
145
dlg_->setAcceptMode(QFileDialog::AcceptMode(opt->acceptMode())); // also sets a default label for accept button
146
// bool useDefaultNameFilters() const;
147
dlg_->setNameFilters(opt->nameFilters());
148
if(!opt->mimeTypeFilters().empty()) {
149
dlg_->setMimeTypeFilters(opt->mimeTypeFilters());
152
dlg_->setDefaultSuffix(opt->defaultSuffix());
153
// QStringList history() const;
155
// explicitly set labels
156
for(int i = 0; i < QFileDialogOptions::DialogLabelCount; ++i) {
157
auto label = static_cast<QFileDialogOptions::DialogLabel>(i);
158
if(opt->isLabelExplicitlySet(label)) {
159
dlg_->setLabelText(static_cast<QFileDialog::DialogLabel>(label), opt->labelText(label));
163
auto url = opt->initialDirectory();
165
dlg_->setDirectory(url);
169
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
170
auto filter = opt->initiallySelectedMimeTypeFilter();
171
if(!filter.isEmpty()) {
172
selectMimeTypeFilter(filter);
175
filter = opt->initiallySelectedNameFilter();
176
if(!filter.isEmpty()) {
177
selectNameFilter(opt->initiallySelectedNameFilter());
181
filter = opt->initiallySelectedNameFilter();
182
if(!filter.isEmpty()) {
183
selectNameFilter(filter);
187
auto selectedFiles = opt->initiallySelectedFiles();
188
for(const auto& selectedFile: selectedFiles) {
189
selectFile(selectedFile);
191
// QStringList supportedSchemes() const;
194
void LXQtFileDialogHelper::loadSettings() {
195
QSettings settings(QSettings::UserScope, "lxqt", "filedialog");
196
settings.beginGroup ("Sizes");
197
dlg_->resize(settings.value("WindowSize", QSize(700, 500)).toSize());
198
dlg_->setSplitterPos(settings.value("SplitterPos", 200).toInt());
202
void LXQtFileDialogHelper::saveSettings() {
203
QSettings settings(QSettings::UserScope, "lxqt", "filedialog");
204
settings.beginGroup ("Sizes");
205
QSize windowSize = dlg_->size();
206
if(settings.value("WindowSize") != windowSize) { // no redundant write
207
settings.setValue("WindowSize", windowSize);
209
int splitterPos = dlg_->splitterPos();
210
if(settings.value("SplitterPos") != splitterPos) {
211
settings.setValue("SplitterPos", splitterPos);
217
FileDialogPlugin::FileDialogPlugin() {
221
QPlatformFileDialogHelper *FileDialogPlugin::createHelper() {
222
return new LXQtFileDialogHelper();