Qt 6 support (#2069)

* Bump minimum Qt version to 5.6

* Switch from QRegExp to QRegularExpression

While still available, QRegExp has been moved to Qt6::Core5Compat module
and is not part of Qt6::Core.

* Use qIsEffectiveTLD instead of QUrl::topLevelDomain

The latter is not part of Qt6::Core. The former is a private utility in
Qt6::Network; using it for now, until (and if) we switch to something
non-Qt-specific.

* Use QStyle::State_Horizontal state when drawing progress bars

Although available for a long time, this state either didn't apply to
progress bars before Qt 6, or was deduced based on bar size. With Qt 6,
failing to specify it results in bad rendering.

* Don't use QStringRef (and associated methods)

While still available, QStringRef has been moved to Qt6::Core5Compat
module and is not part of Qt6::Core. Related method (e.g.
QString::midRef) have been removed in Qt 6.

* Use Qt::ItemIsAutoTristate instead of Qt::ItemIsTristate

The latter was deprecated and replaced with the former in Qt 5.6.

* Don't use QApplication::globalStrut

This property has been deprecated in Qt 5.15 and removed in Qt 6.

* Use QImage::fromHICON instead of QtWin::fromHICON

WinExtras module (providind the latter helper) has been removed in Qt 6.

* Use QStringDecoder instead of QTextCodec

While still available, QTextCodec has been moved to Qt6::Core5Compat
module and is not part of Qt6::Core.

* Don't forward-declare QStringList

Instead of being a standalone class, its definition has changed to
QList<QString> template specialization in Qt 6.

* Use explicit (since Qt 6) QFileInfo constructor

* Use QDateTime's {to,from}SecsSinceEpoch instead of {to,from}Time_t

The latter was deprecated in Qt 5.8 and removed in Qt 6.

* Don't use QFuture<>'s operator==

It has been removed in Qt 6. Since the original issue this code was
solving was caused by future reuse, just don't reuse futures and create
new finished ones when necessary.

* Use std::vector<> instead of QVector<>

The latter has been changed to a typedef for QList<>, which might not be
what one wants, and which also changed behavior a bit leading to
compilation errors.

* Don't use + for flags, cast to int explicitly

Operator+ for enum values has been deleted in Qt 6, so using operator|
instead. Then, there's no conversion from QFlags<> to QVariant, so need
to cast to int.

* Support Qt 6 in CMake and for MSI packaging

* Remove extra (empty) CMake variable use when constructing Qt target names

* Simplify logic in tr_qt_add_translation CMake helper

Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
Mike Gelfand
2021-11-04 00:20:11 +03:00
committed by GitHub
parent 689063b305
commit be74cb6356
31 changed files with 250 additions and 163 deletions

View File

@@ -40,6 +40,7 @@ tr_auto_option(USE_SYSTEM_MINIUPNPC "Use system miniupnpc library" AUTO)
tr_auto_option(USE_SYSTEM_NATPMP "Use system natpmp library" AUTO)
tr_auto_option(USE_SYSTEM_UTP "Use system utp library" AUTO)
tr_auto_option(USE_SYSTEM_B64 "Use system b64 library" AUTO)
tr_auto_option(USE_QT_VERSION "Use specific Qt version" AUTO 5 6)
tr_list_option(WITH_CRYPTO "Use specified crypto library" AUTO openssl cyassl polarssl ccrypto)
tr_auto_option(WITH_INOTIFY "Enable inotify support (on systems that support it)" AUTO)
tr_auto_option(WITH_KQUEUE "Enable kqueue support (on systems that support it)" AUTO)
@@ -117,7 +118,7 @@ set(GTK_MINIMUM 3.4.0)
set(GLIB_MINIMUM 2.50.1)
set(GIO_MINIMUM 2.26.0)
set(LIBAPPINDICATOR_MINIMUM 0.4.90)
set(QT5_MINIMUM 5.2)
set(QT_MINIMUM 5.6)
if(WIN32)
foreach(L C CXX)
@@ -233,34 +234,44 @@ if(ENABLE_QT)
set(ENABLE_QT_COM_INTEROP OFF)
set(ENABLE_QT_DBUS_INTEROP OFF)
set(QT5_REQUIRED_MODULES Core Gui Widgets Network LinguistTools)
set(QT5_OPTIONAL_MODULES DBus AxContainer AxServer)
set(QT_REQUIRED_MODULES Core Gui Widgets Network LinguistTools)
set(QT_OPTIONAL_MODULES DBus AxContainer AxServer)
set(MISSING_QT_MODULE)
if(WIN32)
list(APPEND QT5_REQUIRED_MODULES WinExtras)
set(Qt_NAMES Qt6 Qt5)
if(NOT USE_QT_VERSION STREQUAL "AUTO")
set(Qt_NAMES Qt${USE_QT_VERSION})
endif()
foreach(M ${QT5_REQUIRED_MODULES})
find_package(Qt5${M} ${QT5_MINIMUM} QUIET)
if(Qt5${M}_FOUND)
find_package(Qt NAMES ${Qt_NAMES} ${QT_MINIMUM} QUIET)
if(Qt_FOUND)
if(WIN32 AND Qt_VERSION_MAJOR EQUAL 5)
list(APPEND QT_REQUIRED_MODULES WinExtras)
endif()
foreach(M ${QT_REQUIRED_MODULES})
find_package(Qt${Qt_VERSION_MAJOR}${M} ${QT_MINIMUM} QUIET)
if(Qt${Qt_VERSION_MAJOR}${M}_FOUND)
if(NOT M STREQUAL "LinguistTools")
list(APPEND QT_TARGETS Qt5::${M})
list(APPEND QT_TARGETS Qt${Qt_VERSION_MAJOR}::${M})
endif()
else()
set(QT_TARGETS)
set(MISSING_QT_MODULE "${M}")
break()
endif()
endforeach()
endif()
if(QT_TARGETS)
foreach(M ${QT5_OPTIONAL_MODULES})
find_package(Qt5${M} ${QT5_MINIMUM} QUIET)
if(Qt5${M}_FOUND)
list(APPEND QT_TARGETS Qt5::${M})
foreach(M ${QT_OPTIONAL_MODULES})
find_package(Qt${Qt_VERSION_MAJOR}${M} ${QT_MINIMUM} QUIET)
if(Qt${Qt_VERSION_MAJOR}${M}_FOUND)
list(APPEND QT_TARGETS Qt${Qt_VERSION_MAJOR}::${M})
endif()
endforeach()
if(Qt5AxContainer_FOUND AND Qt5AxServer_FOUND)
if(Qt${Qt_VERSION_MAJOR}AxContainer_FOUND AND Qt${Qt_VERSION_MAJOR}AxServer_FOUND)
set(ENABLE_QT_COM_INTEROP ON)
find_program(MIDL_EXECUTABLE midl)
@@ -269,7 +280,7 @@ if(ENABLE_QT)
endif()
endif()
if(Qt5DBus_FOUND)
if(Qt${Qt_VERSION_MAJOR}DBus_FOUND)
set(ENABLE_QT_DBUS_INTEROP ON)
endif()
endif()
@@ -277,7 +288,7 @@ if(ENABLE_QT)
set(QT_FOUND ON)
if(NOT QT_TARGETS OR NOT (ENABLE_QT_COM_INTEROP OR ENABLE_QT_DBUS_INTEROP))
if(QT_IS_REQUIRED)
message(FATAL_ERROR "Unable to find required Qt libraries.")
message(FATAL_ERROR "Unable to find required Qt libraries (Qt${Qt_VERSION_MAJOR}${MISSING_QT_MODULE})")
endif()
set(QT_FOUND OFF)
endif()

View File

@@ -196,17 +196,27 @@ function(tr_fixup_bundle_item BUNDLE_DIR BUNDLE_ITEMS DEP_DIRS)
endfunction()
macro(tr_qt_wrap_ui)
if(Qt_VERSION_MAJOR EQUAL 6)
qt6_wrap_ui(${ARGN})
else()
qt5_wrap_ui(${ARGN})
endif()
endmacro()
macro(tr_qt_add_resources)
if(Qt_VERSION_MAJOR EQUAL 6)
qt6_add_resources(${ARGN})
else()
qt5_add_resources(${ARGN})
endif()
endmacro()
macro(tr_qt_add_translation)
if (Qt5LinguistTools_VERSION VERSION_LESS 5.11.0)
qt5_add_translation(${ARGN})
else()
if(Qt_VERSION_MAJOR EQUAL 6)
qt6_add_translation(${ARGN} OPTIONS -silent)
elseif(Qt_VERSION GREATER_EQUAL 5.11)
qt5_add_translation(${ARGN} OPTIONS -silent)
else()
qt5_add_translation(${ARGN})
endif()
endmacro()

View File

@@ -22,7 +22,7 @@ if(NOT TR_THIRD_PARTY_DIR)
endif()
if(NOT TR_QT_DIR)
set(TR_QT_DIR "$<TARGET_FILE_DIR:Qt5::Core>/..")
set(TR_QT_DIR "$<TARGET_FILE_DIR:Qt${Qt_VERSION_MAJOR}::Core>/..")
endif()
find_msvc_crt_msm(TR_MSVC_CRT_MSM_FILE)
@@ -82,6 +82,7 @@ wix_candle(${PROJECT_NAME}_OBJS
"SrcDir=${CMAKE_INSTALL_PREFIX}"
"ThirdPartyDir=${TR_THIRD_PARTY_DIR}"
"QtDir=${TR_QT_DIR}"
"QtMajorVer=${Qt_VERSION_MAJOR}"
"LicenseFile=${CMAKE_CURRENT_SOURCE_DIR}/GPLv2.rtf"
"WebSrcDir=${WEBSRCDIR}"
"TrQmSrcDir=${TRQMSRCDIR}"

View File

@@ -85,40 +85,64 @@
</DirectoryRef>
<DirectoryRef Id="INSTALLDIR" FileSource="$(var.QtDir)\bin">
<Component Id="dll.qt5.core">
<File DiskId="1" KeyPath="yes" Name="Qt5Core.dll" />
<Component Id="dll.qt.core">
<File DiskId="1" KeyPath="yes" Name="Qt$(var.QtMajorVer)Core.dll" />
</Component>
<Component Id="dll.qt5.dbus">
<File DiskId="1" KeyPath="yes" Name="Qt5DBus.dll" />
<Component Id="dll.qt.dbus">
<File DiskId="1" KeyPath="yes" Name="Qt$(var.QtMajorVer)DBus.dll" />
</Component>
<Component Id="dll.qt5.gui">
<File DiskId="1" KeyPath="yes" Name="Qt5Gui.dll" />
<Component Id="dll.qt.gui">
<File DiskId="1" KeyPath="yes" Name="Qt$(var.QtMajorVer)Gui.dll" />
</Component>
<Component Id="dll.qt5.network">
<File DiskId="1" KeyPath="yes" Name="Qt5Network.dll" />
<Component Id="dll.qt.network">
<File DiskId="1" KeyPath="yes" Name="Qt$(var.QtMajorVer)Network.dll" />
</Component>
<Component Id="dll.qt5.widgets">
<File DiskId="1" KeyPath="yes" Name="Qt5Widgets.dll" />
<Component Id="dll.qt.widgets">
<File DiskId="1" KeyPath="yes" Name="Qt$(var.QtMajorVer)Widgets.dll" />
</Component>
<Component Id="dll.qt5.winextras">
<File DiskId="1" KeyPath="yes" Name="Qt5WinExtras.dll" />
<?if $(var.QtMajorVer) = 5 ?>
<Component Id="dll.qt.winextras">
<File DiskId="1" KeyPath="yes" Name="Qt$(var.QtMajorVer)WinExtras.dll" />
</Component>
<?endif ?>
</DirectoryRef>
<DirectoryRef Id="INSTALLDIR" FileSource="$(var.QtDir)\plugins">
<?if $(var.QtMajorVer) = 6 ?>
<Directory Id="QTIMAGEFORMATSDIR" Name="imageformats">
<Component Id="dll.qt.plugins.imageformats.gif">
<File DiskId="1" KeyPath="yes" Name="qgif.dll" />
</Component>
<Component Id="dll.qt.plugins.imageformats.ico">
<File DiskId="1" KeyPath="yes" Name="qico.dll" />
</Component>
<Component Id="dll.qt.plugins.imageformats.jpeg">
<File DiskId="1" KeyPath="yes" Name="qjpeg.dll" />
</Component>
</Directory>
<?endif ?>
<Directory Id="QTPLATFORMDIR" Name="platforms">
<Component Id="dll.qt5.plugins.platforms.windows">
<Component Id="dll.qt.plugins.platforms.windows">
<File DiskId="1" KeyPath="yes" Name="qwindows.dll" />
</Component>
</Directory>
<Directory Id="QTSTYLESDIR" Name="styles">
<Component Id="dll.qt5.plugins.styles.windowsvista">
<Component Id="dll.qt.plugins.styles.windowsvista">
<File DiskId="1" KeyPath="yes" Name="qwindowsvistastyle.dll" />
</Component>
</Directory>
<?if $(var.QtMajorVer) = 6 ?>
<Directory Id="QTTLSDIR" Name="tls">
<Component Id="dll.qt.plugins.tls.openssl">
<File DiskId="1" KeyPath="yes" Name="qopensslbackend.dll" />
</Component>
</Directory>
<?endif ?>
</DirectoryRef>
<DirectoryRef Id="INSTALLDIR" FileSource="$(var.ThirdPartyDir)\bin">
@@ -133,14 +157,24 @@
<ComponentGroup Id="QtClientComponents">
<ComponentRef Id="exe.transmission.qt" />
<ComponentRef Id="conf.qt" />
<ComponentRef Id="dll.qt5.core" />
<ComponentRef Id="dll.qt5.dbus" />
<ComponentRef Id="dll.qt5.gui" />
<ComponentRef Id="dll.qt5.network" />
<ComponentRef Id="dll.qt5.widgets" />
<ComponentRef Id="dll.qt5.winextras" />
<ComponentRef Id="dll.qt5.plugins.platforms.windows" />
<ComponentRef Id="dll.qt5.plugins.styles.windowsvista" />
<ComponentRef Id="dll.qt.core" />
<ComponentRef Id="dll.qt.dbus" />
<ComponentRef Id="dll.qt.gui" />
<ComponentRef Id="dll.qt.network" />
<ComponentRef Id="dll.qt.widgets" />
<?if $(var.QtMajorVer) = 5 ?>
<ComponentRef Id="dll.qt.winextras" />
<?endif ?>
<?if $(var.QtMajorVer) = 6 ?>
<ComponentRef Id="dll.qt.plugins.imageformats.gif" />
<ComponentRef Id="dll.qt.plugins.imageformats.ico" />
<ComponentRef Id="dll.qt.plugins.imageformats.jpeg" />
<?endif ?>
<ComponentRef Id="dll.qt.plugins.platforms.windows" />
<ComponentRef Id="dll.qt.plugins.styles.windowsvista" />
<?if $(var.QtMajorVer) = 6 ?>
<ComponentRef Id="dll.qt.plugins.tls.openssl" />
<?endif ?>
<ComponentRef Id="dll.dbus" />
<ComponentGroupRef Id="QtClientTranslationsComponents" />
<ComponentGroupRef Id="QtTranslationsComponents" />

View File

@@ -667,10 +667,7 @@ int tr_main(int argc, char** argv)
{
InteropHelper::initialize();
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
Application::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
Application::setAttribute(Qt::AA_UseHighDpiPixmaps);
Application app(argc, argv);

View File

@@ -24,7 +24,7 @@
#include <QMap>
#include <QMessageBox>
#include <QResizeEvent>
#include <QRegExp>
#include <QRegularExpression>
#include <QStringList>
#include <QStyle>
#include <QTreeWidgetItem>
@@ -1294,7 +1294,7 @@ void DetailsDialog::onAddTrackerClicked()
QSet<QString> urls;
torrent_ids_t ids;
for (auto const& line : text.split(QRegExp(QStringLiteral("[\r\n]+"))))
for (auto const& line : text.split(QRegularExpression(QStringLiteral("[\r\n]+"))))
{
QString const url = line.trimmed();
if (!line.isEmpty() && QUrl(url).isValid())

View File

@@ -20,6 +20,43 @@
****
***/
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
Q_NETWORK_EXPORT bool qIsEffectiveTLD(QStringView domain);
#endif
namespace
{
QString getTopLevelDomain(QUrl const& url)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
auto const host = url.host();
auto const dot = QChar(QLatin1Char('.'));
for (auto dot_pos = host.indexOf(dot); dot_pos != -1; dot_pos = host.indexOf(dot, dot_pos + 1))
{
if (qIsEffectiveTLD(QStringView(&host.data()[dot_pos + 1], host.size() - dot_pos - 1)))
{
return host.mid(dot_pos);
}
}
return {};
#else
return url.topLevelDomain();
#endif
}
} // namespace
/***
****
***/
FaviconCache::FaviconCache()
: nam_(new QNetworkAccessManager(this))
{
@@ -119,7 +156,7 @@ FaviconCache::Key FaviconCache::getKey(QUrl const& url)
auto host = url.host();
// remove tld
auto const suffix = url.topLevelDomain();
auto const suffix = getTopLevelDomain(url);
host.truncate(host.size() - suffix.size());
// remove subdomain

View File

@@ -49,7 +49,7 @@ void FileTreeDelegate::paint(QPainter* painter, QStyleOptionViewItem const& opti
if (column == FileTreeModel::COL_PROGRESS)
{
QStyleOptionProgressBar p;
p.state = option.state | QStyle::State_Small;
p.state = option.state | QStyle::State_Horizontal | QStyle::State_Small;
p.direction = QApplication::layoutDirection();
p.rect = option.rect;
p.rect.setSize(QSize(option.rect.width() - 4, option.rect.height() - 8));

View File

@@ -114,7 +114,7 @@ QVariant FileTreeItem::data(int column, int role) const
case Qt::TextAlignmentRole:
if (column == FileTreeModel::COL_SIZE)
{
value = Qt::AlignRight + Qt::AlignVCenter;
value = static_cast<int>(Qt::AlignRight | Qt::AlignVCenter);
}
break;

View File

@@ -53,7 +53,7 @@ public:
{
int new_slash_index = path_.lastIndexOf(SlashChar, slash_index_);
token_.truncate(0);
token_ += path_.midRef(new_slash_index + 1, slash_index_ - new_slash_index);
token_.append(&path_.data()[new_slash_index + 1], slash_index_ - new_slash_index);
slash_index_ = new_slash_index - 1;
return token_;
}
@@ -82,7 +82,7 @@ public:
}
token_.truncate(0);
token_ += path_.midRef(slash_index_, new_slash_index - slash_index_);
token_.append(&path_.data()[slash_index_], new_slash_index - slash_index_);
slash_index_ = new_slash_index + 1;
return token_;
}
@@ -171,7 +171,7 @@ Qt::ItemFlags FileTreeModel::flags(QModelIndex const& index) const
if (index.column() == COL_WANTED)
{
i |= Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
i |= Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate;
}
return Qt::ItemFlags(i);

View File

@@ -70,7 +70,7 @@ QSize FilterBarComboBox::calculateSize(QSize const& text_size, QSize const& coun
content_size.rwidth() += hmargin + text_size.width();
content_size.rwidth() += hmargin + count_size.width();
return style()->sizeFromContents(QStyle::CT_ComboBox, &option, content_size, this).expandedTo(QApplication::globalStrut());
return style()->sizeFromContents(QStyle::CT_ComboBox, &option, content_size, this);
}
void FilterBarComboBox::paintEvent(QPaintEvent* e)

View File

@@ -24,8 +24,12 @@
#ifdef _WIN32
#include <QPixmapCache>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QImage>
#else
#include <QtWin>
#endif
#endif
#include <libtransmission/transmission.h>
@@ -149,7 +153,11 @@ void IconCache::addAssociatedFileIcon(QFileInfo const& file_info, unsigned int i
{
if (shell_file_info.hIcon != nullptr)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
pixmap = QPixmap::fromImage(QImage::fromHICON(shell_file_info.hIcon));
#else
pixmap = QtWin::fromHICON(shell_file_info.hIcon);
#endif
::DestroyIcon(shell_file_info.hIcon);
}
}

View File

@@ -658,7 +658,7 @@ void MainWindow::openFolder()
QString path(tor->getPath());
FileList const& files = tor->files();
if (files.isEmpty())
if (files.empty())
{
return;
}
@@ -1216,27 +1216,9 @@ void MainWindow::refreshPref(int key)
case Prefs::COMPACT_VIEW:
{
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) // QTBUG-33537
QItemSelectionModel* selection_model(ui_.listView->selectionModel());
QItemSelection const selection(selection_model->selection());
QModelIndex const current_index(selection_model->currentIndex());
#endif
b = prefs_.getBool(key);
ui_.action_CompactView->setChecked(b);
ui_.listView->setItemDelegate(b ? torrent_delegate_min_ : torrent_delegate_);
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) // QTBUG-33537
selectionModel->clear();
ui_.listView->reset(); // force the rows to resize
selectionModel->select(selection, QItemSelectionModel::Select);
selectionModel->setCurrentIndex(current_index, QItemSelectionModel::NoUpdate);
#endif
break;
}

View File

@@ -14,6 +14,7 @@
#include <QMainWindow>
#include <QNetworkReply>
#include <QPointer>
#include <QStringList>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QWidgetList>
@@ -28,7 +29,6 @@
class QAction;
class QIcon;
class QMenu;
class QStringList;
class AboutDialog;
class AddData;

View File

@@ -8,6 +8,8 @@
#include "MakeDialog.h"
#include <vector>
#include <QDir>
#include <QFileInfo>
#include <QMimeData>
@@ -144,7 +146,7 @@ void MakeDialog::makeTorrent()
// get the tiers
int tier = 0;
QVector<tr_tracker_info> trackers;
std::vector<tr_tracker_info> trackers;
for (QString const& line : ui_.trackersEdit->toPlainText().split(QLatin1Char('\n')))
{
@@ -159,7 +161,7 @@ void MakeDialog::makeTorrent()
auto tmp = tr_tracker_info{};
tmp.announce = tr_strdup(announce_url.toUtf8().constData());
tmp.tier = tier;
trackers.append(tmp);
trackers.push_back(tmp);
}
}
@@ -188,7 +190,7 @@ void MakeDialog::makeTorrent()
tr_makeMetaInfo(
builder_.get(),
target.toUtf8().constData(),
trackers.isEmpty() ? nullptr : trackers.data(),
trackers.empty() ? nullptr : trackers.data(),
trackers.size(),
comment.isEmpty() ? nullptr : comment.toUtf8().constData(),
ui_.privateCheck->isChecked(),

View File

@@ -6,6 +6,8 @@
*
*/
#include <algorithm>
#include <QFileInfo>
#include <QPushButton>
@@ -186,8 +188,8 @@ void OptionsDialog::reload()
if (have_info_)
{
priorities_.insert(0, info_.fileCount, TR_PRI_NORMAL);
wanted_.insert(0, info_.fileCount, true);
priorities_.assign(info_.fileCount, TR_PRI_NORMAL);
wanted_.assign(info_.fileCount, true);
for (tr_file_index_t i = 0; i < info_.fileCount; ++i)
{
@@ -198,7 +200,7 @@ void OptionsDialog::reload()
file.size = info_.files[i].length;
file.have = 0;
file.filename = QString::fromUtf8(info_.files[i].name);
files_.append(file);
files_.push_back(file);
}
}
@@ -273,7 +275,7 @@ void OptionsDialog::onAccepted()
dictAdd(&args, TR_KEY_bandwidthPriority, priority);
// files-unwanted
int count = wanted_.count(false);
auto count = std::count(wanted_.begin(), wanted_.end(), false);
if (count > 0)
{
@@ -289,7 +291,7 @@ void OptionsDialog::onAccepted()
}
// priority-low
count = priorities_.count(TR_PRI_LOW);
count = std::count(priorities_.begin(), priorities_.end(), TR_PRI_LOW);
if (count > 0)
{
@@ -305,7 +307,7 @@ void OptionsDialog::onAccepted()
}
// priority-high
count = priorities_.count(TR_PRI_HIGH);
count = std::count(priorities_.begin(), priorities_.end(), TR_PRI_HIGH);
if (count > 0)
{
@@ -380,7 +382,7 @@ void OptionsDialog::clearVerify()
void OptionsDialog::onVerify()
{
clearVerify();
verify_flags_.insert(0, info_.pieceCount, false);
verify_flags_.assign(info_.pieceCount, false);
verify_timer_.setSingleShot(false);
verify_timer_.start(0);
}
@@ -402,7 +404,7 @@ uint64_t getPieceSize(tr_info const* info, tr_piece_index_t piece_index)
void OptionsDialog::onTimeout()
{
if (files_.isEmpty())
if (files_.empty())
{
verify_timer_.stop();
return;
@@ -456,7 +458,7 @@ void OptionsDialog::onTimeout()
{
TorrentFile& f(files_[i.key()]);
f.have += i.value();
changed_files.append(f);
changed_files.push_back(f);
}
}

View File

@@ -8,13 +8,14 @@
#pragma once
#include <vector>
#include <QCryptographicHash>
#include <QDir>
#include <QFile>
#include <QMap>
#include <QString>
#include <QTimer>
#include <QVector>
#include "AddData.h" // AddData
#include "BaseDialog.h"
@@ -68,9 +69,9 @@ private:
QPushButton* verify_button_ = {};
QTimer edit_timer_;
QTimer verify_timer_;
QVector<bool> verify_flags_;
QVector<bool> wanted_;
QVector<int> priorities_;
std::vector<bool> verify_flags_;
std::vector<bool> wanted_;
std::vector<int> priorities_;
Session& session_;
Ui::OptionsDialog ui_ = {};
mybins_t verify_bins_;

View File

@@ -83,8 +83,7 @@ void PathButton::paintEvent(QPaintEvent* /*event*/)
QStyleOptionToolButton option;
initStyleOption(&option);
auto const& strut = QApplication::globalStrut();
QSize const fake_content_size(qMax(100, strut.width()), qMax(100, strut.height()));
QSize const fake_content_size(100, 100);
QSize const fake_size_hint = style()->sizeFromContents(QStyle::CT_ToolButton, &option, fake_content_size, this);
int text_width = width() - (fake_size_hint.width() - fake_content_size.width()) - iconSize().width() - 6;
@@ -156,7 +155,7 @@ void PathButton::updateAppearance()
if (!path_.isEmpty() && path_info.exists())
{
icon = icon_provider.icon(path_);
icon = icon_provider.icon(QFileInfo(path_));
}
if (icon.isNull())

View File

@@ -14,7 +14,11 @@
#include <QDateTime>
#include <QDir>
#include <QFile>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QStringDecoder>
#else
#include <QTextCodec>
#endif
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h>
@@ -180,10 +184,20 @@ auto const SortModes = std::array<std::pair<int, std::string_view>, SortMode::NU
bool isValidUtf8(QByteArray const& byteArray)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
auto decoder = QStringDecoder(QStringConverter::Utf8, QStringConverter::Flag::Stateless);
auto const text = QString(decoder.decode(byteArray));
return !decoder.hasError() && !text.contains(QChar::ReplacementCharacter);
#else
auto const* const codec = QTextCodec::codecForName("UTF-8");
auto state = QTextCodec::ConverterState{};
auto const text = codec->toUnicode(byteArray.constData(), byteArray.size(), &state);
return state.invalidChars == 0;
#endif
}
} // namespace
@@ -310,7 +324,11 @@ Prefs::Prefs(QString config_dir)
auto const value = getValue<time_t>(b);
if (value)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
values_[i].setValue(QDateTime::fromSecsSinceEpoch(*value));
#else
values_[i].setValue(QDateTime::fromTime_t(*value));
#endif
}
}
break;
@@ -391,7 +409,11 @@ Prefs::~Prefs()
break;
case QVariant::DateTime:
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
dictAdd(&current_settings, key, int64_t{ val.toDateTime().toSecsSinceEpoch() });
#else
dictAdd(&current_settings, key, val.toDateTime().toTime_t());
#endif
break;
default:

View File

@@ -70,25 +70,9 @@ void RpcQueue::runNext(RpcResponseFuture const& response)
{
assert(!queue_.isEmpty());
RpcResponseFuture const old_future = future_watcher_.future();
for (;;)
{
auto next = queue_.dequeue();
next_error_handler_ = next.second;
future_watcher_.setFuture((next.first)(response));
if (old_future != future_watcher_.future())
{
break;
}
if (queue_.isEmpty())
{
deleteLater();
break;
}
}
}
void RpcQueue::run()

View File

@@ -94,7 +94,7 @@ private:
};
}
// closure without return value ("auxiliary"), takes response and returns nothing -- internally we reuse the last future
// closure without return value ("auxiliary"), takes response and returns nothing
template<
typename Func,
typename std::enable_if<std::is_same_v<typename std::invoke_result_t<Func, RpcResponse const&>, void>>::type* = nullptr>
@@ -103,7 +103,7 @@ private:
return [func](RpcResponseFuture const& r)
{
func(r.result());
return r;
return createFinishedFuture();
};
}
@@ -111,10 +111,10 @@ private:
template<typename Func, typename std::enable_if<std::is_same_v<typename std::invoke_result_t<Func>, void>>::type* = nullptr>
QueuedFunction normalizeFunc(Func const& func) const
{
return [func](RpcResponseFuture const& r)
return [func](RpcResponseFuture const&)
{
func();
return r;
return createFinishedFuture();
};
}
@@ -140,6 +140,14 @@ private:
};
}
static RpcResponseFuture createFinishedFuture()
{
QFutureInterface<RpcResponse> promise;
promise.reportStarted();
promise.reportFinished();
return promise.future();
}
Tag const tag_;
static Tag next_tag;
bool tolerate_errors_ = {};

View File

@@ -280,7 +280,7 @@ Torrent::fields_t Torrent::update(tr_quark const* keys, tr_variant const* const*
case TR_KEY_files:
{
for (int i = 0; i < files_.size(); ++i)
for (size_t i = 0; i < files_.size(); ++i)
{
files_[i].index = i;
}

View File

@@ -11,6 +11,7 @@
#include <array>
#include <bitset>
#include <ctime> // time_t
#include <vector>
#include <QIcon>
#include <QMetaType>
@@ -58,7 +59,7 @@ struct Peer
double progress;
};
using PeerList = QVector<Peer>;
using PeerList = std::vector<Peer>;
struct TrackerStat
{
@@ -91,7 +92,7 @@ struct TrackerStat
QString last_scrape_result;
};
using TrackerStatsList = QVector<TrackerStat>;
using TrackerStatsList = std::vector<TrackerStat>;
struct TorrentFile
{
@@ -103,7 +104,7 @@ struct TorrentFile
uint64_t have = 0;
};
using FileList = QVector<TorrentFile>;
using FileList = std::vector<TorrentFile>;
class TorrentHash
{

View File

@@ -552,7 +552,7 @@ void TorrentDelegate::drawTorrent(QPainter* painter, QStyleOptionViewItem const&
cr = QPalette::Text;
}
QStyle::State progress_bar_state(option.state);
QStyle::State progress_bar_state(option.state | QStyle::State_Horizontal);
if (is_paused)
{

View File

@@ -236,7 +236,7 @@ void TorrentDelegateMin::drawTorrent(QPainter* painter, QStyleOptionViewItem con
cr = QPalette::Text;
}
QStyle::State progress_bar_state(option.state);
QStyle::State progress_bar_state(option.state | QStyle::State_Horizontal);
if (is_paused)
{

View File

@@ -92,7 +92,7 @@ int TorrentModel::rowCount(QModelIndex const& parent) const
QVariant TorrentModel::data(QModelIndex const& index, int role) const
{
Torrent const* t = torrents_.value(index.row(), nullptr);
auto const* const t = (index.isValid() && index.row() < rowCount()) ? torrents_.at(index.row()) : nullptr;
if (t != nullptr)
{
@@ -449,7 +449,7 @@ void TorrentModel::rowsAdd(torrents_t const& torrents)
{
for (auto const& tor : torrents)
{
auto* const it = std::lower_bound(torrents_.begin(), torrents_.end(), tor, compare);
auto const it = std::lower_bound(torrents_.begin(), torrents_.end(), tor, compare);
auto const row = static_cast<int>(std::distance(torrents_.begin(), it));
beginInsertRows(QModelIndex(), row, row);
@@ -468,8 +468,7 @@ void TorrentModel::rowsRemove(torrents_t const& torrents)
auto const& span = *it;
beginRemoveRows(QModelIndex(), span.first, span.second);
auto const n = span.second + 1 - span.first;
torrents_.remove(span.first, n);
torrents_.erase(torrents_.begin() + span.first, torrents_.begin() + span.second + 1);
endRemoveRows();
}

View File

@@ -12,7 +12,6 @@
#include <vector>
#include <QAbstractListModel>
#include <QVector>
#include "Macros.h"
#include "Torrent.h"
@@ -46,7 +45,7 @@ public:
Torrent* getTorrentFromId(int id);
Torrent const* getTorrentFromId(int id) const;
using torrents_t = QVector<Torrent*>;
using torrents_t = std::vector<Torrent*>;
torrents_t const& torrents() const
{

View File

@@ -25,11 +25,9 @@ QVariant TrackerModel::data(QModelIndex const& index, int role) const
{
QVariant var;
int const row = index.row();
if (0 <= row && row < rows_.size())
if (index.isValid() && index.row() < rowCount())
{
TrackerInfo const& tracker_info = rows_.at(row);
TrackerInfo const& tracker_info = rows_.at(index.row());
switch (role)
{
@@ -83,7 +81,7 @@ struct CompareTrackers
void TrackerModel::refresh(TorrentModel const& torrent_model, torrent_ids_t const& ids)
{
// build a list of the TrackerInfos
QVector<TrackerInfo> trackers;
std::vector<TrackerInfo> trackers;
for (int const id : ids)
{
@@ -98,7 +96,7 @@ void TrackerModel::refresh(TorrentModel const& torrent_model, torrent_ids_t cons
TrackerInfo tracker_info;
tracker_info.st = st;
tracker_info.torrent_id = id;
trackers.append(tracker_info);
trackers.push_back(tracker_info);
}
}
}
@@ -108,8 +106,8 @@ void TrackerModel::refresh(TorrentModel const& torrent_model, torrent_ids_t cons
std::sort(trackers.begin(), trackers.end(), comp);
// merge 'em with the existing list
int old_index = 0;
int new_index = 0;
unsigned int old_index = 0;
unsigned int new_index = 0;
while (old_index < rows_.size() || new_index < trackers.size())
{
@@ -120,7 +118,7 @@ void TrackerModel::refresh(TorrentModel const& torrent_model, torrent_ids_t cons
{
// add this new row
beginInsertRows(QModelIndex(), old_index, old_index);
rows_.insert(old_index, trackers.at(new_index));
rows_.insert(rows_.begin() + old_index, trackers.at(new_index));
endInsertRows();
++old_index;
++new_index;
@@ -129,7 +127,7 @@ void TrackerModel::refresh(TorrentModel const& torrent_model, torrent_ids_t cons
{
// remove this old row
beginRemoveRows(QModelIndex(), old_index, old_index);
rows_.remove(old_index);
rows_.erase(rows_.begin() + old_index);
endRemoveRows();
}
else // update existing row

View File

@@ -8,8 +8,9 @@
#pragma once
#include <vector>
#include <QAbstractListModel>
#include <QVector>
#include "Macros.h"
#include "Torrent.h"
@@ -46,7 +47,7 @@ public:
QVariant data(QModelIndex const& index, int role = Qt::DisplayRole) const override;
private:
using rows_t = QVector<TrackerInfo>;
using rows_t = std::vector<TrackerInfo>;
rows_t rows_;
};

View File

@@ -10,11 +10,6 @@
#include <unordered_map>
#include <unordered_set>
#ifdef _WIN32
#include <windows.h>
#include <shellapi.h>
#endif
#include <QAbstractItemView>
#include <QApplication>
#include <QColor>
@@ -31,10 +26,6 @@
#include <QPixmapCache>
#include <QStyle>
#ifdef _WIN32
#include <QtWin>
#endif
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h> // tr_formatter

View File

@@ -8,11 +8,11 @@
#pragma once
#include <string_view>
#include <optional>
#include <string_view>
#include <vector>
#include <QString>
#include <QVector>
#include <libtransmission/variant.h>
@@ -158,18 +158,18 @@ bool change(T& setme, tr_variant const* variant)
}
template<typename T>
bool change(QVector<T>& setme, tr_variant const* value)
bool change(std::vector<T>& setme, tr_variant const* value)
{
bool changed = false;
int const n = tr_variantListSize(value);
auto const n = tr_variantListSize(value);
if (setme.size() != n)
{
setme.resize(n);
changed = true;
}
for (int i = 0; i < n; ++i)
for (size_t i = 0; i < n; ++i)
{
changed = change(setme[i], tr_variantListChild(const_cast<tr_variant*>(value), i)) || changed;
}