2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2022 Mike Tzou (Chocobo1)
4 * Copyright (C) 2016 Eugene Shalygin
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, the copyright holders give permission to
21 * link this program with the OpenSSL project's "OpenSSL" library (or with
22 * modified versions of it that use the same license as the "OpenSSL" library),
23 * and distribute the linked executables. You must obey the GNU General Public
24 * License in all respects for all of the code used other than "OpenSSL". If you
25 * modify file(s), you may extend this exception to your version of the file(s),
26 * but you are not obligated to do so. If you do not wish to do so, delete this
27 * exception statement from your version.
30 #include "fspathedit_p.h"
33 #include <QContextMenuEvent>
36 #include <QFileSystemModel>
38 #include <QStringList>
41 #include "base/path.h"
43 // -------------------- FileSystemPathValidator ----------------------------------------
44 Private::FileSystemPathValidator::FileSystemPathValidator(QObject
*parent
)
49 bool Private::FileSystemPathValidator::strictMode() const
54 void Private::FileSystemPathValidator::setStrictMode(const bool value
)
59 bool Private::FileSystemPathValidator::existingOnly() const
61 return m_existingOnly
;
64 void Private::FileSystemPathValidator::setExistingOnly(const bool value
)
66 m_existingOnly
= value
;
69 bool Private::FileSystemPathValidator::directoriesOnly() const
71 return m_directoriesOnly
;
74 void Private::FileSystemPathValidator::setDirectoriesOnly(const bool value
)
76 m_directoriesOnly
= value
;
79 bool Private::FileSystemPathValidator::checkReadPermission() const
81 return m_checkReadPermission
;
84 void Private::FileSystemPathValidator::setCheckReadPermission(const bool value
)
86 m_checkReadPermission
= value
;
89 bool Private::FileSystemPathValidator::checkWritePermission() const
91 return m_checkWritePermission
;
94 void Private::FileSystemPathValidator::setCheckWritePermission(const bool value
)
96 m_checkWritePermission
= value
;
99 Private::FileSystemPathValidator::TestResult
100 Private::FileSystemPathValidator::testPath(const Path
&path
) const
102 // `QFileInfo` will cache the query results and avoid exessive querying to filesystem
103 const QFileInfo info
{path
.data()};
105 if (existingOnly() && !info
.exists())
106 return TestResult::DoesNotExist
;
108 if (directoriesOnly())
111 return TestResult::NotADir
;
116 return TestResult::NotAFile
;
119 if (checkReadPermission() && !info
.isReadable())
120 return TestResult::CantRead
;
122 if (checkWritePermission() && !info
.isWritable())
123 return TestResult::CantWrite
;
125 return TestResult::OK
;
128 Private::FileSystemPathValidator::TestResult
Private::FileSystemPathValidator::lastTestResult() const
130 return m_lastTestResult
;
133 QValidator::State
Private::FileSystemPathValidator::lastValidationState() const
135 return m_lastValidationState
;
138 QValidator::State
Private::FileSystemPathValidator::validate(QString
&input
, int &pos
) const
140 // ignore cursor position and validate the full path anyway
143 m_lastTestResult
= testPath(Path(input
));
144 m_lastValidationState
= (m_lastTestResult
== TestResult::OK
)
145 ? QValidator::Acceptable
146 : (strictMode() ? QValidator::Invalid
: QValidator::Intermediate
);
148 return m_lastValidationState
;
151 Private::FileLineEdit::FileLineEdit(QWidget
*parent
)
153 , m_completerModel
{new QFileSystemModel(this)}
154 , m_completer
{new QCompleter(this)}
155 , m_browseAction
{nullptr}
156 , m_warningAction
{nullptr}
158 m_iconProvider
.setOptions(QFileIconProvider::DontUseCustomDirectoryIcons
);
160 m_completerModel
->setIconProvider(&m_iconProvider
);
161 m_completerModel
->setOptions(QFileSystemModel::DontWatchForChanges
);
163 m_completer
->setModel(m_completerModel
);
164 setCompleter(m_completer
);
166 connect(this, &QLineEdit::textChanged
, this, &FileLineEdit::validateText
);
169 Private::FileLineEdit::~FileLineEdit()
171 delete m_completerModel
; // has to be deleted before deleting the m_iconProvider object
174 void Private::FileLineEdit::completeDirectoriesOnly(const bool completeDirsOnly
)
176 const QDir::Filters filters
= QDir::NoDotAndDotDot
177 | (completeDirsOnly
? QDir::Dirs
: QDir::AllEntries
);
178 m_completerModel
->setFilter(filters
);
181 void Private::FileLineEdit::setFilenameFilters(const QStringList
&filters
)
183 m_completerModel
->setNameFilters(filters
);
186 void Private::FileLineEdit::setBrowseAction(QAction
*action
)
188 m_browseAction
= action
;
191 void Private::FileLineEdit::setValidator(QValidator
*validator
)
193 QLineEdit::setValidator(validator
);
196 Path
Private::FileLineEdit::placeholder() const
198 return Path(placeholderText());
201 void Private::FileLineEdit::setPlaceholder(const Path
&val
)
203 setPlaceholderText(val
.toString());
206 QWidget
*Private::FileLineEdit::widget()
211 void Private::FileLineEdit::keyPressEvent(QKeyEvent
*e
)
213 QLineEdit::keyPressEvent(e
);
215 if ((e
->key() == Qt::Key_Space
) && (e
->modifiers() == Qt::CTRL
))
217 m_completerModel
->setRootPath(Path(text()).data());
218 showCompletionPopup();
222 void Private::FileLineEdit::contextMenuEvent(QContextMenuEvent
*event
)
224 QMenu
*menu
= createStandardContextMenu();
225 menu
->setAttribute(Qt::WA_DeleteOnClose
);
229 menu
->addSeparator();
230 menu
->addAction(m_browseAction
);
233 menu
->popup(event
->globalPos());
236 void Private::FileLineEdit::showCompletionPopup()
238 m_completer
->setCompletionPrefix(text());
239 m_completer
->complete();
242 void Private::FileLineEdit::validateText()
244 const auto *validator
= qobject_cast
<const FileSystemPathValidator
*>(this->validator());
248 const FileSystemPathValidator::TestResult lastTestResult
= validator
->lastTestResult();
249 const QValidator::State lastState
= validator
->lastValidationState();
251 if (lastTestResult
== FileSystemPathValidator::TestResult::OK
)
253 delete m_warningAction
;
254 m_warningAction
= nullptr;
258 if (!m_warningAction
)
260 m_warningAction
= new QAction(this);
261 addAction(m_warningAction
, QLineEdit::TrailingPosition
);
267 if (lastState
== QValidator::Invalid
)
268 m_warningAction
->setIcon(style()->standardIcon(QStyle::SP_MessageBoxCritical
));
269 else if (lastState
== QValidator::Intermediate
)
270 m_warningAction
->setIcon(style()->standardIcon(QStyle::SP_MessageBoxInformation
));
271 m_warningAction
->setToolTip(warningText(lastTestResult
));
275 QString
Private::FileLineEdit::warningText(const FileSystemPathValidator::TestResult result
)
277 using TestResult
= FileSystemPathValidator::TestResult
;
280 case TestResult::DoesNotExist
:
281 return tr("Path does not exist");
282 case TestResult::NotADir
:
283 return tr("Path does not point to a directory");
284 case TestResult::NotAFile
:
285 return tr("Path does not point to a file");
286 case TestResult::CantRead
:
287 return tr("Don't have read permission to path");
288 case TestResult::CantWrite
:
289 return tr("Don't have write permission to path");
296 Private::FileComboEdit::FileComboEdit(QWidget
*parent
)
300 setLineEdit(new FileLineEdit(this));
303 void Private::FileComboEdit::completeDirectoriesOnly(bool completeDirsOnly
)
305 static_cast<FileLineEdit
*>(lineEdit())->completeDirectoriesOnly(completeDirsOnly
);
308 void Private::FileComboEdit::setBrowseAction(QAction
*action
)
310 static_cast<FileLineEdit
*>(lineEdit())->setBrowseAction(action
);
313 void Private::FileComboEdit::setValidator(QValidator
*validator
)
315 lineEdit()->setValidator(validator
);
318 Path
Private::FileComboEdit::placeholder() const
320 return Path(lineEdit()->placeholderText());
323 void Private::FileComboEdit::setPlaceholder(const Path
&val
)
325 lineEdit()->setPlaceholderText(val
.toString());
328 void Private::FileComboEdit::setFilenameFilters(const QStringList
&filters
)
330 static_cast<FileLineEdit
*>(lineEdit())->setFilenameFilters(filters
);
333 QWidget
*Private::FileComboEdit::widget()
338 QString
Private::FileComboEdit::text() const
340 return currentText();