Merge pull request #18271 from glassez/v4.5
Backport changes to v4.5.x branch
|
@ -658,8 +658,7 @@ Application::AddTorrentParams Application::parseParams(const QStringList ¶ms
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedParams.torrentSource = param;
|
parsedParams.torrentSources.append(param);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsedParams;
|
return parsedParams;
|
||||||
|
@ -675,10 +674,16 @@ void Application::processParams(const AddTorrentParams ¶ms)
|
||||||
// should be overridden.
|
// should be overridden.
|
||||||
const bool showDialogForThisTorrent = !params.skipTorrentDialog.value_or(!AddNewTorrentDialog::isEnabled());
|
const bool showDialogForThisTorrent = !params.skipTorrentDialog.value_or(!AddNewTorrentDialog::isEnabled());
|
||||||
if (showDialogForThisTorrent)
|
if (showDialogForThisTorrent)
|
||||||
AddNewTorrentDialog::show(params.torrentSource, params.torrentParams, m_window);
|
{
|
||||||
|
for (const QString &torrentSource : params.torrentSources)
|
||||||
|
AddNewTorrentDialog::show(torrentSource, params.torrentParams, m_window);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
BitTorrent::Session::instance()->addTorrent(params.torrentSource, params.torrentParams);
|
{
|
||||||
|
for (const QString &torrentSource : params.torrentSources)
|
||||||
|
BitTorrent::Session::instance()->addTorrent(torrentSource, params.torrentParams);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Application::exec(const QStringList ¶ms)
|
int Application::exec(const QStringList ¶ms)
|
||||||
|
@ -788,12 +793,9 @@ try
|
||||||
});
|
});
|
||||||
|
|
||||||
disconnect(m_desktopIntegration, &DesktopIntegration::activationRequested, this, &Application::createStartupProgressDialog);
|
disconnect(m_desktopIntegration, &DesktopIntegration::activationRequested, this, &Application::createStartupProgressDialog);
|
||||||
// we must not delete menu while it is used by DesktopIntegration
|
|
||||||
auto *oldMenu = m_desktopIntegration->menu();
|
|
||||||
const MainWindow::State windowState = (!m_startupProgressDialog || (m_startupProgressDialog->windowState() & Qt::WindowMinimized))
|
const MainWindow::State windowState = (!m_startupProgressDialog || (m_startupProgressDialog->windowState() & Qt::WindowMinimized))
|
||||||
? MainWindow::Minimized : MainWindow::Normal;
|
? MainWindow::Minimized : MainWindow::Normal;
|
||||||
m_window = new MainWindow(this, windowState);
|
m_window = new MainWindow(this, windowState);
|
||||||
delete oldMenu;
|
|
||||||
delete m_startupProgressDialog;
|
delete m_startupProgressDialog;
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
auto *pref = Preferences::instance();
|
auto *pref = Preferences::instance();
|
||||||
|
|
|
@ -148,7 +148,7 @@ private slots:
|
||||||
private:
|
private:
|
||||||
struct AddTorrentParams
|
struct AddTorrentParams
|
||||||
{
|
{
|
||||||
QString torrentSource;
|
QStringList torrentSources;
|
||||||
BitTorrent::AddTorrentParams torrentParams;
|
BitTorrent::AddTorrentParams torrentParams;
|
||||||
std::optional<bool> skipTorrentDialog;
|
std::optional<bool> skipTorrentDialog;
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
const int TORRENTIDLIST_TYPEID = qRegisterMetaType<QVector<BitTorrent::TorrentID>>();
|
const int TORRENTIDLIST_TYPEID = qRegisterMetaType<QVector<BitTorrent::TorrentID>>();
|
||||||
|
|
||||||
|
@ -59,11 +60,11 @@ void BitTorrent::ResumeDataStorage::loadAll() const
|
||||||
loadingThread->start();
|
loadingThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<BitTorrent::LoadedResumeData> BitTorrent::ResumeDataStorage::fetchLoadedResumeData() const
|
QList<BitTorrent::LoadedResumeData> BitTorrent::ResumeDataStorage::fetchLoadedResumeData() const
|
||||||
{
|
{
|
||||||
const QMutexLocker locker {&m_loadedResumeDataMutex};
|
const QMutexLocker locker {&m_loadedResumeDataMutex};
|
||||||
|
|
||||||
const QVector<BitTorrent::LoadedResumeData> loadedResumeData = m_loadedResumeData;
|
const QList<BitTorrent::LoadedResumeData> loadedResumeData = m_loadedResumeData;
|
||||||
m_loadedResumeData.clear();
|
m_loadedResumeData.clear();
|
||||||
|
|
||||||
return loadedResumeData;
|
return loadedResumeData;
|
||||||
|
|
|
@ -29,9 +29,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QtContainerFwd>
|
#include <QtContainerFwd>
|
||||||
|
#include <QList>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
#include "base/3rdparty/expected.hpp"
|
#include "base/3rdparty/expected.hpp"
|
||||||
#include "base/path.h"
|
#include "base/path.h"
|
||||||
|
@ -65,7 +65,7 @@ namespace BitTorrent
|
||||||
virtual void storeQueue(const QVector<TorrentID> &queue) const = 0;
|
virtual void storeQueue(const QVector<TorrentID> &queue) const = 0;
|
||||||
|
|
||||||
void loadAll() const;
|
void loadAll() const;
|
||||||
QVector<LoadedResumeData> fetchLoadedResumeData() const;
|
QList<LoadedResumeData> fetchLoadedResumeData() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void loadStarted(const QVector<BitTorrent::TorrentID> &torrents);
|
void loadStarted(const QVector<BitTorrent::TorrentID> &torrents);
|
||||||
|
@ -78,7 +78,7 @@ namespace BitTorrent
|
||||||
virtual void doLoadAll() const = 0;
|
virtual void doLoadAll() const = 0;
|
||||||
|
|
||||||
const Path m_path;
|
const Path m_path;
|
||||||
mutable QVector<LoadedResumeData> m_loadedResumeData;
|
mutable QList<LoadedResumeData> m_loadedResumeData;
|
||||||
mutable QMutex m_loadedResumeDataMutex;
|
mutable QMutex m_loadedResumeDataMutex;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,9 +403,6 @@ namespace BitTorrent
|
||||||
virtual Torrent *findTorrent(const InfoHash &infoHash) const = 0;
|
virtual Torrent *findTorrent(const InfoHash &infoHash) const = 0;
|
||||||
virtual QVector<Torrent *> torrents() const = 0;
|
virtual QVector<Torrent *> torrents() const = 0;
|
||||||
virtual qsizetype torrentsCount() const = 0;
|
virtual qsizetype torrentsCount() const = 0;
|
||||||
virtual bool hasActiveTorrents() const = 0;
|
|
||||||
virtual bool hasUnfinishedTorrents() const = 0;
|
|
||||||
virtual bool hasRunningSeed() const = 0;
|
|
||||||
virtual const SessionStatus &status() const = 0;
|
virtual const SessionStatus &status() const = 0;
|
||||||
virtual const CacheStatus &cacheStatus() const = 0;
|
virtual const CacheStatus &cacheStatus() const = 0;
|
||||||
virtual bool isListening() const = 0;
|
virtual bool isListening() const = 0;
|
||||||
|
|
|
@ -322,7 +322,7 @@ struct BitTorrent::SessionImpl::ResumeSessionContext final : public QObject
|
||||||
|
|
||||||
ResumeDataStorage *startupStorage = nullptr;
|
ResumeDataStorage *startupStorage = nullptr;
|
||||||
ResumeDataStorageType currentStorageType = ResumeDataStorageType::Legacy;
|
ResumeDataStorageType currentStorageType = ResumeDataStorageType::Legacy;
|
||||||
QVector<LoadedResumeData> loadedResumeData;
|
QList<LoadedResumeData> loadedResumeData;
|
||||||
int processingResumeDataCount = 0;
|
int processingResumeDataCount = 0;
|
||||||
int64_t totalResumeDataCount = 0;
|
int64_t totalResumeDataCount = 0;
|
||||||
int64_t finishedResumeDataCount = 0;
|
int64_t finishedResumeDataCount = 0;
|
||||||
|
@ -2190,30 +2190,6 @@ Torrent *SessionImpl::findTorrent(const InfoHash &infoHash) const
|
||||||
return m_torrents.value(altID);
|
return m_torrents.value(altID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SessionImpl::hasActiveTorrents() const
|
|
||||||
{
|
|
||||||
return std::any_of(m_torrents.begin(), m_torrents.end(), [](TorrentImpl *torrent)
|
|
||||||
{
|
|
||||||
return TorrentFilter::ActiveTorrent.match(torrent);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SessionImpl::hasUnfinishedTorrents() const
|
|
||||||
{
|
|
||||||
return std::any_of(m_torrents.begin(), m_torrents.end(), [](const TorrentImpl *torrent)
|
|
||||||
{
|
|
||||||
return (!torrent->isSeed() && !torrent->isPaused() && !torrent->isErrored() && torrent->hasMetadata());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SessionImpl::hasRunningSeed() const
|
|
||||||
{
|
|
||||||
return std::any_of(m_torrents.begin(), m_torrents.end(), [](const TorrentImpl *torrent)
|
|
||||||
{
|
|
||||||
return (torrent->isSeed() && !torrent->isPaused());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void SessionImpl::banIP(const QString &ip)
|
void SessionImpl::banIP(const QString &ip)
|
||||||
{
|
{
|
||||||
QStringList bannedIPs = m_bannedIPs;
|
QStringList bannedIPs = m_bannedIPs;
|
||||||
|
@ -2811,6 +2787,19 @@ bool SessionImpl::downloadMetadata(const MagnetUri &magnetUri)
|
||||||
|
|
||||||
lt::add_torrent_params p = magnetUri.addTorrentParams();
|
lt::add_torrent_params p = magnetUri.addTorrentParams();
|
||||||
|
|
||||||
|
if (isAddTrackersEnabled())
|
||||||
|
{
|
||||||
|
// Use "additional trackers" when metadata retrieving (this can help when the DHT nodes are few)
|
||||||
|
p.trackers.reserve(p.trackers.size() + static_cast<std::size_t>(m_additionalTrackerList.size()));
|
||||||
|
p.tracker_tiers.reserve(p.trackers.size() + static_cast<std::size_t>(m_additionalTrackerList.size()));
|
||||||
|
p.tracker_tiers.resize(p.trackers.size(), 0);
|
||||||
|
for (const TrackerEntry &trackerEntry : asConst(m_additionalTrackerList))
|
||||||
|
{
|
||||||
|
p.trackers.push_back(trackerEntry.url.toStdString());
|
||||||
|
p.tracker_tiers.push_back(trackerEntry.tier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
// Preallocation mode
|
// Preallocation mode
|
||||||
if (isPreallocationEnabled())
|
if (isPreallocationEnabled())
|
||||||
|
@ -4638,7 +4627,11 @@ void SessionImpl::handleTorrentFinished(TorrentImpl *const torrent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasUnfinishedTorrents())
|
const bool hasUnfinishedTorrents = std::any_of(m_torrents.cbegin(), m_torrents.cend(), [](const TorrentImpl *torrent)
|
||||||
|
{
|
||||||
|
return !(torrent->isSeed() || torrent->isPaused() || torrent->isErrored());
|
||||||
|
});
|
||||||
|
if (!hasUnfinishedTorrents)
|
||||||
emit allTorrentsFinished();
|
emit allTorrentsFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -376,9 +376,6 @@ namespace BitTorrent
|
||||||
Torrent *findTorrent(const InfoHash &infoHash) const override;
|
Torrent *findTorrent(const InfoHash &infoHash) const override;
|
||||||
QVector<Torrent *> torrents() const override;
|
QVector<Torrent *> torrents() const override;
|
||||||
qsizetype torrentsCount() const override;
|
qsizetype torrentsCount() const override;
|
||||||
bool hasActiveTorrents() const override;
|
|
||||||
bool hasUnfinishedTorrents() const override;
|
|
||||||
bool hasRunningSeed() const override;
|
|
||||||
const SessionStatus &status() const override;
|
const SessionStatus &status() const override;
|
||||||
const CacheStatus &cacheStatus() const override;
|
const CacheStatus &cacheStatus() const override;
|
||||||
bool isListening() const override;
|
bool isListening() const override;
|
||||||
|
|
|
@ -996,6 +996,18 @@ void Preferences::resolvePeerHostNames(const bool resolve)
|
||||||
setValue(u"Preferences/Connection/ResolvePeerHostNames"_qs, resolve);
|
setValue(u"Preferences/Connection/ResolvePeerHostNames"_qs, resolve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
|
||||||
|
bool Preferences::useSystemIcons() const
|
||||||
|
{
|
||||||
|
return value(u"Preferences/Advanced/useSystemIconTheme"_qs, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preferences::useSystemIcons(const bool enabled)
|
||||||
|
{
|
||||||
|
setValue(u"Preferences/Advanced/useSystemIconTheme"_qs, enabled);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Preferences::isRecursiveDownloadEnabled() const
|
bool Preferences::isRecursiveDownloadEnabled() const
|
||||||
{
|
{
|
||||||
return !value(u"Preferences/Advanced/DisableRecursiveDownload"_qs, false);
|
return !value(u"Preferences/Advanced/DisableRecursiveDownload"_qs, false);
|
||||||
|
|
|
@ -281,6 +281,10 @@ public:
|
||||||
void resolvePeerCountries(bool resolve);
|
void resolvePeerCountries(bool resolve);
|
||||||
bool resolvePeerHostNames() const;
|
bool resolvePeerHostNames() const;
|
||||||
void resolvePeerHostNames(bool resolve);
|
void resolvePeerHostNames(bool resolve);
|
||||||
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
|
||||||
|
bool useSystemIcons() const;
|
||||||
|
void useSystemIcons(bool enabled);
|
||||||
|
#endif
|
||||||
bool isRecursiveDownloadEnabled() const;
|
bool isRecursiveDownloadEnabled() const;
|
||||||
void setRecursiveDownloadEnabled(bool enable);
|
void setRecursiveDownloadEnabled(bool enable);
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|
|
@ -53,6 +53,8 @@
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QLocale>
|
||||||
#include <QMimeDatabase>
|
#include <QMimeDatabase>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
@ -403,6 +405,94 @@ QString Utils::Misc::getUserIDString()
|
||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Utils::Misc::languageToLocalizedString(const QString &localeStr)
|
||||||
|
{
|
||||||
|
if (localeStr.startsWith(u"eo", Qt::CaseInsensitive))
|
||||||
|
{
|
||||||
|
// QLocale doesn't work with that locale. Esperanto isn't a "real" language.
|
||||||
|
return C_LOCALE_ESPERANTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localeStr.startsWith(u"ltg", Qt::CaseInsensitive))
|
||||||
|
{
|
||||||
|
// QLocale doesn't work with that locale.
|
||||||
|
return C_LOCALE_LATGALIAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QLocale locale {localeStr};
|
||||||
|
switch (locale.language())
|
||||||
|
{
|
||||||
|
case QLocale::Arabic: return C_LOCALE_ARABIC;
|
||||||
|
case QLocale::Armenian: return C_LOCALE_ARMENIAN;
|
||||||
|
case QLocale::Azerbaijani: return C_LOCALE_AZERBAIJANI;
|
||||||
|
case QLocale::Basque: return C_LOCALE_BASQUE;
|
||||||
|
case QLocale::Bulgarian: return C_LOCALE_BULGARIAN;
|
||||||
|
case QLocale::Byelorussian: return C_LOCALE_BYELORUSSIAN;
|
||||||
|
case QLocale::Catalan: return C_LOCALE_CATALAN;
|
||||||
|
case QLocale::Chinese:
|
||||||
|
switch (locale.country())
|
||||||
|
{
|
||||||
|
case QLocale::China: return C_LOCALE_CHINESE_SIMPLIFIED;
|
||||||
|
case QLocale::HongKong: return C_LOCALE_CHINESE_TRADITIONAL_HK;
|
||||||
|
default: return C_LOCALE_CHINESE_TRADITIONAL_TW;
|
||||||
|
}
|
||||||
|
case QLocale::Croatian: return C_LOCALE_CROATIAN;
|
||||||
|
case QLocale::Czech: return C_LOCALE_CZECH;
|
||||||
|
case QLocale::Danish: return C_LOCALE_DANISH;
|
||||||
|
case QLocale::Dutch: return C_LOCALE_DUTCH;
|
||||||
|
case QLocale::English:
|
||||||
|
switch (locale.country())
|
||||||
|
{
|
||||||
|
case QLocale::Australia: return C_LOCALE_ENGLISH_AUSTRALIA;
|
||||||
|
case QLocale::UnitedKingdom: return C_LOCALE_ENGLISH_UNITEDKINGDOM;
|
||||||
|
default: return C_LOCALE_ENGLISH;
|
||||||
|
}
|
||||||
|
case QLocale::Estonian: return C_LOCALE_ESTONIAN;
|
||||||
|
case QLocale::Finnish: return C_LOCALE_FINNISH;
|
||||||
|
case QLocale::French: return C_LOCALE_FRENCH;
|
||||||
|
case QLocale::Galician: return C_LOCALE_GALICIAN;
|
||||||
|
case QLocale::Georgian: return C_LOCALE_GEORGIAN;
|
||||||
|
case QLocale::German: return C_LOCALE_GERMAN;
|
||||||
|
case QLocale::Greek: return C_LOCALE_GREEK;
|
||||||
|
case QLocale::Hebrew: return C_LOCALE_HEBREW;
|
||||||
|
case QLocale::Hindi: return C_LOCALE_HINDI;
|
||||||
|
case QLocale::Hungarian: return C_LOCALE_HUNGARIAN;
|
||||||
|
case QLocale::Icelandic: return C_LOCALE_ICELANDIC;
|
||||||
|
case QLocale::Indonesian: return C_LOCALE_INDONESIAN;
|
||||||
|
case QLocale::Italian: return C_LOCALE_ITALIAN;
|
||||||
|
case QLocale::Japanese: return C_LOCALE_JAPANESE;
|
||||||
|
case QLocale::Korean: return C_LOCALE_KOREAN;
|
||||||
|
case QLocale::Latvian: return C_LOCALE_LATVIAN;
|
||||||
|
case QLocale::Lithuanian: return C_LOCALE_LITHUANIAN;
|
||||||
|
case QLocale::Malay: return C_LOCALE_MALAY;
|
||||||
|
case QLocale::Mongolian: return C_LOCALE_MONGOLIAN;
|
||||||
|
case QLocale::NorwegianBokmal: return C_LOCALE_NORWEGIAN;
|
||||||
|
case QLocale::Occitan: return C_LOCALE_OCCITAN;
|
||||||
|
case QLocale::Persian: return C_LOCALE_PERSIAN;
|
||||||
|
case QLocale::Polish: return C_LOCALE_POLISH;
|
||||||
|
case QLocale::Portuguese:
|
||||||
|
if (locale.country() == QLocale::Brazil)
|
||||||
|
return C_LOCALE_PORTUGUESE_BRAZIL;
|
||||||
|
return C_LOCALE_PORTUGUESE;
|
||||||
|
case QLocale::Romanian: return C_LOCALE_ROMANIAN;
|
||||||
|
case QLocale::Russian: return C_LOCALE_RUSSIAN;
|
||||||
|
case QLocale::Serbian: return C_LOCALE_SERBIAN;
|
||||||
|
case QLocale::Slovak: return C_LOCALE_SLOVAK;
|
||||||
|
case QLocale::Slovenian: return C_LOCALE_SLOVENIAN;
|
||||||
|
case QLocale::Spanish: return C_LOCALE_SPANISH;
|
||||||
|
case QLocale::Swedish: return C_LOCALE_SWEDISH;
|
||||||
|
case QLocale::Thai: return C_LOCALE_THAI;
|
||||||
|
case QLocale::Turkish: return C_LOCALE_TURKISH;
|
||||||
|
case QLocale::Ukrainian: return C_LOCALE_UKRAINIAN;
|
||||||
|
case QLocale::Uzbek: return C_LOCALE_UZBEK;
|
||||||
|
case QLocale::Vietnamese: return C_LOCALE_VIETNAMESE;
|
||||||
|
default:
|
||||||
|
const QString lang = QLocale::languageToString(locale.language());
|
||||||
|
qWarning() << "Unrecognized language name: " << lang;
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString Utils::Misc::parseHtmlLinks(const QString &rawText)
|
QString Utils::Misc::parseHtmlLinks(const QString &rawText)
|
||||||
{
|
{
|
||||||
QString result = rawText;
|
QString result = rawText;
|
||||||
|
|
|
@ -85,6 +85,8 @@ namespace Utils::Misc
|
||||||
QString userFriendlyDuration(qlonglong seconds, qlonglong maxCap = -1);
|
QString userFriendlyDuration(qlonglong seconds, qlonglong maxCap = -1);
|
||||||
QString getUserIDString();
|
QString getUserIDString();
|
||||||
|
|
||||||
|
QString languageToLocalizedString(const QString &localeStr);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
Path windowsSystemPath();
|
Path windowsSystemPath();
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ public:
|
||||||
clear();
|
clear();
|
||||||
if (m_parent)
|
if (m_parent)
|
||||||
{
|
{
|
||||||
m_parent->m_torrentsCount -= m_torrentsCount;
|
m_parent->decreaseTorrentsCount(m_torrentsCount);
|
||||||
const QString uid = m_parent->m_children.key(this);
|
const QString uid = m_parent->m_children.key(this);
|
||||||
m_parent->m_children.remove(uid);
|
m_parent->m_children.remove(uid);
|
||||||
m_parent->m_childUids.removeOne(uid);
|
m_parent->m_childUids.removeOne(uid);
|
||||||
|
@ -86,18 +86,18 @@ public:
|
||||||
return m_torrentsCount;
|
return m_torrentsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void increaseTorrentsCount()
|
void increaseTorrentsCount(const int delta = 1)
|
||||||
{
|
{
|
||||||
++m_torrentsCount;
|
m_torrentsCount += delta;
|
||||||
if (m_parent)
|
if (m_parent)
|
||||||
m_parent->increaseTorrentsCount();
|
m_parent->increaseTorrentsCount(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decreaseTorrentsCount()
|
void decreaseTorrentsCount(const int delta = 1)
|
||||||
{
|
{
|
||||||
--m_torrentsCount;
|
m_torrentsCount -= delta;
|
||||||
if (m_parent)
|
if (m_parent)
|
||||||
m_parent->decreaseTorrentsCount();
|
m_parent->decreaseTorrentsCount(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pos() const
|
int pos() const
|
||||||
|
@ -139,7 +139,7 @@ public:
|
||||||
item->m_parent = this;
|
item->m_parent = this;
|
||||||
m_children[uid] = item;
|
m_children[uid] = item;
|
||||||
m_childUids.append(uid);
|
m_childUids.append(uid);
|
||||||
m_torrentsCount += item->torrentsCount();
|
increaseTorrentsCount(item->torrentsCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
|
@ -211,7 +211,7 @@ QVariant CategoryFilterModel::data(const QModelIndex &index, int role) const
|
||||||
|
|
||||||
if ((index.column() == 0) && (role == Qt::DecorationRole))
|
if ((index.column() == 0) && (role == Qt::DecorationRole))
|
||||||
{
|
{
|
||||||
return UIThemeManager::instance()->getIcon(u"view-categories"_qs);
|
return UIThemeManager::instance()->getIcon(u"view-categories"_qs, u"inode-directory"_qs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((index.column() == 0) && (role == Qt::DisplayRole))
|
if ((index.column() == 0) && (role == Qt::DisplayRole))
|
||||||
|
@ -408,9 +408,9 @@ void CategoryFilterModel::populate()
|
||||||
m_rootItem->addChild(UID_UNCATEGORIZED, new CategoryModelItem(nullptr, tr("Uncategorized"), torrentsCount));
|
m_rootItem->addChild(UID_UNCATEGORIZED, new CategoryModelItem(nullptr, tr("Uncategorized"), torrentsCount));
|
||||||
|
|
||||||
using BitTorrent::Torrent;
|
using BitTorrent::Torrent;
|
||||||
for (const QString &categoryName : asConst(session->categories()))
|
if (m_isSubcategoriesEnabled)
|
||||||
{
|
{
|
||||||
if (m_isSubcategoriesEnabled)
|
for (const QString &categoryName : asConst(session->categories()))
|
||||||
{
|
{
|
||||||
CategoryModelItem *parent = m_rootItem;
|
CategoryModelItem *parent = m_rootItem;
|
||||||
for (const QString &subcat : asConst(session->expandCategory(categoryName)))
|
for (const QString &subcat : asConst(session->expandCategory(categoryName)))
|
||||||
|
@ -419,16 +419,19 @@ void CategoryFilterModel::populate()
|
||||||
if (!parent->hasChild(subcatName))
|
if (!parent->hasChild(subcatName))
|
||||||
{
|
{
|
||||||
const int torrentsCount = std::count_if(torrents.cbegin(), torrents.cend()
|
const int torrentsCount = std::count_if(torrents.cbegin(), torrents.cend()
|
||||||
, [subcat](Torrent *torrent) { return torrent->category() == subcat; });
|
, [subcat](Torrent *torrent) { return torrent->category() == subcat; });
|
||||||
new CategoryModelItem(parent, subcatName, torrentsCount);
|
new CategoryModelItem(parent, subcatName, torrentsCount);
|
||||||
}
|
}
|
||||||
parent = parent->child(subcatName);
|
parent = parent->child(subcatName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const QString &categoryName : asConst(session->categories()))
|
||||||
{
|
{
|
||||||
const int torrentsCount = std::count_if(torrents.begin(), torrents.end()
|
const int torrentsCount = std::count_if(torrents.begin(), torrents.end()
|
||||||
, [categoryName](Torrent *torrent) { return torrent->belongsToCategory(categoryName); });
|
, [categoryName](Torrent *torrent) { return torrent->belongsToCategory(categoryName); });
|
||||||
new CategoryModelItem(m_rootItem, categoryName, torrentsCount);
|
new CategoryModelItem(m_rootItem, categoryName, torrentsCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,18 +121,18 @@ void CategoryFilterWidget::showMenu()
|
||||||
, this, &CategoryFilterWidget::addSubcategory);
|
, this, &CategoryFilterWidget::addSubcategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-rename"_qs), tr("Edit category...")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-rename"_qs, u"document-edit"_qs), tr("Edit category...")
|
||||||
, this, &CategoryFilterWidget::editCategory);
|
, this, &CategoryFilterWidget::editCategory);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs), tr("Remove category")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs, u"list-remove"_qs), tr("Remove category")
|
||||||
, this, &CategoryFilterWidget::removeCategory);
|
, this, &CategoryFilterWidget::removeCategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs), tr("Remove unused categories")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs, u"list-remove"_qs), tr("Remove unused categories")
|
||||||
, this, &CategoryFilterWidget::removeUnusedCategories);
|
, this, &CategoryFilterWidget::removeUnusedCategories);
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs), tr("Resume torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs, u"media-playback-start"_qs), tr("Resume torrents")
|
||||||
, this, &CategoryFilterWidget::actionResumeTorrentsTriggered);
|
, this, &CategoryFilterWidget::actionResumeTorrentsTriggered);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs), tr("Pause torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs, u"media-playback-pause"_qs), tr("Pause torrents")
|
||||||
, this, &CategoryFilterWidget::actionPauseTorrentsTriggered);
|
, this, &CategoryFilterWidget::actionPauseTorrentsTriggered);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("Remove torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("Remove torrents")
|
||||||
, this, &CategoryFilterWidget::actionDeleteTorrentsTriggered);
|
, this, &CategoryFilterWidget::actionDeleteTorrentsTriggered);
|
||||||
|
|
|
@ -99,6 +99,12 @@ DesktopIntegration::DesktopIntegration(QObject *parent)
|
||||||
connect(Preferences::instance(), &Preferences::changed, this, &DesktopIntegration::onPreferencesChanged);
|
connect(Preferences::instance(), &Preferences::changed, this, &DesktopIntegration::onPreferencesChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DesktopIntegration::~DesktopIntegration()
|
||||||
|
{
|
||||||
|
if (m_menu)
|
||||||
|
delete m_menu;
|
||||||
|
}
|
||||||
|
|
||||||
bool DesktopIntegration::isActive() const
|
bool DesktopIntegration::isActive() const
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
|
@ -135,12 +141,36 @@ void DesktopIntegration::setMenu(QMenu *menu)
|
||||||
if (menu == m_menu)
|
if (menu == m_menu)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if defined Q_OS_MACOS
|
||||||
|
if (m_menu)
|
||||||
|
delete m_menu;
|
||||||
|
|
||||||
m_menu = menu;
|
m_menu = menu;
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
if (m_menu)
|
if (m_menu)
|
||||||
m_menu->setAsDockMenu();
|
m_menu->setAsDockMenu();
|
||||||
|
#elif defined Q_OS_UNIX
|
||||||
|
const bool systemTrayEnabled = m_systrayIcon;
|
||||||
|
if (m_menu)
|
||||||
|
{
|
||||||
|
if (m_systrayIcon)
|
||||||
|
{
|
||||||
|
delete m_systrayIcon;
|
||||||
|
m_systrayIcon = nullptr;
|
||||||
|
}
|
||||||
|
delete m_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_menu = menu;
|
||||||
|
|
||||||
|
if (systemTrayEnabled && !m_systrayIcon)
|
||||||
|
createTrayIcon();
|
||||||
#else
|
#else
|
||||||
|
if (m_menu)
|
||||||
|
delete m_menu;
|
||||||
|
|
||||||
|
m_menu = menu;
|
||||||
|
|
||||||
if (m_systrayIcon)
|
if (m_systrayIcon)
|
||||||
m_systrayIcon->setContextMenu(m_menu);
|
m_systrayIcon->setContextMenu(m_menu);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -49,6 +49,7 @@ class DesktopIntegration final : public QObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DesktopIntegration(QObject *parent = nullptr);
|
explicit DesktopIntegration(QObject *parent = nullptr);
|
||||||
|
~DesktopIntegration() override;
|
||||||
|
|
||||||
bool isActive() const;
|
bool isActive() const;
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,8 @@ ExecutionLogWidget::ExecutionLogWidget(const Log::MsgTypes types, QWidget *paren
|
||||||
m_ui->tabBan->layout()->addWidget(peerView);
|
m_ui->tabBan->layout()->addWidget(peerView);
|
||||||
|
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
m_ui->tabConsole->setTabIcon(0, UIThemeManager::instance()->getIcon(u"help-contents"_qs));
|
m_ui->tabConsole->setTabIcon(0, UIThemeManager::instance()->getIcon(u"help-contents"_qs, u"view-calendar-journal"_qs));
|
||||||
m_ui->tabConsole->setTabIcon(1, UIThemeManager::instance()->getIcon(u"ip-blocked"_qs));
|
m_ui->tabConsole->setTabIcon(1, UIThemeManager::instance()->getIcon(u"ip-blocked"_qs, u"view-filter"_qs));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,8 +134,7 @@ MainWindow::MainWindow(IGUIApplication *app, const State initialState)
|
||||||
m_displaySpeedInTitle = pref->speedInTitleBar();
|
m_displaySpeedInTitle = pref->speedInTitleBar();
|
||||||
// Setting icons
|
// Setting icons
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
const QIcon appLogo(UIThemeManager::instance()->getIcon(u"qbittorrent"_qs, u"qbittorrent-tray"_qs));
|
setWindowIcon(UIThemeManager::instance()->getIcon(u"qbittorrent"_qs));
|
||||||
setWindowIcon(appLogo);
|
|
||||||
#endif // Q_OS_MACOS
|
#endif // Q_OS_MACOS
|
||||||
|
|
||||||
#if (defined(Q_OS_UNIX))
|
#if (defined(Q_OS_UNIX))
|
||||||
|
@ -147,7 +146,7 @@ MainWindow::MainWindow(IGUIApplication *app, const State initialState)
|
||||||
m_ui->actionOpen->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
m_ui->actionOpen->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
||||||
m_ui->actionDownloadFromURL->setIcon(UIThemeManager::instance()->getIcon(u"insert-link"_qs));
|
m_ui->actionDownloadFromURL->setIcon(UIThemeManager::instance()->getIcon(u"insert-link"_qs));
|
||||||
m_ui->actionSetGlobalSpeedLimits->setIcon(UIThemeManager::instance()->getIcon(u"speedometer"_qs));
|
m_ui->actionSetGlobalSpeedLimits->setIcon(UIThemeManager::instance()->getIcon(u"speedometer"_qs));
|
||||||
m_ui->actionCreateTorrent->setIcon(UIThemeManager::instance()->getIcon(u"torrent-creator"_qs));
|
m_ui->actionCreateTorrent->setIcon(UIThemeManager::instance()->getIcon(u"torrent-creator"_qs, u"document-edit"_qs));
|
||||||
m_ui->actionAbout->setIcon(UIThemeManager::instance()->getIcon(u"help-about"_qs));
|
m_ui->actionAbout->setIcon(UIThemeManager::instance()->getIcon(u"help-about"_qs));
|
||||||
m_ui->actionStatistics->setIcon(UIThemeManager::instance()->getIcon(u"view-statistics"_qs));
|
m_ui->actionStatistics->setIcon(UIThemeManager::instance()->getIcon(u"view-statistics"_qs));
|
||||||
m_ui->actionTopQueuePos->setIcon(UIThemeManager::instance()->getIcon(u"go-top"_qs));
|
m_ui->actionTopQueuePos->setIcon(UIThemeManager::instance()->getIcon(u"go-top"_qs));
|
||||||
|
@ -159,13 +158,13 @@ MainWindow::MainWindow(IGUIApplication *app, const State initialState)
|
||||||
m_ui->actionDonateMoney->setIcon(UIThemeManager::instance()->getIcon(u"wallet-open"_qs));
|
m_ui->actionDonateMoney->setIcon(UIThemeManager::instance()->getIcon(u"wallet-open"_qs));
|
||||||
m_ui->actionExit->setIcon(UIThemeManager::instance()->getIcon(u"application-exit"_qs));
|
m_ui->actionExit->setIcon(UIThemeManager::instance()->getIcon(u"application-exit"_qs));
|
||||||
m_ui->actionLock->setIcon(UIThemeManager::instance()->getIcon(u"object-locked"_qs));
|
m_ui->actionLock->setIcon(UIThemeManager::instance()->getIcon(u"object-locked"_qs));
|
||||||
m_ui->actionOptions->setIcon(UIThemeManager::instance()->getIcon(u"configure"_qs));
|
m_ui->actionOptions->setIcon(UIThemeManager::instance()->getIcon(u"configure"_qs, u"preferences-system"_qs));
|
||||||
m_ui->actionPause->setIcon(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs));
|
m_ui->actionPause->setIcon(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs, u"media-playback-pause"_qs));
|
||||||
m_ui->actionPauseAll->setIcon(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs));
|
m_ui->actionPauseAll->setIcon(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs, u"media-playback-pause"_qs));
|
||||||
m_ui->actionStart->setIcon(UIThemeManager::instance()->getIcon(u"torrent-start"_qs));
|
m_ui->actionStart->setIcon(UIThemeManager::instance()->getIcon(u"torrent-start"_qs, u"media-playback-start"_qs));
|
||||||
m_ui->actionStartAll->setIcon(UIThemeManager::instance()->getIcon(u"torrent-start"_qs));
|
m_ui->actionStartAll->setIcon(UIThemeManager::instance()->getIcon(u"torrent-start"_qs, u"media-playback-start"_qs));
|
||||||
m_ui->menuAutoShutdownOnDownloadsCompletion->setIcon(UIThemeManager::instance()->getIcon(u"task-complete"_qs));
|
m_ui->menuAutoShutdownOnDownloadsCompletion->setIcon(UIThemeManager::instance()->getIcon(u"task-complete"_qs, u"application-exit"_qs));
|
||||||
m_ui->actionManageCookies->setIcon(UIThemeManager::instance()->getIcon(u"browser-cookies"_qs));
|
m_ui->actionManageCookies->setIcon(UIThemeManager::instance()->getIcon(u"browser-cookies"_qs, u"preferences-web-browser-cookies"_qs));
|
||||||
m_ui->menuLog->setIcon(UIThemeManager::instance()->getIcon(u"help-contents"_qs));
|
m_ui->menuLog->setIcon(UIThemeManager::instance()->getIcon(u"help-contents"_qs));
|
||||||
m_ui->actionCheckForUpdates->setIcon(UIThemeManager::instance()->getIcon(u"view-refresh"_qs));
|
m_ui->actionCheckForUpdates->setIcon(UIThemeManager::instance()->getIcon(u"view-refresh"_qs));
|
||||||
|
|
||||||
|
@ -464,7 +463,6 @@ MainWindow::MainWindow(IGUIApplication *app, const State initialState)
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
app()->desktopIntegration()->setMenu(nullptr);
|
|
||||||
delete m_ui;
|
delete m_ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1139,7 +1137,12 @@ void MainWindow::closeEvent(QCloseEvent *e)
|
||||||
}
|
}
|
||||||
#endif // Q_OS_MACOS
|
#endif // Q_OS_MACOS
|
||||||
|
|
||||||
if (pref->confirmOnExit() && BitTorrent::Session::instance()->hasActiveTorrents())
|
const QVector<BitTorrent::Torrent *> allTorrents = BitTorrent::Session::instance()->torrents();
|
||||||
|
const bool hasActiveTorrents = std::any_of(allTorrents.cbegin(), allTorrents.cend(), [](BitTorrent::Torrent *torrent)
|
||||||
|
{
|
||||||
|
return torrent->isActive();
|
||||||
|
});
|
||||||
|
if (pref->confirmOnExit() && hasActiveTorrents)
|
||||||
{
|
{
|
||||||
if (e->spontaneous() || m_forceExit)
|
if (e->spontaneous() || m_forceExit)
|
||||||
{
|
{
|
||||||
|
@ -1569,7 +1572,7 @@ void MainWindow::downloadFromURLList(const QStringList &urlList)
|
||||||
|
|
||||||
QMenu *MainWindow::createDesktopIntegrationMenu()
|
QMenu *MainWindow::createDesktopIntegrationMenu()
|
||||||
{
|
{
|
||||||
auto *menu = new QMenu(this);
|
auto *menu = new QMenu;
|
||||||
|
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
connect(menu, &QMenu::aboutToShow, this, [this]()
|
connect(menu, &QMenu::aboutToShow, this, [this]()
|
||||||
|
@ -1903,8 +1906,17 @@ void MainWindow::on_actionAutoShutdown_toggled(bool enabled)
|
||||||
|
|
||||||
void MainWindow::updatePowerManagementState()
|
void MainWindow::updatePowerManagementState()
|
||||||
{
|
{
|
||||||
const bool inhibitSuspend = (Preferences::instance()->preventFromSuspendWhenDownloading() && BitTorrent::Session::instance()->hasUnfinishedTorrents())
|
const QVector<BitTorrent::Torrent *> allTorrents = BitTorrent::Session::instance()->torrents();
|
||||||
|| (Preferences::instance()->preventFromSuspendWhenSeeding() && BitTorrent::Session::instance()->hasRunningSeed());
|
const bool hasUnfinishedTorrents = std::any_of(allTorrents.cbegin(), allTorrents.cend(), [](const BitTorrent::Torrent *torrent)
|
||||||
|
{
|
||||||
|
return (!torrent->isSeed() && !torrent->isPaused() && !torrent->isErrored() && torrent->hasMetadata());
|
||||||
|
});
|
||||||
|
const bool hasRunningSeed = std::any_of(allTorrents.cbegin(), allTorrents.cend(), [](const BitTorrent::Torrent *torrent)
|
||||||
|
{
|
||||||
|
return (torrent->isSeed() && !torrent->isPaused());
|
||||||
|
});
|
||||||
|
const bool inhibitSuspend = (Preferences::instance()->preventFromSuspendWhenDownloading() && hasUnfinishedTorrents)
|
||||||
|
|| (Preferences::instance()->preventFromSuspendWhenSeeding() && hasRunningSeed);
|
||||||
m_pwr->setActivityState(inhibitSuspend);
|
m_pwr->setActivityState(inhibitSuspend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,8 @@
|
||||||
#include "base/rss/rss_session.h"
|
#include "base/rss/rss_session.h"
|
||||||
#include "base/torrentfileguard.h"
|
#include "base/torrentfileguard.h"
|
||||||
#include "base/torrentfileswatcher.h"
|
#include "base/torrentfileswatcher.h"
|
||||||
#include "base/unicodestrings.h"
|
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/net.h"
|
#include "base/utils/net.h"
|
||||||
#include "base/utils/password.h"
|
#include "base/utils/password.h"
|
||||||
#include "base/utils/random.h"
|
#include "base/utils/random.h"
|
||||||
|
@ -89,81 +89,6 @@ namespace
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString languageToLocalizedString(const QLocale &locale)
|
|
||||||
{
|
|
||||||
switch (locale.language())
|
|
||||||
{
|
|
||||||
case QLocale::Arabic: return C_LOCALE_ARABIC;
|
|
||||||
case QLocale::Armenian: return C_LOCALE_ARMENIAN;
|
|
||||||
case QLocale::Azerbaijani: return C_LOCALE_AZERBAIJANI;
|
|
||||||
case QLocale::Basque: return C_LOCALE_BASQUE;
|
|
||||||
case QLocale::Bulgarian: return C_LOCALE_BULGARIAN;
|
|
||||||
case QLocale::Byelorussian: return C_LOCALE_BYELORUSSIAN;
|
|
||||||
case QLocale::Catalan: return C_LOCALE_CATALAN;
|
|
||||||
case QLocale::Chinese:
|
|
||||||
switch (locale.country())
|
|
||||||
{
|
|
||||||
case QLocale::China: return C_LOCALE_CHINESE_SIMPLIFIED;
|
|
||||||
case QLocale::HongKong: return C_LOCALE_CHINESE_TRADITIONAL_HK;
|
|
||||||
default: return C_LOCALE_CHINESE_TRADITIONAL_TW;
|
|
||||||
}
|
|
||||||
case QLocale::Croatian: return C_LOCALE_CROATIAN;
|
|
||||||
case QLocale::Czech: return C_LOCALE_CZECH;
|
|
||||||
case QLocale::Danish: return C_LOCALE_DANISH;
|
|
||||||
case QLocale::Dutch: return C_LOCALE_DUTCH;
|
|
||||||
case QLocale::English:
|
|
||||||
switch (locale.country())
|
|
||||||
{
|
|
||||||
case QLocale::Australia: return C_LOCALE_ENGLISH_AUSTRALIA;
|
|
||||||
case QLocale::UnitedKingdom: return C_LOCALE_ENGLISH_UNITEDKINGDOM;
|
|
||||||
default: return C_LOCALE_ENGLISH;
|
|
||||||
}
|
|
||||||
case QLocale::Estonian: return C_LOCALE_ESTONIAN;
|
|
||||||
case QLocale::Finnish: return C_LOCALE_FINNISH;
|
|
||||||
case QLocale::French: return C_LOCALE_FRENCH;
|
|
||||||
case QLocale::Galician: return C_LOCALE_GALICIAN;
|
|
||||||
case QLocale::Georgian: return C_LOCALE_GEORGIAN;
|
|
||||||
case QLocale::German: return C_LOCALE_GERMAN;
|
|
||||||
case QLocale::Greek: return C_LOCALE_GREEK;
|
|
||||||
case QLocale::Hebrew: return C_LOCALE_HEBREW;
|
|
||||||
case QLocale::Hindi: return C_LOCALE_HINDI;
|
|
||||||
case QLocale::Hungarian: return C_LOCALE_HUNGARIAN;
|
|
||||||
case QLocale::Icelandic: return C_LOCALE_ICELANDIC;
|
|
||||||
case QLocale::Indonesian: return C_LOCALE_INDONESIAN;
|
|
||||||
case QLocale::Italian: return C_LOCALE_ITALIAN;
|
|
||||||
case QLocale::Japanese: return C_LOCALE_JAPANESE;
|
|
||||||
case QLocale::Korean: return C_LOCALE_KOREAN;
|
|
||||||
case QLocale::Latvian: return C_LOCALE_LATVIAN;
|
|
||||||
case QLocale::Lithuanian: return C_LOCALE_LITHUANIAN;
|
|
||||||
case QLocale::Malay: return C_LOCALE_MALAY;
|
|
||||||
case QLocale::Mongolian: return C_LOCALE_MONGOLIAN;
|
|
||||||
case QLocale::NorwegianBokmal: return C_LOCALE_NORWEGIAN;
|
|
||||||
case QLocale::Occitan: return C_LOCALE_OCCITAN;
|
|
||||||
case QLocale::Persian: return C_LOCALE_PERSIAN;
|
|
||||||
case QLocale::Polish: return C_LOCALE_POLISH;
|
|
||||||
case QLocale::Portuguese:
|
|
||||||
if (locale.country() == QLocale::Brazil)
|
|
||||||
return C_LOCALE_PORTUGUESE_BRAZIL;
|
|
||||||
return C_LOCALE_PORTUGUESE;
|
|
||||||
case QLocale::Romanian: return C_LOCALE_ROMANIAN;
|
|
||||||
case QLocale::Russian: return C_LOCALE_RUSSIAN;
|
|
||||||
case QLocale::Serbian: return C_LOCALE_SERBIAN;
|
|
||||||
case QLocale::Slovak: return C_LOCALE_SLOVAK;
|
|
||||||
case QLocale::Slovenian: return C_LOCALE_SLOVENIAN;
|
|
||||||
case QLocale::Spanish: return C_LOCALE_SPANISH;
|
|
||||||
case QLocale::Swedish: return C_LOCALE_SWEDISH;
|
|
||||||
case QLocale::Thai: return C_LOCALE_THAI;
|
|
||||||
case QLocale::Turkish: return C_LOCALE_TURKISH;
|
|
||||||
case QLocale::Ukrainian: return C_LOCALE_UKRAINIAN;
|
|
||||||
case QLocale::Uzbek: return C_LOCALE_UZBEK;
|
|
||||||
case QLocale::Vietnamese: return C_LOCALE_VIETNAMESE;
|
|
||||||
default:
|
|
||||||
const QString lang = QLocale::languageToString(locale.language());
|
|
||||||
qWarning() << "Unrecognized language name: " << lang;
|
|
||||||
return lang;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WheelEventEater final : public QObject
|
class WheelEventEater final : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -203,17 +128,17 @@ OptionsDialog::OptionsDialog(IGUIApplication *app, QWidget *parent)
|
||||||
|
|
||||||
// Main icons
|
// Main icons
|
||||||
m_ui->tabSelection->item(TAB_UI)->setIcon(UIThemeManager::instance()->getIcon(u"preferences-desktop"_qs));
|
m_ui->tabSelection->item(TAB_UI)->setIcon(UIThemeManager::instance()->getIcon(u"preferences-desktop"_qs));
|
||||||
m_ui->tabSelection->item(TAB_BITTORRENT)->setIcon(UIThemeManager::instance()->getIcon(u"preferences-bittorrent"_qs));
|
m_ui->tabSelection->item(TAB_BITTORRENT)->setIcon(UIThemeManager::instance()->getIcon(u"preferences-bittorrent"_qs, u"preferences-system-network"_qs));
|
||||||
m_ui->tabSelection->item(TAB_CONNECTION)->setIcon(UIThemeManager::instance()->getIcon(u"network-connect"_qs));
|
m_ui->tabSelection->item(TAB_CONNECTION)->setIcon(UIThemeManager::instance()->getIcon(u"network-connect"_qs, u"network-wired"_qs));
|
||||||
m_ui->tabSelection->item(TAB_DOWNLOADS)->setIcon(UIThemeManager::instance()->getIcon(u"download"_qs));
|
m_ui->tabSelection->item(TAB_DOWNLOADS)->setIcon(UIThemeManager::instance()->getIcon(u"download"_qs, u"folder-download"_qs));
|
||||||
m_ui->tabSelection->item(TAB_SPEED)->setIcon(UIThemeManager::instance()->getIcon(u"speedometer"_qs));
|
m_ui->tabSelection->item(TAB_SPEED)->setIcon(UIThemeManager::instance()->getIcon(u"speedometer"_qs, u"chronometer"_qs));
|
||||||
m_ui->tabSelection->item(TAB_RSS)->setIcon(UIThemeManager::instance()->getIcon(u"application-rss"_qs));
|
m_ui->tabSelection->item(TAB_RSS)->setIcon(UIThemeManager::instance()->getIcon(u"application-rss"_qs, u"application-rss+xml"_qs));
|
||||||
#ifdef DISABLE_WEBUI
|
#ifdef DISABLE_WEBUI
|
||||||
m_ui->tabSelection->item(TAB_WEBUI)->setHidden(true);
|
m_ui->tabSelection->item(TAB_WEBUI)->setHidden(true);
|
||||||
#else
|
#else
|
||||||
m_ui->tabSelection->item(TAB_WEBUI)->setIcon(UIThemeManager::instance()->getIcon(u"preferences-webui"_qs));
|
m_ui->tabSelection->item(TAB_WEBUI)->setIcon(UIThemeManager::instance()->getIcon(u"preferences-webui"_qs, u"network-server"_qs));
|
||||||
#endif
|
#endif
|
||||||
m_ui->tabSelection->item(TAB_ADVANCED)->setIcon(UIThemeManager::instance()->getIcon(u"preferences-advanced"_qs));
|
m_ui->tabSelection->item(TAB_ADVANCED)->setIcon(UIThemeManager::instance()->getIcon(u"preferences-advanced"_qs, u"preferences-other"_qs));
|
||||||
|
|
||||||
// set uniform size for all icons
|
// set uniform size for all icons
|
||||||
int maxHeight = -1;
|
int maxHeight = -1;
|
||||||
|
@ -288,6 +213,11 @@ void OptionsDialog::loadBehaviorTabOptions()
|
||||||
m_ui->customThemeFilePath->setMode(FileSystemPathEdit::Mode::FileOpen);
|
m_ui->customThemeFilePath->setMode(FileSystemPathEdit::Mode::FileOpen);
|
||||||
m_ui->customThemeFilePath->setDialogCaption(tr("Select qBittorrent UI Theme file"));
|
m_ui->customThemeFilePath->setDialogCaption(tr("Select qBittorrent UI Theme file"));
|
||||||
m_ui->customThemeFilePath->setFileNameFilter(tr("qBittorrent UI Theme file (*.qbtheme config.json)"));
|
m_ui->customThemeFilePath->setFileNameFilter(tr("qBittorrent UI Theme file (*.qbtheme config.json)"));
|
||||||
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
|
||||||
|
m_ui->checkUseSystemIcon->setChecked(pref->useSystemIcons());
|
||||||
|
#else
|
||||||
|
m_ui->checkUseSystemIcon->setVisible(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
m_ui->confirmDeletion->setChecked(pref->confirmTorrentDeletion());
|
m_ui->confirmDeletion->setChecked(pref->confirmTorrentDeletion());
|
||||||
m_ui->checkAltRowColors->setChecked(pref->useAlternatingRowColors());
|
m_ui->checkAltRowColors->setChecked(pref->useAlternatingRowColors());
|
||||||
|
@ -382,6 +312,9 @@ void OptionsDialog::loadBehaviorTabOptions()
|
||||||
|
|
||||||
connect(m_ui->comboI18n, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->comboI18n, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||||
|
|
||||||
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
|
||||||
|
connect(m_ui->checkUseSystemIcon, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||||
|
#endif
|
||||||
connect(m_ui->checkUseCustomTheme, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->checkUseCustomTheme, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->customThemeFilePath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->customThemeFilePath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
|
||||||
|
|
||||||
|
@ -451,6 +384,9 @@ void OptionsDialog::saveBehaviorTabOptions() const
|
||||||
}
|
}
|
||||||
pref->setLocale(locale);
|
pref->setLocale(locale);
|
||||||
|
|
||||||
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
|
||||||
|
pref->useSystemIcons(m_ui->checkUseSystemIcon->isChecked());
|
||||||
|
#endif
|
||||||
pref->setUseCustomUITheme(m_ui->checkUseCustomTheme->isChecked());
|
pref->setUseCustomUITheme(m_ui->checkUseCustomTheme->isChecked());
|
||||||
pref->setCustomUIThemePath(m_ui->customThemeFilePath->selectedPath());
|
pref->setCustomUIThemePath(m_ui->customThemeFilePath->selectedPath());
|
||||||
|
|
||||||
|
@ -1315,25 +1251,8 @@ void OptionsDialog::initializeLanguageCombo()
|
||||||
const QStringList langFiles = langDir.entryList(QStringList(u"qbittorrent_*.qm"_qs), QDir::Files);
|
const QStringList langFiles = langDir.entryList(QStringList(u"qbittorrent_*.qm"_qs), QDir::Files);
|
||||||
for (const QString &langFile : langFiles)
|
for (const QString &langFile : langFiles)
|
||||||
{
|
{
|
||||||
QString localeStr = langFile.mid(12); // remove "qbittorrent_"
|
const QString localeStr = langFile.section(u"_"_qs, 1, -1).section(u"."_qs, 0, 0); // remove "qbittorrent_" and ".qm"
|
||||||
localeStr.chop(3); // Remove ".qm"
|
m_ui->comboI18n->addItem(/*QIcon(":/icons/flags/"+country+".svg"), */ Utils::Misc::languageToLocalizedString(localeStr), localeStr);
|
||||||
QString languageName;
|
|
||||||
if (localeStr.startsWith(u"eo", Qt::CaseInsensitive))
|
|
||||||
{
|
|
||||||
// QLocale doesn't work with that locale. Esperanto isn't a "real" language.
|
|
||||||
languageName = C_LOCALE_ESPERANTO;
|
|
||||||
}
|
|
||||||
else if (localeStr.startsWith(u"ltg", Qt::CaseInsensitive))
|
|
||||||
{
|
|
||||||
// QLocale doesn't work with that locale.
|
|
||||||
languageName = C_LOCALE_LATGALIAN;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QLocale locale(localeStr);
|
|
||||||
languageName = languageToLocalizedString(locale);
|
|
||||||
}
|
|
||||||
m_ui->comboI18n->addItem(/*QIcon(":/icons/flags/"+country+".svg"), */ languageName, localeStr);
|
|
||||||
qDebug() << "Supported locale:" << localeStr;
|
qDebug() << "Supported locale:" << localeStr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,41 +133,18 @@
|
||||||
<string>Interface</string>
|
<string>Interface</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_81">
|
<layout class="QGridLayout" name="gridLayout_81">
|
||||||
<item row="3" column="0" colspan="3">
|
<item row="0" column="0" colspan="2">
|
||||||
<widget class="QGroupBox" name="checkUseCustomTheme">
|
<widget class="QLabel" name="label_15">
|
||||||
<property name="title">
|
<property name="font">
|
||||||
<string>Use custom UI Theme</string>
|
<font>
|
||||||
|
<italic>true</italic>
|
||||||
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="checkable">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string>Changing Interface settings requires application restart</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_18">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_16">
|
|
||||||
<property name="text">
|
|
||||||
<string>UI Theme file:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="FileSystemPathLineEdit" name="customThemeFilePath" native="true"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
|
||||||
<spacer name="horizontalSpacer_111">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>200</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_9">
|
<widget class="QLabel" name="label_9">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -191,15 +168,45 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="1" column="2">
|
||||||
<widget class="QLabel" name="label_15">
|
<spacer name="horizontalSpacer_111">
|
||||||
<property name="font">
|
<property name="orientation">
|
||||||
<font>
|
<enum>Qt::Horizontal</enum>
|
||||||
<italic>true</italic>
|
|
||||||
</font>
|
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="3">
|
||||||
|
<widget class="QGroupBox" name="checkUseCustomTheme">
|
||||||
|
<property name="title">
|
||||||
|
<string>Use custom UI Theme</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_18">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_16">
|
||||||
|
<property name="text">
|
||||||
|
<string>UI Theme file:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="FileSystemPathLineEdit" name="customThemeFilePath" native="true"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="checkUseSystemIcon">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Changing Interface settings requires application restart</string>
|
<string>Use icons from system theme</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -750,7 +750,7 @@ void PropertiesWidget::displayWebSeedListMenu()
|
||||||
|
|
||||||
if (!rows.isEmpty())
|
if (!rows.isEmpty())
|
||||||
{
|
{
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs), tr("Remove Web seed")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs, u"list-remove"_qs), tr("Remove Web seed")
|
||||||
, this, &PropertiesWidget::deleteSelectedUrlSeeds);
|
, this, &PropertiesWidget::deleteSelectedUrlSeeds);
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-copy"_qs), tr("Copy Web seed URL")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-copy"_qs), tr("Copy Web seed URL")
|
||||||
|
|
|
@ -45,7 +45,7 @@ PropTabBar::PropTabBar(QWidget *parent)
|
||||||
// General tab
|
// General tab
|
||||||
QPushButton *mainInfosButton = new QPushButton(
|
QPushButton *mainInfosButton = new QPushButton(
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
UIThemeManager::instance()->getIcon(u"help-about"_qs),
|
UIThemeManager::instance()->getIcon(u"help-about"_qs, u"document-properties"_qs),
|
||||||
#endif
|
#endif
|
||||||
tr("General"), parent);
|
tr("General"), parent);
|
||||||
mainInfosButton->setShortcut(Qt::ALT + Qt::Key_G);
|
mainInfosButton->setShortcut(Qt::ALT + Qt::Key_G);
|
||||||
|
@ -54,7 +54,7 @@ PropTabBar::PropTabBar(QWidget *parent)
|
||||||
// Trackers tab
|
// Trackers tab
|
||||||
QPushButton *trackersButton = new QPushButton(
|
QPushButton *trackersButton = new QPushButton(
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
UIThemeManager::instance()->getIcon(u"trackers"_qs),
|
UIThemeManager::instance()->getIcon(u"trackers"_qs, u"network-server"_qs),
|
||||||
#endif
|
#endif
|
||||||
tr("Trackers"), parent);
|
tr("Trackers"), parent);
|
||||||
trackersButton->setShortcut(Qt::ALT + Qt::Key_C);
|
trackersButton->setShortcut(Qt::ALT + Qt::Key_C);
|
||||||
|
|
|
@ -572,7 +572,7 @@ void TrackerListWidget::showTrackerListMenu()
|
||||||
{
|
{
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-rename"_qs),tr("Edit tracker URL...")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-rename"_qs),tr("Edit tracker URL...")
|
||||||
, this, &TrackerListWidget::editSelectedTracker);
|
, this, &TrackerListWidget::editSelectedTracker);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs), tr("Remove tracker")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs, u"list-remove"_qs), tr("Remove tracker")
|
||||||
, this, &TrackerListWidget::deleteSelectedTrackers);
|
, this, &TrackerListWidget::deleteSelectedTrackers);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-copy"_qs), tr("Copy tracker URL")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-copy"_qs), tr("Copy tracker URL")
|
||||||
, this, &TrackerListWidget::copyTrackerUrl);
|
, this, &TrackerListWidget::copyTrackerUrl);
|
||||||
|
@ -580,10 +580,10 @@ void TrackerListWidget::showTrackerListMenu()
|
||||||
|
|
||||||
if (!torrent->isPaused())
|
if (!torrent->isPaused())
|
||||||
{
|
{
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"reannounce"_qs), tr("Force reannounce to selected trackers")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"reannounce"_qs, u"view-refresh"_qs), tr("Force reannounce to selected trackers")
|
||||||
, this, &TrackerListWidget::reannounceSelected);
|
, this, &TrackerListWidget::reannounceSelected);
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"reannounce"_qs), tr("Force reannounce to all trackers")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"reannounce"_qs, u"view-refresh"_qs), tr("Force reannounce to all trackers")
|
||||||
, this, [this]()
|
, this, [this]()
|
||||||
{
|
{
|
||||||
BitTorrent::Torrent *h = m_properties->getCurrentTorrent();
|
BitTorrent::Torrent *h = m_properties->getCurrentTorrent();
|
||||||
|
|
|
@ -52,7 +52,7 @@ TrackersAdditionDialog::TrackersAdditionDialog(QWidget *parent, BitTorrent::Torr
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
m_ui->downloadButton->setIcon(UIThemeManager::instance()->getIcon(u"downloading"_qs));
|
m_ui->downloadButton->setIcon(UIThemeManager::instance()->getIcon(u"downloading"_qs, u"download"_qs));
|
||||||
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Add"));
|
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Add"));
|
||||||
|
|
||||||
connect(m_ui->downloadButton, &QAbstractButton::clicked, this, &TrackersAdditionDialog::onDownloadButtonClicked);
|
connect(m_ui->downloadButton, &QAbstractButton::clicked, this, &TrackersAdditionDialog::onDownloadButtonClicked);
|
||||||
|
|
|
@ -105,7 +105,7 @@ void ArticleListWidget::handleArticleRead(RSS::Article *rssArticle)
|
||||||
const QColor defaultColor {palette().color(QPalette::Inactive, QPalette::WindowText)};
|
const QColor defaultColor {palette().color(QPalette::Inactive, QPalette::WindowText)};
|
||||||
const QBrush foregroundBrush {UIThemeManager::instance()->getColor(u"RSS.ReadArticle"_qs, defaultColor)};
|
const QBrush foregroundBrush {UIThemeManager::instance()->getColor(u"RSS.ReadArticle"_qs, defaultColor)};
|
||||||
item->setData(Qt::ForegroundRole, foregroundBrush);
|
item->setData(Qt::ForegroundRole, foregroundBrush);
|
||||||
item->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"loading"_qs));
|
item->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"loading"_qs, u"sphere"_qs));
|
||||||
|
|
||||||
checkInvariant();
|
checkInvariant();
|
||||||
}
|
}
|
||||||
|
@ -133,14 +133,14 @@ QListWidgetItem *ArticleListWidget::createItem(RSS::Article *article) const
|
||||||
const QColor defaultColor {palette().color(QPalette::Inactive, QPalette::WindowText)};
|
const QColor defaultColor {palette().color(QPalette::Inactive, QPalette::WindowText)};
|
||||||
const QBrush foregroundBrush {UIThemeManager::instance()->getColor(u"RSS.ReadArticle"_qs, defaultColor)};
|
const QBrush foregroundBrush {UIThemeManager::instance()->getColor(u"RSS.ReadArticle"_qs, defaultColor)};
|
||||||
item->setData(Qt::ForegroundRole, foregroundBrush);
|
item->setData(Qt::ForegroundRole, foregroundBrush);
|
||||||
item->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"loading"_qs));
|
item->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"loading"_qs, u"sphere"_qs));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const QColor defaultColor {palette().color(QPalette::Active, QPalette::Link)};
|
const QColor defaultColor {palette().color(QPalette::Active, QPalette::Link)};
|
||||||
const QBrush foregroundBrush {UIThemeManager::instance()->getColor(u"RSS.UnreadArticle"_qs, defaultColor)};
|
const QBrush foregroundBrush {UIThemeManager::instance()->getColor(u"RSS.UnreadArticle"_qs, defaultColor)};
|
||||||
item->setData(Qt::ForegroundRole, foregroundBrush);
|
item->setData(Qt::ForegroundRole, foregroundBrush);
|
||||||
item->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"loading"_qs));
|
item->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"loading"_qs, u"sphere"_qs));
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
|
|
@ -75,7 +75,7 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
// Icons
|
// Icons
|
||||||
m_ui->removeRuleBtn->setIcon(UIThemeManager::instance()->getIcon(u"edit-clear"_qs));
|
m_ui->removeRuleBtn->setIcon(UIThemeManager::instance()->getIcon(u"edit-clear"_qs, u"list-remove"_qs));
|
||||||
m_ui->addRuleBtn->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
m_ui->addRuleBtn->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
||||||
m_ui->addCategoryBtn->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
m_ui->addCategoryBtn->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
||||||
|
|
||||||
|
@ -521,7 +521,7 @@ void AutomatedRssDownloader::displayRulesListMenu()
|
||||||
{
|
{
|
||||||
if (selection.count() == 1)
|
if (selection.count() == 1)
|
||||||
{
|
{
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs), tr("Delete rule")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs, u"list-remove"_qs), tr("Delete rule")
|
||||||
, this, &AutomatedRssDownloader::on_removeRuleBtn_clicked);
|
, this, &AutomatedRssDownloader::on_removeRuleBtn_clicked);
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-rename"_qs), tr("Rename rule...")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-rename"_qs), tr("Rename rule...")
|
||||||
|
@ -529,7 +529,7 @@ void AutomatedRssDownloader::displayRulesListMenu()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs), tr("Delete selected rules")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs, u"list-remove"_qs), tr("Delete selected rules")
|
||||||
, this, &AutomatedRssDownloader::on_removeRuleBtn_clicked);
|
, this, &AutomatedRssDownloader::on_removeRuleBtn_clicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,7 +759,7 @@ void AutomatedRssDownloader::updateMustLineValidity()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ui->lineContains->setStyleSheet(u"QLineEdit { color: #ff0000; }"_qs);
|
m_ui->lineContains->setStyleSheet(u"QLineEdit { color: #ff0000; }"_qs);
|
||||||
m_ui->labelMustStat->setPixmap(UIThemeManager::instance()->getIcon(u"dialog-warning"_qs).pixmap(16, 16));
|
m_ui->labelMustStat->setPixmap(UIThemeManager::instance()->getIcon(u"dialog-warning"_qs, u"task-attention"_qs).pixmap(16, 16));
|
||||||
m_ui->labelMustStat->setToolTip(error);
|
m_ui->labelMustStat->setToolTip(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -806,7 +806,7 @@ void AutomatedRssDownloader::updateMustNotLineValidity()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ui->lineNotContains->setStyleSheet(u"QLineEdit { color: #ff0000; }"_qs);
|
m_ui->lineNotContains->setStyleSheet(u"QLineEdit { color: #ff0000; }"_qs);
|
||||||
m_ui->labelMustNotStat->setPixmap(UIThemeManager::instance()->getIcon(u"dialog-warning"_qs).pixmap(16, 16));
|
m_ui->labelMustNotStat->setPixmap(UIThemeManager::instance()->getIcon(u"dialog-warning"_qs, u"task-attention"_qs).pixmap(16, 16));
|
||||||
m_ui->labelMustNotStat->setToolTip(error);
|
m_ui->labelMustNotStat->setToolTip(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -824,7 +824,7 @@ void AutomatedRssDownloader::updateEpisodeFilterValidity()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ui->lineEFilter->setStyleSheet(u"QLineEdit { color: #ff0000; }"_qs);
|
m_ui->lineEFilter->setStyleSheet(u"QLineEdit { color: #ff0000; }"_qs);
|
||||||
m_ui->labelEpFilterStat->setPixmap(UIThemeManager::instance()->getIcon(u"dialog-warning"_qs).pixmap(16, 16));
|
m_ui->labelEpFilterStat->setPixmap(UIThemeManager::instance()->getIcon(u"dialog-warning"_qs, u"task-attention"_qs).pixmap(16, 16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace
|
||||||
if (feed->isLoading())
|
if (feed->isLoading())
|
||||||
return UIThemeManager::instance()->getIcon(u"loading"_qs);
|
return UIThemeManager::instance()->getIcon(u"loading"_qs);
|
||||||
if (feed->hasError())
|
if (feed->hasError())
|
||||||
return UIThemeManager::instance()->getIcon(u"task-reject"_qs);
|
return UIThemeManager::instance()->getIcon(u"task-reject"_qs, u"unavailable"_qs);
|
||||||
|
|
||||||
return loadIcon(feed->iconPath(), u"application-rss"_qs);
|
return loadIcon(feed->iconPath(), u"application-rss"_qs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,8 @@ RSSWidget::RSSWidget(QWidget *parent)
|
||||||
// Icons
|
// Icons
|
||||||
m_ui->actionCopyFeedURL->setIcon(UIThemeManager::instance()->getIcon(u"edit-copy"_qs));
|
m_ui->actionCopyFeedURL->setIcon(UIThemeManager::instance()->getIcon(u"edit-copy"_qs));
|
||||||
m_ui->actionDelete->setIcon(UIThemeManager::instance()->getIcon(u"edit-clear"_qs));
|
m_ui->actionDelete->setIcon(UIThemeManager::instance()->getIcon(u"edit-clear"_qs));
|
||||||
m_ui->actionDownloadTorrent->setIcon(UIThemeManager::instance()->getIcon(u"downloading"_qs));
|
m_ui->actionDownloadTorrent->setIcon(UIThemeManager::instance()->getIcon(u"downloading"_qs, u"download"_qs));
|
||||||
m_ui->actionMarkItemsRead->setIcon(UIThemeManager::instance()->getIcon(u"task-complete"_qs));
|
m_ui->actionMarkItemsRead->setIcon(UIThemeManager::instance()->getIcon(u"task-complete"_qs, u"mail-mark-read"_qs));
|
||||||
m_ui->actionNewFolder->setIcon(UIThemeManager::instance()->getIcon(u"folder-new"_qs));
|
m_ui->actionNewFolder->setIcon(UIThemeManager::instance()->getIcon(u"folder-new"_qs));
|
||||||
m_ui->actionNewSubscription->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
m_ui->actionNewSubscription->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
||||||
m_ui->actionOpenNewsURL->setIcon(UIThemeManager::instance()->getIcon(u"application-url"_qs));
|
m_ui->actionOpenNewsURL->setIcon(UIThemeManager::instance()->getIcon(u"application-url"_qs));
|
||||||
|
@ -74,9 +74,9 @@ RSSWidget::RSSWidget(QWidget *parent)
|
||||||
m_ui->actionUpdateAllFeeds->setIcon(UIThemeManager::instance()->getIcon(u"view-refresh"_qs));
|
m_ui->actionUpdateAllFeeds->setIcon(UIThemeManager::instance()->getIcon(u"view-refresh"_qs));
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
m_ui->newFeedButton->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
m_ui->newFeedButton->setIcon(UIThemeManager::instance()->getIcon(u"list-add"_qs));
|
||||||
m_ui->markReadButton->setIcon(UIThemeManager::instance()->getIcon(u"task-complete"_qs));
|
m_ui->markReadButton->setIcon(UIThemeManager::instance()->getIcon(u"task-complete"_qs, u"mail-mark-read"_qs));
|
||||||
m_ui->updateAllButton->setIcon(UIThemeManager::instance()->getIcon(u"view-refresh"_qs));
|
m_ui->updateAllButton->setIcon(UIThemeManager::instance()->getIcon(u"view-refresh"_qs));
|
||||||
m_ui->rssDownloaderBtn->setIcon(UIThemeManager::instance()->getIcon(u"downloading"_qs));
|
m_ui->rssDownloaderBtn->setIcon(UIThemeManager::instance()->getIcon(u"downloading"_qs, u"download"_qs));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_articleListWidget = new ArticleListWidget(m_ui->splitterMain);
|
m_articleListWidget = new ArticleListWidget(m_ui->splitterMain);
|
||||||
|
|
|
@ -392,7 +392,7 @@ void SearchJobWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||||
|
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"download"_qs)
|
menu->addAction(UIThemeManager::instance()->getIcon(u"download"_qs)
|
||||||
, tr("Open download window"), this, [this]() { downloadTorrents(AddTorrentOption::ShowDialog); });
|
, tr("Open download window"), this, [this]() { downloadTorrents(AddTorrentOption::ShowDialog); });
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"downloading"_qs)
|
menu->addAction(UIThemeManager::instance()->getIcon(u"downloading"_qs, u"download"_qs)
|
||||||
, tr("Download"), this, [this]() { downloadTorrents(AddTorrentOption::SkipDialog); });
|
, tr("Download"), this, [this]() { downloadTorrents(AddTorrentOption::SkipDialog); });
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"application-url"_qs), tr("Open description page")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"application-url"_qs), tr("Open description page")
|
||||||
|
@ -401,11 +401,11 @@ void SearchJobWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||||
QMenu *copySubMenu = menu->addMenu(
|
QMenu *copySubMenu = menu->addMenu(
|
||||||
UIThemeManager::instance()->getIcon(u"edit-copy"_qs), tr("Copy"));
|
UIThemeManager::instance()->getIcon(u"edit-copy"_qs), tr("Copy"));
|
||||||
|
|
||||||
copySubMenu->addAction(UIThemeManager::instance()->getIcon(u"name"_qs), tr("Name")
|
copySubMenu->addAction(UIThemeManager::instance()->getIcon(u"name"_qs, u"edit-copy"_qs), tr("Name")
|
||||||
, this, &SearchJobWidget::copyTorrentNames);
|
, this, &SearchJobWidget::copyTorrentNames);
|
||||||
copySubMenu->addAction(UIThemeManager::instance()->getIcon(u"insert-link"_qs), tr("Download link")
|
copySubMenu->addAction(UIThemeManager::instance()->getIcon(u"insert-link"_qs, u"edit-copy"_qs), tr("Download link")
|
||||||
, this, &SearchJobWidget::copyTorrentDownloadLinks);
|
, this, &SearchJobWidget::copyTorrentDownloadLinks);
|
||||||
copySubMenu->addAction(UIThemeManager::instance()->getIcon(u"application-url"_qs), tr("Description page URL")
|
copySubMenu->addAction(UIThemeManager::instance()->getIcon(u"application-url"_qs, u"edit-copy"_qs), tr("Description page URL")
|
||||||
, this, &SearchJobWidget::copyTorrentURLs);
|
, this, &SearchJobWidget::copyTorrentURLs);
|
||||||
|
|
||||||
menu->popup(event->globalPos());
|
menu->popup(event->globalPos());
|
||||||
|
|
|
@ -112,7 +112,7 @@ SearchWidget::SearchWidget(IGUIApplication *app, MainWindow *mainWindow)
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
// Icons
|
// Icons
|
||||||
m_ui->searchButton->setIcon(UIThemeManager::instance()->getIcon(u"edit-find"_qs));
|
m_ui->searchButton->setIcon(UIThemeManager::instance()->getIcon(u"edit-find"_qs));
|
||||||
m_ui->pluginsButton->setIcon(UIThemeManager::instance()->getIcon(u"plugins"_qs));
|
m_ui->pluginsButton->setIcon(UIThemeManager::instance()->getIcon(u"plugins"_qs, u"preferences-system-network"_qs));
|
||||||
#else
|
#else
|
||||||
// On macOS the icons overlap the text otherwise
|
// On macOS the icons overlap the text otherwise
|
||||||
QSize iconSize = m_ui->tabWidget->iconSize();
|
QSize iconSize = m_ui->tabWidget->iconSize();
|
||||||
|
|
|
@ -69,7 +69,7 @@ StatusBar::StatusBar(QWidget *parent)
|
||||||
connect(m_connecStatusLblIcon, &QAbstractButton::clicked, this, &StatusBar::connectionButtonClicked);
|
connect(m_connecStatusLblIcon, &QAbstractButton::clicked, this, &StatusBar::connectionButtonClicked);
|
||||||
|
|
||||||
m_dlSpeedLbl = new QPushButton(this);
|
m_dlSpeedLbl = new QPushButton(this);
|
||||||
m_dlSpeedLbl->setIcon(UIThemeManager::instance()->getIcon(u"downloading"_qs));
|
m_dlSpeedLbl->setIcon(UIThemeManager::instance()->getIcon(u"downloading"_qs, u"downloading_small"_qs));
|
||||||
connect(m_dlSpeedLbl, &QAbstractButton::clicked, this, &StatusBar::capSpeed);
|
connect(m_dlSpeedLbl, &QAbstractButton::clicked, this, &StatusBar::capSpeed);
|
||||||
m_dlSpeedLbl->setFlat(true);
|
m_dlSpeedLbl->setFlat(true);
|
||||||
m_dlSpeedLbl->setFocusPolicy(Qt::NoFocus);
|
m_dlSpeedLbl->setFocusPolicy(Qt::NoFocus);
|
||||||
|
@ -78,7 +78,7 @@ StatusBar::StatusBar(QWidget *parent)
|
||||||
m_dlSpeedLbl->setMinimumWidth(200);
|
m_dlSpeedLbl->setMinimumWidth(200);
|
||||||
|
|
||||||
m_upSpeedLbl = new QPushButton(this);
|
m_upSpeedLbl = new QPushButton(this);
|
||||||
m_upSpeedLbl->setIcon(UIThemeManager::instance()->getIcon(u"upload"_qs));
|
m_upSpeedLbl->setIcon(UIThemeManager::instance()->getIcon(u"upload"_qs, u"seeding"_qs));
|
||||||
connect(m_upSpeedLbl, &QAbstractButton::clicked, this, &StatusBar::capSpeed);
|
connect(m_upSpeedLbl, &QAbstractButton::clicked, this, &StatusBar::capSpeed);
|
||||||
m_upSpeedLbl->setFlat(true);
|
m_upSpeedLbl->setFlat(true);
|
||||||
m_upSpeedLbl->setFocusPolicy(Qt::NoFocus);
|
m_upSpeedLbl->setFocusPolicy(Qt::NoFocus);
|
||||||
|
|
|
@ -123,7 +123,7 @@ QVariant TagFilterModel::data(const QModelIndex &index, int role) const
|
||||||
switch (role)
|
switch (role)
|
||||||
{
|
{
|
||||||
case Qt::DecorationRole:
|
case Qt::DecorationRole:
|
||||||
return UIThemeManager::instance()->getIcon(u"tags"_qs);
|
return UIThemeManager::instance()->getIcon(u"tags"_qs, u"inode-directory"_qs);
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
return u"%1 (%2)"_qs.arg(tagDisplayName(item.tag())).arg(item.torrentsCount());
|
return u"%1 (%2)"_qs.arg(tagDisplayName(item.tag())).arg(item.torrentsCount());
|
||||||
case Qt::UserRole:
|
case Qt::UserRole:
|
||||||
|
|
|
@ -113,16 +113,16 @@ void TagFilterWidget::showMenu()
|
||||||
const auto selectedRows = selectionModel()->selectedRows();
|
const auto selectedRows = selectionModel()->selectedRows();
|
||||||
if (!selectedRows.empty() && !TagFilterModel::isSpecialItem(selectedRows.first()))
|
if (!selectedRows.empty() && !TagFilterModel::isSpecialItem(selectedRows.first()))
|
||||||
{
|
{
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs), tr("Remove tag")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs, u"list-remove"_qs), tr("Remove tag")
|
||||||
, this, &TagFilterWidget::removeTag);
|
, this, &TagFilterWidget::removeTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs), tr("Remove unused tags")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"edit-clear"_qs, u"list-remove"_qs), tr("Remove unused tags")
|
||||||
, this, &TagFilterWidget::removeUnusedTags);
|
, this, &TagFilterWidget::removeUnusedTags);
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs), tr("Resume torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs, u"media-playback-start"_qs), tr("Resume torrents")
|
||||||
, this, &TagFilterWidget::actionResumeTorrentsTriggered);
|
, this, &TagFilterWidget::actionResumeTorrentsTriggered);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs), tr("Pause torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs, u"media-playback-pause"_qs), tr("Pause torrents")
|
||||||
, this, &TagFilterWidget::actionPauseTorrentsTriggered);
|
, this, &TagFilterWidget::actionPauseTorrentsTriggered);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("Remove torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("Remove torrents")
|
||||||
, this, &TagFilterWidget::actionDeleteTorrentsTriggered);
|
, this, &TagFilterWidget::actionDeleteTorrentsTriggered);
|
||||||
|
|
|
@ -133,6 +133,9 @@ QString TorrentCategoryDialog::categoryName() const
|
||||||
void TorrentCategoryDialog::setCategoryName(const QString &categoryName)
|
void TorrentCategoryDialog::setCategoryName(const QString &categoryName)
|
||||||
{
|
{
|
||||||
m_ui->textCategoryName->setText(categoryName);
|
m_ui->textCategoryName->setText(categoryName);
|
||||||
|
|
||||||
|
const int subcategoryNameStart = categoryName.lastIndexOf(u"/") + 1;
|
||||||
|
m_ui->textCategoryName->setSelection(subcategoryNameStart, (categoryName.size() - subcategoryNameStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
BitTorrent::CategoryOptions TorrentCategoryDialog::categoryOptions() const
|
BitTorrent::CategoryOptions TorrentCategoryDialog::categoryOptions() const
|
||||||
|
|
|
@ -29,13 +29,10 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="1" column="1">
|
<item row="0" column="0">
|
||||||
<widget class="FileSystemPathComboEdit" name="comboSavePath" native="true">
|
<widget class="QLabel" name="labelCategoryName">
|
||||||
<property name="sizePolicy">
|
<property name="text">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<string>Name:</string>
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -49,10 +46,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="1" column="1">
|
||||||
<widget class="QLabel" name="labelCategoryName">
|
<widget class="FileSystemPathComboEdit" name="comboSavePath" native="true">
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>Name:</string>
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -173,6 +173,12 @@
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>textCategoryName</tabstop>
|
||||||
|
<tabstop>comboSavePath</tabstop>
|
||||||
|
<tabstop>comboUseDownloadPath</tabstop>
|
||||||
|
<tabstop>comboDownloadPath</tabstop>
|
||||||
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UnifiedFileIconProvider()
|
UnifiedFileIconProvider()
|
||||||
: m_textPlainIcon {UIThemeManager::instance()->getIcon(u"help-about"_qs)}
|
: m_textPlainIcon {UIThemeManager::instance()->getIcon(u"help-about"_qs, u"text-plain"_qs)}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,31 +173,31 @@ StatusFilterWidget::StatusFilterWidget(QWidget *parent, TransferListWidget *tran
|
||||||
// Add status filters
|
// Add status filters
|
||||||
auto *all = new QListWidgetItem(this);
|
auto *all = new QListWidgetItem(this);
|
||||||
all->setData(Qt::DisplayRole, tr("All (0)", "this is for the status filter"));
|
all->setData(Qt::DisplayRole, tr("All (0)", "this is for the status filter"));
|
||||||
all->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"filter-all"_qs));
|
all->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"filter-all"_qs, u"filterall"_qs));
|
||||||
auto *downloading = new QListWidgetItem(this);
|
auto *downloading = new QListWidgetItem(this);
|
||||||
downloading->setData(Qt::DisplayRole, tr("Downloading (0)"));
|
downloading->setData(Qt::DisplayRole, tr("Downloading (0)"));
|
||||||
downloading->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"downloading"_qs));
|
downloading->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"downloading"_qs));
|
||||||
auto *seeding = new QListWidgetItem(this);
|
auto *seeding = new QListWidgetItem(this);
|
||||||
seeding->setData(Qt::DisplayRole, tr("Seeding (0)"));
|
seeding->setData(Qt::DisplayRole, tr("Seeding (0)"));
|
||||||
seeding->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"upload"_qs));
|
seeding->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"upload"_qs, u"uploading"_qs));
|
||||||
auto *completed = new QListWidgetItem(this);
|
auto *completed = new QListWidgetItem(this);
|
||||||
completed->setData(Qt::DisplayRole, tr("Completed (0)"));
|
completed->setData(Qt::DisplayRole, tr("Completed (0)"));
|
||||||
completed->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"checked-completed"_qs));
|
completed->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"checked-completed"_qs, u"completed"_qs));
|
||||||
auto *resumed = new QListWidgetItem(this);
|
auto *resumed = new QListWidgetItem(this);
|
||||||
resumed->setData(Qt::DisplayRole, tr("Resumed (0)"));
|
resumed->setData(Qt::DisplayRole, tr("Resumed (0)"));
|
||||||
resumed->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"torrent-start"_qs));
|
resumed->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"torrent-start"_qs, u"media-playback-start"_qs));
|
||||||
auto *paused = new QListWidgetItem(this);
|
auto *paused = new QListWidgetItem(this);
|
||||||
paused->setData(Qt::DisplayRole, tr("Paused (0)"));
|
paused->setData(Qt::DisplayRole, tr("Paused (0)"));
|
||||||
paused->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"torrent-stop"_qs));
|
paused->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"torrent-stop"_qs, u"media-playback-pause"_qs));
|
||||||
auto *active = new QListWidgetItem(this);
|
auto *active = new QListWidgetItem(this);
|
||||||
active->setData(Qt::DisplayRole, tr("Active (0)"));
|
active->setData(Qt::DisplayRole, tr("Active (0)"));
|
||||||
active->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"filter-active"_qs));
|
active->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"filter-active"_qs, u"filteractive"_qs));
|
||||||
auto *inactive = new QListWidgetItem(this);
|
auto *inactive = new QListWidgetItem(this);
|
||||||
inactive->setData(Qt::DisplayRole, tr("Inactive (0)"));
|
inactive->setData(Qt::DisplayRole, tr("Inactive (0)"));
|
||||||
inactive->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"filter-inactive"_qs));
|
inactive->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"filter-inactive"_qs, u"filterinactive"_qs));
|
||||||
auto *stalled = new QListWidgetItem(this);
|
auto *stalled = new QListWidgetItem(this);
|
||||||
stalled->setData(Qt::DisplayRole, tr("Stalled (0)"));
|
stalled->setData(Qt::DisplayRole, tr("Stalled (0)"));
|
||||||
stalled->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"filter-stalled"_qs));
|
stalled->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"filter-stalled"_qs, u"filterstalled"_qs));
|
||||||
auto *stalledUploading = new QListWidgetItem(this);
|
auto *stalledUploading = new QListWidgetItem(this);
|
||||||
stalledUploading->setData(Qt::DisplayRole, tr("Stalled Uploading (0)"));
|
stalledUploading->setData(Qt::DisplayRole, tr("Stalled Uploading (0)"));
|
||||||
stalledUploading->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"stalledUP"_qs));
|
stalledUploading->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"stalledUP"_qs));
|
||||||
|
@ -206,7 +206,7 @@ StatusFilterWidget::StatusFilterWidget(QWidget *parent, TransferListWidget *tran
|
||||||
stalledDownloading->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"stalledDL"_qs));
|
stalledDownloading->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"stalledDL"_qs));
|
||||||
auto *checking = new QListWidgetItem(this);
|
auto *checking = new QListWidgetItem(this);
|
||||||
checking->setData(Qt::DisplayRole, tr("Checking (0)"));
|
checking->setData(Qt::DisplayRole, tr("Checking (0)"));
|
||||||
checking->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"force-recheck"_qs));
|
checking->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"force-recheck"_qs, u"checking"_qs));
|
||||||
auto *moving = new QListWidgetItem(this);
|
auto *moving = new QListWidgetItem(this);
|
||||||
moving->setData(Qt::DisplayRole, tr("Moving (0)"));
|
moving->setData(Qt::DisplayRole, tr("Moving (0)"));
|
||||||
moving->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"set-location"_qs));
|
moving->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"set-location"_qs));
|
||||||
|
@ -308,9 +308,9 @@ void StatusFilterWidget::showMenu()
|
||||||
QMenu *menu = new QMenu(this);
|
QMenu *menu = new QMenu(this);
|
||||||
menu->setAttribute(Qt::WA_DeleteOnClose);
|
menu->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs), tr("Resume torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs, u"media-playback-start"_qs), tr("Resume torrents")
|
||||||
, transferList, &TransferListWidget::startVisibleTorrents);
|
, transferList, &TransferListWidget::startVisibleTorrents);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs), tr("Pause torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs, u"media-playback-pause"_qs), tr("Pause torrents")
|
||||||
, transferList, &TransferListWidget::pauseVisibleTorrents);
|
, transferList, &TransferListWidget::pauseVisibleTorrents);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("Remove torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("Remove torrents")
|
||||||
, transferList, &TransferListWidget::deleteVisibleTorrents);
|
, transferList, &TransferListWidget::deleteVisibleTorrents);
|
||||||
|
@ -371,16 +371,16 @@ TrackerFiltersList::TrackerFiltersList(QWidget *parent, TransferListWidget *tran
|
||||||
{
|
{
|
||||||
auto *allTrackers = new QListWidgetItem(this);
|
auto *allTrackers = new QListWidgetItem(this);
|
||||||
allTrackers->setData(Qt::DisplayRole, tr("All (0)", "this is for the tracker filter"));
|
allTrackers->setData(Qt::DisplayRole, tr("All (0)", "this is for the tracker filter"));
|
||||||
allTrackers->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"trackers"_qs));
|
allTrackers->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"trackers"_qs, u"network-server"_qs));
|
||||||
auto *noTracker = new QListWidgetItem(this);
|
auto *noTracker = new QListWidgetItem(this);
|
||||||
noTracker->setData(Qt::DisplayRole, tr("Trackerless (0)"));
|
noTracker->setData(Qt::DisplayRole, tr("Trackerless (0)"));
|
||||||
noTracker->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"trackerless"_qs));
|
noTracker->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"trackerless"_qs, u"network-server"_qs));
|
||||||
auto *errorTracker = new QListWidgetItem(this);
|
auto *errorTracker = new QListWidgetItem(this);
|
||||||
errorTracker->setData(Qt::DisplayRole, tr("Error (0)"));
|
errorTracker->setData(Qt::DisplayRole, tr("Error (0)"));
|
||||||
errorTracker->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"tracker-error"_qs));
|
errorTracker->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"tracker-error"_qs, u"dialog-error"_qs));
|
||||||
auto *warningTracker = new QListWidgetItem(this);
|
auto *warningTracker = new QListWidgetItem(this);
|
||||||
warningTracker->setData(Qt::DisplayRole, tr("Warning (0)"));
|
warningTracker->setData(Qt::DisplayRole, tr("Warning (0)"));
|
||||||
warningTracker->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"tracker-warning"_qs));
|
warningTracker->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"tracker-warning"_qs, u"dialog-warning"_qs));
|
||||||
|
|
||||||
m_trackers[NULL_HOST] = {{}, noTracker};
|
m_trackers[NULL_HOST] = {{}, noTracker};
|
||||||
|
|
||||||
|
@ -474,7 +474,7 @@ void TrackerFiltersList::addItems(const QString &trackerURL, const QVector<BitTo
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trackerItem = new QListWidgetItem();
|
trackerItem = new QListWidgetItem();
|
||||||
trackerItem->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"trackers"_qs));
|
trackerItem->setData(Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"trackers"_qs, u"network-server"_qs));
|
||||||
|
|
||||||
const TrackerData trackerData {{}, trackerItem};
|
const TrackerData trackerData {{}, trackerItem};
|
||||||
trackersIt = m_trackers.insert(host, trackerData);
|
trackersIt = m_trackers.insert(host, trackerData);
|
||||||
|
@ -712,9 +712,9 @@ void TrackerFiltersList::showMenu()
|
||||||
QMenu *menu = new QMenu(this);
|
QMenu *menu = new QMenu(this);
|
||||||
menu->setAttribute(Qt::WA_DeleteOnClose);
|
menu->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs), tr("Resume torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs, u"media-playback-start"_qs), tr("Resume torrents")
|
||||||
, transferList, &TransferListWidget::startVisibleTorrents);
|
, transferList, &TransferListWidget::startVisibleTorrents);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs), tr("Pause torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs, u"media-playback-pause"_qs), tr("Pause torrents")
|
||||||
, transferList, &TransferListWidget::pauseVisibleTorrents);
|
, transferList, &TransferListWidget::pauseVisibleTorrents);
|
||||||
menu->addAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("Remove torrents")
|
menu->addAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("Remove torrents")
|
||||||
, transferList, &TransferListWidget::deleteVisibleTorrents);
|
, transferList, &TransferListWidget::deleteVisibleTorrents);
|
||||||
|
|
|
@ -158,15 +158,15 @@ TransferListModel::TransferListModel(QObject *parent)
|
||||||
{BitTorrent::TorrentState::Error, tr("Errored", "Torrent status, the torrent has an error")}
|
{BitTorrent::TorrentState::Error, tr("Errored", "Torrent status, the torrent has an error")}
|
||||||
}
|
}
|
||||||
, m_stateThemeColors {torrentStateColorsFromUITheme()}
|
, m_stateThemeColors {torrentStateColorsFromUITheme()}
|
||||||
, m_checkingIcon {UIThemeManager::instance()->getIcon(u"force-recheck"_qs)}
|
, m_checkingIcon {UIThemeManager::instance()->getIcon(u"force-recheck"_qs, u"checking"_qs)}
|
||||||
, m_completedIcon {UIThemeManager::instance()->getIcon(u"checked-completed"_qs)}
|
, m_completedIcon {UIThemeManager::instance()->getIcon(u"checked-completed"_qs, u"completed"_qs)}
|
||||||
, m_downloadingIcon {UIThemeManager::instance()->getIcon(u"downloading"_qs)}
|
, m_downloadingIcon {UIThemeManager::instance()->getIcon(u"downloading"_qs)}
|
||||||
, m_errorIcon {UIThemeManager::instance()->getIcon(u"error"_qs)}
|
, m_errorIcon {UIThemeManager::instance()->getIcon(u"error"_qs)}
|
||||||
, m_pausedIcon {UIThemeManager::instance()->getIcon(u"torrent-stop"_qs)}
|
, m_pausedIcon {UIThemeManager::instance()->getIcon(u"torrent-stop"_qs, u"media-playback-pause"_qs)}
|
||||||
, m_queuedIcon {UIThemeManager::instance()->getIcon(u"queued"_qs)}
|
, m_queuedIcon {UIThemeManager::instance()->getIcon(u"queued"_qs)}
|
||||||
, m_stalledDLIcon {UIThemeManager::instance()->getIcon(u"stalledDL"_qs)}
|
, m_stalledDLIcon {UIThemeManager::instance()->getIcon(u"stalledDL"_qs)}
|
||||||
, m_stalledUPIcon {UIThemeManager::instance()->getIcon(u"stalledUP"_qs)}
|
, m_stalledUPIcon {UIThemeManager::instance()->getIcon(u"stalledUP"_qs)}
|
||||||
, m_uploadingIcon {UIThemeManager::instance()->getIcon(u"upload"_qs)}
|
, m_uploadingIcon {UIThemeManager::instance()->getIcon(u"upload"_qs, u"uploading"_qs)}
|
||||||
{
|
{
|
||||||
configure();
|
configure();
|
||||||
connect(Preferences::instance(), &Preferences::changed, this, &TransferListModel::configure);
|
connect(Preferences::instance(), &Preferences::changed, this, &TransferListModel::configure);
|
||||||
|
|
|
@ -930,11 +930,11 @@ void TransferListWidget::displayListMenu()
|
||||||
|
|
||||||
// Create actions
|
// Create actions
|
||||||
|
|
||||||
auto *actionStart = new QAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs), tr("&Resume", "Resume/start the torrent"), listMenu);
|
auto *actionStart = new QAction(UIThemeManager::instance()->getIcon(u"torrent-start"_qs, u"media-playback-start"_qs), tr("&Resume", "Resume/start the torrent"), listMenu);
|
||||||
connect(actionStart, &QAction::triggered, this, &TransferListWidget::startSelectedTorrents);
|
connect(actionStart, &QAction::triggered, this, &TransferListWidget::startSelectedTorrents);
|
||||||
auto *actionPause = new QAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs), tr("&Pause", "Pause the torrent"), listMenu);
|
auto *actionPause = new QAction(UIThemeManager::instance()->getIcon(u"torrent-stop"_qs, u"media-playback-pause"_qs), tr("&Pause", "Pause the torrent"), listMenu);
|
||||||
connect(actionPause, &QAction::triggered, this, &TransferListWidget::pauseSelectedTorrents);
|
connect(actionPause, &QAction::triggered, this, &TransferListWidget::pauseSelectedTorrents);
|
||||||
auto *actionForceStart = new QAction(UIThemeManager::instance()->getIcon(u"torrent-start-forced"_qs), tr("Force Resu&me", "Force Resume/start the torrent"), listMenu);
|
auto *actionForceStart = new QAction(UIThemeManager::instance()->getIcon(u"torrent-start-forced"_qs, u"media-playback-start"_qs), tr("Force Resu&me", "Force Resume/start the torrent"), listMenu);
|
||||||
connect(actionForceStart, &QAction::triggered, this, &TransferListWidget::forceStartSelectedTorrents);
|
connect(actionForceStart, &QAction::triggered, this, &TransferListWidget::forceStartSelectedTorrents);
|
||||||
auto *actionDelete = new QAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("&Remove", "Remove the torrent"), listMenu);
|
auto *actionDelete = new QAction(UIThemeManager::instance()->getIcon(u"list-remove"_qs), tr("&Remove", "Remove the torrent"), listMenu);
|
||||||
connect(actionDelete, &QAction::triggered, this, &TransferListWidget::softDeleteSelectedTorrents);
|
connect(actionDelete, &QAction::triggered, this, &TransferListWidget::softDeleteSelectedTorrents);
|
||||||
|
@ -952,21 +952,21 @@ void TransferListWidget::displayListMenu()
|
||||||
connect(actionTopQueuePos, &QAction::triggered, this, &TransferListWidget::topQueuePosSelectedTorrents);
|
connect(actionTopQueuePos, &QAction::triggered, this, &TransferListWidget::topQueuePosSelectedTorrents);
|
||||||
auto *actionBottomQueuePos = new QAction(UIThemeManager::instance()->getIcon(u"go-bottom"_qs), tr("Move to &bottom", "i.e. Move to bottom of the queue"), listMenu);
|
auto *actionBottomQueuePos = new QAction(UIThemeManager::instance()->getIcon(u"go-bottom"_qs), tr("Move to &bottom", "i.e. Move to bottom of the queue"), listMenu);
|
||||||
connect(actionBottomQueuePos, &QAction::triggered, this, &TransferListWidget::bottomQueuePosSelectedTorrents);
|
connect(actionBottomQueuePos, &QAction::triggered, this, &TransferListWidget::bottomQueuePosSelectedTorrents);
|
||||||
auto *actionSetTorrentPath = new QAction(UIThemeManager::instance()->getIcon(u"set-location"_qs), tr("Set loc&ation..."), listMenu);
|
auto *actionSetTorrentPath = new QAction(UIThemeManager::instance()->getIcon(u"set-location"_qs, u"inode-directory"_qs), tr("Set loc&ation..."), listMenu);
|
||||||
connect(actionSetTorrentPath, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsLocation);
|
connect(actionSetTorrentPath, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsLocation);
|
||||||
auto *actionForceRecheck = new QAction(UIThemeManager::instance()->getIcon(u"force-recheck"_qs), tr("Force rec&heck"), listMenu);
|
auto *actionForceRecheck = new QAction(UIThemeManager::instance()->getIcon(u"force-recheck"_qs, u"document-edit-verify"_qs), tr("Force rec&heck"), listMenu);
|
||||||
connect(actionForceRecheck, &QAction::triggered, this, &TransferListWidget::recheckSelectedTorrents);
|
connect(actionForceRecheck, &QAction::triggered, this, &TransferListWidget::recheckSelectedTorrents);
|
||||||
auto *actionForceReannounce = new QAction(UIThemeManager::instance()->getIcon(u"reannounce"_qs), tr("Force r&eannounce"), listMenu);
|
auto *actionForceReannounce = new QAction(UIThemeManager::instance()->getIcon(u"reannounce"_qs, u"document-edit-verify"_qs), tr("Force r&eannounce"), listMenu);
|
||||||
connect(actionForceReannounce, &QAction::triggered, this, &TransferListWidget::reannounceSelectedTorrents);
|
connect(actionForceReannounce, &QAction::triggered, this, &TransferListWidget::reannounceSelectedTorrents);
|
||||||
auto *actionCopyMagnetLink = new QAction(UIThemeManager::instance()->getIcon(u"torrent-magnet"_qs), tr("&Magnet link"), listMenu);
|
auto *actionCopyMagnetLink = new QAction(UIThemeManager::instance()->getIcon(u"torrent-magnet"_qs, u"kt-magnet"_qs), tr("&Magnet link"), listMenu);
|
||||||
connect(actionCopyMagnetLink, &QAction::triggered, this, &TransferListWidget::copySelectedMagnetURIs);
|
connect(actionCopyMagnetLink, &QAction::triggered, this, &TransferListWidget::copySelectedMagnetURIs);
|
||||||
auto *actionCopyID = new QAction(UIThemeManager::instance()->getIcon(u"help-about"_qs), tr("Torrent &ID"), listMenu);
|
auto *actionCopyID = new QAction(UIThemeManager::instance()->getIcon(u"help-about"_qs, u"edit-copy"_qs), tr("Torrent &ID"), listMenu);
|
||||||
connect(actionCopyID, &QAction::triggered, this, &TransferListWidget::copySelectedIDs);
|
connect(actionCopyID, &QAction::triggered, this, &TransferListWidget::copySelectedIDs);
|
||||||
auto *actionCopyName = new QAction(UIThemeManager::instance()->getIcon(u"name"_qs), tr("&Name"), listMenu);
|
auto *actionCopyName = new QAction(UIThemeManager::instance()->getIcon(u"name"_qs, u"edit-copy"_qs), tr("&Name"), listMenu);
|
||||||
connect(actionCopyName, &QAction::triggered, this, &TransferListWidget::copySelectedNames);
|
connect(actionCopyName, &QAction::triggered, this, &TransferListWidget::copySelectedNames);
|
||||||
auto *actionCopyHash1 = new QAction(UIThemeManager::instance()->getIcon(u"hash"_qs), tr("Info &hash v1"), listMenu);
|
auto *actionCopyHash1 = new QAction(UIThemeManager::instance()->getIcon(u"hash"_qs, u"edit-copy"_qs), tr("Info &hash v1"), listMenu);
|
||||||
connect(actionCopyHash1, &QAction::triggered, this, [this]() { copySelectedInfohashes(CopyInfohashPolicy::Version1); });
|
connect(actionCopyHash1, &QAction::triggered, this, [this]() { copySelectedInfohashes(CopyInfohashPolicy::Version1); });
|
||||||
auto *actionCopyHash2 = new QAction(UIThemeManager::instance()->getIcon(u"hash"_qs), tr("Info h&ash v2"), listMenu);
|
auto *actionCopyHash2 = new QAction(UIThemeManager::instance()->getIcon(u"hash"_qs, u"edit-copy"_qs), tr("Info h&ash v2"), listMenu);
|
||||||
connect(actionCopyHash2, &QAction::triggered, this, [this]() { copySelectedInfohashes(CopyInfohashPolicy::Version2); });
|
connect(actionCopyHash2, &QAction::triggered, this, [this]() { copySelectedInfohashes(CopyInfohashPolicy::Version2); });
|
||||||
auto *actionSuperSeedingMode = new TriStateAction(tr("Super seeding mode"), listMenu);
|
auto *actionSuperSeedingMode = new TriStateAction(tr("Super seeding mode"), listMenu);
|
||||||
connect(actionSuperSeedingMode, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsSuperSeeding);
|
connect(actionSuperSeedingMode, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsSuperSeeding);
|
||||||
|
@ -1152,7 +1152,7 @@ void TransferListWidget::displayListMenu()
|
||||||
QStringList tags(BitTorrent::Session::instance()->tags().values());
|
QStringList tags(BitTorrent::Session::instance()->tags().values());
|
||||||
std::sort(tags.begin(), tags.end(), Utils::Compare::NaturalLessThan<Qt::CaseInsensitive>());
|
std::sort(tags.begin(), tags.end(), Utils::Compare::NaturalLessThan<Qt::CaseInsensitive>());
|
||||||
|
|
||||||
QMenu *tagsMenu = listMenu->addMenu(UIThemeManager::instance()->getIcon(u"tags"_qs), tr("Ta&gs"));
|
QMenu *tagsMenu = listMenu->addMenu(UIThemeManager::instance()->getIcon(u"tags"_qs, u"view-categories"_qs), tr("Ta&gs"));
|
||||||
|
|
||||||
tagsMenu->addAction(UIThemeManager::instance()->getIcon(u"list-add"_qs), tr("&Add...", "Add / assign multiple tags...")
|
tagsMenu->addAction(UIThemeManager::instance()->getIcon(u"list-add"_qs), tr("&Add...", "Add / assign multiple tags...")
|
||||||
, this, &TransferListWidget::askAddTagsForSelection);
|
, this, &TransferListWidget::askAddTagsForSelection);
|
||||||
|
|
|
@ -167,7 +167,10 @@ void UIThemeManager::initInstance()
|
||||||
}
|
}
|
||||||
|
|
||||||
UIThemeManager::UIThemeManager()
|
UIThemeManager::UIThemeManager()
|
||||||
: m_useCustomTheme(Preferences::instance()->useCustomUITheme())
|
: m_useCustomTheme {Preferences::instance()->useCustomUITheme()}
|
||||||
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
|
||||||
|
, m_useSystemIcons {Preferences::instance()->useSystemIcons()}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (m_useCustomTheme)
|
if (m_useCustomTheme)
|
||||||
{
|
{
|
||||||
|
@ -196,14 +199,25 @@ void UIThemeManager::applyStyleSheet() const
|
||||||
qApp->setStyleSheet(QString::fromUtf8(m_themeSource->readStyleSheet()));
|
qApp->setStyleSheet(QString::fromUtf8(m_themeSource->readStyleSheet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QIcon UIThemeManager::getIcon(const QString &iconId, const QString &fallback) const
|
QIcon UIThemeManager::getIcon(const QString &iconId, [[maybe_unused]] const QString &fallback) const
|
||||||
{
|
{
|
||||||
// Cache to avoid rescaling svg icons
|
// Cache to avoid rescaling svg icons
|
||||||
const auto iter = m_iconCache.find(iconId);
|
const auto iter = m_iconCache.find(iconId);
|
||||||
if (iter != m_iconCache.end())
|
if (iter != m_iconCache.end())
|
||||||
return *iter;
|
return *iter;
|
||||||
|
|
||||||
const QIcon icon {getIconPathFromResources(iconId, fallback).data()};
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
|
||||||
|
// Don't cache system icons because users might change them at run time
|
||||||
|
if (m_useSystemIcons)
|
||||||
|
{
|
||||||
|
auto icon = QIcon::fromTheme(iconId);
|
||||||
|
if (icon.name() != iconId)
|
||||||
|
icon = QIcon::fromTheme(fallback, QIcon(getIconPathFromResources(iconId).data()));
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const QIcon icon {getIconPathFromResources(iconId).data()};
|
||||||
m_iconCache[iconId] = icon;
|
m_iconCache[iconId] = icon;
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
@ -259,23 +273,33 @@ QIcon UIThemeManager::getSystrayIcon() const
|
||||||
|
|
||||||
Path UIThemeManager::getIconPath(const QString &iconId) const
|
Path UIThemeManager::getIconPath(const QString &iconId) const
|
||||||
{
|
{
|
||||||
return getIconPathFromResources(iconId, {});
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
|
||||||
|
if (m_useSystemIcons)
|
||||||
|
{
|
||||||
|
Path path = Utils::Fs::tempPath() / Path(iconId + u".png");
|
||||||
|
if (!path.exists())
|
||||||
|
{
|
||||||
|
const QIcon icon = QIcon::fromTheme(iconId);
|
||||||
|
if (!icon.isNull())
|
||||||
|
icon.pixmap(32).save(path.toString());
|
||||||
|
else
|
||||||
|
path = getIconPathFromResources(iconId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return getIconPathFromResources(iconId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Path UIThemeManager::getIconPathFromResources(const QString &iconId, const QString &fallback) const
|
Path UIThemeManager::getIconPathFromResources(const QString &iconId) const
|
||||||
{
|
{
|
||||||
if (m_useCustomTheme && m_themeSource)
|
if (m_useCustomTheme && m_themeSource)
|
||||||
{
|
{
|
||||||
const Path customIcon = m_themeSource->iconPath(iconId);
|
const Path customIcon = m_themeSource->iconPath(iconId);
|
||||||
if (!customIcon.isEmpty())
|
if (!customIcon.isEmpty())
|
||||||
return customIcon;
|
return customIcon;
|
||||||
|
|
||||||
if (!fallback.isEmpty())
|
|
||||||
{
|
|
||||||
const Path fallbackIcon = m_themeSource->iconPath(fallback);
|
|
||||||
if (!fallbackIcon.isEmpty())
|
|
||||||
return fallbackIcon;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return findIcon(iconId, DEFAULT_ICONS_DIR);
|
return findIcon(iconId, DEFAULT_ICONS_DIR);
|
||||||
|
|
|
@ -70,13 +70,16 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UIThemeManager(); // singleton class
|
UIThemeManager(); // singleton class
|
||||||
Path getIconPathFromResources(const QString &iconId, const QString &fallback = {}) const;
|
Path getIconPathFromResources(const QString &iconId) const;
|
||||||
void loadColorsFromJSONConfig();
|
void loadColorsFromJSONConfig();
|
||||||
void applyPalette() const;
|
void applyPalette() const;
|
||||||
void applyStyleSheet() const;
|
void applyStyleSheet() const;
|
||||||
|
|
||||||
static UIThemeManager *m_instance;
|
static UIThemeManager *m_instance;
|
||||||
const bool m_useCustomTheme;
|
const bool m_useCustomTheme;
|
||||||
|
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
|
||||||
|
const bool m_useSystemIcons;
|
||||||
|
#endif
|
||||||
std::unique_ptr<UIThemeSource> m_themeSource;
|
std::unique_ptr<UIThemeSource> m_themeSource;
|
||||||
QHash<QString, QColor> m_colors;
|
QHash<QString, QColor> m_colors;
|
||||||
mutable QHash<QString, QIcon> m_iconCache;
|
mutable QHash<QString, QIcon> m_iconCache;
|
||||||
|
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 5.1 KiB |
|
@ -1 +1 @@
|
||||||
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="5.2" transform="matrix(.96198992 0 0 .96361031 .608162 .582235)"><path d="m4.0469562 10.349429 5.7224138-6.2783812 5.722414 6.2783812m-5.722414 17.579469v-22.6021738" stroke="#6495ed"/><path d="m27.953043 21.650571-5.722413 6.278382-5.722414-6.278382m5.722414-17.5794689v22.6021739" stroke="#3cb371"/></g></svg>
|
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="5.00656"><path d="m10.005859 2.0019531a2.5032799 2.5032799 0 0 0 -2.5039059 2.5039063v16.5156246l-1.1484375-1.261718a2.5032799 2.5032799 0 0 0 -3.5371093-.166016 2.5032799 2.5032799 0 0 0 -.1660157 3.535156l5.5039063 6.050781a2.5035303 2.5035303 0 0 0 3.7031251 0l5.505859-6.050781a2.5032799 2.5032799 0 0 0 -.167969-3.535156 2.5032799 2.5032799 0 0 0 -3.535156.166016l-1.15039 1.263671v-16.5175776a2.5032799 2.5032799 0 0 0 -2.503907-2.5039063z" fill="#3cb371"/><path d="m21.994141 2.0019531a2.5035303 2.5035303 0 0 0 -1.851563.8183594l-5.505859 6.0507813a2.5032799 2.5032799 0 0 0 .167969 3.5351562 2.5032799 2.5032799 0 0 0 3.535156-.166016l1.15039-1.263671v16.517578a2.5032799 2.5032799 0 0 0 2.503907 2.503906 2.5032799 2.5032799 0 0 0 2.503906-2.503906v-16.515625l1.148437 1.261718a2.5032799 2.5032799 0 0 0 3.53711.166016 2.5032799 2.5032799 0 0 0 .166015-3.5351562l-5.503906-6.0507813a2.5035303 2.5035303 0 0 0 -1.851562-.8183594z" fill="#1e90ff"/></g></svg>
|
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 1.1 KiB |
|
@ -1 +1 @@
|
||||||
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g stroke="#1e90ff"><path d="m26.502476 9.1481903-1.356007-1.5373535a12.290749 11.977843 0 0 0 -8.916781-3.7185561c-6.8057232 0-12.3273474 5.3810502-12.3273474 12.0135073 0 6.632457 5.5216242 12.013508 12.3273474 12.013508a12.333125 12.019138 0 0 0 11.625587-8.009005" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="3.99096"/><path d="m29.861915 3.2711167v7.6925913a1.1518373 1.1130536 0 0 1 -1.15184 1.113053h-7.960634c-1.026576 0-1.540583-1.198619-.814926-1.899843l7.961356-7.6932866c.725658-.7026152 1.966044-.2045237 1.966044.7874853z" fill="#4285f4" stroke-width=".070767"/></g></svg>
|
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.0016046 0 0 .9993628 .090124 .104351)"><path d="m26.502476 9.1481903-1.356007-1.5373535a12.290749 11.977843 0 0 0 -8.916781-3.7185561c-6.8057232 0-12.3273474 5.3810502-12.3273474 12.0135073 0 6.632457 5.5216242 12.013508 12.3273474 12.013508a12.333125 12.019138 0 0 0 11.625587-8.009005" fill="none" stroke="#1e90ff" stroke-linecap="round" stroke-miterlimit="10" stroke-width="3.99096"/><path d="m29.861915 3.2711167v7.6925913a1.1518373 1.1130536 0 0 1 -1.15184 1.113053h-7.960634c-1.026576 0-1.540583-1.198619-.814926-1.899843l7.961356-7.6932866c.725658-.7026152 1.966044-.2045237 1.966044.7874853z" fill="#1e90ff"/></g></svg>
|
Before Width: | Height: | Size: 697 B After Width: | Height: | Size: 733 B |
|
@ -299,6 +299,8 @@ void AppController::preferencesAction()
|
||||||
|
|
||||||
// Advanced settings
|
// Advanced settings
|
||||||
// qBitorrent preferences
|
// qBitorrent preferences
|
||||||
|
// Resume data storage type
|
||||||
|
data[u"resume_data_storage_type"_qs] = Utils::String::fromEnum(session->resumeDataStorageType());
|
||||||
// Physical memory (RAM) usage limit
|
// Physical memory (RAM) usage limit
|
||||||
data[u"memory_working_set_limit"_qs] = app()->memoryWorkingSetLimit();
|
data[u"memory_working_set_limit"_qs] = app()->memoryWorkingSetLimit();
|
||||||
// Current network interface
|
// Current network interface
|
||||||
|
@ -776,6 +778,9 @@ void AppController::setPreferencesAction()
|
||||||
|
|
||||||
// Advanced settings
|
// Advanced settings
|
||||||
// qBittorrent preferences
|
// qBittorrent preferences
|
||||||
|
// Resume data storage type
|
||||||
|
if (hasKey(u"resume_data_storage_type"_qs))
|
||||||
|
session->setResumeDataStorageType(Utils::String::toEnum(it.value().toString(), BitTorrent::ResumeDataStorageType::Legacy));
|
||||||
// Physical memory (RAM) usage limit
|
// Physical memory (RAM) usage limit
|
||||||
if (hasKey(u"memory_working_set_limit"_qs))
|
if (hasKey(u"memory_working_set_limit"_qs))
|
||||||
app()->setMemoryWorkingSetLimit(it.value().toInt());
|
app()->setMemoryWorkingSetLimit(it.value().toInt());
|
||||||
|
|
|
@ -30,13 +30,13 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class FreeDiskSpaceChecker : public QObject
|
class FreeDiskSpaceChecker final : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY_MOVE(FreeDiskSpaceChecker)
|
Q_DISABLE_COPY_MOVE(FreeDiskSpaceChecker)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FreeDiskSpaceChecker() = default;
|
using QObject::QObject;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void check();
|
void check();
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
#include <QThread>
|
#include <QThreadPool>
|
||||||
|
|
||||||
#include "base/bittorrent/cachestatus.h"
|
#include "base/bittorrent/cachestatus.h"
|
||||||
#include "base/bittorrent/infohash.h"
|
#include "base/bittorrent/infohash.h"
|
||||||
|
@ -49,7 +49,6 @@
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "apierror.h"
|
#include "apierror.h"
|
||||||
#include "freediskspacechecker.h"
|
#include "freediskspacechecker.h"
|
||||||
#include "isessionmanager.h"
|
|
||||||
#include "serialize/serialize_torrent.h"
|
#include "serialize/serialize_torrent.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -177,7 +176,7 @@ namespace
|
||||||
switch (static_cast<QMetaType::Type>(value.type()))
|
switch (static_cast<QMetaType::Type>(value.type()))
|
||||||
{
|
{
|
||||||
case QMetaType::QVariantMap:
|
case QMetaType::QVariantMap:
|
||||||
{
|
{
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
processMap(prevData[key].toMap(), value.toMap(), map);
|
processMap(prevData[key].toMap(), value.toMap(), map);
|
||||||
if (!map.isEmpty())
|
if (!map.isEmpty())
|
||||||
|
@ -185,7 +184,7 @@ namespace
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QMetaType::QVariantHash:
|
case QMetaType::QVariantHash:
|
||||||
{
|
{
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
processHash(prevData[key].toHash(), value.toHash(), map, removedItems);
|
processHash(prevData[key].toHash(), value.toHash(), map, removedItems);
|
||||||
if (!map.isEmpty())
|
if (!map.isEmpty())
|
||||||
|
@ -195,7 +194,7 @@ namespace
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QMetaType::QVariantList:
|
case QMetaType::QVariantList:
|
||||||
{
|
{
|
||||||
QVariantList list;
|
QVariantList list;
|
||||||
processList(prevData[key].toList(), value.toList(), list, removedItems);
|
processList(prevData[key].toList(), value.toList(), list, removedItems);
|
||||||
if (!list.isEmpty())
|
if (!list.isEmpty())
|
||||||
|
@ -372,15 +371,7 @@ namespace
|
||||||
|
|
||||||
SyncController::SyncController(IApplication *app, QObject *parent)
|
SyncController::SyncController(IApplication *app, QObject *parent)
|
||||||
: APIController(app, parent)
|
: APIController(app, parent)
|
||||||
, m_freeDiskSpaceChecker {new FreeDiskSpaceChecker}
|
|
||||||
, m_freeDiskSpaceThread {new QThread}
|
|
||||||
{
|
{
|
||||||
m_freeDiskSpaceChecker->moveToThread(m_freeDiskSpaceThread.get());
|
|
||||||
|
|
||||||
connect(m_freeDiskSpaceThread.get(), &QThread::finished, m_freeDiskSpaceChecker, &QObject::deleteLater);
|
|
||||||
connect(m_freeDiskSpaceChecker, &FreeDiskSpaceChecker::checked, this, &SyncController::freeDiskSpaceSizeUpdated);
|
|
||||||
|
|
||||||
m_freeDiskSpaceThread->start();
|
|
||||||
invokeChecker();
|
invokeChecker();
|
||||||
m_freeDiskSpaceElapsedTimer.start();
|
m_freeDiskSpaceElapsedTimer.start();
|
||||||
}
|
}
|
||||||
|
@ -595,20 +586,27 @@ void SyncController::torrentPeersAction()
|
||||||
qint64 SyncController::getFreeDiskSpace()
|
qint64 SyncController::getFreeDiskSpace()
|
||||||
{
|
{
|
||||||
if (m_freeDiskSpaceElapsedTimer.hasExpired(FREEDISKSPACE_CHECK_TIMEOUT))
|
if (m_freeDiskSpaceElapsedTimer.hasExpired(FREEDISKSPACE_CHECK_TIMEOUT))
|
||||||
{
|
|
||||||
invokeChecker();
|
invokeChecker();
|
||||||
m_freeDiskSpaceElapsedTimer.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_freeDiskSpace;
|
return m_freeDiskSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyncController::freeDiskSpaceSizeUpdated(qint64 freeSpaceSize)
|
void SyncController::invokeChecker()
|
||||||
{
|
{
|
||||||
m_freeDiskSpace = freeSpaceSize;
|
if (m_isFreeDiskSpaceCheckerRunning)
|
||||||
}
|
return;
|
||||||
|
|
||||||
void SyncController::invokeChecker() const
|
auto *freeDiskSpaceChecker = new FreeDiskSpaceChecker;
|
||||||
{
|
connect(freeDiskSpaceChecker, &FreeDiskSpaceChecker::checked, this, [this](const qint64 freeSpaceSize)
|
||||||
QMetaObject::invokeMethod(m_freeDiskSpaceChecker, &FreeDiskSpaceChecker::check, Qt::QueuedConnection);
|
{
|
||||||
|
m_freeDiskSpace = freeSpaceSize;
|
||||||
|
m_isFreeDiskSpaceCheckerRunning = false;
|
||||||
|
m_freeDiskSpaceElapsedTimer.restart();
|
||||||
|
});
|
||||||
|
connect(freeDiskSpaceChecker, &FreeDiskSpaceChecker::checked, freeDiskSpaceChecker, &QObject::deleteLater);
|
||||||
|
m_isFreeDiskSpaceCheckerRunning = true;
|
||||||
|
QThreadPool::globalInstance()->start([freeDiskSpaceChecker]
|
||||||
|
{
|
||||||
|
freeDiskSpaceChecker->check();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
#include "base/utils/thread.h"
|
|
||||||
#include "apicontroller.h"
|
#include "apicontroller.h"
|
||||||
|
|
||||||
class QThread;
|
class QThread;
|
||||||
|
@ -51,16 +50,14 @@ public:
|
||||||
private slots:
|
private slots:
|
||||||
void maindataAction();
|
void maindataAction();
|
||||||
void torrentPeersAction();
|
void torrentPeersAction();
|
||||||
void freeDiskSpaceSizeUpdated(qint64 freeSpaceSize);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
qint64 getFreeDiskSpace();
|
qint64 getFreeDiskSpace();
|
||||||
void invokeChecker() const;
|
void invokeChecker();
|
||||||
|
|
||||||
qint64 m_freeDiskSpace = 0;
|
qint64 m_freeDiskSpace = 0;
|
||||||
FreeDiskSpaceChecker *m_freeDiskSpaceChecker = nullptr;
|
|
||||||
Utils::Thread::UniquePtr m_freeDiskSpaceThread;
|
|
||||||
QElapsedTimer m_freeDiskSpaceElapsedTimer;
|
QElapsedTimer m_freeDiskSpaceElapsedTimer;
|
||||||
|
bool m_isFreeDiskSpaceCheckerRunning = false;
|
||||||
|
|
||||||
QVariantMap m_lastMaindataResponse;
|
QVariantMap m_lastMaindataResponse;
|
||||||
QVariantMap m_lastAcceptedMaindataResponse;
|
QVariantMap m_lastAcceptedMaindataResponse;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
@ -112,6 +113,22 @@ namespace
|
||||||
|
|
||||||
return u"no-store"_qs;
|
return u"no-store"_qs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString createLanguagesOptionsHtml()
|
||||||
|
{
|
||||||
|
// List language files
|
||||||
|
const QDir langDir {u":/www/translations"_qs};
|
||||||
|
const QStringList langFiles = langDir.entryList(QStringList(u"webui_*.qm"_qs), QDir::Files);
|
||||||
|
QStringList languages;
|
||||||
|
for (const QString &langFile : langFiles)
|
||||||
|
{
|
||||||
|
const QString localeStr = langFile.section(u"_"_qs, 1, -1).section(u"."_qs, 0, 0); // remove "webui_" and ".qm"
|
||||||
|
languages << u"<option value=\"%1\">%2</option>"_qs.arg(localeStr, Utils::Misc::languageToLocalizedString(localeStr));
|
||||||
|
qDebug() << "Supported locale:" << localeStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return languages.join(u'\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WebApplication::WebApplication(IApplication *app, QObject *parent)
|
WebApplication::WebApplication(IApplication *app, QObject *parent)
|
||||||
|
@ -472,13 +489,17 @@ void WebApplication::sendFile(const Path &path)
|
||||||
const QMimeType mimeType = QMimeDatabase().mimeTypeForFileNameAndData(path.data(), data);
|
const QMimeType mimeType = QMimeDatabase().mimeTypeForFileNameAndData(path.data(), data);
|
||||||
const bool isTranslatable = !m_isAltUIUsed && mimeType.inherits(u"text/plain"_qs);
|
const bool isTranslatable = !m_isAltUIUsed && mimeType.inherits(u"text/plain"_qs);
|
||||||
|
|
||||||
// Translate the file
|
|
||||||
if (isTranslatable)
|
if (isTranslatable)
|
||||||
{
|
{
|
||||||
auto dataStr = QString::fromUtf8(data);
|
auto dataStr = QString::fromUtf8(data);
|
||||||
|
// Translate the file
|
||||||
translateDocument(dataStr);
|
translateDocument(dataStr);
|
||||||
data = dataStr.toUtf8();
|
|
||||||
|
|
||||||
|
// Add the language options
|
||||||
|
if (path == (m_rootFolder / Path(PRIVATE_FOLDER) / Path(u"views/preferences.html"_qs)))
|
||||||
|
dataStr.replace(u"${LANGUAGE_OPTIONS}"_qs, createLanguagesOptionsHtml());
|
||||||
|
|
||||||
|
data = dataStr.toUtf8();
|
||||||
m_translatedFiles[path] = {data, mimeType.name(), lastModified}; // caching translated file
|
m_translatedFiles[path] = {data, mimeType.name(), lastModified}; // caching translated file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
#include "base/utils/version.h"
|
#include "base/utils/version.h"
|
||||||
#include "api/isessionmanager.h"
|
#include "api/isessionmanager.h"
|
||||||
|
|
||||||
inline const Utils::Version<3, 2> API_VERSION {2, 8, 18};
|
inline const Utils::Version<3, 2> API_VERSION {2, 8, 19};
|
||||||
|
|
||||||
class APIController;
|
class APIController;
|
||||||
class AuthController;
|
class AuthController;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="5.2" transform="matrix(.96198992 0 0 .96361031 .608162 .582235)"><path d="m4.0469562 10.349429 5.7224138-6.2783812 5.722414 6.2783812m-5.722414 17.579469v-22.6021738" stroke="#6495ed"/><path d="m27.953043 21.650571-5.722413 6.278382-5.722414-6.278382m5.722414-17.5794689v22.6021739" stroke="#3cb371"/></g></svg>
|
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="5.00656"><path d="m10.005859 2.0019531a2.5032799 2.5032799 0 0 0 -2.5039059 2.5039063v16.5156246l-1.1484375-1.261718a2.5032799 2.5032799 0 0 0 -3.5371093-.166016 2.5032799 2.5032799 0 0 0 -.1660157 3.535156l5.5039063 6.050781a2.5035303 2.5035303 0 0 0 3.7031251 0l5.505859-6.050781a2.5032799 2.5032799 0 0 0 -.167969-3.535156 2.5032799 2.5032799 0 0 0 -3.535156.166016l-1.15039 1.263671v-16.5175776a2.5032799 2.5032799 0 0 0 -2.503907-2.5039063z" fill="#3cb371"/><path d="m21.994141 2.0019531a2.5035303 2.5035303 0 0 0 -1.851563.8183594l-5.505859 6.0507813a2.5032799 2.5032799 0 0 0 .167969 3.5351562 2.5032799 2.5032799 0 0 0 3.535156-.166016l1.15039-1.263671v16.517578a2.5032799 2.5032799 0 0 0 2.503907 2.503906 2.5032799 2.5032799 0 0 0 2.503906-2.503906v-16.515625l1.148437 1.261718a2.5032799 2.5032799 0 0 0 3.53711.166016 2.5032799 2.5032799 0 0 0 .166015-3.5351562l-5.503906-6.0507813a2.5035303 2.5035303 0 0 0 -1.851562-.8183594z" fill="#1e90ff"/></g></svg>
|
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 1.1 KiB |
1
src/webui/www/private/images/folder-documents.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g fill="#1e90ff"><path d="m20.949219 13.083984-9.898438 9.898438c.555802.551364 1.200161 1.005584 1.90625 1.34375.165012.080142.333109.153763.503907.220703.045118.018.091118.033781.136718.050781.760655.238926 1.535072.444831 2.357422.431641.0149 0 .030022.003906.044922.003906.08443 0 .16632-.010672.25-.013672.136229-.00253.272354-.009051.408203-.019531.13051-.0122.258379-.033534.386719-.052734.840074-.172598 1.62762-.465682 2.33789-.865235.710271-.399553 1.343205-.903889 1.873047-1.498047.529843-.594157.957068-1.278743 1.25586-2.035156.298791-.756412.46921-1.586339.486328-2.472656v-.042969c0-.1096-.008672-.216009-.013672-.324219-.06609-.712616-.139954-1.410863-.423828-2.095703-.00642-.01956-.012931-.039093-.019531-.058593-.001-.003-.002937-.00386-.003907-.00586-.349361-.924496-.890527-1.764536-1.58789-2.464844z"/><path d="m2.7773438 2c-.4308891 0-.7773438.446-.7773438 1v3.921875 2.078125 20.078125c0 .5114.3190539.921875.7167969.921875h26.5664061c.397743 0 .716797-.410474.716797-.921875v-22.15625c0-.5113999-.319054-.921875-.716797-.921875h-12.726562c-.886457.034-1.316068-.264328-1.707032-.7363281l-1.849609-2.4199219c-.261411-.4404-.457783-.84375-.888672-.84375zm13.2226562 8.033203c1.0138 0 1.982426.19057 2.873047.535156.890621.344587 1.703238.843189 2.408203 1.464844l.375.34375c.11897.11897.23239.24879.34375.375.621655.704965 1.122211 1.519535 1.466797 2.410156.344586.890622.533203 1.857294.533203 2.871094 0 1.10457-.224084 2.158128-.628906 3.115235-.404822.957106-.990986 1.819111-1.714844 2.542968-.723858.723858-1.585862 1.308069-2.542969 1.712891s-2.008711.628906-3.113281.628906c-1.0138 0-1.982426-.188617-2.873047-.533203s-1.703238-.845142-2.408203-1.466797c-.219938-.213654-.510719-.451508-.71875-.71875-.6216549-.704965-1.1222107-1.517582-1.4667969-2.408203s-.5332031-1.859247-.5332031-2.873047c0-1.10457.2240844-2.156174.6289062-3.113281.4048219-.957107.9909863-1.819111 1.7148438-2.542969.723857-.723857 1.585862-1.310022 2.542969-1.714844s2.008711-.628906 3.113281-.628906z"/></g></svg>
|
After Width: | Height: | Size: 2.1 KiB |
1
src/webui/www/private/images/task-reject.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><path d="m28.122773 8.9725973c-1.251859-2.1448373-2.95009-3.843056-5.094918-5.0949173-2.145273-1.2518613-4.487221-1.87768-7.027407-1.87768-2.539963 0-4.882582.6258187-7.0274094 1.87768-2.1450513 1.2516373-3.8432821 2.949856-5.0951397 5.0949173-1.2520819 2.1450427-1.8778989 4.4876717-1.8778989 7.0274027 0 2.539955.6260408 4.882136 1.8776749 7.027403 1.251858 2.144613 2.9500888 3.843056 5.0951399 5.094917 2.1450512 1.251861 4.4874462 1.87768 7.0274092 1.87768 2.539962 0 4.882579-.625819 7.027407-1.87768 2.144828-1.251637 3.843059-2.95008 5.094918-5.094917 1.251635-2.145043 1.877451-4.487672 1.877451-7.027403 0-2.539955-.625816-4.882584-1.877227-7.0274027zm-5.523614 10.3267547c.230907.230673.346582.50456.346582.820475 0 .32801-.115687.607693-.346582.838376l-1.640504 1.640725c-.230906.230907-.510364.34636-.838599.34636-.315929 0-.589794-.115547-.820253-.34636l-3.299579-3.299576-3.29958 3.299576c-.230907.230907-.504323.34636-.820252.34636-.328235 0-.607694-.115547-.8386-.34636l-1.6407277-1.640725c-.2309067-.230674-.3463584-.510366-.3463584-.838376 0-.315915.1154534-.589792.3463584-.820475l3.2995797-3.299352-3.2995797-3.299576c-.2309067-.230673-.3463584-.504336-.3463584-.820251 0-.328234.1154534-.607693.3463584-.8386l1.6407277-1.640501c.230907-.2309067.510365-.34636.8386-.34636.315929 0 .589346.1155467.820252.34636l3.29958 3.299352 3.299579-3.299352c.230459-.2309067.504324-.34636.820253-.34636.328235 0 .607693.1155467.838599.34636l1.640504 1.640501c.230907.230907.346582.510366.346582.8386 0 .315915-.115687.589568-.346582.820251l-3.299356 3.299576z" fill="#f00" stroke-width="2.333333"/></svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -1 +1 @@
|
||||||
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g stroke="#1e90ff"><path d="m26.502476 9.1481903-1.356007-1.5373535a12.290749 11.977843 0 0 0 -8.916781-3.7185561c-6.8057232 0-12.3273474 5.3810502-12.3273474 12.0135073 0 6.632457 5.5216242 12.013508 12.3273474 12.013508a12.333125 12.019138 0 0 0 11.625587-8.009005" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="3.99096"/><path d="m29.861915 3.2711167v7.6925913a1.1518373 1.1130536 0 0 1 -1.15184 1.113053h-7.960634c-1.026576 0-1.540583-1.198619-.814926-1.899843l7.961356-7.6932866c.725658-.7026152 1.966044-.2045237 1.966044.7874853z" fill="#4285f4" stroke-width=".070767"/></g></svg>
|
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.0016046 0 0 .9993628 .090124 .104351)"><path d="m26.502476 9.1481903-1.356007-1.5373535a12.290749 11.977843 0 0 0 -8.916781-3.7185561c-6.8057232 0-12.3273474 5.3810502-12.3273474 12.0135073 0 6.632457 5.5216242 12.013508 12.3273474 12.013508a12.333125 12.019138 0 0 0 11.625587-8.009005" fill="none" stroke="#1e90ff" stroke-linecap="round" stroke-miterlimit="10" stroke-width="3.99096"/><path d="m29.861915 3.2711167v7.6925913a1.1518373 1.1130536 0 0 1 -1.15184 1.113053h-7.960634c-1.026576 0-1.540583-1.198619-.814926-1.899843l7.961356-7.6932866c.725658-.7026152 1.966044-.2045237 1.966044.7874853z" fill="#1e90ff"/></g></svg>
|
Before Width: | Height: | Size: 697 B After Width: | Height: | Size: 733 B |
|
@ -14,7 +14,7 @@
|
||||||
<iframe id="upload_frame" name="upload_frame" class="invisible" src="about:blank"></iframe>
|
<iframe id="upload_frame" name="upload_frame" class="invisible" src="about:blank"></iframe>
|
||||||
<form action="api/v2/torrents/add" enctype="multipart/form-data" method="post" id="uploadForm" style="text-align: center;" target="upload_frame" autocorrect="off" autocapitalize="none">
|
<form action="api/v2/torrents/add" enctype="multipart/form-data" method="post" id="uploadForm" style="text-align: center;" target="upload_frame" autocorrect="off" autocapitalize="none">
|
||||||
<div style="margin-top: 25px; display: inline-block; border: 1px solid lightgrey; border-radius: 4px;">
|
<div style="margin-top: 25px; display: inline-block; border: 1px solid lightgrey; border-radius: 4px;">
|
||||||
<input type="file" id="fileselect" accept="application/x-bittorrent, .torrent" name="fileselect[]" multiple />
|
<input type="file" id="fileselect" accept=".torrent, application/x-bittorrent" name="fileselect[]" multiple />
|
||||||
</div>
|
</div>
|
||||||
<fieldset class="settings" style="border: 0; text-align: left; margin-top: 12px;">
|
<fieldset class="settings" style="border: 0; text-align: left; margin-top: 12px;">
|
||||||
<table style="margin: auto;">
|
<table style="margin: auto;">
|
||||||
|
|
|
@ -666,62 +666,7 @@
|
||||||
<legend>QBT_TR(Language)QBT_TR[CONTEXT=OptionsDialog]</legend>
|
<legend>QBT_TR(Language)QBT_TR[CONTEXT=OptionsDialog]</legend>
|
||||||
<label for="locale_select">QBT_TR(User Interface Language:)QBT_TR[CONTEXT=OptionsDialog]</label>
|
<label for="locale_select">QBT_TR(User Interface Language:)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||||
<select id="locale_select">
|
<select id="locale_select">
|
||||||
<option value="ar_AE">عربي</option>
|
${LANGUAGE_OPTIONS}
|
||||||
<option value="az@latin">Azərbaycan dili</option>
|
|
||||||
<option value="be_BY">Беларуская</option>
|
|
||||||
<option value="bg_BG">Български</option>
|
|
||||||
<option value="ca_ES">Català</option>
|
|
||||||
<option value="cs_CZ">Čeština</option>
|
|
||||||
<option value="da_DK">Dansk</option>
|
|
||||||
<option value="de_DE">Deutsch</option>
|
|
||||||
<option value="el_GR">Ελληνικά</option>
|
|
||||||
<option value="en">English</option>
|
|
||||||
<option value="en_AU">English (Australia)</option>
|
|
||||||
<option value="en_GB">English (United Kingdom)</option>
|
|
||||||
<option value="eo_EO">Esperanto</option>
|
|
||||||
<option value="es_ES">Español</option>
|
|
||||||
<option value="et">Eesti, eesti keel</option>
|
|
||||||
<option value="eu_ES">Euskara</option>
|
|
||||||
<option value="fa">فارسی</option>
|
|
||||||
<option value="fi_FI">Suomi</option>
|
|
||||||
<option value="fr_FR">Français</option>
|
|
||||||
<option value="gl_ES">Galego</option>
|
|
||||||
<option value="he_IL">עברית</option>
|
|
||||||
<option value="hi_IN">हिन्दी, हिंदी</option>
|
|
||||||
<option value="hr_HR">Hrvatski</option>
|
|
||||||
<option value="hu_HU">Magyar</option>
|
|
||||||
<option value="hy_AM">Հայերեն</option>
|
|
||||||
<option value="id">Bahasa Indonesia</option>
|
|
||||||
<option value="is">Íslenska</option>
|
|
||||||
<option value="it_IT">Italiano</option>
|
|
||||||
<option value="ja_JP">日本語</option>
|
|
||||||
<option value="ka_GE">ქართული</option>
|
|
||||||
<option value="ko_KR">한국어</option>
|
|
||||||
<option value="ltg">Latgalīšu volūda</option>
|
|
||||||
<option value="lt_LT">Lietuvių</option>
|
|
||||||
<option value="lv_LV">Latviešu valoda</option>
|
|
||||||
<option value="mn_MN">Монгол хэл</option>
|
|
||||||
<option value="ms_MY">بهاس ملايو</option>
|
|
||||||
<option value="nb_NO">Norsk</option>
|
|
||||||
<option value="nl_NL">Nederlands</option>
|
|
||||||
<option value="oc">lenga d'òc</option>
|
|
||||||
<option value="pl_PL">Polski</option>
|
|
||||||
<option value="pt_BR">Português brasileiro</option>
|
|
||||||
<option value="pt_PT">Português</option>
|
|
||||||
<option value="ro_RO">Română</option>
|
|
||||||
<option value="ru_RU">Русский</option>
|
|
||||||
<option value="sk_SK">Slovenčina</option>
|
|
||||||
<option value="sl_SI">Slovenščina</option>
|
|
||||||
<option value="sr_CS">Српски</option>
|
|
||||||
<option value="sv_SE">Svenska</option>
|
|
||||||
<option value="th">ไทย</option>
|
|
||||||
<option value="tr_TR">Türkçe</option>
|
|
||||||
<option value="uk_UA">Українська</option>
|
|
||||||
<option value="uz@Latn">أۇزبېك</option>
|
|
||||||
<option value="vi_VN">Tiếng Việt</option>
|
|
||||||
<option value="zh">简体中文</option>
|
|
||||||
<option value="zh_HK">香港正體字</option>
|
|
||||||
<option value="zh_TW">正體中文</option>
|
|
||||||
</select>
|
</select>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
@ -934,6 +879,17 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
<fieldset class="settings">
|
<fieldset class="settings">
|
||||||
<legend>QBT_TR(qBittorrent Section)QBT_TR[CONTEXT=OptionsDialog] (<a href="https://github.com/qbittorrent/qBittorrent/wiki/Explanation-of-Options-in-qBittorrent#Advanced" target="_blank">QBT_TR(Open documentation)QBT_TR[CONTEXT=HttpServer]</a>)</legend>
|
<legend>QBT_TR(qBittorrent Section)QBT_TR[CONTEXT=OptionsDialog] (<a href="https://github.com/qbittorrent/qBittorrent/wiki/Explanation-of-Options-in-qBittorrent#Advanced" target="_blank">QBT_TR(Open documentation)QBT_TR[CONTEXT=HttpServer]</a>)</legend>
|
||||||
<table>
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="resumeDataStorageType">QBT_TR(Resume data storage type (requires restart):)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="resumeDataStorageType" style="width: 15em;">
|
||||||
|
<option value="Legacy">QBT_TR(Fastresume files)QBT_TR[CONTEXT=OptionsDialog]</option>
|
||||||
|
<option value="SQLite">QBT_TR(SQLite database (experimental))QBT_TR[CONTEXT=OptionsDialog]</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label for="memoryWorkingSetLimit">QBT_TR(Physical memory (RAM) usage limit (applied if libtorrent >= 2.0):)QBT_TR[CONTEXT=OptionsDialog] <a href="https://wikipedia.org/wiki/Working_set" target="_blank">(?)</a></label>
|
<label for="memoryWorkingSetLimit">QBT_TR(Physical memory (RAM) usage limit (applied if libtorrent >= 2.0):)QBT_TR[CONTEXT=OptionsDialog] <a href="https://wikipedia.org/wiki/Working_set" target="_blank">(?)</a></label>
|
||||||
|
@ -1408,6 +1364,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
updateWebUICustomHTTPHeadersSettings: updateWebUICustomHTTPHeadersSettings,
|
updateWebUICustomHTTPHeadersSettings: updateWebUICustomHTTPHeadersSettings,
|
||||||
updateWebUIReverseProxySettings: updateWebUIReverseProxySettings,
|
updateWebUIReverseProxySettings: updateWebUIReverseProxySettings,
|
||||||
updateDynDnsSettings: updateDynDnsSettings,
|
updateDynDnsSettings: updateDynDnsSettings,
|
||||||
|
updateWebuiLocaleSelect: updateWebuiLocaleSelect,
|
||||||
registerDynDns: registerDynDns,
|
registerDynDns: registerDynDns,
|
||||||
applyPreferences: applyPreferences
|
applyPreferences: applyPreferences
|
||||||
};
|
};
|
||||||
|
@ -1737,6 +1694,18 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
}).send();
|
}).send();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateWebuiLocaleSelect = (selected) => {
|
||||||
|
let languages = [];
|
||||||
|
for (let i = 0; i < $('locale_select').options.length; i++)
|
||||||
|
languages.push($('locale_select').options[i].value);
|
||||||
|
|
||||||
|
if (!languages.includes(selected)) {
|
||||||
|
const lang = selected.slice(0, selected.indexOf('_'));
|
||||||
|
selected = languages.includes(lang) ? lang : 'en';
|
||||||
|
}
|
||||||
|
$('locale_select').setProperty('value', selected);
|
||||||
|
};
|
||||||
|
|
||||||
const loadPreferences = function() {
|
const loadPreferences = function() {
|
||||||
const url = 'api/v2/app/preferences';
|
const url = 'api/v2/app/preferences';
|
||||||
new Request.JSON({
|
new Request.JSON({
|
||||||
|
@ -2013,7 +1982,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
|
|
||||||
// Web UI tab
|
// Web UI tab
|
||||||
// Language
|
// Language
|
||||||
$('locale_select').setProperty('value', ((pref.locale === "en_US") ? "en" : pref.locale));
|
updateWebuiLocaleSelect(pref.locale);
|
||||||
$('performanceWarning').setProperty('checked', pref.performance_warning);
|
$('performanceWarning').setProperty('checked', pref.performance_warning);
|
||||||
|
|
||||||
// HTTP Server
|
// HTTP Server
|
||||||
|
@ -2068,6 +2037,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
|
|
||||||
// Advanced settings
|
// Advanced settings
|
||||||
// qBittorrent section
|
// qBittorrent section
|
||||||
|
$('resumeDataStorageType').setProperty('value', pref.resume_data_storage_type);
|
||||||
$('memoryWorkingSetLimit').setProperty('value', pref.memory_working_set_limit);
|
$('memoryWorkingSetLimit').setProperty('value', pref.memory_working_set_limit);
|
||||||
updateNetworkInterfaces(pref.current_network_interface);
|
updateNetworkInterfaces(pref.current_network_interface);
|
||||||
updateInterfaceAddresses(pref.current_network_interface, pref.current_interface_address);
|
updateInterfaceAddresses(pref.current_network_interface, pref.current_interface_address);
|
||||||
|
@ -2495,6 +2465,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
|
|
||||||
// Update advanced settings
|
// Update advanced settings
|
||||||
// qBittorrent section
|
// qBittorrent section
|
||||||
|
settings.set('resume_data_storage_type', $('resumeDataStorageType').getProperty('value'));
|
||||||
settings.set('memory_working_set_limit', $('memoryWorkingSetLimit').getProperty('value'));
|
settings.set('memory_working_set_limit', $('memoryWorkingSetLimit').getProperty('value'));
|
||||||
settings.set('current_network_interface', $('networkInterface').getProperty('value'));
|
settings.set('current_network_interface', $('networkInterface').getProperty('value'));
|
||||||
settings.set('current_interface_address', $('optionalIPAddressToBind').getProperty('value'));
|
settings.set('current_interface_address', $('optionalIPAddressToBind').getProperty('value'));
|
||||||
|
|
|
@ -309,6 +309,7 @@
|
||||||
<file>private/images/flags/za.svg</file>
|
<file>private/images/flags/za.svg</file>
|
||||||
<file>private/images/flags/zm.svg</file>
|
<file>private/images/flags/zm.svg</file>
|
||||||
<file>private/images/flags/zw.svg</file>
|
<file>private/images/flags/zw.svg</file>
|
||||||
|
<file>private/images/folder-documents.svg</file>
|
||||||
<file>private/images/folder-new.svg</file>
|
<file>private/images/folder-new.svg</file>
|
||||||
<file>private/images/force-recheck.svg</file>
|
<file>private/images/force-recheck.svg</file>
|
||||||
<file>private/images/go-bottom.svg</file>
|
<file>private/images/go-bottom.svg</file>
|
||||||
|
@ -348,6 +349,7 @@
|
||||||
<file>private/images/tabs.gif</file>
|
<file>private/images/tabs.gif</file>
|
||||||
<file>private/images/tags.svg</file>
|
<file>private/images/tags.svg</file>
|
||||||
<file>private/images/task-complete.svg</file>
|
<file>private/images/task-complete.svg</file>
|
||||||
|
<file>private/images/task-reject.svg</file>
|
||||||
<file>private/images/toolbox-divider.gif</file>
|
<file>private/images/toolbox-divider.gif</file>
|
||||||
<file>private/images/torrent-magnet.svg</file>
|
<file>private/images/torrent-magnet.svg</file>
|
||||||
<file>private/images/torrent-start-forced.svg</file>
|
<file>private/images/torrent-start-forced.svg</file>
|
||||||
|
|