diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 7a444a8e5..818f3f975 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -40,6 +40,8 @@ cookiesmodel.h deletionconfirmationdlg.h downloadfromurldlg.h executionlog.h +fspathedit.h +fspathedit_p.h guiiconprovider.h hidabletabwidget.h ico.h @@ -80,6 +82,8 @@ categoryfilterwidget.cpp cookiesdialog.cpp cookiesmodel.cpp executionlog.cpp +fspathedit.cpp +fspathedit_p.cpp guiiconprovider.cpp ico.cpp loglistwidget.cpp diff --git a/src/gui/fspathedit.cpp b/src/gui/fspathedit.cpp new file mode 100644 index 000000000..d5a3eda36 --- /dev/null +++ b/src/gui/fspathedit.cpp @@ -0,0 +1,363 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Eugene Shalygin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "fspathedit.h" + +#include +#include +#include +#include +#include +#include + +#include "base/utils/fs.h" +#include "fspathedit_p.h" + +namespace +{ + struct TrStringWithComment + { + const char *source; + const char *comment; + + QString tr() const + { + return QObject::tr(source, comment); + } + }; + + constexpr TrStringWithComment browseButtonBriefText = + QT_TRANSLATE_NOOP3("FileSystemPathEdit", "...", "Launch file dialog button text (brief)"); + constexpr TrStringWithComment browseButtonFullText = + QT_TRANSLATE_NOOP3("FileSystemPathEdit", "&Browse...", "Launch file dialog button text (full)"); + constexpr TrStringWithComment defaultDialogCaptionForFile = + QT_TRANSLATE_NOOP3("FileSystemPathEdit", "Choose a file", "Caption for file open/save dialog"); + constexpr TrStringWithComment defaultDialogCaptionForDirectory = + QT_TRANSLATE_NOOP3("FileSystemPathEdit", "Choose a folder", "Caption for directory open dialog"); +} + +class FileSystemPathEdit::FileSystemPathEditPrivate +{ + Q_DECLARE_PUBLIC(FileSystemPathEdit) + Q_DISABLE_COPY(FileSystemPathEditPrivate) + + FileSystemPathEditPrivate(FileSystemPathEdit *q, Private::FileEditorWithCompletion *editor); + + void modeChanged(); + void browseActionTriggered(); + QString dialogCaptionOrDefault() const; + + FileSystemPathEdit *q_ptr; + QScopedPointer m_editor; + QAction *m_browseAction; + QToolButton *m_browseBtn; + QString m_fileNameFilter; + Mode m_mode; + QString m_lastSignaledPath; + QString m_dialogCaption; +}; + +FileSystemPathEdit::FileSystemPathEditPrivate::FileSystemPathEditPrivate( + FileSystemPathEdit *q, Private::FileEditorWithCompletion *editor) + : q_ptr {q} + , m_editor {editor} + , m_browseAction {new QAction(q)} + , m_browseBtn {new QToolButton(q)} + , m_mode {FileSystemPathEdit::Mode::FileOpen} +{ + m_browseAction->setIconText(browseButtonBriefText.tr()); + m_browseAction->setText(browseButtonFullText.tr()); + m_browseAction->setToolTip(browseButtonFullText.tr().remove(QLatin1Char('&'))); + m_browseAction->setShortcut(Qt::CTRL + Qt::Key_B); + m_browseBtn->setDefaultAction(m_browseAction); + m_fileNameFilter = tr("Any file") + QLatin1String(" (*)"); + m_editor->setBrowseAction(m_browseAction); + modeChanged(); +} + +void FileSystemPathEdit::FileSystemPathEditPrivate::browseActionTriggered() +{ + Q_Q(FileSystemPathEdit); + QString filter = q->fileNameFilter(); + QString directory = q->currentDirectory().isEmpty() ? QDir::homePath() : q->currentDirectory(); + + QString selectedPath; + switch (m_mode) { + case FileSystemPathEdit::Mode::FileOpen: + selectedPath = QFileDialog::getOpenFileName(q, dialogCaptionOrDefault(), directory, filter); + break; + case FileSystemPathEdit::Mode::FileSave: + selectedPath = QFileDialog::getSaveFileName(q, dialogCaptionOrDefault(), directory, filter, &filter); + break; + case FileSystemPathEdit::Mode::DirectoryOpen: + case FileSystemPathEdit::Mode::DirectorySave: + selectedPath = QFileDialog::getExistingDirectory(q, dialogCaptionOrDefault(), + directory, QFileDialog::DontResolveSymlinks | QFileDialog::ShowDirsOnly); + break; + default: + throw std::logic_error("Unknown FileSystemPathEdit mode"); + } + if (!selectedPath.isEmpty()) + q->setEditWidgetText(selectedPath); +} + +QString FileSystemPathEdit::FileSystemPathEditPrivate::dialogCaptionOrDefault() const +{ + if (!m_dialogCaption.isEmpty()) + return m_dialogCaption; + + switch (m_mode) { + case FileSystemPathEdit::Mode::FileOpen: + case FileSystemPathEdit::Mode::FileSave: + return defaultDialogCaptionForFile.tr(); + case FileSystemPathEdit::Mode::DirectoryOpen: + case FileSystemPathEdit::Mode::DirectorySave: + return defaultDialogCaptionForDirectory.tr(); + default: + throw std::logic_error("Unknown FileSystemPathEdit mode"); + } +} + +void FileSystemPathEdit::FileSystemPathEditPrivate::modeChanged() +{ + QStyle::StandardPixmap pixmap = QStyle::SP_DialogOpenButton; + bool showDirsOnly = false; + switch (m_mode) { + case FileSystemPathEdit::Mode::FileOpen: + case FileSystemPathEdit::Mode::FileSave: + pixmap = QStyle::SP_DialogOpenButton; + showDirsOnly = false; + break; + case FileSystemPathEdit::Mode::DirectoryOpen: + case FileSystemPathEdit::Mode::DirectorySave: + pixmap = QStyle::SP_DirOpenIcon; + showDirsOnly = true; + break; + default: + throw std::logic_error("Unknown FileSystemPathEdit mode"); + } + m_browseAction->setIcon(QApplication::style()->standardIcon(pixmap)); + m_editor->completeDirectoriesOnly(showDirsOnly); +} + +FileSystemPathEdit::FileSystemPathEdit(Private::FileEditorWithCompletion *editor, QWidget *parent) + : QWidget(parent) + , d_ptr(new FileSystemPathEditPrivate(this, editor)) +{ + Q_D(FileSystemPathEdit); + editor->widget()->setParent(this); + + QHBoxLayout *layout = new QHBoxLayout(this); + layout->addWidget(editor->widget()); + layout->addWidget(d->m_browseBtn); + + connect(d->m_browseAction, &QAction::triggered, [this]() {this->d_func()->browseActionTriggered();}); +} + +FileSystemPathEdit::~FileSystemPathEdit() = default; + +QString FileSystemPathEdit::selectedPath() const +{ + return Utils::Fs::fromNativePath(editWidgetText()); +} + +void FileSystemPathEdit::setSelectedPath(const QString &val) +{ + Q_D(FileSystemPathEdit); + setEditWidgetText(Utils::Fs::toNativePath(val)); + d->m_editor->widget()->setToolTip(val); +} + +QString FileSystemPathEdit::fileNameFilter() const +{ + Q_D(const FileSystemPathEdit); + return d->m_fileNameFilter; +} + +void FileSystemPathEdit::setFileNameFilter(const QString &val) +{ + Q_D(FileSystemPathEdit); + d->m_fileNameFilter = val; + +#if 0 + // QFileSystemModel applies name filters to directories too. + // To use the filters we have to subclass QFileSystemModel and skip directories while filtering + // extract file masks + const int openBracePos = val.indexOf(QLatin1Char('('), 0); + const int closeBracePos = val.indexOf(QLatin1Char(')'), openBracePos + 1); + if ((openBracePos > 0) && (closeBracePos > 0) && (closeBracePos > openBracePos + 2)) { + QString filterString = val.mid(openBracePos + 1, closeBracePos - openBracePos - 1); + if (filterString == QLatin1String("*")) { // no filters + d->m_editor->setFilenameFilters({}); + } + else { + QStringList filters = filterString.split(QLatin1Char(' '), QString::SkipEmptyParts); + d->m_editor->setFilenameFilters(filters); + } + } + else { + d->m_editor->setFilenameFilters({}); + } +#endif +} + +bool FileSystemPathEdit::briefBrowseButtonCaption() const +{ + Q_D(const FileSystemPathEdit); + return d->m_browseBtn->text() == browseButtonBriefText.tr(); +} + +void FileSystemPathEdit::setBriefBrowseButtonCaption(bool brief) +{ + Q_D(FileSystemPathEdit); + d->m_browseBtn->setText(brief ? browseButtonBriefText.tr() : browseButtonFullText.tr()); +} + +void FileSystemPathEdit::onPathEdited() +{ + Q_D(FileSystemPathEdit); + QString newPath = selectedPath(); + if (newPath != d->m_lastSignaledPath) { + emit selectedPathChanged(newPath); + d->m_lastSignaledPath = newPath; + d->m_editor->widget()->setToolTip(editWidgetText()); + } +} + +FileSystemPathEdit::Mode FileSystemPathEdit::mode() const +{ + Q_D(const FileSystemPathEdit); + return d->m_mode; +} + +void FileSystemPathEdit::setMode(FileSystemPathEdit::Mode theMode) +{ + Q_D(FileSystemPathEdit); + d->m_mode = theMode; + d->modeChanged(); +} + +QString FileSystemPathEdit::dialogCaption() const +{ + Q_D(const FileSystemPathEdit); + return d->m_dialogCaption; +} + +void FileSystemPathEdit::setDialogCaption(const QString &caption) +{ + Q_D(FileSystemPathEdit); + d->m_dialogCaption = caption; +} + +QString FileSystemPathEdit::currentDirectory() const +{ + return QFileInfo(selectedPath()).absoluteDir().absolutePath(); +} + +QWidget *FileSystemPathEdit::editWidgetImpl() const +{ + Q_D(const FileSystemPathEdit); + return d->m_editor->widget(); +} + +// ------------------------- FileSystemPathLineEdit ---------------------- +FileSystemPathLineEdit::FileSystemPathLineEdit(QWidget *parent) + : FileSystemPathEdit(new WidgetType(), parent) +{ + connect(editWidget(), &QLineEdit::editingFinished, this, &FileSystemPathLineEdit::onPathEdited); + connect(editWidget(), &QLineEdit::textChanged, this, &FileSystemPathLineEdit::onPathEdited); +} + +QString FileSystemPathLineEdit::editWidgetText() const +{ + return editWidget()->text(); +} + +void FileSystemPathLineEdit::clear() +{ + editWidget()->clear(); +} + +void FileSystemPathLineEdit::setEditWidgetText(const QString &text) +{ + editWidget()->setText(text); +} + +// ----------------------- FileSystemPathComboEdit ----------------------- +FileSystemPathComboEdit::FileSystemPathComboEdit(QWidget *parent) + : FileSystemPathEdit(new WidgetType(), parent) +{ + editWidget()->setEditable(true); + connect(editWidget(), &QComboBox::currentTextChanged, this, &FileSystemPathComboEdit::onPathEdited); + connect(editWidget()->lineEdit(), &QLineEdit::editingFinished, this, &FileSystemPathComboEdit::onPathEdited); +} + +void FileSystemPathComboEdit::clear() +{ + editWidget()->clear(); +} + +int FileSystemPathComboEdit::count() const +{ + return editWidget()->count(); +} + +QString FileSystemPathComboEdit::item(int index) const +{ + return Utils::Fs::fromNativePath(editWidget()->itemText(index)); +} + +void FileSystemPathComboEdit::addItem(const QString &text) +{ + editWidget()->addItem(Utils::Fs::toNativePath(text)); +} + +void FileSystemPathComboEdit::insertItem(int index, const QString& text) +{ + editWidget()->insertItem(index, Utils::Fs::toNativePath(text)); +} + +int FileSystemPathComboEdit::currentIndex() const +{ + return editWidget()->currentIndex(); +} + +void FileSystemPathComboEdit::setCurrentIndex(int index) +{ + editWidget()->setCurrentIndex(index); +} + +QString FileSystemPathComboEdit::editWidgetText() const +{ + return editWidget()->currentText(); +} + +void FileSystemPathComboEdit::setEditWidgetText(const QString &text) +{ + editWidget()->setCurrentText(text); +} diff --git a/src/gui/fspathedit.h b/src/gui/fspathedit.h new file mode 100644 index 000000000..e7bf496ab --- /dev/null +++ b/src/gui/fspathedit.h @@ -0,0 +1,151 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Eugene Shalygin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_FSPATHEDIT_H +#define QBT_FSPATHEDIT_H + +#include +#include + +namespace Private +{ + class FileEditorWithCompletion; + class FileLineEdit; + class FileComboEdit; +} + +/*! + * \brief + * Widget for editing strings which are paths in filesystem + */ +class FileSystemPathEdit: public QWidget +{ + Q_OBJECT + Q_ENUMS(Mode) + Q_PROPERTY(Mode mode READ mode WRITE setMode) + Q_PROPERTY(QString selectedPath READ selectedPath WRITE setSelectedPath NOTIFY selectedPathChanged) + Q_PROPERTY(QString fileNameFilter READ fileNameFilter WRITE setFileNameFilter) + Q_PROPERTY(QString dialogCaption READ dialogCaption WRITE setDialogCaption) + +public: + ~FileSystemPathEdit() override; + + enum class Mode + { + FileOpen, //!< opening files, shows open file dialog + FileSave, //!< saving files, shows save file dialog + DirectoryOpen, //!< selecting existing directories + DirectorySave //!< selecting directories for saving + }; + + Mode mode() const; + void setMode(Mode mode); + + QString currentDirectory() const; + QString selectedPath() const; + void setSelectedPath(const QString &val); + + QString fileNameFilter() const; + void setFileNameFilter(const QString &val); + + /// The browse button caption is "..." if true, and "Browse" otherwise + bool briefBrowseButtonCaption() const; + void setBriefBrowseButtonCaption(bool brief); + + QString dialogCaption() const; + void setDialogCaption(const QString &caption); + + virtual void clear() = 0; + +signals: + void selectedPathChanged(const QString &path); + +protected: + explicit FileSystemPathEdit(Private::FileEditorWithCompletion *editor, QWidget *parent); + + template + Widget *editWidget() const + { + return static_cast(editWidgetImpl()); + } + +protected slots: + void onPathEdited(); + +private: + virtual QString editWidgetText() const = 0; + virtual void setEditWidgetText(const QString &text) = 0; + + QWidget *editWidgetImpl() const; + Q_DISABLE_COPY(FileSystemPathEdit) + class FileSystemPathEditPrivate; + Q_DECLARE_PRIVATE(FileSystemPathEdit) + QScopedPointer const d_ptr; +}; + +/// Widget which uses QLineEdit for path editing +class FileSystemPathLineEdit: public FileSystemPathEdit +{ + using base = FileSystemPathEdit; + using WidgetType = Private::FileLineEdit; + +public: + explicit FileSystemPathLineEdit(QWidget *parent = nullptr); + + void clear() override; + +private: + QString editWidgetText() const override; + void setEditWidgetText(const QString &text) override; +}; + +/// Widget which uses QComboBox for path editing +class FileSystemPathComboEdit: public FileSystemPathEdit +{ + using base = FileSystemPathEdit; + using WidgetType = Private::FileComboEdit; + +public: + explicit FileSystemPathComboEdit(QWidget *parent = nullptr); + + void clear() override; + + int count() const; + QString item(int index) const; + void addItem(const QString &text); + void insertItem(int index, const QString &text); + + int currentIndex() const; + void setCurrentIndex(int index); + +private: + QString editWidgetText() const override; + void setEditWidgetText(const QString &text) override; +}; + +#endif // QBT_FSPATHEDIT_H diff --git a/src/gui/fspathedit_p.cpp b/src/gui/fspathedit_p.cpp new file mode 100644 index 000000000..8be1a87b7 --- /dev/null +++ b/src/gui/fspathedit_p.cpp @@ -0,0 +1,133 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Eugene Shalygin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "fspathedit_p.h" + +#include +#include + +Private::FileLineEdit::FileLineEdit(QWidget *parent) + : QLineEdit {parent} + , m_completerModel {new QFileSystemModel(this)} + , m_completer {new QCompleter(this)} + , m_browseAction {nullptr} +{ + m_completerModel->setRootPath(""); + m_completerModel->setIconProvider(&m_iconProvider); + m_completer->setModel(m_completerModel); + m_completer->setCompletionMode(QCompleter::PopupCompletion); + setCompleter(m_completer); + + connect(m_completerModel, &QFileSystemModel::directoryLoaded, this, &FileLineEdit::showCompletionPopup); +} + +Private::FileLineEdit::~FileLineEdit() +{ + delete m_completerModel; // has to be deleted before deleting the m_iconProvider object +} + +void Private::FileLineEdit::completeDirectoriesOnly(bool completeDirsOnly) +{ + QDir::Filters filters = completeDirsOnly ? QDir::Dirs : QDir::AllEntries; + filters |= QDir::NoDotAndDotDot; + m_completerModel->setFilter(filters); +} + +void Private::FileLineEdit::setFilenameFilters(const QStringList &filters) +{ + m_completerModel->setNameFilters(filters); +} + +void Private::FileLineEdit::setBrowseAction(QAction *action) +{ + m_browseAction = action; +} + +QWidget *Private::FileLineEdit::widget() +{ + return this; +} + +void Private::FileLineEdit::keyPressEvent(QKeyEvent *e) +{ + QLineEdit::keyPressEvent(e); + if ((e->key() == Qt::Key_Space) && (e->modifiers() == Qt::CTRL)) { + m_completerModel->setRootPath(QFileInfo(text()).absoluteDir().absolutePath()); + showCompletionPopup(); + } +} + +void Private::FileLineEdit::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu *menu = createStandardContextMenu(); + menu->addSeparator(); + if (m_browseAction) { + menu->addSeparator(); + menu->addAction(m_browseAction); + } + menu->exec(event->globalPos()); + delete menu; +} + +void Private::FileLineEdit::showCompletionPopup() +{ + m_completer->setCompletionPrefix(text()); + m_completer->complete(); +} + +Private::FileComboEdit::FileComboEdit(QWidget *parent) + : QComboBox {parent} +{ + setEditable(true); + setLineEdit(new FileLineEdit(this)); +} + +void Private::FileComboEdit::completeDirectoriesOnly(bool completeDirsOnly) +{ + static_cast(lineEdit())->completeDirectoriesOnly(completeDirsOnly); +} + +void Private::FileComboEdit::setBrowseAction(QAction *action) +{ + static_cast(lineEdit())->setBrowseAction(action); +} + +void Private::FileComboEdit::setFilenameFilters(const QStringList &filters) +{ + static_cast(lineEdit())->setFilenameFilters(filters); +} + +QWidget *Private::FileComboEdit::widget() +{ + return this; +} + +QString Private::FileComboEdit::text() const +{ + return currentText(); +} diff --git a/src/gui/fspathedit_p.h b/src/gui/fspathedit_p.h new file mode 100644 index 000000000..450a3ea52 --- /dev/null +++ b/src/gui/fspathedit_p.h @@ -0,0 +1,101 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Eugene Shalygin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_GUI_FSPATHEDIT_P_H +#define QBT_GUI_FSPATHEDIT_P_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Private +{ + class FileEditorWithCompletion + { + public: + virtual ~FileEditorWithCompletion() = default; + virtual void completeDirectoriesOnly(bool completeDirsOnly) = 0; + virtual void setFilenameFilters(const QStringList &filters) = 0; + virtual void setBrowseAction(QAction *action) = 0; + virtual QWidget *widget() = 0; + }; + + class FileLineEdit: public QLineEdit, public FileEditorWithCompletion + { + Q_OBJECT + Q_DISABLE_COPY(FileLineEdit) + + public: + FileLineEdit(QWidget *parent = nullptr); + ~FileLineEdit(); + + void completeDirectoriesOnly(bool completeDirsOnly) override; + void setFilenameFilters(const QStringList &filters) override; + void setBrowseAction(QAction *action) override; + QWidget *widget() override; + + protected: + void keyPressEvent(QKeyEvent *event) override; + void contextMenuEvent(QContextMenuEvent *event) override; + + private slots: + void showCompletionPopup(); + + private: + QFileSystemModel *m_completerModel; + QCompleter *m_completer; + QAction *m_browseAction; + QFileIconProvider m_iconProvider; + }; + + + class FileComboEdit: public QComboBox, public FileEditorWithCompletion + { + Q_OBJECT + + public: + FileComboEdit(QWidget *parent = nullptr); + + void completeDirectoriesOnly(bool completeDirsOnly) override; + void setFilenameFilters(const QStringList &filters) override; + void setBrowseAction(QAction *action) override; + QWidget *widget() override; + + protected: + QString text() const; + }; +} + +#endif // QBT_GUI_FSPATHEDIT_P_H diff --git a/src/gui/gui.pri b/src/gui/gui.pri index 5cb464ed7..85673e271 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -56,7 +56,9 @@ HEADERS += \ $$PWD/rss/articlelistwidget.h \ $$PWD/rss/feedlistwidget.h \ $$PWD/rss/automatedrssdownloader.h \ - $$PWD/rss/htmlbrowser.h + $$PWD/rss/htmlbrowser.h \ + $$PWD/fspathedit.h \ + $$PWD/fspathedit_p.h \ SOURCES += \ $$PWD/mainwindow.cpp \ @@ -104,7 +106,9 @@ SOURCES += \ $$PWD/rss/articlelistwidget.cpp \ $$PWD/rss/feedlistwidget.cpp \ $$PWD/rss/automatedrssdownloader.cpp \ - $$PWD/rss/htmlbrowser.cpp + $$PWD/rss/htmlbrowser.cpp \ + $$PWD/fspathedit.cpp \ + $$PWD/fspathedit_p.cpp win32|macx { HEADERS += $$PWD/programupdater.h