Browse Source

Merge pull request #5375 from evsh/filename-edit-widget

Add a widget for editing file names
adaptive-webui-19844
Eugene Shalygin 8 years ago committed by GitHub
parent
commit
954f05b4a9
  1. 4
      src/gui/CMakeLists.txt
  2. 79
      src/gui/addnewtorrentdialog.cpp
  3. 3
      src/gui/addnewtorrentdialog.h
  4. 34
      src/gui/addnewtorrentdialog.ui
  5. 363
      src/gui/fspathedit.cpp
  6. 151
      src/gui/fspathedit.h
  7. 133
      src/gui/fspathedit_p.cpp
  8. 101
      src/gui/fspathedit_p.h
  9. 8
      src/gui/gui.pri
  10. 139
      src/gui/optionsdlg.cpp
  11. 6
      src/gui/optionsdlg.h
  12. 229
      src/gui/optionsdlg.ui

4
src/gui/CMakeLists.txt

@ -40,6 +40,8 @@ cookiesmodel.h @@ -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 @@ -80,6 +82,8 @@ categoryfilterwidget.cpp
cookiesdialog.cpp
cookiesmodel.cpp
executionlog.cpp
fspathedit.cpp
fspathedit_p.cpp
guiiconprovider.cpp
ico.cpp
loglistwidget.cpp

79
src/gui/addnewtorrentdialog.cpp

@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
#include <QUrl>
#include <QMenu>
#include <QFileDialog>
#include <QPushButton>
#include "base/preferences.h"
#include "base/settingsstorage.h"
@ -90,6 +91,9 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP @@ -90,6 +91,9 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
ui->lblMetaLoading->setVisible(false);
ui->progMetaLoading->setVisible(false);
ui->savePath->setMode(FileSystemPathEdit::Mode::DirectorySave);
ui->savePath->setDialogCaption(tr("Choose save path"));
auto session = BitTorrent::Session::instance();
if (m_torrentParams.addPaused == TriStateBool::True)
@ -103,8 +107,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP @@ -103,8 +107,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
ui->comboTTM->setCurrentIndex(!session->isAutoTMMDisabledByDefault());
ui->comboTTM->blockSignals(false);
populateSavePathComboBox();
connect(ui->savePathComboBox, SIGNAL(currentIndexChanged(int)), SLOT(onSavePathChanged(int)));
connect(ui->browseButton, SIGNAL(clicked()), SLOT(browseButton_clicked()));
connect(ui->savePath, &FileSystemPathEdit::selectedPathChanged, this, &AddNewTorrentDialog::onSavePathChanged);
ui->defaultSavePathCheckBox->setVisible(false); // Default path is selected by default
if (m_torrentParams.createSubfolder == TriStateBool::True)
@ -353,7 +356,7 @@ void AddNewTorrentDialog::showAdvancedSettings(bool show) @@ -353,7 +356,7 @@ void AddNewTorrentDialog::showAdvancedSettings(bool show)
void AddNewTorrentDialog::saveSavePathHistory() const
{
QDir selectedSavePath(ui->savePathComboBox->itemData(ui->savePathComboBox->currentIndex()).toString());
QDir selectedSavePath(ui->savePath->selectedPath());
// Get current history
QStringList history = settings()->loadValue(KEY_SAVEPATHHISTORY).toStringList();
QList<QDir> historyDirs;
@ -374,8 +377,8 @@ void AddNewTorrentDialog::saveSavePathHistory() const @@ -374,8 +377,8 @@ void AddNewTorrentDialog::saveSavePathHistory() const
int AddNewTorrentDialog::indexOfSavePath(const QString &save_path)
{
QDir saveDir(save_path);
for (int i = 0; i < ui->savePathComboBox->count(); ++i)
if (QDir(ui->savePathComboBox->itemData(i).toString()) == saveDir)
for (int i = 0; i < ui->savePath->count(); ++i)
if (QDir(ui->savePath->item(i)) == saveDir)
return i;
return -1;
}
@ -401,23 +404,18 @@ void AddNewTorrentDialog::updateDiskSpaceLabel() @@ -401,23 +404,18 @@ void AddNewTorrentDialog::updateDiskSpaceLabel()
QString size_string = torrent_size ? Utils::Misc::friendlyUnit(torrent_size) : QString(tr("Not Available", "This size is unavailable."));
size_string += " (";
size_string += tr("Free space on disk: %1").arg(Utils::Misc::friendlyUnit(Utils::Fs::freeDiskSpaceOnPath(
ui->savePathComboBox->itemData(
ui->savePathComboBox->currentIndex()).toString())));
ui->savePath->selectedPath())));
size_string += ")";
ui->size_lbl->setText(size_string);
}
void AddNewTorrentDialog::onSavePathChanged(int index)
void AddNewTorrentDialog::onSavePathChanged(const QString &newPath)
{
// Toggle default save path setting checkbox visibility
ui->defaultSavePathCheckBox->setChecked(false);
ui->defaultSavePathCheckBox->setVisible(
QDir(ui->savePathComboBox->itemData(ui->savePathComboBox->currentIndex()).toString())
!= QDir(BitTorrent::Session::instance()->defaultSavePath()));
ui->defaultSavePathCheckBox->setVisible(QDir(newPath) != QDir(BitTorrent::Session::instance()->defaultSavePath()));
// Remember index
m_oldIndex = index;
m_oldIndex = ui->savePath->currentIndex();
updateDiskSpaceLabel();
}
@ -427,8 +425,7 @@ void AddNewTorrentDialog::categoryChanged(int index) @@ -427,8 +425,7 @@ void AddNewTorrentDialog::categoryChanged(int index)
if (ui->comboTTM->currentIndex() == 1) {
QString savePath = BitTorrent::Session::instance()->categorySavePath(ui->categoryComboBox->currentText());
ui->savePathComboBox->setItemText(0, Utils::Fs::toNativePath(savePath));
ui->savePathComboBox->setItemData(0, savePath);
ui->savePath->setSelectedPath(Utils::Fs::toNativePath(savePath));
}
}
@ -437,35 +434,11 @@ void AddNewTorrentDialog::setSavePath(const QString &newPath) @@ -437,35 +434,11 @@ void AddNewTorrentDialog::setSavePath(const QString &newPath)
int existingIndex = indexOfSavePath(newPath);
if (existingIndex < 0) {
// New path, prepend to combo box
ui->savePathComboBox->insertItem(0, Utils::Fs::toNativePath(newPath), newPath);
ui->savePath->insertItem(0, newPath);
existingIndex = 0;
}
ui->savePathComboBox->setCurrentIndex(existingIndex);
onSavePathChanged(existingIndex);
}
void AddNewTorrentDialog::browseButton_clicked()
{
disconnect(ui->savePathComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onSavePathChanged(int)));
// User is asking for a new save path
QString curSavePath = ui->savePathComboBox->itemText(m_oldIndex);
QString newPath;
if (!curSavePath.isEmpty() && QDir(curSavePath).exists())
newPath = QFileDialog::getExistingDirectory(this, tr("Choose save path"), curSavePath);
else
newPath = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
if (!newPath.isEmpty()) {
setSavePath(newPath);
}
else {
// Restore index
ui->savePathComboBox->setCurrentIndex(m_oldIndex);
}
connect(ui->savePathComboBox, SIGNAL(currentIndexChanged(int)), SLOT(onSavePathChanged(int)));
ui->savePath->setCurrentIndex(existingIndex);
onSavePathChanged(newPath);
}
void AddNewTorrentDialog::renameSelectedFile()
@ -573,14 +546,14 @@ void AddNewTorrentDialog::populateSavePathComboBox() @@ -573,14 +546,14 @@ void AddNewTorrentDialog::populateSavePathComboBox()
{
QString defSavePath = BitTorrent::Session::instance()->defaultSavePath();
ui->savePathComboBox->clear();
ui->savePathComboBox->addItem(Utils::Fs::toNativePath(defSavePath), defSavePath);
ui->savePath->clear();
ui->savePath->addItem(defSavePath);
QDir defaultSaveDir(defSavePath);
// Load save path history
foreach (const QString &savePath, settings()->loadValue(KEY_SAVEPATHHISTORY).toStringList())
if (QDir(savePath) != defaultSaveDir)
ui->savePathComboBox->addItem(Utils::Fs::toNativePath(savePath), savePath);
ui->savePath->addItem(savePath);
if (!m_torrentParams.savePath.isEmpty())
setSavePath(m_torrentParams.savePath);
}
@ -646,7 +619,7 @@ void AddNewTorrentDialog::accept() @@ -646,7 +619,7 @@ void AddNewTorrentDialog::accept()
m_torrentParams.addPaused = TriStateBool(!ui->startTorrentCheckBox->isChecked());
m_torrentParams.createSubfolder = TriStateBool(ui->createSubfolderCheckBox->isChecked());
QString savePath = ui->savePathComboBox->itemData(ui->savePathComboBox->currentIndex()).toString();
QString savePath = ui->savePath->selectedPath();
if (ui->comboTTM->currentIndex() != 1) { // 0 is Manual mode and 1 is Automatic mode. Handle all non 1 values as manual mode.
m_torrentParams.savePath = savePath;
saveSavePathHistory();
@ -776,16 +749,16 @@ void AddNewTorrentDialog::TMMChanged(int index) @@ -776,16 +749,16 @@ void AddNewTorrentDialog::TMMChanged(int index)
if (index != 1) { // 0 is Manual mode and 1 is Automatic mode. Handle all non 1 values as manual mode.
populateSavePathComboBox();
ui->groupBoxSavePath->setEnabled(true);
ui->savePathComboBox->blockSignals(false);
ui->savePathComboBox->setCurrentIndex(m_oldIndex < ui->savePathComboBox->count() ? m_oldIndex : ui->savePathComboBox->count() - 1);
ui->savePath->blockSignals(false);
ui->savePath->setCurrentIndex(m_oldIndex < ui->savePath->count() ? m_oldIndex : ui->savePath->count() - 1);
ui->adv_button->setEnabled(true);
}
else {
ui->groupBoxSavePath->setEnabled(false);
ui->savePathComboBox->blockSignals(true);
ui->savePathComboBox->clear();
ui->savePath->blockSignals(true);
ui->savePath->clear();
QString savePath = BitTorrent::Session::instance()->categorySavePath(ui->categoryComboBox->currentText());
ui->savePathComboBox->addItem(Utils::Fs::toNativePath(savePath), savePath);
ui->savePath->addItem(savePath);
ui->defaultSavePathCheckBox->setVisible(false);
ui->adv_button->setChecked(true);
ui->adv_button->setEnabled(false);

3
src/gui/addnewtorrentdialog.h

@ -73,10 +73,9 @@ private slots: @@ -73,10 +73,9 @@ private slots:
void showAdvancedSettings(bool show);
void displayContentTreeMenu(const QPoint&);
void updateDiskSpaceLabel();
void onSavePathChanged(int);
void onSavePathChanged(const QString &newPath);
void renameSelectedFile();
void updateMetadata(const BitTorrent::TorrentInfo &info);
void browseButton_clicked();
void handleDownloadFailed(const QString &url, const QString &reason);
void handleRedirectedToMagnet(const QString &url, const QString &magnetUri);
void handleDownloadFinished(const QString &url, const QString &filePath);

34
src/gui/addnewtorrentdialog.ui

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>414</width>
<height>661</height>
<height>630</height>
</rect>
</property>
<layout class="QVBoxLayout" name="AddNewTorrentDialogLayout">
@ -59,28 +59,7 @@ @@ -59,28 +59,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QComboBox" name="savePathComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="browseButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
</layout>
<widget class="FileSystemPathComboEdit" name="savePath" native="true"/>
</item>
<item>
<widget class="QCheckBox" name="defaultSavePathCheckBox">
@ -405,10 +384,15 @@ @@ -405,10 +384,15 @@
<extends>QTreeView</extends>
<header>torrentcontenttreeview.h</header>
</customwidget>
<customwidget>
<class>FileSystemPathComboEdit</class>
<extends>QWidget</extends>
<header>fspathedit.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>savePathComboBox</tabstop>
<tabstop>browseButton</tabstop>
<tabstop>savePath</tabstop>
<tabstop>defaultSavePathCheckBox</tabstop>
<tabstop>never_show_cb</tabstop>
<tabstop>adv_button</tabstop>

363
src/gui/fspathedit.cpp

@ -0,0 +1,363 @@ @@ -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 <QAction>
#include <QApplication>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QStyle>
#include <QToolButton>
#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<Private::FileEditorWithCompletion> 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<WidgetType>(), &QLineEdit::editingFinished, this, &FileSystemPathLineEdit::onPathEdited);
connect(editWidget<WidgetType>(), &QLineEdit::textChanged, this, &FileSystemPathLineEdit::onPathEdited);
}
QString FileSystemPathLineEdit::editWidgetText() const
{
return editWidget<WidgetType>()->text();
}
void FileSystemPathLineEdit::clear()
{
editWidget<WidgetType>()->clear();
}
void FileSystemPathLineEdit::setEditWidgetText(const QString &text)
{
editWidget<WidgetType>()->setText(text);
}
// ----------------------- FileSystemPathComboEdit -----------------------
FileSystemPathComboEdit::FileSystemPathComboEdit(QWidget *parent)
: FileSystemPathEdit(new WidgetType(), parent)
{
editWidget<WidgetType>()->setEditable(true);
connect(editWidget<WidgetType>(), &QComboBox::currentTextChanged, this, &FileSystemPathComboEdit::onPathEdited);
connect(editWidget<WidgetType>()->lineEdit(), &QLineEdit::editingFinished, this, &FileSystemPathComboEdit::onPathEdited);
}
void FileSystemPathComboEdit::clear()
{
editWidget<WidgetType>()->clear();
}
int FileSystemPathComboEdit::count() const
{
return editWidget<WidgetType>()->count();
}
QString FileSystemPathComboEdit::item(int index) const
{
return Utils::Fs::fromNativePath(editWidget<WidgetType>()->itemText(index));
}
void FileSystemPathComboEdit::addItem(const QString &text)
{
editWidget<WidgetType>()->addItem(Utils::Fs::toNativePath(text));
}
void FileSystemPathComboEdit::insertItem(int index, const QString& text)
{
editWidget<WidgetType>()->insertItem(index, Utils::Fs::toNativePath(text));
}
int FileSystemPathComboEdit::currentIndex() const
{
return editWidget<WidgetType>()->currentIndex();
}
void FileSystemPathComboEdit::setCurrentIndex(int index)
{
editWidget<WidgetType>()->setCurrentIndex(index);
}
QString FileSystemPathComboEdit::editWidgetText() const
{
return editWidget<WidgetType>()->currentText();
}
void FileSystemPathComboEdit::setEditWidgetText(const QString &text)
{
editWidget<WidgetType>()->setCurrentText(text);
}

151
src/gui/fspathedit.h

@ -0,0 +1,151 @@ @@ -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 <QScopedPointer>
#include <QWidget>
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 <class Widget>
Widget *editWidget() const
{
return static_cast<Widget *>(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<FileSystemPathEditPrivate> 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

133
src/gui/fspathedit_p.cpp

@ -0,0 +1,133 @@ @@ -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 <QCompleter>
#include <QFileInfo>
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<FileLineEdit *>(lineEdit())->completeDirectoriesOnly(completeDirsOnly);
}
void Private::FileComboEdit::setBrowseAction(QAction *action)
{
static_cast<FileLineEdit *>(lineEdit())->setBrowseAction(action);
}
void Private::FileComboEdit::setFilenameFilters(const QStringList &filters)
{
static_cast<FileLineEdit *>(lineEdit())->setFilenameFilters(filters);
}
QWidget *Private::FileComboEdit::widget()
{
return this;
}
QString Private::FileComboEdit::text() const
{
return currentText();
}

101
src/gui/fspathedit_p.h

@ -0,0 +1,101 @@ @@ -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 <QAction>
#include <QComboBox>
#include <QCompleter>
#include <QContextMenuEvent>
#include <QDir>
#include <QFileIconProvider>
#include <QFileSystemModel>
#include <QKeyEvent>
#include <QLineEdit>
#include <QMenu>
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

8
src/gui/gui.pri

@ -56,7 +56,9 @@ HEADERS += \ @@ -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 += \ @@ -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

139
src/gui/optionsdlg.cpp

@ -196,7 +196,7 @@ OptionsDialog::OptionsDialog(QWidget *parent) @@ -196,7 +196,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
connect(m_ui->checkAssociateMagnetLinks, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
#endif
connect(m_ui->checkFileLog, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->textFileLogPath, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->textFileLogPath, SIGNAL(selectedPathChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->checkFileLogBackup, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->checkFileLogBackup, SIGNAL(toggled(bool)), m_ui->spinFileLogSize, SLOT(setEnabled(bool)));
connect(m_ui->checkFileLogDelete, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
@ -206,13 +206,13 @@ OptionsDialog::OptionsDialog(QWidget *parent) @@ -206,13 +206,13 @@ OptionsDialog::OptionsDialog(QWidget *parent)
connect(m_ui->spinFileLogAge, SIGNAL(valueChanged(int)), this, SLOT(enableApplyButton()));
connect(m_ui->comboFileLogAgeType, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton()));
// Downloads tab
connect(m_ui->textSavePath, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->textSavePath, SIGNAL(selectedPathChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->checkUseSubcategories, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->comboSavingMode, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton()));
connect(m_ui->comboTorrentCategoryChanged, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton()));
connect(m_ui->comboCategoryDefaultPathChanged, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton()));
connect(m_ui->comboCategoryChanged, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton()));
connect(m_ui->textTempPath, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->textTempPath, SIGNAL(selectedPathChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->checkAppendqB, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->checkPreallocateAll, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->checkAdditionDialog, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
@ -223,17 +223,14 @@ OptionsDialog::OptionsDialog(QWidget *parent) @@ -223,17 +223,14 @@ OptionsDialog::OptionsDialog(QWidget *parent)
connect(m_ui->deleteCancelledTorrentBox, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->checkExportDir, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->checkExportDir, SIGNAL(toggled(bool)), m_ui->textExportDir, SLOT(setEnabled(bool)));
connect(m_ui->checkExportDir, SIGNAL(toggled(bool)), m_ui->browseExportDirButton, SLOT(setEnabled(bool)));
connect(m_ui->checkExportDirFin, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->checkExportDirFin, SIGNAL(toggled(bool)), m_ui->textExportDirFin, SLOT(setEnabled(bool)));
connect(m_ui->checkExportDirFin, SIGNAL(toggled(bool)), m_ui->browseExportDirFinButton, SLOT(setEnabled(bool)));
connect(m_ui->textExportDir, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->textExportDirFin, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->textExportDir, SIGNAL(selectedPathChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->textExportDirFin, SIGNAL(selectedPathChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->actionTorrentDlOnDblClBox, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton()));
connect(m_ui->actionTorrentFnOnDblClBox, SIGNAL(currentIndexChanged(int)), this, SLOT(enableApplyButton()));
connect(m_ui->checkTempFolder, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->checkTempFolder, SIGNAL(toggled(bool)), m_ui->textTempPath, SLOT(setEnabled(bool)));
connect(m_ui->checkTempFolder, SIGNAL(toggled(bool)), m_ui->browseTempDirButton, SLOT(setEnabled(bool)));
connect(m_ui->addScanFolderButton, SIGNAL(clicked()), this, SLOT(enableApplyButton()));
connect(m_ui->removeScanFolderButton, SIGNAL(clicked()), this, SLOT(enableApplyButton()));
connect(m_ui->groupMailNotification, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
@ -244,7 +241,7 @@ OptionsDialog::OptionsDialog(QWidget *parent) @@ -244,7 +241,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
connect(m_ui->mailNotifUsername, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->mailNotifPassword, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->autoRunBox, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->autoRun_txt, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
connect(m_ui->autoRun_txt, SIGNAL(selectedPathChanged(QString)), this, SLOT(enableApplyButton()));
const QString autoRunStr = QString::fromUtf8("%1\n %2\n %3\n %4\n %5\n %6\n %7\n %8\n %9\n %10\n%11")
.arg(tr("Supported parameters (case sensitive):"))
@ -311,7 +308,6 @@ OptionsDialog::OptionsDialog(QWidget *parent) @@ -311,7 +308,6 @@ OptionsDialog::OptionsDialog(QWidget *parent)
// Misc tab
connect(m_ui->checkIPFilter, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
connect(m_ui->checkIPFilter, SIGNAL(toggled(bool)), m_ui->textFilterPath, SLOT(setEnabled(bool)));
connect(m_ui->checkIPFilter, SIGNAL(toggled(bool)), m_ui->browseFilterButton, SLOT(setEnabled(bool)));
connect(m_ui->checkIPFilter, SIGNAL(toggled(bool)), m_ui->IpFilterRefreshBtn, SLOT(setEnabled(bool)));
connect(m_ui->checkIpFilterTrackers, SIGNAL(toggled(bool)), SLOT(enableApplyButton()));
connect(m_ui->textFilterPath, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
@ -357,6 +353,25 @@ OptionsDialog::OptionsDialog(QWidget *parent) @@ -357,6 +353,25 @@ OptionsDialog::OptionsDialog(QWidget *parent)
m_ui->advPageLayout->addWidget(advancedSettings);
connect(advancedSettings, SIGNAL(settingsChanged()), this, SLOT(enableApplyButton()));
m_ui->textFileLogPath->setDialogCaption(tr("Choose a save directory"));
m_ui->textFileLogPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
m_ui->textExportDir->setDialogCaption(tr("Choose export directory"));
m_ui->textExportDir->setMode(FileSystemPathEdit::Mode::DirectorySave);
m_ui->textExportDirFin->setDialogCaption(tr("Choose export directory"));
m_ui->textExportDirFin->setMode(FileSystemPathEdit::Mode::DirectorySave);
m_ui->textFilterPath->setDialogCaption(tr("Choose an IP filter file"));
m_ui->textFilterPath->setFileNameFilter(tr("All supported filters")
+ QLatin1String(" (*.dat *.p2p *.p2b);;.dat (*.dat);;.p2p (*.p2p);;.p2b (*.p2b)"));
m_ui->textSavePath->setDialogCaption(tr("Choose a save directory"));
m_ui->textSavePath->setMode(FileSystemPathEdit::Mode::DirectorySave);
m_ui->textTempPath->setDialogCaption(tr("Choose a save directory"));
m_ui->textTempPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
show();
loadWindowState();
}
@ -481,7 +496,7 @@ void OptionsDialog::saveOptions() @@ -481,7 +496,7 @@ void OptionsDialog::saveOptions()
}
#endif
Application * const app = static_cast<Application*>(QCoreApplication::instance());
app->setFileLoggerPath(Utils::Fs::fromNativePath(m_ui->textFileLogPath->text()));
app->setFileLoggerPath(m_ui->textFileLogPath->selectedPath());
app->setFileLoggerBackup(m_ui->checkFileLogBackup->isChecked());
app->setFileLoggerMaxSize(m_ui->spinFileLogSize->value());
app->setFileLoggerAge(m_ui->spinFileLogAge->value());
@ -498,14 +513,14 @@ void OptionsDialog::saveOptions() @@ -498,14 +513,14 @@ void OptionsDialog::saveOptions()
auto session = BitTorrent::Session::instance();
// Downloads preferences
session->setDefaultSavePath(Utils::Fs::expandPathAbs(m_ui->textSavePath->text()));
session->setDefaultSavePath(Utils::Fs::expandPathAbs(m_ui->textSavePath->selectedPath()));
session->setSubcategoriesEnabled(m_ui->checkUseSubcategories->isChecked());
session->setAutoTMMDisabledByDefault(m_ui->comboSavingMode->currentIndex() == 0);
session->setDisableAutoTMMWhenCategoryChanged(m_ui->comboTorrentCategoryChanged->currentIndex() == 1);
session->setDisableAutoTMMWhenCategorySavePathChanged(m_ui->comboCategoryChanged->currentIndex() == 1);
session->setDisableAutoTMMWhenDefaultSavePathChanged(m_ui->comboCategoryDefaultPathChanged->currentIndex() == 1);
session->setTempPathEnabled(m_ui->checkTempFolder->isChecked());
session->setTempPath(Utils::Fs::expandPathAbs(m_ui->textTempPath->text()));
session->setTempPath(Utils::Fs::expandPathAbs(m_ui->textTempPath->selectedPath()));
session->setAppendExtensionEnabled(m_ui->checkAppendqB->isChecked());
session->setPreallocationEnabled(preAllocateAllFiles());
AddNewTorrentDialog::setEnabled(useAdditionDialog());
@ -527,7 +542,7 @@ void OptionsDialog::saveOptions() @@ -527,7 +542,7 @@ void OptionsDialog::saveOptions()
pref->setMailNotificationSMTPUsername(m_ui->mailNotifUsername->text());
pref->setMailNotificationSMTPPassword(m_ui->mailNotifPassword->text());
pref->setAutoRunEnabled(m_ui->autoRunBox->isChecked());
pref->setAutoRunProgram(m_ui->autoRun_txt->text().trimmed());
pref->setAutoRunProgram(m_ui->autoRun_txt->selectedPath().trimmed());
pref->setActionOnDblClOnTorrentDl(getActionOnDblClOnTorrentDl());
pref->setActionOnDblClOnTorrentFn(getActionOnDblClOnTorrentFn());
TorrentFileGuard::setAutoDeleteMode(!m_ui->deleteTorrentBox->isChecked() ? TorrentFileGuard::Never
@ -588,7 +603,7 @@ void OptionsDialog::saveOptions() @@ -588,7 +603,7 @@ void OptionsDialog::saveOptions()
// * IPFilter
session->setIPFilteringEnabled(isIPFilteringEnabled());
session->setTrackerFilteringEnabled(m_ui->checkIpFilterTrackers->isChecked());
session->setIPFilterFile(m_ui->textFilterPath->text());
session->setIPFilterFile(m_ui->textFilterPath->selectedPath());
// End IPFilter preferences
// Queueing system
session->setQueueingSystemEnabled(isQueueingSystemEnabled());
@ -694,7 +709,7 @@ void OptionsDialog::loadOptions() @@ -694,7 +709,7 @@ void OptionsDialog::loadOptions()
const Application * const app = static_cast<Application*>(QCoreApplication::instance());
m_ui->checkFileLog->setChecked(app->isFileLoggerEnabled());
m_ui->textFileLogPath->setText(Utils::Fs::toNativePath(app->fileLoggerPath()));
m_ui->textFileLogPath->setSelectedPath(app->fileLoggerPath());
fileLogBackup = app->isFileLoggerBackup();
m_ui->checkFileLogBackup->setChecked(fileLogBackup);
m_ui->spinFileLogSize->setEnabled(fileLogBackup);
@ -723,7 +738,7 @@ void OptionsDialog::loadOptions() @@ -723,7 +738,7 @@ void OptionsDialog::loadOptions()
m_ui->deleteTorrentBox->setChecked(autoDeleteMode != TorrentFileGuard::Never);
m_ui->deleteCancelledTorrentBox->setChecked(autoDeleteMode == TorrentFileGuard::Always);
m_ui->textSavePath->setText(Utils::Fs::toNativePath(session->defaultSavePath()));
m_ui->textSavePath->setSelectedPath(session->defaultSavePath());
m_ui->checkUseSubcategories->setChecked(session->isSubcategoriesEnabled());
m_ui->comboSavingMode->setCurrentIndex(!session->isAutoTMMDisabledByDefault());
m_ui->comboTorrentCategoryChanged->setCurrentIndex(session->isDisableAutoTMMWhenCategoryChanged());
@ -731,39 +746,35 @@ void OptionsDialog::loadOptions() @@ -731,39 +746,35 @@ void OptionsDialog::loadOptions()
m_ui->comboCategoryDefaultPathChanged->setCurrentIndex(session->isDisableAutoTMMWhenDefaultSavePathChanged());
m_ui->checkTempFolder->setChecked(session->isTempPathEnabled());
m_ui->textTempPath->setEnabled(m_ui->checkTempFolder->isChecked());
m_ui->browseTempDirButton->setEnabled(m_ui->checkTempFolder->isChecked());
m_ui->textTempPath->setText(Utils::Fs::toNativePath(session->tempPath()));
m_ui->textTempPath->setEnabled(m_ui->checkTempFolder->isChecked());
m_ui->textTempPath->setSelectedPath(Utils::Fs::toNativePath(session->tempPath()));
m_ui->checkAppendqB->setChecked(session->isAppendExtensionEnabled());
m_ui->checkPreallocateAll->setChecked(session->isPreallocationEnabled());
strValue = Utils::Fs::toNativePath(session->torrentExportDirectory());
strValue = session->torrentExportDirectory();
if (strValue.isEmpty()) {
// Disable
m_ui->checkExportDir->setChecked(false);
m_ui->textExportDir->setEnabled(false);
m_ui->browseExportDirButton->setEnabled(false);
}
else {
// Enable
m_ui->checkExportDir->setChecked(true);
m_ui->textExportDir->setEnabled(true);
m_ui->browseExportDirButton->setEnabled(true);
m_ui->textExportDir->setText(strValue);
m_ui->textExportDir->setSelectedPath(strValue);
}
strValue = Utils::Fs::toNativePath(session->finishedTorrentExportDirectory());
strValue = session->finishedTorrentExportDirectory();
if (strValue.isEmpty()) {
// Disable
m_ui->checkExportDirFin->setChecked(false);
m_ui->textExportDirFin->setEnabled(false);
m_ui->browseExportDirFinButton->setEnabled(false);
}
else {
// Enable
m_ui->checkExportDirFin->setChecked(true);
m_ui->textExportDirFin->setEnabled(true);
m_ui->browseExportDirFinButton->setEnabled(true);
m_ui->textExportDirFin->setText(strValue);
m_ui->textExportDirFin->setSelectedPath(strValue);
}
m_ui->groupMailNotification->setChecked(pref->isMailNotificationEnabled());
@ -775,7 +786,7 @@ void OptionsDialog::loadOptions() @@ -775,7 +786,7 @@ void OptionsDialog::loadOptions()
m_ui->mailNotifPassword->setText(pref->getMailNotificationSMTPPassword());
m_ui->autoRunBox->setChecked(pref->isAutoRunEnabled());
m_ui->autoRun_txt->setText(pref->getAutoRunProgram());
m_ui->autoRun_txt->setSelectedPath(pref->getAutoRunProgram());
intValue = pref->getActionOnDblClOnTorrentDl();
if (intValue >= m_ui->actionTorrentDlOnDblClBox->count())
intValue = 0;
@ -880,8 +891,7 @@ void OptionsDialog::loadOptions() @@ -880,8 +891,7 @@ void OptionsDialog::loadOptions()
m_ui->checkIPFilter->setChecked(session->isIPFilteringEnabled());
m_ui->textFilterPath->setEnabled(m_ui->checkIPFilter->isChecked());
m_ui->textFilterPath->setText(Utils::Fs::toNativePath(session->IPFilterFile()));
m_ui->browseFilterButton->setEnabled(m_ui->checkIPFilter->isChecked());
m_ui->textFilterPath->setSelectedPath(session->IPFilterFile());
m_ui->IpFilterRefreshBtn->setEnabled(m_ui->checkIPFilter->isChecked());
m_ui->checkIpFilterTrackers->setChecked(session->isTrackerFilteringEnabled());
// End Connection preferences
@ -1332,14 +1342,14 @@ void OptionsDialog::setLocale(const QString &localeStr) @@ -1332,14 +1342,14 @@ void OptionsDialog::setLocale(const QString &localeStr)
QString OptionsDialog::getTorrentExportDir() const
{
if (m_ui->checkExportDir->isChecked())
return Utils::Fs::expandPathAbs(m_ui->textExportDir->text());
return Utils::Fs::expandPathAbs(m_ui->textExportDir->selectedPath());
return QString();
}
QString OptionsDialog::getFinishedTorrentExportDir() const
{
if (m_ui->checkExportDirFin->isChecked())
return Utils::Fs::expandPathAbs(m_ui->textExportDirFin->text());
return Utils::Fs::expandPathAbs(m_ui->textExportDirFin->selectedPath());
return QString();
}
@ -1420,73 +1430,10 @@ QString OptionsDialog::askForExportDir(const QString& currentExportPath) @@ -1420,73 +1430,10 @@ QString OptionsDialog::askForExportDir(const QString& currentExportPath)
return dir;
}
void OptionsDialog::on_browseFileLogDir_clicked()
{
const QString path = Utils::Fs::expandPathAbs(Utils::Fs::fromNativePath(m_ui->textFileLogPath->text()));
QDir pathDir(path);
QString dir;
if (!path.isEmpty() && pathDir.exists())
dir = QFileDialog::getExistingDirectory(this, tr("Choose a save directory"), pathDir.absolutePath());
else
dir = QFileDialog::getExistingDirectory(this, tr("Choose a save directory"), QDir::homePath());
if (!dir.isNull())
m_ui->textFileLogPath->setText(Utils::Fs::toNativePath(dir));
}
void OptionsDialog::on_browseExportDirButton_clicked()
{
const QString newExportDir = askForExportDir(m_ui->textExportDir->text());
if (!newExportDir.isNull())
m_ui->textExportDir->setText(Utils::Fs::toNativePath(newExportDir));
}
void OptionsDialog::on_browseExportDirFinButton_clicked()
{
const QString newExportDir = askForExportDir(m_ui->textExportDirFin->text());
if (!newExportDir.isNull())
m_ui->textExportDirFin->setText(Utils::Fs::toNativePath(newExportDir));
}
void OptionsDialog::on_browseFilterButton_clicked()
{
QDir lastDir(Utils::Fs::fromNativePath(m_ui->textFilterPath->text()));
QString lastPath = lastDir.exists() ? lastDir.absolutePath() : QDir::homePath();
QString newPath = QFileDialog::getOpenFileName(this, tr("Choose an IP filter file"), lastPath, tr("All supported filters") + QString(" (*.dat *.p2p *.p2b);;.dat (*.dat);;.p2p (*.p2p);;.p2b (*.p2b)"));
if (!newPath.isEmpty())
m_ui->textFilterPath->setText(Utils::Fs::toNativePath(newPath));
}
// Display dialog to choose save dir
void OptionsDialog::on_browseSaveDirButton_clicked()
{
const QString save_path = Utils::Fs::expandPathAbs(m_ui->textSavePath->text());
QDir saveDir(save_path);
QString dir;
if (!save_path.isEmpty() && saveDir.exists())
dir = QFileDialog::getExistingDirectory(this, tr("Choose a save directory"), saveDir.absolutePath());
else
dir = QFileDialog::getExistingDirectory(this, tr("Choose a save directory"), QDir::homePath());
if (!dir.isNull())
m_ui->textSavePath->setText(Utils::Fs::toNativePath(dir));
}
void OptionsDialog::on_browseTempDirButton_clicked()
{
const QString temp_path = Utils::Fs::expandPathAbs(m_ui->textTempPath->text());
QDir tempDir(temp_path);
QString dir;
if (!temp_path.isEmpty() && tempDir.exists())
dir = QFileDialog::getExistingDirectory(this, tr("Choose a save directory"), tempDir.absolutePath());
else
dir = QFileDialog::getExistingDirectory(this, tr("Choose a save directory"), QDir::homePath());
if (!dir.isNull())
m_ui->textTempPath->setText(Utils::Fs::toNativePath(dir));
}
// Return Filter object to apply to BT session
QString OptionsDialog::getFilter() const
{
return Utils::Fs::fromNativePath(m_ui->textFilterPath->text());
return m_ui->textFilterPath->selectedPath();
}
// Web UI

6
src/gui/optionsdlg.h

@ -95,12 +95,6 @@ private slots: @@ -95,12 +95,6 @@ private slots:
void on_IpFilterRefreshBtn_clicked();
void handleIPFilterParsed(bool error, int ruleCount);
void on_banListButton_clicked();
void on_browseFileLogDir_clicked();
void on_browseExportDirButton_clicked();
void on_browseExportDirFinButton_clicked();
void on_browseFilterButton_clicked();
void on_browseSaveDirButton_clicked();
void on_browseTempDirButton_clicked();
void on_randomButton_clicked();
void on_addScanFolderButton_clicked();
void on_removeScanFolderButton_clicked();

229
src/gui/optionsdlg.ui

@ -6,8 +6,8 @@ @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>779</width>
<height>591</height>
<width>1116</width>
<height>838</height>
</rect>
</property>
<property name="windowTitle">
@ -90,7 +90,7 @@ @@ -90,7 +90,7 @@
</widget>
<widget class="QStackedWidget" name="tabOption">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="tabBehaviorPage">
<layout class="QVBoxLayout" name="verticalLayout_10">
@ -390,7 +390,7 @@ @@ -390,7 +390,7 @@
<item>
<widget class="QGroupBox" name="checkShowSystray">
<property name="title">
<string>Show qBittorrent in notification area</string>
<string>Show &amp;qBittorrent in notification area</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -491,7 +491,7 @@ @@ -491,7 +491,7 @@
<item>
<widget class="QGroupBox" name="checkFileLog">
<property name="title">
<string>Log file</string>
<string>&amp;Log file</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -504,26 +504,19 @@ @@ -504,26 +504,19 @@
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Save path:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="textFileLogPath"/>
</item>
<item>
<widget class="QToolButton" name="browseFileLogDir">
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="text">
<string notr="true">...</string>
</property>
</widget>
<widget class="FileSystemPathLineEdit" name="textFileLogPath" native="true"/>
</item>
</layout>
</item>
@ -692,7 +685,7 @@ @@ -692,7 +685,7 @@
<item>
<widget class="QGroupBox" name="checkAdditionDialog">
<property name="title">
<string>Display torrent content and some options</string>
<string>Display &amp;torrent content and some options</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -737,7 +730,7 @@ @@ -737,7 +730,7 @@
<string>Should the .torrent file be deleted after adding it</string>
</property>
<property name="title">
<string>Delete .torrent files afterwards </string>
<string>De&amp;lete .torrent files afterwards </string>
</property>
<property name="checkable">
<bool>true</bool>
@ -969,91 +962,48 @@ @@ -969,91 +962,48 @@
</item>
<item>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="labelSavePath">
<property name="text">
<string>Default Save Path:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLineEdit" name="textSavePath">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="FileSystemPathLineEdit" name="textSavePath" native="true"/>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QToolButton" name="browseSaveDirButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>27</height>
</size>
</property>
<property name="text">
<string notr="true">...</string>
</property>
</widget>
<widget class="FileSystemPathLineEdit" name="textExportDirFin" native="true"/>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkTempFolder">
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="FileSystemPathLineEdit" name="textExportDir" native="true"/>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkExportDirFin">
<property name="text">
<string>Keep incomplete torrents in:</string>
<string>Copy .torrent files for finished downloads to:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_111">
<item>
<widget class="QLineEdit" name="textTempPath"/>
</item>
<item>
<widget class="QToolButton" name="browseTempDirButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>25</horstretch>
<verstretch>27</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>27</height>
</size>
</property>
<property name="text">
<string notr="true">...</string>
</property>
</widget>
<widget class="FileSystemPathLineEdit" name="textTempPath" native="true"/>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelSavePath">
<property name="text">
<string>Default Save Path:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkExportDir">
<property name="text">
@ -1061,65 +1011,13 @@ @@ -1061,65 +1011,13 @@
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLineEdit" name="textExportDir"/>
</item>
<item>
<widget class="QToolButton" name="browseExportDirButton">
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>27</height>
</size>
</property>
<property name="text">
<string notr="true">...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkExportDirFin">
<item row="1" column="0">
<widget class="QCheckBox" name="checkTempFolder">
<property name="text">
<string>Copy .torrent files for finished downloads to:</string>
<string>Keep incomplete torrents in:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QLineEdit" name="textExportDirFin"/>
</item>
<item>
<widget class="QToolButton" name="browseExportDirFinButton">
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>27</height>
</size>
</property>
<property name="text">
<string notr="true">...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
@ -1226,7 +1124,7 @@ @@ -1226,7 +1124,7 @@
<item>
<widget class="QGroupBox" name="groupMailNotification">
<property name="title">
<string>Email notification upon download completion</string>
<string>Email notification &amp;upon download completion</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -1311,7 +1209,7 @@ @@ -1311,7 +1209,7 @@
<item>
<widget class="QGroupBox" name="autoRunBox">
<property name="title">
<string>Run external program on torrent completion</string>
<string>Run e&amp;xternal program on torrent completion</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -1321,7 +1219,7 @@ @@ -1321,7 +1219,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_19">
<item>
<widget class="QLineEdit" name="autoRun_txt"/>
<widget class="FileSystemPathLineEdit" name="autoRun_txt" native="true"/>
</item>
<item>
<widget class="QLabel" name="autoRun_param">
@ -1681,7 +1579,7 @@ @@ -1681,7 +1579,7 @@
<bool>false</bool>
</property>
<property name="title">
<string>Authentication</string>
<string>A&amp;uthentication</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -1734,7 +1632,7 @@ @@ -1734,7 +1632,7 @@
<item>
<widget class="QGroupBox" name="groupIPFilter">
<property name="title">
<string>IP Filtering</string>
<string>IP Fi&amp;ltering</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_17">
<item>
@ -1747,20 +1645,7 @@ @@ -1747,20 +1645,7 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="textFilterPath"/>
</item>
<item>
<widget class="QToolButton" name="browseFilterButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="text">
<string notr="true">...</string>
</property>
</widget>
<widget class="FileSystemPathLineEdit" name="textFilterPath" native="true"/>
</item>
<item>
<widget class="QToolButton" name="IpFilterRefreshBtn">
@ -1946,7 +1831,7 @@ @@ -1946,7 +1831,7 @@
<item row="2" column="0" colspan="5">
<widget class="QGroupBox" name="check_schedule">
<property name="title">
<string>Schedule the use of alternative rate limits</string>
<string>Schedule &amp;the use of alternative rate limits</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -2363,7 +2248,7 @@ @@ -2363,7 +2248,7 @@
<item>
<widget class="QGroupBox" name="checkEnableQueueing">
<property name="title">
<string>Torrent Queueing</string>
<string>&amp;Torrent Queueing</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -2562,7 +2447,7 @@ @@ -2562,7 +2447,7 @@
</sizepolicy>
</property>
<property name="title">
<string>Automatically add these trackers to new downloads:</string>
<string>A&amp;utomatically add these trackers to new downloads:</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -2813,7 +2698,7 @@ @@ -2813,7 +2698,7 @@
<item>
<widget class="QGroupBox" name="checkWebUiHttps">
<property name="title">
<string>Use HTTPS instead of HTTP</string>
<string>&amp;Use HTTPS instead of HTTP</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -3000,7 +2885,7 @@ @@ -3000,7 +2885,7 @@
<item>
<widget class="QGroupBox" name="checkDynDNS">
<property name="title">
<string>Update my dynamic domain name</string>
<string>Upda&amp;te my dynamic domain name</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -3139,11 +3024,17 @@ @@ -3139,11 +3024,17 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>FileSystemPathLineEdit</class>
<extends>QWidget</extends>
<header>fspathedit.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>tabOption</tabstop>
<tabstop>comboI18n</tabstop>
<tabstop>textSavePath</tabstop>
<tabstop>browseSaveDirButton</tabstop>
<tabstop>checkStartPaused</tabstop>
<tabstop>spinPort</tabstop>
<tabstop>checkUPnP</tabstop>

Loading…
Cancel
Save