refactor: remove exit-time destructors from transmission-qt (#1395)
* refactor: remove exit-time destructors from transmission-qt
This commit is contained in:
parent
677dc73eac
commit
68920f5fa6
|
@ -406,6 +406,7 @@ set(WARNING_CANDIDATES
|
|||
-Wextra
|
||||
-Wcast-align
|
||||
-Wduplicated-cond
|
||||
-Wexit-time-destructors
|
||||
-Wextra-semi
|
||||
-Wextra-semi-stmt
|
||||
-Wextra-tokens
|
||||
|
|
|
@ -20,7 +20,7 @@ Checks: >
|
|||
-clang-diagnostic-sign-conversion,
|
||||
-clang-diagnostic-switch-enum,
|
||||
-clang-diagnostic-undefined-reinterpret-cast,
|
||||
+ -clang-diagnostic-unused-member-function,
|
||||
-clang-diagnostic-unused-member-function,
|
||||
cppcoreguidelines-*,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-init-variables,
|
||||
|
|
|
@ -44,9 +44,6 @@
|
|||
namespace
|
||||
{
|
||||
|
||||
auto const MyConfigName = QStringLiteral("transmission");
|
||||
auto const MyReadableName = QStringLiteral("transmission-qt");
|
||||
|
||||
std::array<tr_option, 8> const Opts =
|
||||
{
|
||||
tr_option{ 'g', "config-dir", "Where to look for configuration files", "g", true, "<path>" },
|
||||
|
@ -88,13 +85,13 @@ bool loadTranslation(QTranslator& translator, QString const& name, QLocale const
|
|||
} // namespace
|
||||
|
||||
Application::Application(int& argc, char** argv) :
|
||||
QApplication(argc, argv)
|
||||
QApplication(argc, argv),
|
||||
config_name_{QStringLiteral("transmission")},
|
||||
display_name_{QStringLiteral("transmission-qt")}
|
||||
{
|
||||
setApplicationName(MyConfigName);
|
||||
setApplicationName(config_name_);
|
||||
loadTranslations();
|
||||
|
||||
Formatter::initUnits();
|
||||
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
|
||||
if (QIcon::themeName().isEmpty())
|
||||
|
@ -162,13 +159,13 @@ Application::Application(int& argc, char** argv) :
|
|||
break;
|
||||
|
||||
case 'v':
|
||||
std::cerr << qPrintable(MyReadableName) << ' ' << LONG_VERSION_STRING << std::endl;
|
||||
std::cerr << qPrintable(display_name_) << ' ' << LONG_VERSION_STRING << std::endl;
|
||||
quitLater();
|
||||
return;
|
||||
|
||||
case TR_OPT_ERR:
|
||||
std::cerr << qPrintable(QObject::tr("Invalid option")) << std::endl;
|
||||
tr_getopt_usage(qPrintable(MyReadableName), getUsage(), Opts.data());
|
||||
tr_getopt_usage(qPrintable(display_name_), getUsage(), Opts.data());
|
||||
quitLater();
|
||||
return;
|
||||
|
||||
|
@ -379,8 +376,8 @@ void Application::loadTranslations()
|
|||
installTranslator(&qt_translator_);
|
||||
}
|
||||
|
||||
if (loadTranslation(app_translator_, MyConfigName, locale, app_qm_dirs) ||
|
||||
loadTranslation(app_translator_, MyConfigName, english_locale, app_qm_dirs))
|
||||
if (loadTranslation(app_translator_, config_name_, locale, app_qm_dirs) ||
|
||||
loadTranslation(app_translator_, config_name_, english_locale, app_qm_dirs))
|
||||
{
|
||||
installTranslator(&app_translator_);
|
||||
}
|
||||
|
|
|
@ -69,6 +69,9 @@ private:
|
|||
QTranslator qt_translator_;
|
||||
QTranslator app_translator_;
|
||||
FaviconCache favicons_;
|
||||
|
||||
QString const config_name_;
|
||||
QString const display_name_;
|
||||
};
|
||||
|
||||
#undef qApp
|
||||
|
|
|
@ -19,6 +19,7 @@ set(${PROJECT_NAME}_SOURCES
|
|||
Filters.cc
|
||||
Formatter.cc
|
||||
FreeSpaceLabel.cc
|
||||
IconCache.cc
|
||||
IconToolButton.cc
|
||||
InteropHelper.cc
|
||||
InteropObject.cc
|
||||
|
@ -84,6 +85,7 @@ set(${PROJECT_NAME}_HEADERS
|
|||
Filters.h
|
||||
Formatter.h
|
||||
FreeSpaceLabel.h
|
||||
IconCache.h
|
||||
IconToolButton.h
|
||||
InteropHelper.h
|
||||
InteropObject.h
|
||||
|
|
|
@ -17,15 +17,6 @@
|
|||
#include "DBusInteropHelper.h"
|
||||
#include "InteropObject.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
auto const DBusService = QStringLiteral("com.transmissionbt.Transmission");
|
||||
auto const DBusObjectPath = QStringLiteral("/com/transmissionbt/Transmission");
|
||||
auto const DBusInterface = QStringLiteral("com.transmissionbt.Transmission");
|
||||
|
||||
} // namespace
|
||||
|
||||
bool DBusInteropHelper::isConnected() const
|
||||
{
|
||||
return QDBusConnection::sessionBus().isConnected();
|
||||
|
@ -33,8 +24,12 @@ bool DBusInteropHelper::isConnected() const
|
|||
|
||||
QVariant DBusInteropHelper::addMetainfo(QString const& metainfo)
|
||||
{
|
||||
QDBusMessage request = QDBusMessage::createMethodCall(DBusService, DBusObjectPath, DBusInterface,
|
||||
QStringLiteral("AddMetainfo"));
|
||||
auto request = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("com.transmissionbt.Transmission"),
|
||||
QStringLiteral("com/transmissionbt/Transmission"),
|
||||
QStringLiteral("com.transmissionbt.Transmission"),
|
||||
QStringLiteral("AddMetainfo")
|
||||
);
|
||||
request.setArguments(QVariantList() << metainfo);
|
||||
|
||||
QDBusReply<bool> const response = QDBusConnection::sessionBus().call(request);
|
||||
|
@ -43,20 +38,21 @@ QVariant DBusInteropHelper::addMetainfo(QString const& metainfo)
|
|||
|
||||
void DBusInteropHelper::registerObject(QObject* parent)
|
||||
{
|
||||
QDBusConnection bus = QDBusConnection::sessionBus();
|
||||
|
||||
auto bus = QDBusConnection::sessionBus();
|
||||
if (!bus.isConnected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bus.registerService(DBusService))
|
||||
auto const service_name = QStringLiteral("com.transmissionbt.Transmission");
|
||||
if (!bus.registerService(service_name))
|
||||
{
|
||||
std::cerr << "couldn't register " << qPrintable(DBusService) << std::endl;
|
||||
std::cerr << "couldn't register " << qPrintable(service_name) << std::endl;
|
||||
}
|
||||
|
||||
if (!bus.registerObject(DBusObjectPath, new InteropObject(parent), QDBusConnection::ExportAllSlots))
|
||||
auto const object_path = QStringLiteral("com/transmissionbt/Transmission");
|
||||
if (!bus.registerObject(object_path, new InteropObject(parent), QDBusConnection::ExportAllSlots))
|
||||
{
|
||||
std::cerr << "couldn't register " << qPrintable(DBusObjectPath) << std::endl;
|
||||
std::cerr << "couldn't register " << qPrintable(object_path) << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,7 +206,9 @@ DetailsDialog::DetailsDialog(Session& session, Prefs& prefs, TorrentModel const&
|
|||
BaseDialog(parent),
|
||||
session_(session),
|
||||
prefs_(prefs),
|
||||
model_(model)
|
||||
model_(model),
|
||||
icon_encrypted_(QStringLiteral(":/icons/encrypted.png")),
|
||||
icon_unencrypted_()
|
||||
{
|
||||
ui_.setupUi(this);
|
||||
|
||||
|
@ -511,13 +513,13 @@ void DetailsDialog::refreshUI()
|
|||
double const d = size_when_done == 0 ?
|
||||
100.0 :
|
||||
100.0 * static_cast<double>(size_when_done - left_until_done) / static_cast<double>(size_when_done);
|
||||
auto const pct = Formatter::percentToString(d);
|
||||
auto const pct = Formatter::get().percentToString(d);
|
||||
|
||||
if (have_unverified == 0 && left_until_done == 0)
|
||||
{
|
||||
//: Text following the "Have:" label in torrent properties dialog;
|
||||
//: %1 is amount of downloaded and verified data
|
||||
string = tr("%1 (100%)").arg(Formatter::sizeToString(have_verified));
|
||||
string = tr("%1 (100%)").arg(Formatter::get().sizeToString(have_verified));
|
||||
}
|
||||
else if (have_unverified == 0)
|
||||
{
|
||||
|
@ -525,7 +527,7 @@ void DetailsDialog::refreshUI()
|
|||
//: %1 is amount of downloaded and verified data,
|
||||
//: %2 is overall size of torrent data,
|
||||
//: %3 is percentage (%1/%2*100)
|
||||
string = tr("%1 of %2 (%3%)").arg(Formatter::sizeToString(have_verified)).arg(Formatter::sizeToString(
|
||||
string = tr("%1 of %2 (%3%)").arg(Formatter::get().sizeToString(have_verified)).arg(Formatter::get().sizeToString(
|
||||
size_when_done)).
|
||||
arg(pct);
|
||||
}
|
||||
|
@ -536,8 +538,8 @@ void DetailsDialog::refreshUI()
|
|||
//: %2 is overall size of torrent data,
|
||||
//: %3 is percentage (%1/%2*100),
|
||||
//: %4 is amount of downloaded but not yet verified data
|
||||
string = tr("%1 of %2 (%3%), %4 Unverified").arg(Formatter::sizeToString(have_verified + have_unverified)).
|
||||
arg(Formatter::sizeToString(size_when_done)).arg(pct).arg(Formatter::sizeToString(have_unverified));
|
||||
string = tr("%1 of %2 (%3%), %4 Unverified").arg(Formatter::get().sizeToString(have_verified + have_unverified)).
|
||||
arg(Formatter::get().sizeToString(size_when_done)).arg(pct).arg(Formatter::get().sizeToString(have_unverified));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,7 +553,7 @@ void DetailsDialog::refreshUI()
|
|||
else
|
||||
{
|
||||
auto const percent = 100.0 * static_cast<double>(available) / static_cast<double>(size_when_done);
|
||||
string = QStringLiteral("%1%").arg(Formatter::percentToString(percent));
|
||||
string = QStringLiteral("%1%").arg(Formatter::get().percentToString(percent));
|
||||
}
|
||||
|
||||
ui_.availabilityValueLabel->setText(string);
|
||||
|
@ -572,8 +574,8 @@ void DetailsDialog::refreshUI()
|
|||
f += t->failedEver();
|
||||
}
|
||||
|
||||
QString const dstr = Formatter::sizeToString(d);
|
||||
QString const fstr = Formatter::sizeToString(f);
|
||||
QString const dstr = Formatter::get().sizeToString(d);
|
||||
QString const fstr = Formatter::get().sizeToString(f);
|
||||
|
||||
if (f != 0)
|
||||
{
|
||||
|
@ -603,7 +605,8 @@ void DetailsDialog::refreshUI()
|
|||
d += t->downloadedEver();
|
||||
}
|
||||
|
||||
string = tr("%1 (Ratio: %2)").arg(Formatter::sizeToString(u)).arg(Formatter::ratioToString(tr_getRatio(u, d)));
|
||||
string = tr("%1 (Ratio: %2)").arg(Formatter::get().sizeToString(u)).arg(Formatter::get().ratioToString(tr_getRatio(u,
|
||||
d)));
|
||||
}
|
||||
|
||||
ui_.uploadedValueLabel->setText(string);
|
||||
|
@ -643,7 +646,7 @@ void DetailsDialog::refreshUI()
|
|||
{
|
||||
auto const now = time(nullptr);
|
||||
auto const seconds = int(std::difftime(now, baseline));
|
||||
string = Formatter::timeToString(seconds);
|
||||
string = Formatter::get().timeToString(seconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -677,7 +680,7 @@ void DetailsDialog::refreshUI()
|
|||
}
|
||||
else
|
||||
{
|
||||
string = Formatter::timeToString(baseline);
|
||||
string = Formatter::get().timeToString(baseline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -716,7 +719,7 @@ void DetailsDialog::refreshUI()
|
|||
}
|
||||
else
|
||||
{
|
||||
string = tr("%1 ago").arg(Formatter::timeToString(seconds));
|
||||
string = tr("%1 ago").arg(Formatter::get().timeToString(seconds));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -779,12 +782,12 @@ void DetailsDialog::refreshUI()
|
|||
}
|
||||
else if (piece_size > 0)
|
||||
{
|
||||
string = tr("%1 (%Ln pieces @ %2)", "", pieces).arg(Formatter::sizeToString(size)).
|
||||
arg(Formatter::memToString(piece_size));
|
||||
string = tr("%1 (%Ln pieces @ %2)", "", pieces).arg(Formatter::get().sizeToString(size)).
|
||||
arg(Formatter::get().memToString(piece_size));
|
||||
}
|
||||
else
|
||||
{
|
||||
string = tr("%1 (%Ln pieces)", "", pieces).arg(Formatter::sizeToString(size));
|
||||
string = tr("%1 (%Ln pieces)", "", pieces).arg(Formatter::get().sizeToString(size));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1072,13 +1075,11 @@ void DetailsDialog::refreshUI()
|
|||
|
||||
if (item == nullptr) // new peer has connected
|
||||
{
|
||||
static QIcon const EncryptionIcon(QStringLiteral(":/icons/encrypted.png"));
|
||||
static QIcon const EmptyIcon;
|
||||
item = new PeerItem(peer);
|
||||
item->setTextAlignment(COL_UP, Qt::AlignRight | Qt::AlignVCenter);
|
||||
item->setTextAlignment(COL_DOWN, Qt::AlignRight | Qt::AlignVCenter);
|
||||
item->setTextAlignment(COL_PERCENT, Qt::AlignRight | Qt::AlignVCenter);
|
||||
item->setIcon(COL_LOCK, peer.is_encrypted ? EncryptionIcon : EmptyIcon);
|
||||
item->setIcon(COL_LOCK, peer.is_encrypted ? icon_encrypted_ : icon_unencrypted_);
|
||||
item->setToolTip(COL_LOCK, peer.is_encrypted ? tr("Encrypted connection") : QString());
|
||||
item->setText(COL_ADDRESS, peer.address);
|
||||
item->setText(COL_CLIENT, peer.client_name);
|
||||
|
@ -1157,8 +1158,9 @@ void DetailsDialog::refreshUI()
|
|||
code_tip.resize(code_tip.size() - 1); // eat the trailing linefeed
|
||||
}
|
||||
|
||||
item->setText(COL_UP, peer.rate_to_peer.isZero() ? QString() : Formatter::speedToString(peer.rate_to_peer));
|
||||
item->setText(COL_DOWN, peer.rate_to_client.isZero() ? QString() : Formatter::speedToString(peer.rate_to_client));
|
||||
item->setText(COL_UP, peer.rate_to_peer.isZero() ? QString() : Formatter::get().speedToString(peer.rate_to_peer));
|
||||
item->setText(COL_DOWN,
|
||||
peer.rate_to_client.isZero() ? QString() : Formatter::get().speedToString(peer.rate_to_client));
|
||||
item->setText(COL_PERCENT, peer.progress > 0 ? QStringLiteral("%1%").arg(int(peer.progress * 100.0)) :
|
||||
QString());
|
||||
item->setText(COL_STATUS, code);
|
||||
|
@ -1391,7 +1393,7 @@ void DetailsDialog::onRemoveTrackerClicked()
|
|||
|
||||
void DetailsDialog::initOptionsTab()
|
||||
{
|
||||
auto const speed_unit_str = Formatter::unitStr(Formatter::SPEED, Formatter::KB);
|
||||
auto const speed_unit_str = Formatter::get().unitStr(Formatter::SPEED, Formatter::KB);
|
||||
|
||||
ui_.singleDownSpin->setSuffix(QStringLiteral(" %1").arg(speed_unit_str));
|
||||
ui_.singleUpSpin->setSuffix(QStringLiteral(" %1").arg(speed_unit_str));
|
||||
|
|
|
@ -132,4 +132,7 @@ private:
|
|||
TrackerDelegate* tracker_delegate_ = {};
|
||||
|
||||
QMap<QString, QTreeWidgetItem*> peers_;
|
||||
|
||||
QIcon const icon_encrypted_;
|
||||
QIcon const icon_unencrypted_;
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "FileTreeItem.h"
|
||||
#include "FileTreeModel.h"
|
||||
#include "Formatter.h"
|
||||
#include "Utils.h" // mime icons
|
||||
#include "IconCache.h"
|
||||
|
||||
QHash<QString, int> const& FileTreeItem::getMyChildRows()
|
||||
{
|
||||
|
@ -171,7 +171,7 @@ QVariant FileTreeItem::data(int column, int role) const
|
|||
}
|
||||
else
|
||||
{
|
||||
value = Utils::guessMimeIcon(name());
|
||||
value = IconCache::get().guessMimeIcon(name());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ double FileTreeItem::progress() const
|
|||
|
||||
QString FileTreeItem::sizeString() const
|
||||
{
|
||||
return Formatter::sizeToString(size());
|
||||
return Formatter::get().sizeToString(size());
|
||||
}
|
||||
|
||||
uint64_t FileTreeItem::size() const
|
||||
|
|
|
@ -89,9 +89,10 @@ void FileTreeView::resizeEvent(QResizeEvent* event)
|
|||
switch (column)
|
||||
{
|
||||
case FileTreeModel::COL_SIZE:
|
||||
for (int s = Formatter::B; s <= Formatter::TB; ++s)
|
||||
for (int s = Formatter::get().B; s <= Formatter::get().TB; ++s)
|
||||
{
|
||||
item_texts << QStringLiteral("999.9 ") + Formatter::unitStr(Formatter::MEM, static_cast<Formatter::Size>(s));
|
||||
item_texts << QStringLiteral("999.9 ") + Formatter::get().unitStr(Formatter::MEM,
|
||||
static_cast<Formatter::Size>(s));
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -6,35 +6,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <cstdint> // uint64_t
|
||||
|
||||
#include "Filters.h"
|
||||
|
||||
std::array<QString, FilterMode::NUM_MODES> const FilterMode::Names =
|
||||
{
|
||||
QStringLiteral("show-all"),
|
||||
QStringLiteral("show-active"),
|
||||
QStringLiteral("show-downloading"),
|
||||
QStringLiteral("show-seeding"),
|
||||
QStringLiteral("show-paused"),
|
||||
QStringLiteral("show-finished"),
|
||||
QStringLiteral("show-verifying"),
|
||||
QStringLiteral("show-error")
|
||||
};
|
||||
|
||||
int FilterMode::modeFromName(QString const& name)
|
||||
{
|
||||
for (int i = 0; i < NUM_MODES; ++i)
|
||||
{
|
||||
if (Names[i] == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return FilterMode().mode(); // use the default value
|
||||
}
|
||||
|
||||
// NB: if you change this function, update TorrentFields too
|
||||
bool FilterMode::test(Torrent const& tor, int mode)
|
||||
{
|
||||
|
@ -65,34 +38,3 @@ bool FilterMode::test(Torrent const& tor, int mode)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
std::array<QString, SortMode::NUM_MODES> const SortMode::Names =
|
||||
{
|
||||
QStringLiteral("sort-by-activity"),
|
||||
QStringLiteral("sort-by-age"),
|
||||
QStringLiteral("sort-by-eta"),
|
||||
QStringLiteral("sort-by-name"),
|
||||
QStringLiteral("sort-by-progress"),
|
||||
QStringLiteral("sort-by-queue"),
|
||||
QStringLiteral("sort-by-ratio"),
|
||||
QStringLiteral("sort-by-size"),
|
||||
QStringLiteral("sort-by-state"),
|
||||
QStringLiteral("sort-by-id")
|
||||
};
|
||||
|
||||
int SortMode::modeFromName(QString const& name)
|
||||
{
|
||||
for (int i = 0; i < NUM_MODES; ++i)
|
||||
{
|
||||
if (Names[i] == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return SortMode().mode(); // use the default value
|
||||
}
|
||||
|
|
38
qt/Filters.h
38
qt/Filters.h
|
@ -10,10 +10,6 @@
|
|||
|
||||
#include <array>
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
#include "Torrent.h"
|
||||
|
||||
class FilterMode
|
||||
|
@ -38,28 +34,11 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
FilterMode(QString const& name) :
|
||||
mode_(modeFromName(name))
|
||||
{
|
||||
}
|
||||
|
||||
int mode() const
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
QString const& name() const
|
||||
{
|
||||
return nameFromMode(mode_);
|
||||
}
|
||||
|
||||
static int modeFromName(QString const& name);
|
||||
|
||||
static QString const& nameFromMode(int mode)
|
||||
{
|
||||
return Names[mode];
|
||||
}
|
||||
|
||||
/* The Torrent properties that can affect this filter.
|
||||
When one of these changes, it's time to refilter. */
|
||||
static Torrent::fields_t constexpr TorrentFields = {
|
||||
|
@ -75,8 +54,6 @@ public:
|
|||
|
||||
private:
|
||||
int mode_;
|
||||
|
||||
static std::array<QString, NUM_MODES> const Names;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FilterMode)
|
||||
|
@ -105,28 +82,13 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
SortMode(QString const& name) :
|
||||
mode_(modeFromName(name))
|
||||
{
|
||||
}
|
||||
|
||||
int mode() const
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
QString const& name() const
|
||||
{
|
||||
return Names[mode_];
|
||||
}
|
||||
|
||||
static int modeFromName(QString const& name);
|
||||
static QString const& nameFromMode(int mode);
|
||||
|
||||
private:
|
||||
int mode_ = SORT_BY_ID;
|
||||
|
||||
static std::array<QString, NUM_MODES> const Names;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(SortMode)
|
||||
|
|
104
qt/Formatter.cc
104
qt/Formatter.cc
|
@ -15,59 +15,47 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
/***
|
||||
**** Constants
|
||||
***/
|
||||
|
||||
namespace
|
||||
Formatter& Formatter::get()
|
||||
{
|
||||
|
||||
auto constexpr SpeedBase = 1000;
|
||||
auto constexpr SizeBase = 1000;
|
||||
auto constexpr MemBase = 1024;
|
||||
|
||||
} // namespace
|
||||
|
||||
std::array<std::array<QString, Formatter::NUM_SIZES>, Formatter::NUM_TYPES> const Formatter::UnitStrings =
|
||||
{{
|
||||
/* SPEED */ { tr("B/s"), tr("kB/s"), tr("MB/s"), tr("GB/s"), tr("TB/s") },
|
||||
/* SIZE */ { tr("B"), tr("kB"), tr("MB"), tr("GB"), tr("TB") },
|
||||
/* MEM */ { tr("B"), tr("KiB"), tr("MiB"), tr("GiB"), tr("TiB") }
|
||||
}};
|
||||
|
||||
void Formatter::initUnits()
|
||||
{
|
||||
tr_formatter_speed_init(SpeedBase, UnitStrings[SPEED][KB].toUtf8().constData(),
|
||||
UnitStrings[SPEED][MB].toUtf8().constData(), UnitStrings[SPEED][GB].toUtf8().constData(),
|
||||
UnitStrings[SPEED][TB].toUtf8().constData());
|
||||
|
||||
tr_formatter_size_init(SizeBase, UnitStrings[SIZE][KB].toUtf8().constData(),
|
||||
UnitStrings[SIZE][MB].toUtf8().constData(),
|
||||
UnitStrings[SIZE][GB].toUtf8().constData(), UnitStrings[SIZE][TB].toUtf8().constData());
|
||||
|
||||
tr_formatter_mem_init(MemBase, UnitStrings[MEM][KB].toUtf8().constData(), UnitStrings[MEM][MB].toUtf8().constData(),
|
||||
UnitStrings[MEM][GB].toUtf8().constData(), UnitStrings[MEM][TB].toUtf8().constData());
|
||||
static auto& singleton = *new Formatter();
|
||||
return singleton;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
double Speed::getKBps() const
|
||||
Formatter::Formatter() :
|
||||
UnitStrings{{
|
||||
{ tr("B/s"), tr("kB/s"), tr("MB/s"), tr("GB/s"), tr("TB/s") }, // SPEED
|
||||
{ tr("B"), tr("kB"), tr("MB"), tr("GB"), tr("TB") }, // SIZE
|
||||
{ tr("B"), tr("KiB"), tr("MiB"), tr("GiB"), tr("TiB") } // MEM
|
||||
}}
|
||||
{
|
||||
return getBps() / static_cast<double>(SpeedBase);
|
||||
auto const& speed = UnitStrings[SPEED];
|
||||
tr_formatter_speed_init(SpeedBase,
|
||||
speed[KB].toUtf8().constData(),
|
||||
speed[MB].toUtf8().constData(),
|
||||
speed[GB].toUtf8().constData(),
|
||||
speed[TB].toUtf8().constData());
|
||||
|
||||
auto const& size = UnitStrings[SIZE];
|
||||
tr_formatter_size_init(SizeBase,
|
||||
size[KB].toUtf8().constData(),
|
||||
size[MB].toUtf8().constData(),
|
||||
size[GB].toUtf8().constData(),
|
||||
size[TB].toUtf8().constData());
|
||||
|
||||
auto const& mem = UnitStrings[MEM];
|
||||
tr_formatter_mem_init(MemBase,
|
||||
mem[KB].toUtf8().constData(),
|
||||
mem[MB].toUtf8().constData(),
|
||||
mem[GB].toUtf8().constData(),
|
||||
mem[TB].toUtf8().constData());
|
||||
}
|
||||
|
||||
Speed Speed::fromKBps(double KBps)
|
||||
QString Formatter::unitStr(Type t, Size s) const
|
||||
{
|
||||
return Speed{ static_cast<int>(KBps * SpeedBase) };
|
||||
return UnitStrings[t][s];
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
QString Formatter::memToString(int64_t bytes)
|
||||
QString Formatter::memToString(int64_t bytes) const
|
||||
{
|
||||
if (bytes < 0)
|
||||
{
|
||||
|
@ -84,7 +72,7 @@ QString Formatter::memToString(int64_t bytes)
|
|||
return QString::fromUtf8(buf.data());
|
||||
}
|
||||
|
||||
QString Formatter::sizeToString(int64_t bytes)
|
||||
QString Formatter::sizeToString(int64_t bytes) const
|
||||
{
|
||||
if (bytes < 0)
|
||||
{
|
||||
|
@ -101,40 +89,40 @@ QString Formatter::sizeToString(int64_t bytes)
|
|||
return QString::fromUtf8(buf.data());
|
||||
}
|
||||
|
||||
QString Formatter::speedToString(Speed const& speed)
|
||||
QString Formatter::speedToString(Speed const& speed) const
|
||||
{
|
||||
auto buf = std::array<char, 128>{};
|
||||
tr_formatter_speed_KBps(buf.data(), speed.getKBps(), buf.size());
|
||||
return QString::fromUtf8(buf.data());
|
||||
}
|
||||
|
||||
QString Formatter::uploadSpeedToString(Speed const& upload_speed)
|
||||
QString Formatter::uploadSpeedToString(Speed const& upload_speed) const
|
||||
{
|
||||
static QChar constexpr UploadSymbol(0x25B4);
|
||||
|
||||
return tr("%1 %2").arg(speedToString(upload_speed)).arg(UploadSymbol);
|
||||
}
|
||||
|
||||
QString Formatter::downloadSpeedToString(Speed const& download_speed)
|
||||
QString Formatter::downloadSpeedToString(Speed const& download_speed) const
|
||||
{
|
||||
static QChar constexpr DownloadSymbol(0x25BE);
|
||||
|
||||
return tr("%1 %2").arg(speedToString(download_speed)).arg(DownloadSymbol);
|
||||
}
|
||||
|
||||
QString Formatter::percentToString(double x)
|
||||
QString Formatter::percentToString(double x) const
|
||||
{
|
||||
auto buf = std::array<char, 128>{};
|
||||
return QString::fromUtf8(tr_strpercent(buf.data(), x, buf.size()));
|
||||
}
|
||||
|
||||
QString Formatter::ratioToString(double ratio)
|
||||
QString Formatter::ratioToString(double ratio) const
|
||||
{
|
||||
auto buf = std::array<char, 128>{};
|
||||
return QString::fromUtf8(tr_strratio(buf.data(), buf.size(), ratio, "\xE2\x88\x9E"));
|
||||
}
|
||||
|
||||
QString Formatter::timeToString(int seconds)
|
||||
QString Formatter::timeToString(int seconds) const
|
||||
{
|
||||
seconds = std::max(seconds, 0);
|
||||
auto const days = seconds / 86400;
|
||||
|
@ -189,3 +177,17 @@ QString Formatter::timeToString(int seconds)
|
|||
|
||||
return str;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
double Speed::getKBps() const
|
||||
{
|
||||
return getBps() / static_cast<double>(Formatter::SpeedBase);
|
||||
}
|
||||
|
||||
Speed Speed::fromKBps(double KBps)
|
||||
{
|
||||
return Speed{ static_cast<int>(KBps * Formatter::SpeedBase) };
|
||||
}
|
||||
|
|
|
@ -41,23 +41,25 @@ public:
|
|||
NUM_TYPES
|
||||
};
|
||||
|
||||
public:
|
||||
static QString memToString(int64_t bytes);
|
||||
static QString sizeToString(int64_t bytes);
|
||||
static QString speedToString(Speed const& speed);
|
||||
static QString percentToString(double x);
|
||||
static QString ratioToString(double ratio);
|
||||
static QString timeToString(int seconds);
|
||||
static QString uploadSpeedToString(Speed const& up);
|
||||
static QString downloadSpeedToString(Speed const& down);
|
||||
static constexpr int SpeedBase = 1000;
|
||||
static constexpr int SizeBase = 1000;
|
||||
static constexpr int MemBase = 1024;
|
||||
|
||||
static QString unitStr(Type t, Size s)
|
||||
{
|
||||
return UnitStrings[t][s];
|
||||
}
|
||||
static Formatter& get();
|
||||
|
||||
static void initUnits();
|
||||
QString memToString(int64_t bytes) const;
|
||||
QString sizeToString(int64_t bytes) const;
|
||||
QString speedToString(Speed const& speed) const;
|
||||
QString percentToString(double x) const;
|
||||
QString ratioToString(double ratio) const;
|
||||
QString timeToString(int seconds) const;
|
||||
QString uploadSpeedToString(Speed const& up) const;
|
||||
QString downloadSpeedToString(Speed const& down) const;
|
||||
QString unitStr(Type t, Size s) const;
|
||||
|
||||
protected:
|
||||
Formatter();
|
||||
|
||||
private:
|
||||
static std::array<std::array<QString, Formatter::NUM_SIZES>, Formatter::NUM_TYPES> const UnitStrings;
|
||||
std::array<std::array<QString, Formatter::NUM_SIZES>, Formatter::NUM_TYPES> const UnitStrings;
|
||||
};
|
||||
|
|
|
@ -84,7 +84,7 @@ void FreeSpaceLabel::onTimer()
|
|||
auto const bytes = dictFind<int64_t>(r.args.get(), TR_KEY_size_bytes);
|
||||
if (bytes && *bytes > 1)
|
||||
{
|
||||
setText(tr("%1 free").arg(Formatter::sizeToString(*bytes)));
|
||||
setText(tr("%1 free").arg(Formatter::get().sizeToString(*bytes)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* This file Copyright (C) 2009-2015 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "IconCache.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#endif
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileIconProvider>
|
||||
#include <QFileInfo>
|
||||
#include <QIcon>
|
||||
#include <QObject>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <QPixmapCache>
|
||||
#include <QtWin>
|
||||
#else
|
||||
#include <QMimeDatabase>
|
||||
#include <QMimeType>
|
||||
#endif
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
IconCache& IconCache::get()
|
||||
{
|
||||
static auto& singleton = *new IconCache();
|
||||
return singleton;
|
||||
}
|
||||
|
||||
IconCache::IconCache() :
|
||||
folder_icon_(QFileIconProvider().icon(QFileIconProvider::Folder)),
|
||||
file_icon_(QFileIconProvider().icon(QFileIconProvider::Folder))
|
||||
{
|
||||
}
|
||||
|
||||
QIcon IconCache::guessMimeIcon(QString const& filename) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
QIcon icon;
|
||||
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
QFileInfo const file_info(filename);
|
||||
|
||||
addAssociatedFileIcon(file_info, SHGFI_SMALLICON, icon);
|
||||
addAssociatedFileIcon(file_info, 0, icon);
|
||||
addAssociatedFileIcon(file_info, SHGFI_LARGEICON, icon);
|
||||
}
|
||||
|
||||
return icon;
|
||||
|
||||
#else
|
||||
|
||||
return getMimeIcon(filename);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void IconCache::addAssociatedFileIcon(QFileInfo const& file_info, UINT icon_size, QIcon& icon) const
|
||||
{
|
||||
QString const pixmap_cache_key = QStringLiteral("tr_file_ext_") + QString::number(icon_size) + QLatin1Char('_') +
|
||||
file_info.suffix();
|
||||
|
||||
QPixmap pixmap;
|
||||
|
||||
if (!QPixmapCache::find(pixmap_cache_key, &pixmap))
|
||||
{
|
||||
auto const filename = file_info.fileName().toStdWString();
|
||||
|
||||
SHFILEINFO shell_file_info;
|
||||
|
||||
if (::SHGetFileInfoW(filename.data(), FILE_ATTRIBUTE_NORMAL, &shell_file_info,
|
||||
sizeof(shell_file_info), SHGFI_ICON | icon_size | SHGFI_USEFILEATTRIBUTES) != 0)
|
||||
{
|
||||
if (shell_file_info.hIcon != nullptr)
|
||||
{
|
||||
pixmap = QtWin::fromHICON(shell_file_info.hIcon);
|
||||
::DestroyIcon(shell_file_info.hIcon);
|
||||
}
|
||||
}
|
||||
|
||||
QPixmapCache::insert(pixmap_cache_key, pixmap);
|
||||
}
|
||||
|
||||
if (!pixmap.isNull())
|
||||
{
|
||||
icon.addPixmap(pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
QIcon IconCache::getMimeIcon(QString const& filename) const
|
||||
{
|
||||
// If the suffix doesn't match a mime type, treat it as a folder.
|
||||
// This heuristic is fast and yields good results for torrent names.
|
||||
if (suffixes_.empty())
|
||||
{
|
||||
for (auto const& type : QMimeDatabase().allMimeTypes())
|
||||
{
|
||||
auto const tmp = type.suffixes();
|
||||
suffixes_.insert(tmp.begin(), tmp.end());
|
||||
}
|
||||
}
|
||||
|
||||
auto const ext = QFileInfo(filename).suffix();
|
||||
if (suffixes_.count(ext) == 0)
|
||||
{
|
||||
return folder_icon_;
|
||||
}
|
||||
|
||||
QIcon& icon = icon_cache_[ext];
|
||||
if (icon.isNull()) // cache miss
|
||||
{
|
||||
QMimeDatabase mime_db;
|
||||
QMimeType type = mime_db.mimeTypeForFile(filename, QMimeDatabase::MatchExtension);
|
||||
if (icon.isNull())
|
||||
{
|
||||
icon = QIcon::fromTheme(type.iconName());
|
||||
}
|
||||
|
||||
if (icon.isNull())
|
||||
{
|
||||
icon = QIcon::fromTheme(type.genericIconName());
|
||||
}
|
||||
|
||||
if (icon.isNull())
|
||||
{
|
||||
icon = file_icon_;
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* This file Copyright (C) 2009-2015 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h> // UINT
|
||||
class QFileInfo;
|
||||
#else
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "Utils.h" // std::hash<QString>()
|
||||
#endif
|
||||
|
||||
#include <QIcon>
|
||||
#include <QString>
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
class IconCache
|
||||
{
|
||||
public:
|
||||
static IconCache& get();
|
||||
|
||||
QIcon folderIcon() const { return folder_icon_; }
|
||||
QIcon fileIcon() const { return file_icon_; }
|
||||
QIcon guessMimeIcon(QString const& filename) const;
|
||||
|
||||
protected:
|
||||
IconCache();
|
||||
|
||||
private:
|
||||
QIcon const folder_icon_;
|
||||
QIcon const file_icon_;
|
||||
|
||||
#if defined(_WIN32)
|
||||
void addAssociatedFileIcon(QFileInfo const& file_info, UINT icon_size, QIcon& icon) const;
|
||||
#else
|
||||
mutable std::unordered_map<QString, QIcon> icon_cache_;
|
||||
mutable std::unordered_set<QString> suffixes_;
|
||||
QIcon getMimeIcon(QString const& filename) const;
|
||||
#endif
|
||||
};
|
|
@ -50,16 +50,6 @@
|
|||
#define STATS_MODE_KEY "stats-mode"
|
||||
#define SORT_MODE_KEY "sort-mode"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
auto const TotalRatioStatsModeName = QStringLiteral("total-ratio");
|
||||
auto const TotalTransferStatsModeName = QStringLiteral("total-transfer");
|
||||
auto const SessionRatioStatsModeName = QStringLiteral("session-ratio");
|
||||
auto const SessionTransferStatsModeName = QStringLiteral("session-transfer");
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* This is a proxy-style for that forces it to be always disabled.
|
||||
* We use this to make our torrent list view behave consistently on
|
||||
|
@ -147,6 +137,11 @@ MainWindow::MainWindow(Session& session, Prefs& prefs, TorrentModel& model, bool
|
|||
torrent_delegate_(new TorrentDelegate(this)),
|
||||
torrent_delegate_min_(new TorrentDelegateMin(this)),
|
||||
network_timer_(this),
|
||||
total_ratio_stats_mode_name_(QStringLiteral("total-ratio")),
|
||||
total_transfer_stats_mode_name_(QStringLiteral("total-transfer")),
|
||||
session_ratio_stats_mode_name_(QStringLiteral("session-ratio")),
|
||||
session_transfer_stats_mode_name_(QStringLiteral("session-transfer")),
|
||||
show_options_checkbox_name_(QStringLiteral("show-options-checkbox")),
|
||||
refresh_timer_(this)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
|
@ -395,7 +390,7 @@ void MainWindow::initStatusBar()
|
|||
ui_.optionsButton->setMenu(createOptionsMenu());
|
||||
|
||||
int const minimum_speed_width =
|
||||
ui_.downloadSpeedLabel->fontMetrics().boundingRect(Formatter::uploadSpeedToString(Speed::fromKBps(999.99))).width();
|
||||
ui_.downloadSpeedLabel->fontMetrics().boundingRect(Formatter::get().uploadSpeedToString(Speed::fromKBps(999.99))).width();
|
||||
ui_.downloadSpeedLabel->setMinimumWidth(minimum_speed_width);
|
||||
ui_.uploadSpeedLabel->setMinimumWidth(minimum_speed_width);
|
||||
|
||||
|
@ -420,7 +415,8 @@ QMenu* MainWindow::createOptionsMenu()
|
|||
action_group->addAction(off_action);
|
||||
connect(off_action, SIGNAL(triggered(bool)), this, SLOT(onSetPrefs(bool)));
|
||||
|
||||
on_action = menu->addAction(tr("Limited at %1").arg(Formatter::speedToString(Speed::fromKBps(current_value))));
|
||||
on_action =
|
||||
menu->addAction(tr("Limited at %1").arg(Formatter::get().speedToString(Speed::fromKBps(current_value))));
|
||||
on_action->setCheckable(true);
|
||||
on_action->setProperty(PREF_VARIANTS_KEY, QVariantList() << pref << current_value << enabled_pref << true);
|
||||
action_group->addAction(on_action);
|
||||
|
@ -430,7 +426,7 @@ QMenu* MainWindow::createOptionsMenu()
|
|||
|
||||
for (int const i : stock_speeds)
|
||||
{
|
||||
QAction* action = menu->addAction(Formatter::speedToString(Speed::fromKBps(i)));
|
||||
QAction* action = menu->addAction(Formatter::get().speedToString(Speed::fromKBps(i)));
|
||||
action->setProperty(PREF_VARIANTS_KEY, QVariantList() << pref << i << enabled_pref << true);
|
||||
connect(action, SIGNAL(triggered(bool)), this, SLOT(onSetPrefs()));
|
||||
}
|
||||
|
@ -450,7 +446,7 @@ QMenu* MainWindow::createOptionsMenu()
|
|||
action_group->addAction(off_action);
|
||||
connect(off_action, SIGNAL(triggered(bool)), this, SLOT(onSetPrefs(bool)));
|
||||
|
||||
on_action = menu->addAction(tr("Stop at Ratio (%1)").arg(Formatter::ratioToString(current_value)));
|
||||
on_action = menu->addAction(tr("Stop at Ratio (%1)").arg(Formatter::get().ratioToString(current_value)));
|
||||
on_action->setCheckable(true);
|
||||
on_action->setProperty(PREF_VARIANTS_KEY, QVariantList() << pref << current_value << enabled_pref << true);
|
||||
action_group->addAction(on_action);
|
||||
|
@ -460,7 +456,7 @@ QMenu* MainWindow::createOptionsMenu()
|
|||
|
||||
for (double const i : stock_ratios)
|
||||
{
|
||||
QAction* action = menu->addAction(Formatter::ratioToString(i));
|
||||
QAction* action = menu->addAction(Formatter::get().ratioToString(i));
|
||||
action->setProperty(PREF_VARIANTS_KEY, QVariantList() << pref << i << enabled_pref << true);
|
||||
connect(action, SIGNAL(triggered(bool)), this, SLOT(onSetPrefs()));
|
||||
}
|
||||
|
@ -485,10 +481,10 @@ QMenu* MainWindow::createStatsModeMenu()
|
|||
{
|
||||
std::array<QPair<QAction*, QString>, 4> stats_modes =
|
||||
{
|
||||
qMakePair(ui_.action_TotalRatio, TotalRatioStatsModeName),
|
||||
qMakePair(ui_.action_TotalTransfer, TotalTransferStatsModeName),
|
||||
qMakePair(ui_.action_SessionRatio, SessionRatioStatsModeName),
|
||||
qMakePair(ui_.action_SessionTransfer, SessionTransferStatsModeName)
|
||||
qMakePair(ui_.action_TotalRatio, total_ratio_stats_mode_name_),
|
||||
qMakePair(ui_.action_TotalTransfer, total_transfer_stats_mode_name_),
|
||||
qMakePair(ui_.action_SessionRatio, session_ratio_stats_mode_name_),
|
||||
qMakePair(ui_.action_SessionTransfer, session_transfer_stats_mode_name_)
|
||||
};
|
||||
|
||||
auto* action_group = new QActionGroup(this);
|
||||
|
@ -786,12 +782,13 @@ void MainWindow::refreshTrayIcon(TransferStats const& stats)
|
|||
}
|
||||
else if (stats.peers_sending != 0)
|
||||
{
|
||||
tip = Formatter::downloadSpeedToString(stats.speed_down) + QStringLiteral(" ") + Formatter::uploadSpeedToString(
|
||||
tip = Formatter::get().downloadSpeedToString(stats.speed_down) + QStringLiteral(" ") +
|
||||
Formatter::get().uploadSpeedToString(
|
||||
stats.speed_up);
|
||||
}
|
||||
else if (stats.peers_receiving != 0)
|
||||
{
|
||||
tip = Formatter::uploadSpeedToString(stats.speed_up);
|
||||
tip = Formatter::get().uploadSpeedToString(stats.speed_up);
|
||||
}
|
||||
|
||||
tray_icon_.setToolTip(tip);
|
||||
|
@ -799,9 +796,9 @@ void MainWindow::refreshTrayIcon(TransferStats const& stats)
|
|||
|
||||
void MainWindow::refreshStatusBar(TransferStats const& stats)
|
||||
{
|
||||
ui_.uploadSpeedLabel->setText(Formatter::uploadSpeedToString(stats.speed_up));
|
||||
ui_.uploadSpeedLabel->setText(Formatter::get().uploadSpeedToString(stats.speed_up));
|
||||
ui_.uploadSpeedLabel->setVisible(stats.peers_sending || stats.peers_receiving);
|
||||
ui_.downloadSpeedLabel->setText(Formatter::downloadSpeedToString(stats.speed_down));
|
||||
ui_.downloadSpeedLabel->setText(Formatter::get().downloadSpeedToString(stats.speed_down));
|
||||
ui_.downloadSpeedLabel->setVisible(stats.peers_sending);
|
||||
|
||||
ui_.networkLabel->setVisible(!session_.isServer());
|
||||
|
@ -809,30 +806,30 @@ void MainWindow::refreshStatusBar(TransferStats const& stats)
|
|||
auto const mode = prefs_.getString(Prefs::STATUSBAR_STATS);
|
||||
auto str = QString {};
|
||||
|
||||
if (mode == SessionRatioStatsModeName)
|
||||
if (mode == session_ratio_stats_mode_name_)
|
||||
{
|
||||
str = tr("Ratio: %1")
|
||||
.arg(Formatter::ratioToString(session_.getStats().ratio));
|
||||
.arg(Formatter::get().ratioToString(session_.getStats().ratio));
|
||||
}
|
||||
else if (mode == SessionTransferStatsModeName)
|
||||
else if (mode == session_transfer_stats_mode_name_)
|
||||
{
|
||||
auto const& st = session_.getStats();
|
||||
str = tr("Down: %1, Up: %2")
|
||||
.arg(Formatter::sizeToString(st.downloadedBytes))
|
||||
.arg(Formatter::sizeToString(st.uploadedBytes));
|
||||
.arg(Formatter::get().sizeToString(st.downloadedBytes))
|
||||
.arg(Formatter::get().sizeToString(st.uploadedBytes));
|
||||
}
|
||||
else if (mode == TotalTransferStatsModeName)
|
||||
else if (mode == total_transfer_stats_mode_name_)
|
||||
{
|
||||
auto const& st = session_.getCumulativeStats();
|
||||
str = tr("Down: %1, Up: %2")
|
||||
.arg(Formatter::sizeToString(st.downloadedBytes))
|
||||
.arg(Formatter::sizeToString(st.uploadedBytes));
|
||||
.arg(Formatter::get().sizeToString(st.downloadedBytes))
|
||||
.arg(Formatter::get().sizeToString(st.uploadedBytes));
|
||||
}
|
||||
else // default is "total-ratio"
|
||||
{
|
||||
assert(mode == TotalRatioStatsModeName);
|
||||
assert(mode == total_ratio_stats_mode_name_);
|
||||
str = tr("Ratio: %1")
|
||||
.arg(Formatter::ratioToString(session_.getCumulativeStats().ratio));
|
||||
.arg(Formatter::get().ratioToString(session_.getCumulativeStats().ratio));
|
||||
}
|
||||
|
||||
ui_.statsLabel->setText(str);
|
||||
|
@ -1149,7 +1146,8 @@ void MainWindow::refreshPref(int key)
|
|||
break;
|
||||
|
||||
case Prefs::DSPEED:
|
||||
dlimit_on_action_->setText(tr("Limited at %1").arg(Formatter::speedToString(Speed::fromKBps(prefs_.get<int>(key)))));
|
||||
dlimit_on_action_->setText(tr("Limited at %1").arg(Formatter::get().speedToString(Speed::fromKBps(prefs_.get<int>(
|
||||
key)))));
|
||||
break;
|
||||
|
||||
case Prefs::USPEED_ENABLED:
|
||||
|
@ -1157,7 +1155,8 @@ void MainWindow::refreshPref(int key)
|
|||
break;
|
||||
|
||||
case Prefs::USPEED:
|
||||
ulimit_on_action_->setText(tr("Limited at %1").arg(Formatter::speedToString(Speed::fromKBps(prefs_.get<int>(key)))));
|
||||
ulimit_on_action_->setText(tr("Limited at %1").arg(Formatter::get().speedToString(Speed::fromKBps(prefs_.get<int>(
|
||||
key)))));
|
||||
break;
|
||||
|
||||
case Prefs::RATIO_ENABLED:
|
||||
|
@ -1165,7 +1164,7 @@ void MainWindow::refreshPref(int key)
|
|||
break;
|
||||
|
||||
case Prefs::RATIO:
|
||||
ratio_on_action_->setText(tr("Stop at Ratio (%1)").arg(Formatter::ratioToString(prefs_.get<double>(key))));
|
||||
ratio_on_action_->setText(tr("Stop at Ratio (%1)").arg(Formatter::get().ratioToString(prefs_.get<double>(key))));
|
||||
break;
|
||||
|
||||
case Prefs::FILTERBAR:
|
||||
|
@ -1239,7 +1238,7 @@ void MainWindow::refreshPref(int key)
|
|||
tr("Click to enable Temporary Speed Limits\n (%1 down, %2 up)");
|
||||
Speed const d = Speed::fromKBps(prefs_.getInt(Prefs::ALT_SPEED_LIMIT_DOWN));
|
||||
Speed const u = Speed::fromKBps(prefs_.getInt(Prefs::ALT_SPEED_LIMIT_UP));
|
||||
ui_.altSpeedButton->setToolTip(fmt.arg(Formatter::speedToString(d)).arg(Formatter::speedToString(u)));
|
||||
ui_.altSpeedButton->setToolTip(fmt.arg(Formatter::get().speedToString(d)).arg(Formatter::get().speedToString(u)));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1252,13 +1251,6 @@ void MainWindow::refreshPref(int key)
|
|||
****
|
||||
***/
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
auto const ShowOptionsCheckboxName = QStringLiteral("show-options-checkbox");
|
||||
|
||||
} // namespace
|
||||
|
||||
void MainWindow::newTorrent()
|
||||
{
|
||||
auto* dialog = new MakeDialog(session_, this);
|
||||
|
@ -1280,7 +1272,7 @@ void MainWindow::openTorrent()
|
|||
{
|
||||
auto* b = new QCheckBox(tr("Show &options dialog"));
|
||||
b->setChecked(prefs_.getBool(Prefs::OPTIONS_PROMPT));
|
||||
b->setObjectName(ShowOptionsCheckboxName);
|
||||
b->setObjectName(show_options_checkbox_name_);
|
||||
l->addWidget(b, l->rowCount(), 0, 1, -1, Qt::AlignLeft);
|
||||
}
|
||||
|
||||
|
@ -1314,7 +1306,7 @@ void MainWindow::addTorrents(QStringList const& filenames)
|
|||
|
||||
if (file_dialog != nullptr)
|
||||
{
|
||||
auto const* const b = file_dialog->findChild<QCheckBox const*>(ShowOptionsCheckboxName);
|
||||
auto const* const b = file_dialog->findChild<QCheckBox const*>(show_options_checkbox_name_);
|
||||
|
||||
if (b != nullptr)
|
||||
{
|
||||
|
@ -1499,7 +1491,7 @@ void MainWindow::updateNetworkIcon()
|
|||
}
|
||||
else if (seconds_since_last_read < 60 * 2)
|
||||
{
|
||||
tip = tr("%1 last responded %2 ago").arg(url).arg(Formatter::timeToString(seconds_since_last_read));
|
||||
tip = tr("%1 last responded %2 ago").arg(url).arg(Formatter::get().timeToString(seconds_since_last_read));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -180,6 +180,13 @@ private:
|
|||
QAction* alt_speed_action_ = {};
|
||||
QString error_message_;
|
||||
|
||||
QString const total_ratio_stats_mode_name_;
|
||||
QString const total_transfer_stats_mode_name_;
|
||||
QString const session_ratio_stats_mode_name_;
|
||||
QString const session_transfer_stats_mode_name_;
|
||||
|
||||
QString const show_options_checkbox_name_;
|
||||
|
||||
struct TransferStats
|
||||
{
|
||||
Speed speed_up;
|
||||
|
|
|
@ -221,8 +221,8 @@ void MakeDialog::onSourceChanged()
|
|||
{
|
||||
QString files = tr("%Ln File(s)", nullptr, builder_->fileCount);
|
||||
QString pieces = tr("%Ln Piece(s)", nullptr, builder_->pieceCount);
|
||||
text = tr("%1 in %2; %3 @ %4").arg(Formatter::sizeToString(builder_->totalSize)).arg(files).arg(pieces).
|
||||
arg(Formatter::sizeToString(builder_->pieceSize));
|
||||
text = tr("%1 in %2; %3 @ %4").arg(Formatter::get().sizeToString(builder_->totalSize)).arg(files).arg(pieces).
|
||||
arg(Formatter::get().sizeToString(builder_->pieceSize));
|
||||
}
|
||||
|
||||
ui_.sourceSizeLabel->setText(text);
|
||||
|
|
55
qt/Prefs.cc
55
qt/Prefs.cc
|
@ -130,12 +130,33 @@ std::array<Prefs::PrefItem, Prefs::PREFS_COUNT> const Prefs::Items
|
|||
***/
|
||||
|
||||
Prefs::Prefs(QString config_dir) :
|
||||
config_dir_(std::move(config_dir))
|
||||
config_dir_(std::move(config_dir)),
|
||||
FilterModes{
|
||||
std::make_pair(FilterMode::SHOW_ALL, QStringLiteral("show-all")),
|
||||
std::make_pair(FilterMode::SHOW_ACTIVE, QStringLiteral("show-active")),
|
||||
std::make_pair(FilterMode::SHOW_DOWNLOADING, QStringLiteral("show-downloading")),
|
||||
std::make_pair(FilterMode::SHOW_SEEDING, QStringLiteral("show-seeding")),
|
||||
std::make_pair(FilterMode::SHOW_PAUSED, QStringLiteral("show-paused")),
|
||||
std::make_pair(FilterMode::SHOW_FINISHED, QStringLiteral("show-finished")),
|
||||
std::make_pair(FilterMode::SHOW_VERIFYING, QStringLiteral("show-verifying")),
|
||||
std::make_pair(FilterMode::SHOW_ERROR, QStringLiteral("show-error"))
|
||||
},
|
||||
SortModes{
|
||||
std::make_pair(SortMode::SORT_BY_NAME, QStringLiteral("sort-by-name")),
|
||||
std::make_pair(SortMode::SORT_BY_ACTIVITY, QStringLiteral("sort-by-activity")),
|
||||
std::make_pair(SortMode::SORT_BY_AGE, QStringLiteral("sort-by-age")),
|
||||
std::make_pair(SortMode::SORT_BY_ETA, QStringLiteral("sort-by-eta")),
|
||||
std::make_pair(SortMode::SORT_BY_PROGRESS, QStringLiteral("sort-by-progress")),
|
||||
std::make_pair(SortMode::SORT_BY_QUEUE, QStringLiteral("sort-by-queue")),
|
||||
std::make_pair(SortMode::SORT_BY_RATIO, QStringLiteral("sort-by-ratio")),
|
||||
std::make_pair(SortMode::SORT_BY_SIZE, QStringLiteral("sort-by-size")),
|
||||
std::make_pair(SortMode::SORT_BY_STATE, QStringLiteral("sort-by-state")),
|
||||
std::make_pair(SortMode::SORT_BY_ID, QStringLiteral("sort-by-id"))
|
||||
}
|
||||
{
|
||||
static_assert(sizeof(Items) / sizeof(Items[0]) == PREFS_COUNT);
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
for (int i = 0; i < PREFS_COUNT; ++i)
|
||||
{
|
||||
assert(Items[i].id == i);
|
||||
|
@ -173,7 +194,10 @@ Prefs::Prefs(QString config_dir) :
|
|||
auto const value = getValue<QString>(b);
|
||||
if (value)
|
||||
{
|
||||
values_[i] = QVariant::fromValue(SortMode(*value));
|
||||
auto test = [&value](auto const& item) { return item.second == *value; };
|
||||
auto it = std::find_if(std::cbegin(SortModes), std::cend(SortModes), test);
|
||||
auto const& pair = it == std::end(SortModes) ? SortModes[0] : *it;
|
||||
values_[i] = QVariant::fromValue(SortMode(pair.first));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -183,7 +207,10 @@ Prefs::Prefs(QString config_dir) :
|
|||
auto const value = getValue<QString>(b);
|
||||
if (value)
|
||||
{
|
||||
values_[i] = QVariant::fromValue(FilterMode(*value));
|
||||
auto test = [&value](auto const& item) { return item.second == *value; };
|
||||
auto it = std::find_if(std::cbegin(FilterModes), std::cend(FilterModes), test);
|
||||
auto const& pair = it == std::end(FilterModes) ? FilterModes[0] : *it;
|
||||
values_[i] = QVariant::fromValue(FilterMode(pair.first));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -260,12 +287,24 @@ Prefs::~Prefs()
|
|||
break;
|
||||
|
||||
case CustomVariantType::SortModeType:
|
||||
dictAdd(¤t_settings, key, val.value<SortMode>().name());
|
||||
break;
|
||||
{
|
||||
auto const mode = val.value<SortMode>().mode();
|
||||
auto test = [&mode](auto const& item) { return item.first == mode; };
|
||||
auto it = std::find_if(std::cbegin(SortModes), std::cend(SortModes), test);
|
||||
auto const& pair = it == std::end(SortModes) ? SortModes[0] : *it;
|
||||
dictAdd(¤t_settings, key, pair.second);
|
||||
break;
|
||||
}
|
||||
|
||||
case CustomVariantType::FilterModeType:
|
||||
dictAdd(¤t_settings, key, val.value<FilterMode>().name());
|
||||
break;
|
||||
{
|
||||
auto const mode = val.value<FilterMode>().mode();
|
||||
auto test = [&mode](auto const& item) { return item.first == mode; };
|
||||
auto it = std::find_if(std::cbegin(FilterModes), std::cend(FilterModes), test);
|
||||
auto const& pair = it == std::end(FilterModes) ? FilterModes[0] : *it;
|
||||
dictAdd(¤t_settings, key, pair.second);
|
||||
break;
|
||||
}
|
||||
|
||||
case QVariant::String:
|
||||
dictAdd(¤t_settings, key, val.toString());
|
||||
|
|
|
@ -204,6 +204,8 @@ private:
|
|||
void set(int key, char const* value) = delete;
|
||||
|
||||
QString const config_dir_;
|
||||
std::array<std::pair<int, QString>, FilterMode::NUM_MODES> const FilterModes;
|
||||
std::array<std::pair<int, QString>, SortMode::NUM_MODES> const SortModes;
|
||||
|
||||
QSet<int> temporary_prefs_;
|
||||
QVariant mutable values_[PREFS_COUNT];
|
||||
|
|
|
@ -324,7 +324,7 @@ void PrefsDialog::altSpeedDaysEdited(int i)
|
|||
|
||||
void PrefsDialog::initSpeedTab()
|
||||
{
|
||||
QString const speed_unit_str = Formatter::unitStr(Formatter::SPEED, Formatter::KB);
|
||||
QString const speed_unit_str = Formatter::get().unitStr(Formatter::get().SPEED, Formatter::get().KB);
|
||||
auto const suffix = QStringLiteral(" %1").arg(speed_unit_str);
|
||||
QLocale const locale;
|
||||
|
||||
|
|
196
qt/Session.cc
196
qt/Session.cc
|
@ -8,8 +8,11 @@
|
|||
|
||||
#include "Session.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string_view>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QByteArray>
|
||||
|
@ -46,19 +49,6 @@ using ::trqt::variant_helpers::listAdd;
|
|||
****
|
||||
***/
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using KeyList = Torrent::KeyList;
|
||||
|
||||
// If this object is passed as "ids" (compared by address), then recently active torrents are queried.
|
||||
auto const RecentlyActiveIDs = torrent_ids_t{ -1 };
|
||||
|
||||
// If this object is passed as "ids" (compared by being empty), then all torrents are queried.
|
||||
auto const AllIDs = torrent_ids_t{};
|
||||
|
||||
} // namespace
|
||||
|
||||
void Session::sessionSet(tr_quark const key, QVariant const& value)
|
||||
{
|
||||
tr_variant args;
|
||||
|
@ -120,11 +110,12 @@ void Session::portTest()
|
|||
void Session::copyMagnetLinkToClipboard(int torrent_id)
|
||||
{
|
||||
auto constexpr MagnetLinkKey = std::string_view { "magnetLink" };
|
||||
auto constexpr Fields = std::array<std::string_view, 1>{ MagnetLinkKey };
|
||||
|
||||
tr_variant args;
|
||||
tr_variantInitDict(&args, 2);
|
||||
dictAdd(&args, TR_KEY_ids, std::array<int, 1>{ torrent_id });
|
||||
dictAdd(&args, TR_KEY_fields, std::array<std::string_view, 1>{ MagnetLinkKey });
|
||||
dictAdd(&args, TR_KEY_fields, Fields);
|
||||
|
||||
auto* q = new RpcQueue();
|
||||
|
||||
|
@ -263,7 +254,7 @@ void Session::updatePref(int key)
|
|||
case Prefs::RPC_PORT:
|
||||
if (session_ != nullptr)
|
||||
{
|
||||
tr_sessionSetRPCPort(session_, prefs_.getInt(key));
|
||||
tr_sessionSetRPCPort(session_, static_cast<tr_port>(prefs_.getInt(key)));
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -405,10 +396,7 @@ bool Session::isLocal() const
|
|||
****
|
||||
***/
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void addOptionalIds(tr_variant* args, torrent_ids_t const& ids)
|
||||
void Session::addOptionalIds(tr_variant* args, torrent_ids_t const& ids)
|
||||
{
|
||||
auto constexpr RecentlyActiveKey = std::string_view { "recently-active" };
|
||||
|
||||
|
@ -422,8 +410,6 @@ void addOptionalIds(tr_variant* args, torrent_ids_t const& ids)
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Session::Tag Session::torrentSetImpl(tr_variant* args)
|
||||
{
|
||||
auto* const q = new RpcQueue();
|
||||
|
@ -541,30 +527,151 @@ void Session::torrentRenamePath(torrent_ids_t const& ids, QString const& oldpath
|
|||
|
||||
q->add([this, ids](RpcResponse const& /*r*/)
|
||||
{
|
||||
refreshTorrents(ids, { TR_KEY_fileStats, TR_KEY_files, TR_KEY_id, TR_KEY_name });
|
||||
refreshTorrents(ids, TorrentProperties::Rename);
|
||||
});
|
||||
|
||||
q->run();
|
||||
}
|
||||
|
||||
void Session::refreshTorrents(torrent_ids_t const& ids, KeyList const& keys)
|
||||
std::vector<std::string_view> const& Session::getKeyNames(TorrentProperties props)
|
||||
{
|
||||
auto constexpr TableKey = std::string_view { "table" };
|
||||
std::vector<std::string_view>& names = names_[props];
|
||||
|
||||
if (names.empty())
|
||||
{
|
||||
// unchanging fields needed by the main window
|
||||
static auto constexpr MainInfoKeys = std::array<tr_quark, 6>{
|
||||
TR_KEY_addedDate,
|
||||
TR_KEY_downloadDir,
|
||||
TR_KEY_hashString,
|
||||
TR_KEY_name,
|
||||
TR_KEY_totalSize,
|
||||
TR_KEY_trackers,
|
||||
};
|
||||
|
||||
// changing fields needed by the main window
|
||||
static auto constexpr MainStatKeys = std::array<tr_quark, 25>{
|
||||
TR_KEY_downloadedEver,
|
||||
TR_KEY_editDate,
|
||||
TR_KEY_error,
|
||||
TR_KEY_errorString,
|
||||
TR_KEY_eta,
|
||||
TR_KEY_haveUnchecked,
|
||||
TR_KEY_haveValid,
|
||||
TR_KEY_isFinished,
|
||||
TR_KEY_leftUntilDone,
|
||||
TR_KEY_manualAnnounceTime,
|
||||
TR_KEY_metadataPercentComplete,
|
||||
TR_KEY_peersConnected,
|
||||
TR_KEY_peersGettingFromUs,
|
||||
TR_KEY_peersSendingToUs,
|
||||
TR_KEY_percentDone,
|
||||
TR_KEY_queuePosition,
|
||||
TR_KEY_rateDownload,
|
||||
TR_KEY_rateUpload,
|
||||
TR_KEY_recheckProgress,
|
||||
TR_KEY_seedRatioLimit,
|
||||
TR_KEY_seedRatioMode,
|
||||
TR_KEY_sizeWhenDone,
|
||||
TR_KEY_status,
|
||||
TR_KEY_uploadedEver,
|
||||
TR_KEY_webseedsSendingToUs
|
||||
};
|
||||
|
||||
// unchanging fields needed by the details dialog
|
||||
static auto constexpr DetailInfoKeys = std::array<tr_quark, 8>{
|
||||
TR_KEY_comment,
|
||||
TR_KEY_creator,
|
||||
TR_KEY_dateCreated,
|
||||
TR_KEY_files,
|
||||
TR_KEY_isPrivate,
|
||||
TR_KEY_pieceCount,
|
||||
TR_KEY_pieceSize,
|
||||
TR_KEY_trackers
|
||||
};
|
||||
|
||||
// changing fields needed by the details dialog
|
||||
static auto constexpr DetailStatKeys = std::array<tr_quark, 17>{
|
||||
TR_KEY_activityDate,
|
||||
TR_KEY_bandwidthPriority,
|
||||
TR_KEY_corruptEver,
|
||||
TR_KEY_desiredAvailable,
|
||||
TR_KEY_downloadedEver,
|
||||
TR_KEY_downloadLimit,
|
||||
TR_KEY_downloadLimited,
|
||||
TR_KEY_fileStats,
|
||||
TR_KEY_honorsSessionLimits,
|
||||
TR_KEY_peer_limit,
|
||||
TR_KEY_peers,
|
||||
TR_KEY_seedIdleLimit,
|
||||
TR_KEY_seedIdleMode,
|
||||
TR_KEY_startDate,
|
||||
TR_KEY_trackerStats,
|
||||
TR_KEY_uploadLimit,
|
||||
TR_KEY_uploadLimited
|
||||
};
|
||||
|
||||
// keys needed after renaming a torrent
|
||||
static auto constexpr RenameKeys = std::array<tr_quark, 3>{
|
||||
TR_KEY_fileStats,
|
||||
TR_KEY_files,
|
||||
TR_KEY_name
|
||||
};
|
||||
|
||||
auto const append = [&names](tr_quark key)
|
||||
{
|
||||
size_t len = {};
|
||||
char const* str = tr_quark_get_string(key, &len);
|
||||
names.emplace_back(str, len);
|
||||
};
|
||||
|
||||
switch (props)
|
||||
{
|
||||
case TorrentProperties::DetailInfo:
|
||||
std::for_each(DetailInfoKeys.begin(), DetailInfoKeys.end(), append);
|
||||
break;
|
||||
|
||||
case TorrentProperties::DetailStat:
|
||||
std::for_each(DetailStatKeys.begin(), DetailStatKeys.end(), append);
|
||||
break;
|
||||
|
||||
case TorrentProperties::MainAll:
|
||||
std::for_each(MainInfoKeys.begin(), MainInfoKeys.end(), append);
|
||||
std::for_each(MainStatKeys.begin(), MainStatKeys.end(), append);
|
||||
break;
|
||||
|
||||
case TorrentProperties::MainInfo:
|
||||
std::for_each(MainInfoKeys.begin(), MainInfoKeys.end(), append);
|
||||
break;
|
||||
|
||||
case TorrentProperties::MainStats:
|
||||
std::for_each(MainStatKeys.begin(), MainStatKeys.end(), append);
|
||||
break;
|
||||
|
||||
case TorrentProperties::Rename:
|
||||
std::for_each(RenameKeys.begin(), RenameKeys.end(), append);
|
||||
break;
|
||||
}
|
||||
|
||||
// must be in every torrent req
|
||||
append(TR_KEY_id);
|
||||
|
||||
// sort and remove dupes
|
||||
std::sort(names.begin(), names.end());
|
||||
names.erase(std::unique(names.begin(), names.end()), names.end());
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
void Session::refreshTorrents(torrent_ids_t const& ids, TorrentProperties props)
|
||||
{
|
||||
auto constexpr Table = std::string_view{ "table" };
|
||||
|
||||
tr_variant args;
|
||||
tr_variantInitDict(&args, 3);
|
||||
dictAdd(&args, TR_KEY_format, TableKey);
|
||||
|
||||
std::vector<std::string_view> keystrs;
|
||||
keystrs.reserve(keys.size());
|
||||
for (auto const& key : keys)
|
||||
{
|
||||
auto len = size_t{};
|
||||
auto const* str = tr_quark_get_string(key, &len);
|
||||
keystrs.emplace_back(str, len);
|
||||
}
|
||||
|
||||
dictAdd(&args, TR_KEY_fields, keystrs);
|
||||
dictAdd(&args, TR_KEY_format, Table);
|
||||
dictAdd(&args, TR_KEY_fields, getKeyNames(props));
|
||||
addOptionalIds(&args, ids);
|
||||
|
||||
auto* q = new RpcQueue();
|
||||
|
@ -596,12 +703,12 @@ void Session::refreshTorrents(torrent_ids_t const& ids, KeyList const& keys)
|
|||
|
||||
void Session::refreshDetailInfo(torrent_ids_t const& ids)
|
||||
{
|
||||
refreshTorrents(ids, Torrent::DetailInfoKeys);
|
||||
refreshTorrents(ids, TorrentProperties::DetailInfo);
|
||||
}
|
||||
|
||||
void Session::refreshExtraStats(torrent_ids_t const& ids)
|
||||
{
|
||||
refreshTorrents(ids, Torrent::MainStatKeys + Torrent::DetailStatKeys);
|
||||
refreshTorrents(ids, TorrentProperties::DetailStat);
|
||||
}
|
||||
|
||||
void Session::sendTorrentRequest(std::string_view request, torrent_ids_t const& ids)
|
||||
|
@ -619,7 +726,7 @@ void Session::sendTorrentRequest(std::string_view request, torrent_ids_t const&
|
|||
|
||||
q->add([this, ids]()
|
||||
{
|
||||
refreshTorrents(ids, Torrent::MainStatKeys);
|
||||
refreshTorrents(ids, TorrentProperties::MainStats);
|
||||
});
|
||||
|
||||
q->run();
|
||||
|
@ -662,17 +769,20 @@ void Session::queueMoveBottom(torrent_ids_t const& ids)
|
|||
|
||||
void Session::refreshActiveTorrents()
|
||||
{
|
||||
refreshTorrents(RecentlyActiveIDs, Torrent::MainStatKeys);
|
||||
// If this object is passed as "ids" (compared by address), then recently active torrents are queried.
|
||||
refreshTorrents(RecentlyActiveIDs, TorrentProperties::MainStats);
|
||||
}
|
||||
|
||||
void Session::refreshAllTorrents()
|
||||
{
|
||||
refreshTorrents(AllIDs, Torrent::MainStatKeys);
|
||||
// if an empty ids object is used, all torrents are queried.
|
||||
torrent_ids_t const ids = {};
|
||||
refreshTorrents(ids, TorrentProperties::MainStats);
|
||||
}
|
||||
|
||||
void Session::initTorrents(torrent_ids_t const& ids)
|
||||
{
|
||||
refreshTorrents(ids, Torrent::AllMainKeys);
|
||||
refreshTorrents(ids, TorrentProperties::MainAll);
|
||||
}
|
||||
|
||||
void Session::refreshSessionStats()
|
||||
|
@ -772,7 +882,7 @@ void Session::updateStats(tr_variant* d, tr_session_stats* stats)
|
|||
stats->secondsActive = *value;
|
||||
}
|
||||
|
||||
stats->ratio = tr_getRatio(stats->uploadedBytes, stats->downloadedBytes);
|
||||
stats->ratio = static_cast<float>(tr_getRatio(stats->uploadedBytes, stats->downloadedBytes));
|
||||
}
|
||||
|
||||
void Session::updateStats(tr_variant* d)
|
||||
|
|
20
qt/Session.h
20
qt/Session.h
|
@ -8,7 +8,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
@ -105,6 +107,16 @@ public:
|
|||
void reannounceTorrents(torrent_ids_t const& torrent_ids);
|
||||
void refreshExtraStats(torrent_ids_t const& ids);
|
||||
|
||||
enum class TorrentProperties
|
||||
{
|
||||
MainInfo,
|
||||
MainStats,
|
||||
MainAll,
|
||||
DetailInfo,
|
||||
DetailStat,
|
||||
Rename
|
||||
};
|
||||
|
||||
public slots:
|
||||
void addTorrent(AddData const& addme);
|
||||
void launchWebInterface();
|
||||
|
@ -141,14 +153,19 @@ private:
|
|||
void sessionSet(tr_quark const key, QVariant const& variant);
|
||||
void pumpRequests();
|
||||
void sendTorrentRequest(std::string_view request, torrent_ids_t const& torrent_ids);
|
||||
void refreshTorrents(torrent_ids_t const& torrent_ids, Torrent::KeyList const& keys);
|
||||
void refreshTorrents(torrent_ids_t const& ids, TorrentProperties props);
|
||||
std::vector<std::string_view> const& getKeyNames(TorrentProperties props);
|
||||
|
||||
static void updateStats(tr_variant* d, tr_session_stats* stats);
|
||||
|
||||
void addOptionalIds(tr_variant* args, torrent_ids_t const& ids);
|
||||
|
||||
private:
|
||||
QString const config_dir_;
|
||||
Prefs& prefs_;
|
||||
|
||||
std::map<TorrentProperties, std::vector<std::string_view>> names_;
|
||||
|
||||
int64_t blocklist_size_ = -1;
|
||||
tr_session* session_ = {};
|
||||
QStringList idle_json_;
|
||||
|
@ -158,4 +175,5 @@ private:
|
|||
QString session_id_;
|
||||
bool is_definitely_local_session_ = true;
|
||||
RpcClient rpc_;
|
||||
torrent_ids_t const RecentlyActiveIDs = { -1 };
|
||||
};
|
||||
|
|
|
@ -55,15 +55,15 @@ void StatsDialog::updateStats()
|
|||
tr_session_stats const& current(session_.getStats());
|
||||
tr_session_stats const& total(session_.getCumulativeStats());
|
||||
|
||||
ui_.currentUploadedValueLabel->setText(Formatter::sizeToString(current.uploadedBytes));
|
||||
ui_.currentDownloadedValueLabel->setText(Formatter::sizeToString(current.downloadedBytes));
|
||||
ui_.currentRatioValueLabel->setText(Formatter::ratioToString(current.ratio));
|
||||
ui_.currentDurationValueLabel->setText(Formatter::timeToString(current.secondsActive));
|
||||
ui_.currentUploadedValueLabel->setText(Formatter::get().sizeToString(current.uploadedBytes));
|
||||
ui_.currentDownloadedValueLabel->setText(Formatter::get().sizeToString(current.downloadedBytes));
|
||||
ui_.currentRatioValueLabel->setText(Formatter::get().ratioToString(current.ratio));
|
||||
ui_.currentDurationValueLabel->setText(Formatter::get().timeToString(current.secondsActive));
|
||||
|
||||
ui_.totalUploadedValueLabel->setText(Formatter::sizeToString(total.uploadedBytes));
|
||||
ui_.totalDownloadedValueLabel->setText(Formatter::sizeToString(total.downloadedBytes));
|
||||
ui_.totalRatioValueLabel->setText(Formatter::ratioToString(total.ratio));
|
||||
ui_.totalDurationValueLabel->setText(Formatter::timeToString(total.secondsActive));
|
||||
ui_.totalUploadedValueLabel->setText(Formatter::get().sizeToString(total.uploadedBytes));
|
||||
ui_.totalDownloadedValueLabel->setText(Formatter::get().sizeToString(total.downloadedBytes));
|
||||
ui_.totalRatioValueLabel->setText(Formatter::get().ratioToString(total.ratio));
|
||||
ui_.totalDurationValueLabel->setText(Formatter::get().timeToString(total.secondsActive));
|
||||
|
||||
ui_.startCountLabel->setText(tr("Started %Ln time(s)", nullptr, total.sessionCount));
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <libtransmission/variant.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "IconCache.h"
|
||||
#include "Prefs.h"
|
||||
#include "Torrent.h"
|
||||
#include "Utils.h"
|
||||
|
@ -26,95 +27,9 @@
|
|||
|
||||
using ::trqt::variant_helpers::change;
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
// unchanging fields needed by the main window
|
||||
Torrent::KeyList const Torrent::MainInfoKeys{
|
||||
TR_KEY_addedDate,
|
||||
TR_KEY_downloadDir,
|
||||
TR_KEY_hashString,
|
||||
TR_KEY_id, // must be in every req
|
||||
TR_KEY_name,
|
||||
TR_KEY_totalSize,
|
||||
TR_KEY_trackers,
|
||||
};
|
||||
|
||||
// changing fields needed by the main window
|
||||
Torrent::KeyList const Torrent::MainStatKeys{
|
||||
TR_KEY_downloadedEver,
|
||||
TR_KEY_editDate,
|
||||
TR_KEY_error,
|
||||
TR_KEY_errorString,
|
||||
TR_KEY_eta,
|
||||
TR_KEY_haveUnchecked,
|
||||
TR_KEY_haveValid,
|
||||
TR_KEY_id, // must be in every req
|
||||
TR_KEY_isFinished,
|
||||
TR_KEY_leftUntilDone,
|
||||
TR_KEY_manualAnnounceTime,
|
||||
TR_KEY_metadataPercentComplete,
|
||||
TR_KEY_peersConnected,
|
||||
TR_KEY_peersGettingFromUs,
|
||||
TR_KEY_peersSendingToUs,
|
||||
TR_KEY_percentDone,
|
||||
TR_KEY_queuePosition,
|
||||
TR_KEY_rateDownload,
|
||||
TR_KEY_rateUpload,
|
||||
TR_KEY_recheckProgress,
|
||||
TR_KEY_seedRatioLimit,
|
||||
TR_KEY_seedRatioMode,
|
||||
TR_KEY_sizeWhenDone,
|
||||
TR_KEY_status,
|
||||
TR_KEY_uploadedEver,
|
||||
TR_KEY_webseedsSendingToUs
|
||||
};
|
||||
|
||||
Torrent::KeyList const Torrent::AllMainKeys = Torrent::MainInfoKeys + Torrent::MainStatKeys;
|
||||
|
||||
// unchanging fields needed by the details dialog
|
||||
Torrent::KeyList const Torrent::DetailInfoKeys{
|
||||
TR_KEY_comment,
|
||||
TR_KEY_creator,
|
||||
TR_KEY_dateCreated,
|
||||
TR_KEY_files,
|
||||
TR_KEY_id, // must be in every req
|
||||
TR_KEY_isPrivate,
|
||||
TR_KEY_pieceCount,
|
||||
TR_KEY_pieceSize,
|
||||
TR_KEY_trackers
|
||||
};
|
||||
|
||||
// changing fields needed by the details dialog
|
||||
Torrent::KeyList const Torrent::DetailStatKeys{
|
||||
TR_KEY_activityDate,
|
||||
TR_KEY_bandwidthPriority,
|
||||
TR_KEY_corruptEver,
|
||||
TR_KEY_desiredAvailable,
|
||||
TR_KEY_downloadedEver,
|
||||
TR_KEY_downloadLimit,
|
||||
TR_KEY_downloadLimited,
|
||||
TR_KEY_fileStats,
|
||||
TR_KEY_honorsSessionLimits,
|
||||
TR_KEY_id, // must be in every req
|
||||
TR_KEY_peer_limit,
|
||||
TR_KEY_peers,
|
||||
TR_KEY_seedIdleLimit,
|
||||
TR_KEY_seedIdleMode,
|
||||
TR_KEY_startDate,
|
||||
TR_KEY_trackerStats,
|
||||
TR_KEY_uploadLimit,
|
||||
TR_KEY_uploadLimited
|
||||
};
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
Torrent::Torrent(Prefs const& prefs, int id) :
|
||||
id_(id),
|
||||
icon_(Utils::getFileIcon()),
|
||||
icon_(IconCache::get().fileIcon()),
|
||||
prefs_(prefs)
|
||||
{
|
||||
}
|
||||
|
@ -248,20 +163,21 @@ int Torrent::compareETA(Torrent const& that) const
|
|||
void Torrent::updateMimeIcon()
|
||||
{
|
||||
auto const& files = files_;
|
||||
auto const& icon_cache = IconCache::get();
|
||||
|
||||
QIcon icon;
|
||||
|
||||
if (files.size() > 1)
|
||||
{
|
||||
icon = Utils::getFolderIcon();
|
||||
icon = icon_cache.folderIcon();
|
||||
}
|
||||
else if (files.size() == 1)
|
||||
{
|
||||
icon = Utils::guessMimeIcon(files.at(0).filename);
|
||||
icon = icon_cache.guessMimeIcon(files.at(0).filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
icon = Utils::guessMimeIcon(name());
|
||||
icon = icon_cache.guessMimeIcon(name());
|
||||
}
|
||||
|
||||
icon_ = icon;
|
||||
|
|
|
@ -503,13 +503,6 @@ public:
|
|||
return icon_;
|
||||
}
|
||||
|
||||
using KeyList = QSet<tr_quark>;
|
||||
static KeyList const AllMainKeys;
|
||||
static KeyList const DetailInfoKeys;
|
||||
static KeyList const DetailStatKeys;
|
||||
static KeyList const MainInfoKeys;
|
||||
static KeyList const MainStatKeys;
|
||||
|
||||
enum Field
|
||||
{
|
||||
ACTIVITY_DATE,
|
||||
|
|
|
@ -168,7 +168,7 @@ QString TorrentDelegate::progressString(Torrent const& tor)
|
|||
//: First part of torrent progress string;
|
||||
//: %1 is the percentage of torrent metadata downloaded
|
||||
str = tr("Magnetized transfer - retrieving metadata (%1%)").
|
||||
arg(Formatter::percentToString(tor.metadataPercentDone() * 100.0));
|
||||
arg(Formatter::get().percentToString(tor.metadataPercentDone() * 100.0));
|
||||
}
|
||||
else if (!is_done) // downloading
|
||||
{
|
||||
|
@ -176,8 +176,10 @@ QString TorrentDelegate::progressString(Torrent const& tor)
|
|||
//: %1 is how much we've got,
|
||||
//: %2 is how much we'll have when done,
|
||||
//: %3 is a percentage of the two
|
||||
str = tr("%1 of %2 (%3%)").arg(Formatter::sizeToString(have_total)).arg(Formatter::sizeToString(tor.sizeWhenDone())).
|
||||
arg(Formatter::percentToString(tor.percentDone() * 100.0));
|
||||
str =
|
||||
tr("%1 of %2 (%3%)").arg(Formatter::get().sizeToString(have_total)).arg(Formatter::get().sizeToString(
|
||||
tor.sizeWhenDone())).
|
||||
arg(Formatter::get().percentToString(tor.percentDone() * 100.0));
|
||||
}
|
||||
else if (!is_seed) // partial seed
|
||||
{
|
||||
|
@ -190,11 +192,11 @@ QString TorrentDelegate::progressString(Torrent const& tor)
|
|||
//: %4 is how much we've uploaded,
|
||||
//: %5 is our upload-to-download ratio,
|
||||
//: %6 is the ratio we want to reach before we stop uploading
|
||||
str = tr("%1 of %2 (%3%), uploaded %4 (Ratio: %5 Goal: %6)").arg(Formatter::sizeToString(have_total)).
|
||||
arg(Formatter::sizeToString(tor.totalSize())).
|
||||
arg(Formatter::percentToString(tor.percentComplete() * 100.0)).
|
||||
arg(Formatter::sizeToString(tor.uploadedEver())).arg(Formatter::ratioToString(tor.ratio())).
|
||||
arg(Formatter::ratioToString(seed_ratio));
|
||||
str = tr("%1 of %2 (%3%), uploaded %4 (Ratio: %5 Goal: %6)").arg(Formatter::get().sizeToString(have_total)).
|
||||
arg(Formatter::get().sizeToString(tor.totalSize())).
|
||||
arg(Formatter::get().percentToString(tor.percentComplete() * 100.0)).
|
||||
arg(Formatter::get().sizeToString(tor.uploadedEver())).arg(Formatter::get().ratioToString(tor.ratio())).
|
||||
arg(Formatter::get().ratioToString(seed_ratio));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -204,10 +206,10 @@ QString TorrentDelegate::progressString(Torrent const& tor)
|
|||
//: %3 is a percentage of the two,
|
||||
//: %4 is how much we've uploaded,
|
||||
//: %5 is our upload-to-download ratio
|
||||
str = tr("%1 of %2 (%3%), uploaded %4 (Ratio: %5)").arg(Formatter::sizeToString(have_total)).
|
||||
arg(Formatter::sizeToString(tor.totalSize())).
|
||||
arg(Formatter::percentToString(tor.percentComplete() * 100.0)).
|
||||
arg(Formatter::sizeToString(tor.uploadedEver())).arg(Formatter::ratioToString(tor.ratio()));
|
||||
str = tr("%1 of %2 (%3%), uploaded %4 (Ratio: %5)").arg(Formatter::get().sizeToString(have_total)).
|
||||
arg(Formatter::get().sizeToString(tor.totalSize())).
|
||||
arg(Formatter::get().percentToString(tor.percentComplete() * 100.0)).
|
||||
arg(Formatter::get().sizeToString(tor.uploadedEver())).arg(Formatter::get().ratioToString(tor.ratio()));
|
||||
}
|
||||
}
|
||||
else // seeding
|
||||
|
@ -219,9 +221,9 @@ QString TorrentDelegate::progressString(Torrent const& tor)
|
|||
//: %2 is how much we've uploaded,
|
||||
//: %3 is our upload-to-download ratio,
|
||||
//: %4 is the ratio we want to reach before we stop uploading
|
||||
str = tr("%1, uploaded %2 (Ratio: %3 Goal: %4)").arg(Formatter::sizeToString(have_total)).
|
||||
arg(Formatter::sizeToString(tor.uploadedEver())).arg(Formatter::ratioToString(tor.ratio())).
|
||||
arg(Formatter::ratioToString(seed_ratio));
|
||||
str = tr("%1, uploaded %2 (Ratio: %3 Goal: %4)").arg(Formatter::get().sizeToString(have_total)).
|
||||
arg(Formatter::get().sizeToString(tor.uploadedEver())).arg(Formatter::get().ratioToString(tor.ratio())).
|
||||
arg(Formatter::get().ratioToString(seed_ratio));
|
||||
}
|
||||
else // seeding w/o a ratio
|
||||
{
|
||||
|
@ -229,8 +231,8 @@ QString TorrentDelegate::progressString(Torrent const& tor)
|
|||
//: %1 is the torrent's total size,
|
||||
//: %2 is how much we've uploaded,
|
||||
//: %3 is our upload-to-download ratio
|
||||
str = tr("%1, uploaded %2 (Ratio: %3)").arg(Formatter::sizeToString(have_total)).
|
||||
arg(Formatter::sizeToString(tor.uploadedEver())).arg(Formatter::ratioToString(tor.ratio()));
|
||||
str = tr("%1, uploaded %2 (Ratio: %3)").arg(Formatter::get().sizeToString(have_total)).
|
||||
arg(Formatter::get().sizeToString(tor.uploadedEver())).arg(Formatter::get().ratioToString(tor.ratio()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +244,7 @@ QString TorrentDelegate::progressString(Torrent const& tor)
|
|||
//: Second (optional) part of torrent progress string;
|
||||
//: %1 is duration;
|
||||
//: notice that leading space (before the dash) is included here
|
||||
str += tr(" - %1 left").arg(Formatter::timeToString(tor.getETA()));
|
||||
str += tr(" - %1 left").arg(Formatter::get().timeToString(tor.getETA()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -264,12 +266,12 @@ QString TorrentDelegate::shortTransferString(Torrent const& tor)
|
|||
|
||||
if (have_down)
|
||||
{
|
||||
str = Formatter::downloadSpeedToString(tor.downloadSpeed()) + QStringLiteral(" ") +
|
||||
Formatter::uploadSpeedToString(tor.uploadSpeed());
|
||||
str = Formatter::get().downloadSpeedToString(tor.downloadSpeed()) + QStringLiteral(" ") +
|
||||
Formatter::get().uploadSpeedToString(tor.uploadSpeed());
|
||||
}
|
||||
else if (have_up)
|
||||
{
|
||||
str = Formatter::uploadSpeedToString(tor.uploadSpeed());
|
||||
str = Formatter::get().uploadSpeedToString(tor.uploadSpeed());
|
||||
}
|
||||
|
||||
return str.trimmed();
|
||||
|
@ -282,12 +284,13 @@ QString TorrentDelegate::shortStatusString(Torrent const& tor)
|
|||
switch (tor.getActivity())
|
||||
{
|
||||
case TR_STATUS_CHECK:
|
||||
str = tr("Verifying local data (%1% tested)").arg(Formatter::percentToString(tor.getVerifyProgress() * 100.0));
|
||||
str = tr("Verifying local data (%1% tested)").arg(Formatter::get().percentToString(tor.getVerifyProgress() * 100.0));
|
||||
break;
|
||||
|
||||
case TR_STATUS_DOWNLOAD:
|
||||
case TR_STATUS_SEED:
|
||||
str = shortTransferString(tor) + QStringLiteral(" ") + tr("Ratio: %1").arg(Formatter::ratioToString(tor.ratio()));
|
||||
str = shortTransferString(tor) + QStringLiteral(" ") + tr("Ratio: %1").arg(Formatter::get().ratioToString(
|
||||
tor.ratio()));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -322,7 +325,7 @@ QString TorrentDelegate::statusString(Torrent const& tor)
|
|||
if (!tor.hasMetadata())
|
||||
{
|
||||
str = tr("Downloading metadata from %Ln peer(s) (%1% done)", nullptr, tor.peersWeAreDownloadingFrom()).
|
||||
arg(Formatter::percentToString(100.0 * tor.metadataPercentDone()));
|
||||
arg(Formatter::get().percentToString(100.0 * tor.metadataPercentDone()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -146,7 +146,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
|||
b->peersWeAreUploadingTo() + b->webseedsWeAreDownloadingFrom());
|
||||
}
|
||||
|
||||
// fall through
|
||||
[[fallthrough]];
|
||||
|
||||
case SortMode::SORT_BY_STATE:
|
||||
if (val == 0)
|
||||
|
@ -169,7 +169,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
|||
val = compare(a->hasError(), b->hasError());
|
||||
}
|
||||
|
||||
// fall through
|
||||
[[fallthrough]];
|
||||
|
||||
case SortMode::SORT_BY_PROGRESS:
|
||||
if (val == 0)
|
||||
|
@ -192,7 +192,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
|||
val = -compare(a->queuePosition(), b->queuePosition());
|
||||
}
|
||||
|
||||
// fall through
|
||||
[[fallthrough]];
|
||||
|
||||
case SortMode::SORT_BY_RATIO:
|
||||
if (val == 0)
|
||||
|
|
|
@ -166,7 +166,7 @@ QString timeToStringRounded(int seconds)
|
|||
seconds -= seconds % 60;
|
||||
}
|
||||
|
||||
return Formatter::timeToString(seconds);
|
||||
return Formatter::get().timeToString(seconds);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -52,6 +52,7 @@ bool isSlashChar(QChar const& c)
|
|||
return c == QLatin1Char('/') || c == QLatin1Char('\\');
|
||||
}
|
||||
|
||||
#if 0
|
||||
QIcon folderIcon()
|
||||
{
|
||||
static QIcon icon;
|
||||
|
@ -156,10 +157,12 @@ QIcon getMimeIcon(QString const& filename)
|
|||
return icon;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#if 0
|
||||
QIcon Utils::getFolderIcon()
|
||||
{
|
||||
return folderIcon();
|
||||
|
@ -194,6 +197,8 @@ QIcon Utils::guessMimeIcon(QString const& filename)
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
QIcon Utils::getIconFromIndex(QModelIndex const& index)
|
||||
{
|
||||
QVariant const variant = index.data(Qt::DecorationRole);
|
||||
|
|
41
qt/Utils.h
41
qt/Utils.h
|
@ -9,7 +9,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <cctype> // isxdigit()
|
||||
#include <functional>
|
||||
|
||||
#include <QHash>
|
||||
#include <QPointer>
|
||||
#include <QRect>
|
||||
#include <QString>
|
||||
|
@ -20,12 +22,27 @@ class QHeaderView;
|
|||
class QIcon;
|
||||
class QModelIndex;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<>
|
||||
struct hash<QString>
|
||||
{
|
||||
std::size_t operator ()(QString const& s) const
|
||||
{
|
||||
return qHash(s);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
static QIcon getFileIcon();
|
||||
static QIcon getFolderIcon();
|
||||
static QIcon guessMimeIcon(QString const& filename);
|
||||
static QIcon getIconFromIndex(QModelIndex const& index);
|
||||
|
||||
// Test if string is UTF-8 or not
|
||||
|
@ -98,21 +115,3 @@ public:
|
|||
s.startsWith(QStringLiteral("https://"));
|
||||
}
|
||||
};
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<>
|
||||
struct hash<QString>
|
||||
{
|
||||
std::size_t operator ()(QString const& s) const
|
||||
{
|
||||
return qHash(s);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
|
||||
#include "VariantHelpers.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include <QUrl>
|
||||
#include <QtGlobal> // qFuzzyCompare
|
||||
|
||||
#include "Application.h" // qApp
|
||||
#include "Filters.h"
|
||||
|
@ -21,7 +23,7 @@ namespace trqt::variant_helpers
|
|||
|
||||
bool change(double& setme, double const& value)
|
||||
{
|
||||
bool const changed = !qFuzzyCompare(setme + 1, value + 1);
|
||||
bool const changed = std::fabs(setme - value) > std::numeric_limits<double>::epsilon();
|
||||
|
||||
if (changed)
|
||||
{
|
||||
|
|
|
@ -91,6 +91,7 @@ SOURCES += AboutDialog.cc \
|
|||
Filters.cc \
|
||||
Formatter.cc \
|
||||
FreeSpaceLabel.cc \
|
||||
IconCache.cc \
|
||||
IconToolButton.cc \
|
||||
InteropHelper.cc \
|
||||
InteropObject.cc \
|
||||
|
|
Loading…
Reference in New Issue