Merge pull request #18104 from sledgehammer999/remove_dead_code
[qBittorrent.git] / src / gui / fspathedit_p.cpp
blobc0488fff1e26b7ed2733816135c23eba1d7fba08
1 /*
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"
32 #include <QCompleter>
33 #include <QContextMenuEvent>
34 #include <QDir>
35 #include <QFileInfo>
36 #include <QFileSystemModel>
37 #include <QMenu>
38 #include <QStringList>
39 #include <QStyle>
41 #include "base/path.h"
43 // -------------------- FileSystemPathValidator ----------------------------------------
44 Private::FileSystemPathValidator::FileSystemPathValidator(QObject *parent)
45 : QValidator(parent)
49 bool Private::FileSystemPathValidator::strictMode() const
51 return m_strictMode;
54 void Private::FileSystemPathValidator::setStrictMode(const bool value)
56 m_strictMode = 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())
110 if (!info.isDir())
111 return TestResult::NotADir;
113 else
115 if (!info.isFile())
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
141 Q_UNUSED(pos);
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)
152 : QLineEdit {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()
208 return this;
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);
227 if (m_browseAction)
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());
245 if (!validator)
246 return;
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;
256 else
258 if (!m_warningAction)
260 m_warningAction = new QAction(this);
261 addAction(m_warningAction, QLineEdit::TrailingPosition);
265 if (m_warningAction)
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;
278 switch (result)
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");
290 default:
291 break;
293 return {};
296 Private::FileComboEdit::FileComboEdit(QWidget *parent)
297 : QComboBox {parent}
299 setEditable(true);
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()
335 return this;
338 QString Private::FileComboEdit::text() const
340 return currentText();