File indexing completed on 2024-12-22 05:17:22
0001 // SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert <jbb@kaidan.im> 0002 // 0003 // SPDX-License-Identifier: LGPL-2.0-or-later 0004 0005 #include "mobilefiledialog.h" 0006 0007 #include <QGuiApplication> 0008 #include <QQmlApplicationEngine> 0009 #include <QQmlContext> 0010 #include <QQuickWindow> 0011 #include <QStandardPaths> 0012 0013 #include <KLocalizedContext> 0014 #include <KLocalizedString> 0015 0016 #include "dirmodel.h" 0017 #include "dirmodelutils.h" 0018 #include "fileplacesmodel.h" 0019 #include "mobilefiledialog_debug.h" 0020 0021 #include "filechooserqmlcallback.h" 0022 0023 constexpr auto URI = "org.kde.kirigamifilepicker"; 0024 0025 MobileFileDialog::MobileFileDialog(QObject *parent) 0026 : QObject(parent) 0027 , m_engine(new QQmlApplicationEngine(this)) 0028 , m_window(nullptr) 0029 , m_customTitleSet(false) 0030 { 0031 qmlRegisterType<DirModel>(URI, 0, 1, "DirModel"); 0032 qmlRegisterSingletonType<DirModelUtils>(URI, 0, 1, "DirModelUtils", [=](QQmlEngine *, QJSEngine *) { 0033 return new DirModelUtils; 0034 }); 0035 qmlRegisterType<FileChooserQmlCallback>(URI, 0, 1, "FileChooserCallback"); 0036 qmlRegisterType<FilePlacesModel>(URI, 0, 1, "FilePlacesModel"); 0037 0038 Q_INIT_RESOURCE(filepicker); 0039 0040 auto *i18nContext = new KLocalizedContext(m_engine); 0041 m_engine->rootContext()->setContextObject(i18nContext); 0042 0043 m_engine->load(QStringLiteral("qrc:/org.kde.kirigamifilepicker/FilePickerWindow.qml")); 0044 m_window = qobject_cast<QQuickWindow *>(m_engine->rootObjects().first()); 0045 m_callback = m_window->findChild<FileChooserQmlCallback *>(QStringLiteral("callback")); 0046 0047 // Connect everything to callback 0048 connect(m_callback, &FileChooserQmlCallback::accepted, this, &MobileFileDialog::accepted); 0049 connect(m_callback, &FileChooserQmlCallback::cancel, this, &MobileFileDialog::cancel); 0050 connect(m_callback, &FileChooserQmlCallback::titleChanged, this, &MobileFileDialog::titleChanged); 0051 connect(m_callback, &FileChooserQmlCallback::selectMultipleChanged, this, &MobileFileDialog::selectMultipleChanged); 0052 connect(m_callback, &FileChooserQmlCallback::selectExistingChanged, this, &MobileFileDialog::selectExistingChanged); 0053 connect(m_callback, &FileChooserQmlCallback::nameFiltersChanged, this, &MobileFileDialog::nameFiltersChanged); 0054 connect(m_callback, &FileChooserQmlCallback::mimeTypeFiltersChanged, this, &MobileFileDialog::mimeTypeFiltersChanged); 0055 connect(m_callback, &FileChooserQmlCallback::folderChanged, this, &MobileFileDialog::folderChanged); 0056 connect(m_callback, &FileChooserQmlCallback::currentFileChanged, this, &MobileFileDialog::currentFileChanged); 0057 connect(m_callback, &FileChooserQmlCallback::acceptLabelChanged, this, &MobileFileDialog::acceptLabelChanged); 0058 connect(m_callback, &FileChooserQmlCallback::selectFolderChanged, this, &MobileFileDialog::selectFolderChanged); 0059 0060 // Set default path for file dialog 0061 setFolder(QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation))); 0062 } 0063 0064 // FileDialog methods pass through to the callback to provide a nice c++ api 0065 QString MobileFileDialog::title() const 0066 { 0067 return m_callback->title(); 0068 } 0069 0070 void MobileFileDialog::setTitle(const QString &title) 0071 { 0072 // Don't accept an empty titles 0073 if (!title.isEmpty()) { 0074 m_customTitleSet = true; 0075 m_callback->setTitle(title); 0076 } 0077 } 0078 0079 bool MobileFileDialog::selectMultiple() const 0080 { 0081 return m_callback->selectMultiple(); 0082 } 0083 0084 void MobileFileDialog::setSelectMultiple(bool selectMultiple) 0085 { 0086 m_callback->setSelectMultiple(selectMultiple); 0087 } 0088 0089 bool MobileFileDialog::selectExisting() const 0090 { 0091 return m_callback->selectExisting(); 0092 } 0093 0094 void MobileFileDialog::setSelectExisting(bool selectExisting) 0095 { 0096 m_callback->setSelectExisting(selectExisting); 0097 0098 // Detect that no custom title is set 0099 if (!m_customTitleSet) { 0100 if (selectFolder()) { 0101 setTitle(i18n("Select Folder")); 0102 } else { 0103 if (selectExisting) { 0104 setTitle(i18n("Open File")); 0105 } else { 0106 setTitle(i18n("Save File")); 0107 } 0108 } 0109 } 0110 } 0111 0112 QStringList MobileFileDialog::nameFilters() const 0113 { 0114 return m_callback->nameFilters(); 0115 } 0116 0117 void MobileFileDialog::setNameFilters(const QStringList &nameFilters) 0118 { 0119 m_callback->setNameFilters(nameFilters); 0120 } 0121 0122 QStringList MobileFileDialog::mimeTypeFilters() const 0123 { 0124 return m_callback->mimeTypeFilters(); 0125 } 0126 0127 void MobileFileDialog::setMimeTypeFilters(const QStringList &mimeTypeFilters) 0128 { 0129 m_callback->setMimeTypeFilters(mimeTypeFilters); 0130 } 0131 0132 QUrl MobileFileDialog::folder() const 0133 { 0134 return m_callback->folder(); 0135 } 0136 0137 void MobileFileDialog::setFolder(const QUrl &folder) 0138 { 0139 m_callback->setFolder(folder); 0140 } 0141 0142 QString MobileFileDialog::currentFile() const 0143 { 0144 return m_callback->currentFile(); 0145 } 0146 0147 void MobileFileDialog::setCurrentFile(const QString ¤tFile) 0148 { 0149 m_callback->setCurrentFile(currentFile); 0150 } 0151 0152 QString MobileFileDialog::acceptLabel() const 0153 { 0154 return m_callback->acceptLabel(); 0155 } 0156 0157 void MobileFileDialog::setAcceptLabel(const QString &acceptLabel) 0158 { 0159 m_callback->setAcceptLabel(acceptLabel); 0160 } 0161 0162 bool MobileFileDialog::selectFolder() const 0163 { 0164 return m_callback->selectFolder(); 0165 } 0166 0167 void MobileFileDialog::setSelectFolder(bool selectFolder) 0168 { 0169 m_callback->setSelectFolder(selectFolder); 0170 } 0171 0172 uint MobileFileDialog::exec() 0173 { 0174 // Show window 0175 m_window->setVisible(true); 0176 m_window->raise(); 0177 m_window->requestActivate(); 0178 m_window->setIcon(QIcon::fromTheme(QStringLiteral("system-file-manager"))); 0179 0180 // Reset old data 0181 m_results.clear(); 0182 0183 uint exitCode = 0; 0184 0185 const auto acceptedConn = connect(m_callback, &FileChooserQmlCallback::accepted, this, [this, &exitCode](const QList<QUrl> &urls) { 0186 m_results = urls; 0187 exitCode = 0; 0188 qDebug(KirigamiFilepicker) << "Got results" << m_results; 0189 }); 0190 const auto cancelConn = connect(m_callback, &FileChooserQmlCallback::cancel, this, [&exitCode] { 0191 qDebug(KirigamiFilepicker) << "Quit without results"; 0192 exitCode = 1; 0193 }); 0194 0195 QEventLoop loop; 0196 0197 connect(this, &MobileFileDialog::accepted, &loop, &QEventLoop::quit); 0198 connect(this, &MobileFileDialog::cancel, &loop, &QEventLoop::quit); 0199 0200 loop.exec(); 0201 0202 qDebug(KirigamiFilepicker) << "exiting file dialog"; 0203 0204 // Disconnect signals, to avoid them being connected twice 0205 // when the dialog is used again 0206 disconnect(acceptedConn); 0207 disconnect(cancelConn); 0208 0209 if (m_window) { 0210 m_window->setVisible(false); 0211 } 0212 0213 return exitCode; 0214 } 0215 0216 QList<QUrl> MobileFileDialog::results() const 0217 { 0218 return m_results; 0219 } 0220 0221 #include "moc_mobilefiledialog.cpp"