mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-25 10:46:15 +03:00
Implement search filters in the proxy model. Partially closes #972
This commit is contained in:
parent
93d8cadaaf
commit
1336cb7a61
16 changed files with 704 additions and 133 deletions
|
@ -86,7 +86,9 @@ static struct { const char *source; const char *comment; } units[] = {
|
|||
QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)")
|
||||
QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "PiB", "pebibytes (1024 tebibytes)"),
|
||||
QT_TRANSLATE_NOOP3("misc", "EiB", "exbibytes (1024 pebibytes)")
|
||||
};
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
|
@ -318,30 +320,58 @@ QString Utils::Misc::pythonVersionComplete() {
|
|||
return version;
|
||||
}
|
||||
|
||||
// return best userfriendly storage unit (B, KiB, MiB, GiB, TiB)
|
||||
QString Utils::Misc::unitString(Utils::Misc::SizeUnit unit)
|
||||
{
|
||||
return QCoreApplication::translate("misc",
|
||||
units[static_cast<int>(unit)].source, units[static_cast<int>(unit)].comment);
|
||||
}
|
||||
|
||||
// return best userfriendly storage unit (B, KiB, MiB, GiB, TiB, ...)
|
||||
// use Binary prefix standards from IEC 60027-2
|
||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||
// value must be given in bytes
|
||||
// to send numbers instead of strings with suffixes
|
||||
QString Utils::Misc::friendlyUnit(qreal val, bool is_speed)
|
||||
bool Utils::Misc::friendlyUnit(qint64 sizeInBytes, qreal &val, Utils::Misc::SizeUnit &unit)
|
||||
{
|
||||
if (val < 0)
|
||||
return QCoreApplication::translate("misc", "Unknown", "Unknown (size)");
|
||||
if (sizeInBytes < 0) return false;
|
||||
|
||||
int i = 0;
|
||||
while(val >= 1024. && i < 4) {
|
||||
val /= 1024.;
|
||||
qreal rawVal = static_cast<qreal>(sizeInBytes);
|
||||
|
||||
while ((rawVal >= 1024.) && (i <= static_cast<int>(SizeUnit::ExbiByte))) {
|
||||
rawVal /= 1024.;
|
||||
++i;
|
||||
}
|
||||
val = rawVal;
|
||||
unit = static_cast<SizeUnit>(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Utils::Misc::friendlyUnit(qint64 bytesValue, bool isSpeed)
|
||||
{
|
||||
SizeUnit unit;
|
||||
qreal friendlyVal;
|
||||
if (!friendlyUnit(bytesValue, friendlyVal, unit)) {
|
||||
return QCoreApplication::translate("misc", "Unknown", "Unknown (size)");
|
||||
}
|
||||
QString ret;
|
||||
if (i == 0)
|
||||
ret = QString::number((long)val) + " " + QCoreApplication::translate("misc", units[0].source, units[0].comment);
|
||||
if (unit == SizeUnit::Byte)
|
||||
ret = QString::number(bytesValue) + " " + unitString(unit);
|
||||
else
|
||||
ret = Utils::String::fromDouble(val, 1) + " " + QCoreApplication::translate("misc", units[i].source, units[i].comment);
|
||||
if (is_speed)
|
||||
ret = Utils::String::fromDouble(friendlyVal, 1) + " " + unitString(unit);
|
||||
if (isSpeed)
|
||||
ret += QCoreApplication::translate("misc", "/s", "per second");
|
||||
return ret;
|
||||
}
|
||||
|
||||
qlonglong Utils::Misc::sizeInBytes(qreal size, Utils::Misc::SizeUnit unit)
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(unit); ++i) {
|
||||
size *= 1024;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool Utils::Misc::isPreviewable(const QString& extension)
|
||||
{
|
||||
static QSet<QString> multimedia_extensions;
|
||||
|
|
|
@ -48,6 +48,22 @@ namespace Utils
|
|||
{
|
||||
namespace Misc
|
||||
{
|
||||
// use binary prefix standards from IEC 60027-2
|
||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||
enum class SizeUnit
|
||||
{
|
||||
Byte, // 1024^0,
|
||||
KibiByte, // 1024^1,
|
||||
MebiByte, // 1024^2,
|
||||
GibiByte, // 1024^3,
|
||||
TebiByte, // 1024^4,
|
||||
PebiByte, // 1024^5,
|
||||
ExbiByte // 1024^6,
|
||||
// int64 is used for sizes and thus the next units can not be handled
|
||||
// ZebiByte, // 1024^7,
|
||||
// YobiByte, // 1024^8
|
||||
};
|
||||
|
||||
QString parseHtmlLinks(const QString &raw_text);
|
||||
bool isUrl(const QString &s);
|
||||
|
||||
|
@ -64,11 +80,15 @@ namespace Utils
|
|||
int pythonVersion();
|
||||
QString pythonExecutable();
|
||||
QString pythonVersionComplete();
|
||||
// return best userfriendly storage unit (B, KiB, MiB, GiB, TiB)
|
||||
// use Binary prefix standards from IEC 60027-2
|
||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||
|
||||
QString unitString(SizeUnit unit);
|
||||
|
||||
// return best user friendly storage unit (B, KiB, MiB, GiB, TiB)
|
||||
// value must be given in bytes
|
||||
QString friendlyUnit(qreal val, bool is_speed = false);
|
||||
bool friendlyUnit(qint64 sizeInBytes, qreal& val, SizeUnit& unit);
|
||||
QString friendlyUnit(qint64 bytesValue, bool isSpeed = false);
|
||||
qint64 sizeInBytes(qreal size, SizeUnit unit);
|
||||
|
||||
bool isPreviewable(const QString& extension);
|
||||
|
||||
// Take a number of seconds and return an user-friendly
|
||||
|
|
|
@ -113,6 +113,7 @@ FORMS += \
|
|||
$$PWD/torrentcreatordlg.ui \
|
||||
$$PWD/search/searchwidget.ui \
|
||||
$$PWD/search/pluginselectdlg.ui \
|
||||
$$PWD/search/pluginsourcedlg.ui
|
||||
$$PWD/search/pluginsourcedlg.ui \
|
||||
$$PWD/search/searchtab.ui
|
||||
|
||||
RESOURCES += $$PWD/about.qrc
|
||||
|
|
|
@ -56,7 +56,7 @@ void SearchListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
|||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, (index.data().toLongLong() >= 0) ? index.data().toString() : tr("Unknown"));
|
||||
break;
|
||||
case SearchSortModel::LEECHS:
|
||||
case SearchSortModel::LEECHES:
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, (index.data().toLongLong() >= 0) ? index.data().toString() : tr("Unknown"));
|
||||
break;
|
||||
|
|
|
@ -29,26 +29,136 @@
|
|||
#include "searchsortmodel.h"
|
||||
|
||||
SearchSortModel::SearchSortModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
: base(parent)
|
||||
, m_isNameFilterEnabled(false)
|
||||
, m_minSeeds(0)
|
||||
, m_maxSeeds(-1)
|
||||
, m_minLeeches(0)
|
||||
, m_maxLeeches(-1)
|
||||
, m_minSize(0)
|
||||
, m_maxSize(-1)
|
||||
{
|
||||
}
|
||||
|
||||
void SearchSortModel::enableNameFilter(bool enable)
|
||||
{
|
||||
m_isNameFilterEnabled = enable;
|
||||
}
|
||||
|
||||
void SearchSortModel::setNameFilter(const QString &searchTerm)
|
||||
{
|
||||
m_searchTerm = searchTerm;
|
||||
if (searchTerm.length() > 2
|
||||
&& searchTerm.startsWith(QLatin1Char('"')) && searchTerm.endsWith(QLatin1Char('"'))) {
|
||||
m_searchTermWords = QStringList(m_searchTerm.mid(1, m_searchTerm.length() - 2));
|
||||
}
|
||||
else {
|
||||
m_searchTermWords = searchTerm.split(QLatin1Char(' '), QString::SkipEmptyParts);
|
||||
}
|
||||
}
|
||||
|
||||
void SearchSortModel::setSizeFilter(qint64 minSize, qint64 maxSize)
|
||||
{
|
||||
m_minSize = std::max(static_cast<qint64>(0), minSize);
|
||||
m_maxSize = std::max(static_cast<qint64>(-1), maxSize);
|
||||
}
|
||||
|
||||
void SearchSortModel::setSeedsFilter(int minSeeds, int maxSeeds)
|
||||
{
|
||||
m_minSeeds = std::max(0, minSeeds);
|
||||
m_maxSeeds = std::max(-1, maxSeeds);
|
||||
}
|
||||
|
||||
void SearchSortModel::setLeechesFilter(int minLeeches, int maxLeeches)
|
||||
{
|
||||
m_minLeeches = std::max(0, minLeeches);
|
||||
m_maxLeeches = std::max(-1, maxLeeches);
|
||||
}
|
||||
|
||||
bool SearchSortModel::isNameFilterEnabled() const
|
||||
{
|
||||
return m_isNameFilterEnabled;
|
||||
}
|
||||
|
||||
QString SearchSortModel::searchTerm() const
|
||||
{
|
||||
return m_searchTerm;
|
||||
}
|
||||
|
||||
int SearchSortModel::minSeeds() const
|
||||
{
|
||||
return m_minSeeds;
|
||||
}
|
||||
|
||||
int SearchSortModel::maxSeeds() const
|
||||
{
|
||||
return m_maxSeeds;
|
||||
}
|
||||
|
||||
qint64 SearchSortModel::minSize() const
|
||||
{
|
||||
return m_minSize;
|
||||
}
|
||||
|
||||
qint64 SearchSortModel::maxSize() const
|
||||
{
|
||||
return m_maxSize;
|
||||
}
|
||||
|
||||
bool SearchSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
if ((sortColumn() == NAME) || (sortColumn() == ENGINE_URL)) {
|
||||
QVariant vL = sourceModel()->data(left);
|
||||
QVariant vR = sourceModel()->data(right);
|
||||
if (!(vL.isValid() && vR.isValid()))
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
return base::lessThan(left, right);
|
||||
Q_ASSERT(vL.isValid());
|
||||
Q_ASSERT(vR.isValid());
|
||||
|
||||
bool res = false;
|
||||
if (Utils::String::naturalSort(vL.toString(), vR.toString(), res))
|
||||
return res;
|
||||
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
return base::lessThan(left, right);
|
||||
}
|
||||
|
||||
bool SearchSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
const QAbstractItemModel* const sourceModel = this->sourceModel();
|
||||
if (m_isNameFilterEnabled && !m_searchTerm.isEmpty()) {
|
||||
QString name = sourceModel->data(sourceModel->index(sourceRow, NAME, sourceParent)).toString();
|
||||
for (const QString& word: m_searchTermWords) {
|
||||
int i = name.indexOf(word, 0, Qt::CaseInsensitive);
|
||||
if (i == -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_minSize > 0 || m_maxSize >= 0) {
|
||||
qlonglong size = sourceModel->data(sourceModel->index(sourceRow, SIZE, sourceParent)).toLongLong();
|
||||
if ((m_minSize > 0 && size < m_minSize)
|
||||
|| (m_maxSize > 0 && size > m_maxSize)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_minSeeds > 0 || m_maxSeeds >= 0) {
|
||||
int seeds = sourceModel->data(sourceModel->index(sourceRow, SEEDS, sourceParent)).toInt();
|
||||
if ((m_minSeeds > 0 && seeds < m_minSeeds)
|
||||
|| (m_maxSeeds > 0 && seeds > m_maxSeeds)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_minLeeches > 0 || m_maxLeeches >= 0) {
|
||||
int leeches = sourceModel->data(sourceModel->index(sourceRow, LEECHES, sourceParent)).toInt();
|
||||
if ((m_minLeeches > 0 && leeches < m_minLeeches)
|
||||
|| (m_maxLeeches > 0 && leeches > m_maxLeeches)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return base::filterAcceptsRow(sourceRow, sourceParent);
|
||||
}
|
||||
|
|
|
@ -30,17 +30,20 @@
|
|||
#define SEARCHSORTMODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStringList>
|
||||
#include "base/utils/string.h"
|
||||
|
||||
class SearchSortModel: public QSortFilterProxyModel
|
||||
{
|
||||
using base = QSortFilterProxyModel;
|
||||
|
||||
public:
|
||||
enum SearchColumn
|
||||
{
|
||||
NAME,
|
||||
SIZE,
|
||||
SEEDS,
|
||||
LEECHS,
|
||||
LEECHES,
|
||||
ENGINE_URL,
|
||||
DL_LINK,
|
||||
DESC_LINK,
|
||||
|
@ -49,8 +52,45 @@ public:
|
|||
|
||||
explicit SearchSortModel(QObject *parent = 0);
|
||||
|
||||
void enableNameFilter(bool enabled);
|
||||
void setNameFilter(const QString& searchTerm = QString());
|
||||
|
||||
//! \brief Sets parameters for filtering by size
|
||||
//! \param minSize minimal size in bytes
|
||||
//! \param maxSize maximal size in bytes, negative value to disable filtering
|
||||
void setSizeFilter(qint64 minSize, qint64 maxSize);
|
||||
|
||||
//! \brief Sets parameters for filtering by seeds number
|
||||
//! \param minSeeds minimal number of seeders
|
||||
//! \param maxSeeds maximal number of seeders, negative value to disable filtering
|
||||
void setSeedsFilter(int minSeeds, int maxSeeds);
|
||||
|
||||
//! \brief Sets parameters for filtering by leeches number
|
||||
//! \param minLeeches minimal number of leechers
|
||||
//! \param maxLeeches maximal number of leechers, negative value to disable filtering
|
||||
void setLeechesFilter(int minLeeches, int maxLeeches);
|
||||
|
||||
bool isNameFilterEnabled() const;
|
||||
|
||||
QString searchTerm() const;
|
||||
|
||||
int minSeeds() const;
|
||||
int maxSeeds() const;
|
||||
|
||||
qint64 minSize() const;
|
||||
qint64 maxSize() const;
|
||||
|
||||
protected:
|
||||
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
private:
|
||||
bool m_isNameFilterEnabled;
|
||||
QString m_searchTerm;
|
||||
QStringList m_searchTermWords;
|
||||
int m_minSeeds, m_maxSeeds;
|
||||
int m_minLeeches, m_maxLeeches;
|
||||
qint64 m_minSize, m_maxSize;
|
||||
};
|
||||
|
||||
#endif // SEARCHSORTMODEL_H
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
*/
|
||||
|
||||
#include <QDir>
|
||||
#include <QMetaEnum>
|
||||
#include <QTreeView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QHeaderView>
|
||||
|
@ -41,16 +42,28 @@
|
|||
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/preferences.h"
|
||||
#include "base/settingsstorage.h"
|
||||
#include "guiiconprovider.h"
|
||||
#include "searchsortmodel.h"
|
||||
#include "searchlistdelegate.h"
|
||||
#include "searchwidget.h"
|
||||
#include "searchtab.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
#define SETTINGS_KEY(name) "Search/" name
|
||||
|
||||
const QString KEY_FILTER_MODE_SETTING_NAME = SETTINGS_KEY("FilteringMode");
|
||||
}
|
||||
|
||||
SearchTab::SearchTab(SearchWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_parent(parent)
|
||||
{
|
||||
m_box = new QVBoxLayout(this);
|
||||
setupUi(this);
|
||||
retranslateUi(this);
|
||||
|
||||
m_box = static_cast<QVBoxLayout*>(this->layout());
|
||||
m_resultsLbl = new QLabel(this);
|
||||
m_resultsBrowser = new QTreeView(this);
|
||||
#ifdef QBT_USES_QT5
|
||||
|
@ -65,14 +78,12 @@ SearchTab::SearchTab(SearchWidget *parent)
|
|||
m_box->addWidget(m_resultsLbl);
|
||||
m_box->addWidget(m_resultsBrowser);
|
||||
|
||||
setLayout(m_box);
|
||||
|
||||
// Set Search results list model
|
||||
m_searchListModel = new QStandardItemModel(0, SearchSortModel::NB_SEARCH_COLUMNS, this);
|
||||
m_searchListModel->setHeaderData(SearchSortModel::NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
|
||||
m_searchListModel->setHeaderData(SearchSortModel::SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
|
||||
m_searchListModel->setHeaderData(SearchSortModel::SEEDS, Qt::Horizontal, tr("Seeders", "i.e: Number of full sources"));
|
||||
m_searchListModel->setHeaderData(SearchSortModel::LEECHS, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources"));
|
||||
m_searchListModel->setHeaderData(SearchSortModel::LEECHES, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources"));
|
||||
m_searchListModel->setHeaderData(SearchSortModel::ENGINE_URL, Qt::Horizontal, tr("Search engine"));
|
||||
|
||||
m_proxyModel = new SearchSortModel(this);
|
||||
|
@ -99,6 +110,22 @@ SearchTab::SearchTab(SearchWidget *parent)
|
|||
|
||||
// Sort by Seeds
|
||||
m_resultsBrowser->sortByColumn(SearchSortModel::SEEDS, Qt::DescendingOrder);
|
||||
|
||||
fillFilterComboBoxes();
|
||||
|
||||
updateFilter();
|
||||
|
||||
connect(filterMode, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFilter()));
|
||||
connect(minSeeds, SIGNAL(editingFinished()), this, SLOT(updateFilter()));
|
||||
connect(minSeeds, SIGNAL(valueChanged(int)), this, SLOT(updateFilter()));
|
||||
connect(maxSeeds, SIGNAL(editingFinished()), this, SLOT(updateFilter()));
|
||||
connect(maxSeeds, SIGNAL(valueChanged(int)), this, SLOT(updateFilter()));
|
||||
connect(minSize, SIGNAL(editingFinished()), this, SLOT(updateFilter()));
|
||||
connect(minSize, SIGNAL(valueChanged(double)), this, SLOT(updateFilter()));
|
||||
connect(maxSize, SIGNAL(editingFinished()), this, SLOT(updateFilter()));
|
||||
connect(maxSize, SIGNAL(valueChanged(double)), this, SLOT(updateFilter()));
|
||||
connect(minSizeUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFilter()));
|
||||
connect(maxSizeUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFilter()));
|
||||
}
|
||||
|
||||
void SearchTab::downloadSelectedItem(const QModelIndex &index)
|
||||
|
@ -123,24 +150,18 @@ bool SearchTab::loadColWidthResultsList()
|
|||
return false;
|
||||
|
||||
unsigned int listSize = widthList.size();
|
||||
for (unsigned int i = 0; i < listSize; ++i) {
|
||||
for (unsigned int i = 0; i < listSize; ++i)
|
||||
m_resultsBrowser->header()->resizeSection(i, widthList.at(i).toInt());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QLabel* SearchTab::getCurrentLabel() const
|
||||
{
|
||||
return m_resultsLbl;
|
||||
}
|
||||
|
||||
QTreeView* SearchTab::getCurrentTreeView() const
|
||||
{
|
||||
return m_resultsBrowser;
|
||||
}
|
||||
|
||||
QSortFilterProxyModel* SearchTab::getCurrentSearchListProxy() const
|
||||
SearchSortModel* SearchTab::getCurrentSearchListProxy() const
|
||||
{
|
||||
return m_proxyModel;
|
||||
}
|
||||
|
@ -154,19 +175,128 @@ QStandardItemModel* SearchTab::getCurrentSearchListModel() const
|
|||
void SearchTab::setRowColor(int row, QString color)
|
||||
{
|
||||
m_proxyModel->setDynamicSortFilter(false);
|
||||
for (int i = 0; i < m_proxyModel->columnCount(); ++i) {
|
||||
for (int i = 0; i < m_proxyModel->columnCount(); ++i)
|
||||
m_proxyModel->setData(m_proxyModel->index(row, i), QVariant(QColor(color)), Qt::ForegroundRole);
|
||||
}
|
||||
|
||||
m_proxyModel->setDynamicSortFilter(true);
|
||||
}
|
||||
|
||||
QString SearchTab::status() const
|
||||
SearchTab::Status SearchTab::status() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
void SearchTab::setStatus(const QString &value)
|
||||
void SearchTab::setStatus(Status value)
|
||||
{
|
||||
m_status = value;
|
||||
setStatusTip(statusText(value));
|
||||
const int thisTabIndex = m_parent->searchTabs()->indexOf(this);
|
||||
m_parent->searchTabs()->setTabToolTip(thisTabIndex, statusTip());
|
||||
m_parent->searchTabs()->setTabIcon(thisTabIndex, GuiIconProvider::instance()->getIcon(statusIconName(value)));
|
||||
}
|
||||
|
||||
void SearchTab::updateResultsCount()
|
||||
{
|
||||
const int totalResults = getCurrentSearchListModel() ? getCurrentSearchListModel()->rowCount(QModelIndex()) : 0;
|
||||
const int filteredResults = getCurrentSearchListProxy() ? getCurrentSearchListProxy()->rowCount(QModelIndex()) : totalResults;
|
||||
m_resultsLbl->setText(tr("Results (showing <i>%1</i> out of <i>%2</i>):", "i.e: Search results")
|
||||
.arg(filteredResults).arg(totalResults));
|
||||
}
|
||||
|
||||
void SearchTab::updateFilter()
|
||||
{
|
||||
using Utils::Misc::SizeUnit;
|
||||
SearchSortModel* filterModel = getCurrentSearchListProxy();
|
||||
filterModel->enableNameFilter(filteringMode() == OnlyNames);
|
||||
// we update size and seeds filter parameters in the model even if they are disabled
|
||||
// because we need to read them from the model when search tabs switch
|
||||
filterModel->setSeedsFilter(minSeeds->value(), maxSeeds->value());
|
||||
filterModel->setSizeFilter(
|
||||
sizeInBytes(minSize->value(), static_cast<SizeUnit>(minSizeUnit->currentIndex())),
|
||||
sizeInBytes(maxSize->value(), static_cast<SizeUnit>(maxSizeUnit->currentIndex())));
|
||||
|
||||
SettingsStorage::instance()->storeValue(KEY_FILTER_MODE_SETTING_NAME,
|
||||
filterMode->itemData(filterMode->currentIndex()));
|
||||
filterModel->invalidate();
|
||||
updateResultsCount();
|
||||
}
|
||||
|
||||
void SearchTab::fillFilterComboBoxes()
|
||||
{
|
||||
using Utils::Misc::SizeUnit;
|
||||
QStringList unitStrings;
|
||||
unitStrings.append(unitString(SizeUnit::Byte));
|
||||
unitStrings.append(unitString(SizeUnit::KibiByte));
|
||||
unitStrings.append(unitString(SizeUnit::MebiByte));
|
||||
unitStrings.append(unitString(SizeUnit::GibiByte));
|
||||
unitStrings.append(unitString(SizeUnit::TebiByte));
|
||||
unitStrings.append(unitString(SizeUnit::PebiByte));
|
||||
unitStrings.append(unitString(SizeUnit::ExbiByte));
|
||||
|
||||
minSizeUnit->clear();
|
||||
maxSizeUnit->clear();
|
||||
minSizeUnit->addItems(unitStrings);
|
||||
maxSizeUnit->addItems(unitStrings);
|
||||
|
||||
minSize->setValue(0);
|
||||
minSizeUnit->setCurrentIndex(static_cast<int>(SizeUnit::MebiByte));
|
||||
|
||||
maxSize->setValue(-1);
|
||||
maxSizeUnit->setCurrentIndex(static_cast<int>(SizeUnit::TebiByte));
|
||||
|
||||
filterMode->clear();
|
||||
|
||||
QMetaEnum nameFilteringModeEnum =
|
||||
this->metaObject()->enumerator(this->metaObject()->indexOfEnumerator("NameFilteringMode"));
|
||||
|
||||
filterMode->addItem(tr("Torrent names only"), nameFilteringModeEnum.valueToKey(OnlyNames));
|
||||
filterMode->addItem(tr("Everywhere"), nameFilteringModeEnum.valueToKey(Everywhere));
|
||||
|
||||
QVariant selectedMode = SettingsStorage::instance()->loadValue(
|
||||
KEY_FILTER_MODE_SETTING_NAME, nameFilteringModeEnum.valueToKey(OnlyNames));
|
||||
int index = filterMode->findData(selectedMode);
|
||||
filterMode->setCurrentIndex(index == -1 ? 0 : index);
|
||||
}
|
||||
|
||||
QString SearchTab::statusText(SearchTab::Status st)
|
||||
{
|
||||
switch (st) {
|
||||
case Status::Ongoing:
|
||||
return tr("Searching...");
|
||||
case Status::Finished:
|
||||
return tr("Search has finished");
|
||||
case Status::Aborted:
|
||||
return tr("Search aborted");
|
||||
case Status::Error:
|
||||
return tr("An error occurred during search...");
|
||||
case Status::NoResults:
|
||||
return tr("Search returned no results");
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QString SearchTab::statusIconName(SearchTab::Status st)
|
||||
{
|
||||
switch (st) {
|
||||
case Status::Ongoing:
|
||||
return QLatin1String("task-ongoing");
|
||||
case Status::Finished:
|
||||
return QLatin1String("task-complete");
|
||||
case Status::Aborted:
|
||||
return QLatin1String("task-reject");
|
||||
case Status::Error:
|
||||
return QLatin1String("task-attention");
|
||||
case Status::NoResults:
|
||||
return QLatin1String("task-attention");
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
SearchTab::NameFilteringMode SearchTab::filteringMode() const
|
||||
{
|
||||
QMetaEnum metaEnum =
|
||||
this->metaObject()->enumerator(this->metaObject()->indexOfEnumerator("NameFilteringMode"));
|
||||
return static_cast<NameFilteringMode>(metaEnum.keyToValue(filterMode->itemData(filterMode->currentIndex()).toByteArray()));
|
||||
}
|
||||
|
|
|
@ -31,42 +31,71 @@
|
|||
#ifndef SEARCHTAB_H
|
||||
#define SEARCHTAB_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QVariant> // I don't know why <QMetaType> is not enought for Qt's 4.8.7 moc
|
||||
#include "ui_searchtab.h"
|
||||
|
||||
#define ENGINE_URL_COLUMN 4
|
||||
#define URL_COLUMN 5
|
||||
|
||||
class QLabel;
|
||||
class QModelIndex;
|
||||
class QTreeView;
|
||||
class QHeaderView;
|
||||
class QStandardItemModel;
|
||||
class QSortFilterProxyModel;
|
||||
class QModelIndex;
|
||||
class QVBoxLayout;
|
||||
|
||||
class SearchSortModel;
|
||||
class SearchListDelegate;
|
||||
class SearchWidget;
|
||||
|
||||
class SearchTab: public QWidget
|
||||
class SearchTab: public QWidget, private Ui::SearchTab
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SearchTab(SearchWidget *m_parent);
|
||||
|
||||
QLabel* getCurrentLabel() const;
|
||||
enum NameFilteringMode
|
||||
{
|
||||
Everywhere,
|
||||
OnlyNames
|
||||
};
|
||||
|
||||
Q_ENUMS(NameFilteringMode)
|
||||
|
||||
explicit SearchTab(SearchWidget *parent);
|
||||
|
||||
QStandardItemModel* getCurrentSearchListModel() const;
|
||||
QSortFilterProxyModel* getCurrentSearchListProxy() const;
|
||||
SearchSortModel* getCurrentSearchListProxy() const;
|
||||
QTreeView* getCurrentTreeView() const;
|
||||
QHeaderView* header() const;
|
||||
QString status() const;
|
||||
|
||||
bool loadColWidthResultsList();
|
||||
void setRowColor(int row, QString color);
|
||||
void setStatus(const QString &value);
|
||||
|
||||
enum class Status
|
||||
{
|
||||
Ongoing,
|
||||
Finished,
|
||||
Error,
|
||||
Aborted,
|
||||
NoResults
|
||||
};
|
||||
|
||||
void setStatus(Status value);
|
||||
Status status() const;
|
||||
|
||||
void updateResultsCount();
|
||||
|
||||
private slots:
|
||||
void downloadSelectedItem(const QModelIndex &index);
|
||||
void updateFilter();
|
||||
|
||||
private:
|
||||
void fillFilterComboBoxes();
|
||||
NameFilteringMode filteringMode() const;
|
||||
static QString statusText(Status st);
|
||||
static QString statusIconName(Status st);
|
||||
|
||||
QVBoxLayout *m_box;
|
||||
QLabel *m_resultsLbl;
|
||||
QTreeView *m_resultsBrowser;
|
||||
|
@ -74,8 +103,9 @@ private:
|
|||
SearchSortModel *m_proxyModel;
|
||||
SearchListDelegate *m_searchDelegate;
|
||||
SearchWidget *m_parent;
|
||||
QString m_status;
|
||||
Status m_status;
|
||||
};
|
||||
|
||||
#endif // SEARCHTAB_H
|
||||
Q_DECLARE_METATYPE(SearchTab::NameFilteringMode)
|
||||
|
||||
#endif // SEARCHTAB_H
|
||||
|
|
240
src/gui/search/searchtab.ui
Normal file
240
src/gui/search/searchtab.ui
Normal file
|
@ -0,0 +1,240 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SearchTab</class>
|
||||
<widget class="QWidget" name="SearchTab">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1216</width>
|
||||
<height>364</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Search in:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>filterMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="filterMode">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Some search engines search in torrent description and in torrent file names too. Whether such results will be shown in the list below is controlled by this mode.</p><p><span style=" font-weight:600;">Everywhere </span>disables filtering and shows everyhing returned by the search engines.</p><p><span style=" font-weight:600;">Torrent names only</span> shows only torrents whose names match the search query.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>12</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Set minimal and maximal allowed number of seeders</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Seeds:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="minSeeds">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Minimal number of seeds</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="maxSeeds">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Maximal number of seeds</p></body></html></string>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string>∞</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>12</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Set minimal and maximal allowed size of a torrent</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="minSize">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Minimal torrent size</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="minSizeUnit">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="maxSize">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Maximal torrent size</p></body></html></string>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string>∞</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="maxSizeUnit">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -45,6 +45,7 @@
|
|||
#include <QClipboard>
|
||||
#include <QProcess>
|
||||
#include <QDebug>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <iostream>
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -74,7 +75,6 @@ SearchWidget::SearchWidget(MainWindow *mainWindow)
|
|||
, m_mainWindow(mainWindow)
|
||||
, m_isNewQueryString(false)
|
||||
, m_noSearchResults(true)
|
||||
, m_nbSearchResults(0)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
|
@ -82,6 +82,26 @@ SearchWidget::SearchWidget(MainWindow *mainWindow)
|
|||
searchBarLayout->insertWidget(0, m_searchPattern);
|
||||
connect(m_searchPattern, SIGNAL(returnPressed()), searchButton, SLOT(click()));
|
||||
|
||||
QString searchPatternHint;
|
||||
QTextStream stream(&searchPatternHint, QIODevice::WriteOnly);
|
||||
|
||||
stream << "<html><head/><body><p>"
|
||||
<< tr("A phrase to search for.") << "<br>"
|
||||
<< tr("Spaces in a search term may be protected by double quotes.")
|
||||
<< "</p><p>"
|
||||
<< tr("Example:", "Search phrase example")
|
||||
<< "<br>"
|
||||
<< tr("<b>foo bar</b>: search for <b>foo</b> and <b>bar</b>",
|
||||
"Search phrase example, illustrates quotes usage, a pair of "
|
||||
"space delimited words, individal words are highlighted")
|
||||
<< "<br>"
|
||||
<< tr("<b>"foo bar"</b>: search for <b>foo bar</b>",
|
||||
"Search phrase example, illustrates quotes usage, double quoted"
|
||||
"pair of space delimited words, the whole pair is highlighted")
|
||||
<< "</p></body></html>" << flush;
|
||||
|
||||
m_searchPattern->setToolTip(searchPatternHint);
|
||||
|
||||
// Icons
|
||||
searchButton->setIcon(GuiIconProvider::instance()->getIcon("edit-find"));
|
||||
downloadButton->setIcon(GuiIconProvider::instance()->getIcon("download"));
|
||||
|
@ -158,7 +178,6 @@ void SearchWidget::tab_changed(int t)
|
|||
goToDescBtn->setEnabled(false);
|
||||
copyURLBtn->setEnabled(false);
|
||||
}
|
||||
searchStatus->setText(m_currentSearchTab->status());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +206,11 @@ void SearchWidget::giveFocusToSearchInput()
|
|||
m_searchPattern->setFocus();
|
||||
}
|
||||
|
||||
QTabWidget *SearchWidget::searchTabs() const
|
||||
{
|
||||
return tabWidget;
|
||||
}
|
||||
|
||||
// Function called when we click on search button
|
||||
void SearchWidget::on_searchButton_clicked()
|
||||
{
|
||||
|
@ -222,6 +246,7 @@ void SearchWidget::on_searchButton_clicked()
|
|||
tabName.replace(QRegExp("&{1}"), "&&");
|
||||
tabWidget->addTab(m_currentSearchTab, tabName);
|
||||
tabWidget->setCurrentWidget(m_currentSearchTab);
|
||||
m_currentSearchTab->getCurrentSearchListProxy()->setNameFilter(pattern);
|
||||
|
||||
QStringList plugins;
|
||||
if (selectedPlugin() == "all") plugins = m_searchEngine->allPlugins();
|
||||
|
@ -233,10 +258,9 @@ void SearchWidget::on_searchButton_clicked()
|
|||
|
||||
// Update SearchEngine widgets
|
||||
m_noSearchResults = true;
|
||||
m_nbSearchResults = 0;
|
||||
|
||||
// Changing the text of the current label
|
||||
m_activeSearchTab->getCurrentLabel()->setText(tr("Results <i>(%1)</i>:", "i.e: Search results").arg(0));
|
||||
m_activeSearchTab->updateResultsCount();
|
||||
|
||||
// Launch search
|
||||
m_searchEngine->startSearch(pattern, selectedCategory(), plugins);
|
||||
|
@ -268,9 +292,7 @@ void SearchWidget::downloadTorrent(QString url)
|
|||
void SearchWidget::searchStarted()
|
||||
{
|
||||
// Update SearchEngine widgets
|
||||
m_activeSearchTab->setStatus(tr("Searching..."));
|
||||
searchStatus->setText(m_currentSearchTab->status());
|
||||
searchStatus->repaint();
|
||||
m_activeSearchTab->setStatus(SearchTab::Status::Ongoing);
|
||||
searchButton->setText(tr("Stop"));
|
||||
}
|
||||
|
||||
|
@ -285,13 +307,12 @@ void SearchWidget::searchFinished(bool cancelled)
|
|||
if (m_activeSearchTab.isNull()) return; // The active tab was closed
|
||||
|
||||
if (cancelled)
|
||||
m_activeSearchTab->setStatus(tr("Search aborted"));
|
||||
m_activeSearchTab->setStatus(SearchTab::Status::Aborted);
|
||||
else if (m_noSearchResults)
|
||||
m_activeSearchTab->setStatus(tr("Search returned no results"));
|
||||
m_activeSearchTab->setStatus(SearchTab::Status::NoResults);
|
||||
else
|
||||
m_activeSearchTab->setStatus(tr("Search has finished"));
|
||||
m_activeSearchTab->setStatus(SearchTab::Status::Finished);
|
||||
|
||||
searchStatus->setText(m_currentSearchTab->status());
|
||||
m_activeSearchTab = 0;
|
||||
searchButton->setText(tr("Search"));
|
||||
}
|
||||
|
@ -304,9 +325,9 @@ void SearchWidget::searchFailed()
|
|||
if (m_activeSearchTab.isNull()) return; // The active tab was closed
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
m_activeSearchTab->setStatus(tr("Search aborted"));
|
||||
m_activeSearchTab->setStatus(SearchTab::Status::Aborted);
|
||||
#else
|
||||
m_activeSearchTab->setStatus(tr("An error occurred during search..."));
|
||||
m_activeSearchTab->setStatus(SearchTab::Status::Error);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -331,14 +352,13 @@ void SearchWidget::appendSearchResults(const QList<SearchResult> &results)
|
|||
curModel->setData(curModel->index(row, SearchSortModel::NAME), result.fileName); // Name
|
||||
curModel->setData(curModel->index(row, SearchSortModel::SIZE), result.fileSize); // Size
|
||||
curModel->setData(curModel->index(row, SearchSortModel::SEEDS), result.nbSeeders); // Seeders
|
||||
curModel->setData(curModel->index(row, SearchSortModel::LEECHS), result.nbLeechers); // Leechers
|
||||
curModel->setData(curModel->index(row, SearchSortModel::LEECHES), result.nbLeechers); // Leechers
|
||||
curModel->setData(curModel->index(row, SearchSortModel::ENGINE_URL), result.siteUrl); // Search site URL
|
||||
curModel->setData(curModel->index(row, SearchSortModel::DESC_LINK), result.descrLink); // Description Link
|
||||
}
|
||||
|
||||
m_noSearchResults = false;
|
||||
m_nbSearchResults += results.size();
|
||||
m_activeSearchTab->getCurrentLabel()->setText(tr("Results <i>(%1)</i>:", "i.e: Search results").arg(m_nbSearchResults));
|
||||
m_activeSearchTab->updateResultsCount();
|
||||
|
||||
// Enable clear & download buttons
|
||||
downloadButton->setEnabled(true);
|
||||
|
@ -361,7 +381,6 @@ void SearchWidget::closeTab(int index)
|
|||
if (!m_allTabs.size()) {
|
||||
downloadButton->setEnabled(false);
|
||||
goToDescBtn->setEnabled(false);
|
||||
searchStatus->setText(tr("Stopped"));
|
||||
copyURLBtn->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
void downloadTorrent(QString url);
|
||||
void giveFocusToSearchInput();
|
||||
|
||||
QTabWidget* searchTabs() const;
|
||||
|
||||
private slots:
|
||||
// Search slots
|
||||
void tab_changed(int); //to prevent the use of the download button when the tab is empty
|
||||
|
@ -89,7 +91,6 @@ private:
|
|||
bool m_isNewQueryString;
|
||||
bool m_noSearchResults;
|
||||
QByteArray m_searchResultLineTruncated;
|
||||
unsigned long m_nbSearchResults;
|
||||
};
|
||||
|
||||
#endif // SEARCHWIDGET_H
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>820</width>
|
||||
<height>453</height>
|
||||
<width>1382</width>
|
||||
<height>669</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="searchBarLayout">
|
||||
<item>
|
||||
|
@ -32,67 +32,14 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="status_lbl">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Status:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="searchStatus">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stopped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>188</width>
|
||||
<height>21</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget"/>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout">
|
||||
|
|
|
@ -306,6 +306,9 @@
|
|||
<file>icons/oxygen/services.png</file>
|
||||
<file>icons/oxygen/tab-close.png</file>
|
||||
<file>icons/oxygen/task-attention.png</file>
|
||||
<file>icons/oxygen/task-complete.png</file>
|
||||
<file>icons/oxygen/task-ongoing.png</file>
|
||||
<file>icons/oxygen/task-reject.png</file>
|
||||
<file>icons/oxygen/text-plain.png</file>
|
||||
<file>icons/oxygen/tools-report-bug.png</file>
|
||||
<file>icons/oxygen/unavailable.png</file>
|
||||
|
|
BIN
src/icons/oxygen/task-complete.png
Normal file
BIN
src/icons/oxygen/task-complete.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 756 B |
BIN
src/icons/oxygen/task-ongoing.png
Normal file
BIN
src/icons/oxygen/task-ongoing.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 958 B |
BIN
src/icons/oxygen/task-reject.png
Normal file
BIN
src/icons/oxygen/task-reject.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 842 B |
Loading…
Reference in a new issue