From f906e9a9661fd00eea205e84aee80a4fff05f2fd Mon Sep 17 00:00:00 2001 From: rakshasa Date: Wed, 1 Jan 2025 12:15:54 +0000 Subject: [PATCH 1/9] Added missing base64.h header. --- .gitignore | 1 + src/Makefile.am | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index cde4aa20..901b7963 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ .libs Makefile aclocal.m4 +ar-lib autom4te.cache compile config.h diff --git a/src/Makefile.am b/src/Makefile.am index b3769aad..457b05f2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -155,6 +155,7 @@ libsub_root_a_SOURCES = \ ui/root.cc \ ui/root.h \ \ + utils/base64.h \ utils/directory.cc \ utils/directory.h \ utils/file_status_cache.cc \ From 73fed24459463869aa82308cc002ab50d29e0141 Mon Sep 17 00:00:00 2001 From: stickz Date: Mon, 30 Dec 2024 13:16:40 -0500 Subject: [PATCH 2/9] tinyxml2: Change from i4 to i8 We need to follow the same specification as xmlrpc-c until we deprecate it. It is breaking various software such as sonarr. We can't have xmlrpc using i8 and tinyxml2 using i4, while we allow both to be used. --- src/rpc/xmlrpc_tinyxml2.cc | 10 +++----- test/rpc/xmlrpc_test.cc | 2 +- test/rpc/xmlrpc_test_data.txt | 46 +++++++++++++++++------------------ 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/rpc/xmlrpc_tinyxml2.cc b/src/rpc/xmlrpc_tinyxml2.cc index 42ee5589..1c9f669d 100644 --- a/src/rpc/xmlrpc_tinyxml2.cc +++ b/src/rpc/xmlrpc_tinyxml2.cc @@ -142,11 +142,7 @@ print_object_xml(const torrent::Object& obj, tinyxml2::XMLPrinter* printer) { printer->CloseElement(true); break; case torrent::Object::TYPE_VALUE: - if (obj.as_value() > ((torrent::Object::value_type)2 << 30) || obj.as_value() < -((torrent::Object::value_type)2 << 30)) { - printer->OpenElement("i8", true); - } else { - printer->OpenElement("i4", true); - } + printer->OpenElement("i8", true); printer->PushText(std::to_string(obj.as_value()).c_str()); printer->CloseElement(true); break; @@ -194,7 +190,7 @@ print_object_xml(const torrent::Object& obj, tinyxml2::XMLPrinter* printer) { printer->CloseElement(true); break; default: - printer->OpenElement("i4", true); + printer->OpenElement("i8", true); printer->PushText(0); printer->CloseElement(true); } @@ -320,7 +316,7 @@ print_xmlrpc_fault(int faultCode, std::string faultString, tinyxml2::XMLPrinter* printer->PushText("faultCode"); printer->CloseElement(true); printer->OpenElement("value", true); - printer->OpenElement("i4", true); + printer->OpenElement("i8", true); printer->PushText(faultCode); printer->CloseElement(true); printer->CloseElement(true); diff --git a/test/rpc/xmlrpc_test.cc b/test/rpc/xmlrpc_test.cc index a5c2932d..51120a11 100644 --- a/test/rpc/xmlrpc_test.cc +++ b/test/rpc/xmlrpc_test.cc @@ -78,7 +78,7 @@ XmlrpcTest::test_invalid_utf8() { void XmlrpcTest::test_size_limit() { std::string input = "xmlrpc_reflect\xc3\x28"; - std::string expected = "faultCode-509faultStringContent size exceeds maximum XML-RPC limit"; + std::string expected = "faultCode-509faultStringContent size exceeds maximum XML-RPC limit"; std::string output; m_xmlrpc.set_size_limit(1); m_xmlrpc.process(input.c_str(), input.size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); diff --git a/test/rpc/xmlrpc_test_data.txt b/test/rpc/xmlrpc_test_data.txt index b1e0fc2e..c7adb105 100644 --- a/test/rpc/xmlrpc_test_data.txt +++ b/test/rpc/xmlrpc_test_data.txt @@ -18,9 +18,9 @@ xmlrpc_reflectZm9vYmFy foobar -# i4 ints -xmlrpc_reflect41 -41 +# i8 ints +xmlrpc_reflect41 +41 # i8 ints xmlrpc_reflect2247483647 @@ -43,37 +43,37 @@ # Simple struct -xmlrpc_reflectlowerBound18upperBound139 -lowerBound18upperBound139 +xmlrpc_reflectlowerBound18upperBound139 +lowerBound18upperBound139 # Invalid - missing method -no_such_method41 -faultCode-506faultStringmethod 'no_such_method' not defined +no_such_method41 +faultCode-506faultStringmethod 'no_such_method' not defined -# Invalid - i4 target -xmlrpc_reflect41 -faultCode-500faultStringinvalid parameters: target must be a string +# Invalid - i8 target +xmlrpc_reflect41 +faultCode-500faultStringinvalid parameters: target must be a string # Invalid - empty int tag -xmlrpc_reflect -faultCode-501faultStringunable to parse empty integer +xmlrpc_reflect +faultCode-501faultStringunable to parse empty integer # Invalid - empty int text -xmlrpc_reflect -faultCode-501faultStringunable to parse empty integer +xmlrpc_reflect +faultCode-501faultStringunable to parse empty integer # Invalid - broken XML -thodCall>test_a41faultCode-503faultStringError=XML_ERROR_PARSING_ELEMENT ErrorID=6 (0x6) Line number=1: XMLElement name=method +thodCall>test_a41faultCode-503faultStringError=XML_ERROR_PARSING_ELEMENT ErrorID=6 (0x6) Line number=1: XMLElement name=method -# Invalid - non-integer i4 -xmlrpc_reflectstring value -faultCode-501faultStringunable to parse integer value +# Invalid - non-integer i8 +xmlrpc_reflectstring value +faultCode-501faultStringunable to parse integer value -# Invalid - float i4 -xmlrpc_reflect3.14 -faultCode-501faultStringunable to parse integer value +# Invalid - float i8 +xmlrpc_reflect3.14 +faultCode-501faultStringunable to parse integer value # Invalid - non-boolean boolean xmlrpc_reflectstring value -faultCode-501faultStringunknown boolean value: string value +faultCode-501faultStringunknown boolean value: string value From a9c0b65b9dd188cf6d79d848ed7293d3171fc6f4 Mon Sep 17 00:00:00 2001 From: simonc56 Date: Sat, 28 Dec 2024 14:08:19 +0100 Subject: [PATCH 3/9] tinyxml2: in xmlrpc an array must include values in a data element --- src/rpc/xmlrpc_tinyxml2.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rpc/xmlrpc_tinyxml2.cc b/src/rpc/xmlrpc_tinyxml2.cc index 1c9f669d..700cc93b 100644 --- a/src/rpc/xmlrpc_tinyxml2.cc +++ b/src/rpc/xmlrpc_tinyxml2.cc @@ -148,12 +148,14 @@ print_object_xml(const torrent::Object& obj, tinyxml2::XMLPrinter* printer) { break; case torrent::Object::TYPE_LIST: printer->OpenElement("array", true); + printer->OpenElement("data", true); for (const auto& itr : obj.as_list()) { printer->OpenElement("value", true); print_object_xml(itr, printer); printer->CloseElement(true); } printer->CloseElement(true); + printer->CloseElement(true); break; case torrent::Object::TYPE_MAP: printer->OpenElement("struct", true); From 2bf81aa8f56186c548f8e1b71675f0fdd261ee52 Mon Sep 17 00:00:00 2001 From: simonc56 Date: Sat, 28 Dec 2024 15:11:43 +0100 Subject: [PATCH 4/9] tinyxml2: array with data for dict type --- src/rpc/xmlrpc_tinyxml2.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rpc/xmlrpc_tinyxml2.cc b/src/rpc/xmlrpc_tinyxml2.cc index 700cc93b..6aee9504 100644 --- a/src/rpc/xmlrpc_tinyxml2.cc +++ b/src/rpc/xmlrpc_tinyxml2.cc @@ -173,7 +173,7 @@ print_object_xml(const torrent::Object& obj, tinyxml2::XMLPrinter* printer) { break; case torrent::Object::TYPE_DICT_KEY: printer->OpenElement("array", true); - + printer->OpenElement("data", true); printer->OpenElement("value", true); print_object_xml(obj.as_dict_key(), printer); printer->CloseElement(true); @@ -190,6 +190,7 @@ print_object_xml(const torrent::Object& obj, tinyxml2::XMLPrinter* printer) { printer->CloseElement(true); } printer->CloseElement(true); + printer->CloseElement(true); break; default: printer->OpenElement("i8", true); From 31602917b7fdc59a77e611768326d540db1c9091 Mon Sep 17 00:00:00 2001 From: rakshasa Date: Wed, 1 Jan 2025 12:59:06 +0000 Subject: [PATCH 5/9] Release 0.15.1. --- configure.ac | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 7df42666..329c0ad1 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ m4_pattern_allow([PKG_CHECK_EXISTS]) -AC_INIT([rtorrent],[0.15.0],[sundell.software@gmail.com]) +AC_INIT([rtorrent],[0.15.1],[sundell.software@gmail.com]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIRS([scripts]) @@ -9,7 +9,6 @@ AM_PROG_AR AC_DEFINE([API_VERSION], [10], [api version]) -AC_PROG_RANLIB AC_PROG_CXX AC_SYS_LARGEFILE LT_INIT @@ -51,7 +50,7 @@ fi PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG]) PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"]) -PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.0]) +PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.1]) AC_LANG_PUSH(C++) TORRENT_WITH_XMLRPC_C From 350d03ca04fedc2153927b7bf26d43030e23d962 Mon Sep 17 00:00:00 2001 From: kannibalox Date: Sat, 28 Dec 2024 11:24:04 -0500 Subject: [PATCH 6/9] Update XMLRPC unit tests to include for arrays --- test/rpc/xmlrpc_test.cc | 2 +- test/rpc/xmlrpc_test_data.txt | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/test/rpc/xmlrpc_test.cc b/test/rpc/xmlrpc_test.cc index 51120a11..7ca22657 100644 --- a/test/rpc/xmlrpc_test.cc +++ b/test/rpc/xmlrpc_test.cc @@ -69,7 +69,7 @@ XmlrpcTest::test_invalid_utf8() { // valid UTF-8, but doesn't check strings, and Object strings are // just a series of bytes so it reflects just fine. std::string input = "xmlrpc_reflect\xc3\x28"; - std::string expected = "\xc3\x28"; + std::string expected = "\xc3\x28"; std::string output; m_xmlrpc.process(input.c_str(), input.size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); CPPUNIT_ASSERT_EQUAL(expected, output); diff --git a/test/rpc/xmlrpc_test_data.txt b/test/rpc/xmlrpc_test_data.txt index c7adb105..bab15b23 100644 --- a/test/rpc/xmlrpc_test_data.txt +++ b/test/rpc/xmlrpc_test_data.txt @@ -1,50 +1,51 @@ # Basic call xmlrpc_reflect - + # Basic call without params xmlrpc_reflect - + # UTF-8 string xmlrpc_reflectчао -чао +чао # emoji string xmlrpc_reflect😊 -😊 +😊 # base64 data (which gets returned as a string) xmlrpc_reflectZm9vYmFy -foobar +foobar # i8 ints xmlrpc_reflect41 -41 +41 # i8 ints xmlrpc_reflect2247483647 -2247483647 +2247483647 # negative i8 ints xmlrpc_reflect-2347483647 --2347483647 - -# Empty array -xmlrpc_reflect2247483647 -2247483647 +-2347483647 # Simple array +xmlrpc_reflect2247483647 +2247483647 + +# Empty array xmlrpc_reflect - + # Empty struct xmlrpc_reflect - + # Simple struct + xmlrpc_reflectlowerBound18upperBound139 -lowerBound18upperBound139 +lowerBound18upperBound139 # Invalid - missing method no_such_method41 From c2c6a4be268aee3f74fe4d0abcf944208b8617ba Mon Sep 17 00:00:00 2001 From: rakshasa Date: Thu, 2 Jan 2025 20:58:48 +0000 Subject: [PATCH 7/9] Inline test data instead of using separate text file. --- test/rpc/xmlrpc_test.cc | 115 +++++++++++++++++++++++++--------- test/rpc/xmlrpc_test_data.txt | 80 ----------------------- 2 files changed, 86 insertions(+), 109 deletions(-) delete mode 100644 test/rpc/xmlrpc_test_data.txt diff --git a/test/rpc/xmlrpc_test.cc b/test/rpc/xmlrpc_test.cc index 7ca22657..be0dee19 100644 --- a/test/rpc/xmlrpc_test.cc +++ b/test/rpc/xmlrpc_test.cc @@ -15,6 +15,89 @@ torrent::Object xmlrpc_cmd_test_reflect(rpc::target_type t, const torrent::Objec void initialize_command_dynamic(); #if defined(HAVE_XMLRPC_TINYXML2) && !defined(HAVE_XMLRPC_C) + +std::vector> basic_requests = { + std::make_tuple("Basic call", + "xmlrpc_reflect", + ""), + + std::make_tuple("Basic call without params", + "xmlrpc_reflect", + ""), + + std::make_tuple("UTF-8 string", + "xmlrpc_reflectчао", + "чао"), + + std::make_tuple("emoji string", + "xmlrpc_reflect😊", + "😊"), + + std::make_tuple("base64 data (which gets returned as a string)", + "xmlrpc_reflectZm9vYmFy", + "foobar"), + + std::make_tuple("i8 ints", + "xmlrpc_reflect41", + "41"), + + std::make_tuple("i8 ints", + "xmlrpc_reflect2247483647", + "2247483647"), + + std::make_tuple("negative i8 ints", + "xmlrpc_reflect-2347483647", + "-2347483647"), + + std::make_tuple("Simple array", + "xmlrpc_reflect2247483647", + "2247483647"), + + std::make_tuple("Empty array", + "xmlrpc_reflect", + ""), + + std::make_tuple("Empty struct", + "xmlrpc_reflect", + ""), + + std::make_tuple("Simple struct", + "xmlrpc_reflectlowerBound18upperBound139", + "lowerBound18upperBound139"), + + std::make_tuple("Invalid - missing method", + "no_such_method41", + "faultCode-506faultStringmethod 'no_such_method' not defined"), + + std::make_tuple("Invalid - i8 target", + "xmlrpc_reflect41", + "faultCode-500faultStringinvalid parameters: target must be a string"), + + std::make_tuple("Invalid - empty int tag", + "xmlrpc_reflect", + "faultCode-501faultStringunable to parse empty integer"), + + std::make_tuple("Invalid - empty int text", + "xmlrpc_reflect", + "faultCode-501faultStringunable to parse empty integer"), + + std::make_tuple("Invalid - broken XML", + "thodCall>test_a41faultCode-503faultStringError=XML_ERROR_PARSING_ELEMENT ErrorID=6 (0x6) Line number=1: XMLElement name=method"), + + std::make_tuple("Invalid - non-integer i8", + "xmlrpc_reflectstring value", + "faultCode-501faultStringunable to parse integer value"), + + std::make_tuple("Invalid - float i8", + "xmlrpc_reflect3.14", + "faultCode-501faultStringunable to parse integer value"), + + std::make_tuple("Invalid - non-boolean boolean", + "xmlrpc_reflectstring value", + "faultCode-501faultStringunknown boolean value: string value") +}; + void XmlrpcTest::setUp() { m_commandItr = m_commands; @@ -30,36 +113,10 @@ XmlrpcTest::setUp() { void XmlrpcTest::test_basics() { - std::ifstream file; file.open("rpc/xmlrpc_test_data.txt"); - CPPUNIT_ASSERT(file.good()); - std::vector titles; - std::vector inputs; - std::vector outputs; - std::string line; - int index = 0; - // Read file into inputs/outputs - while (std::getline(file, line)) { - if (line.size() == 0) { - continue; - } - if (line[0] == '#') { - titles.push_back(line); - continue; - } - if (index % 2) { - outputs.push_back(line); - } else { - inputs.push_back(line); - } - index++; - } - - // Sanity check the above parser - CPPUNIT_ASSERT_MESSAGE("Could not parse test data", inputs.size() > 0 && inputs.size() == outputs.size() && inputs.size() == titles.size()); - for (int i = 0; i < inputs.size(); i++) { + for (auto& test : basic_requests) { std::string output; - m_xmlrpc.process(inputs[i].c_str(), inputs[i].size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); - CPPUNIT_ASSERT_EQUAL_MESSAGE(titles[i], std::string(outputs[i]), output); + m_xmlrpc.process(std::get<1>(test).c_str(), std::get<1>(test).size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); + CPPUNIT_ASSERT_EQUAL_MESSAGE(std::get<0>(test), std::get<2>(test), output); } } diff --git a/test/rpc/xmlrpc_test_data.txt b/test/rpc/xmlrpc_test_data.txt deleted file mode 100644 index bab15b23..00000000 --- a/test/rpc/xmlrpc_test_data.txt +++ /dev/null @@ -1,80 +0,0 @@ -# Basic call -xmlrpc_reflect - - -# Basic call without params -xmlrpc_reflect - - -# UTF-8 string -xmlrpc_reflectчао -чао - -# emoji string -xmlrpc_reflect😊 -😊 - -# base64 data (which gets returned as a string) -xmlrpc_reflectZm9vYmFy -foobar - -# i8 ints -xmlrpc_reflect41 -41 - -# i8 ints -xmlrpc_reflect2247483647 -2247483647 - -# negative i8 ints -xmlrpc_reflect-2347483647 --2347483647 - -# Simple array -xmlrpc_reflect2247483647 -2247483647 - -# Empty array -xmlrpc_reflect - - -# Empty struct -xmlrpc_reflect - - -# Simple struct - -xmlrpc_reflectlowerBound18upperBound139 -lowerBound18upperBound139 - -# Invalid - missing method -no_such_method41 -faultCode-506faultStringmethod 'no_such_method' not defined - -# Invalid - i8 target -xmlrpc_reflect41 -faultCode-500faultStringinvalid parameters: target must be a string - -# Invalid - empty int tag -xmlrpc_reflect -faultCode-501faultStringunable to parse empty integer - -# Invalid - empty int text -xmlrpc_reflect -faultCode-501faultStringunable to parse empty integer - -# Invalid - broken XML -thodCall>test_a41faultCode-503faultStringError=XML_ERROR_PARSING_ELEMENT ErrorID=6 (0x6) Line number=1: XMLElement name=method - -# Invalid - non-integer i8 -xmlrpc_reflectstring value -faultCode-501faultStringunable to parse integer value - -# Invalid - float i8 -xmlrpc_reflect3.14 -faultCode-501faultStringunable to parse integer value - -# Invalid - non-boolean boolean -xmlrpc_reflectstring value -faultCode-501faultStringunknown boolean value: string value From 4876301cf49450a022f41a92c84e1ed2652e38d6 Mon Sep 17 00:00:00 2001 From: kannibalox Date: Fri, 13 Dec 2024 16:40:00 -0500 Subject: [PATCH 8/9] Add page up/down and home/end bindings to download list --- src/command_ui.cc | 2 + src/core/view.cc | 69 ++++++-------- src/core/view.h | 43 +-------- src/display/window_download_list.cc | 33 ++++--- src/display/window_download_list.h | 3 + src/ui/element_download_list.cc | 139 ++++++++++++++-------------- src/ui/element_download_list.h | 80 +++++----------- 7 files changed, 155 insertions(+), 214 deletions(-) diff --git a/src/command_ui.cc b/src/command_ui.cc index 7e3b7aae..7f55463c 100644 --- a/src/command_ui.cc +++ b/src/command_ui.cc @@ -843,6 +843,8 @@ initialize_command_ui() { CMD2_VAR_VALUE ("ui.throttle.global.step.medium", 50); CMD2_VAR_VALUE ("ui.throttle.global.step.large", 500); + CMD2_VAR_VALUE ("ui.focus.page_size", 0); + CMD2_ANY_LIST ("ui.status.throttle.up.set", std::bind(&cmd_status_throttle_names, true, std::placeholders::_2)); CMD2_ANY_LIST ("ui.status.throttle.down.set", std::bind(&cmd_status_throttle_names, false, std::placeholders::_2)); diff --git a/src/core/view.cc b/src/core/view.cc index e975ed85..7d28af65 100644 --- a/src/core/view.cc +++ b/src/core/view.cc @@ -1,39 +1,3 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - #include "config.h" #include @@ -236,20 +200,45 @@ View::set_not_visible(Download* download) { } void -View::next_focus() { +View::next_focus(unsigned int i) { if (empty()) return; - m_focus = (m_focus + 1) % (size() + 1); + // If at the boundary, roll over + if (m_focus == size() - 1) { + m_focus = size(); + emit_changed(); + return; + } + + // Move forward, stop at the boundary + if (m_focus == size()) // Needs special handling to ensure it's not off by one + m_focus = i - 1; + else + m_focus += i; + if (m_focus > size() - 1) + m_focus = size() - 1; + emit_changed(); } void -View::prev_focus() { +View::prev_focus(unsigned int i) { if (empty()) return; - m_focus = (m_focus - 1 + size() + 1) % (size() + 1); + // If at the boundary, roll over + if (m_focus == size()) { + m_focus = size() - 1; + emit_changed(); + return; + } + + // Move backward, stop at the boundary + m_focus -= i; + if (m_focus < 0 || m_focus > size()) + m_focus = size(); + emit_changed(); } diff --git a/src/core/view.h b/src/core/view.h index 837acb6b..1fe6f2be 100644 --- a/src/core/view.h +++ b/src/core/view.h @@ -1,39 +1,3 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - // Provides a filtered and sorted list of downloads that can be // updated auto-magically. // @@ -114,8 +78,11 @@ public: void set_visible(Download* download); void set_not_visible(Download* download); - void next_focus(); - void prev_focus(); + void next_focus(unsigned int i); + void prev_focus(unsigned int i); + + void next_focus() { next_focus(1); } + void prev_focus() { prev_focus(1); } void sort(); diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc index 6b4936d2..e76de744 100644 --- a/src/display/window_download_list.cc +++ b/src/display/window_download_list.cc @@ -72,6 +72,27 @@ WindowDownloadList::set_view(core::View* l) { m_changed_itr = m_view->signal_changed().insert(m_view->signal_changed().begin(), std::bind(&Window::mark_dirty, this)); } +int +WindowDownloadList::page_size(const std::string layout_name) { + // Calculate the page size for torrents. This is a public method + // because it's also used to determine the default size for page + // up/down actions. + int layout_height; + if (layout_name == "full") { + layout_height = 3; + } else if (layout_name == "compact") { + layout_height = 1; + } else { + return 0; + } + return m_canvas->height() / layout_height; +} + +int +WindowDownloadList::page_size() { + return page_size(rpc::call_command_string("ui.torrent_list.layout")); +} + void WindowDownloadList::redraw() { m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds()); @@ -95,24 +116,14 @@ WindowDownloadList::redraw() { m_canvas->print(m_canvas->width() - 16, 0, "[%5d of %-5d]", item_idx + 1, m_view->size()); } - int layout_height; const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout"); - if (layout_name == "full") { - layout_height = 3; - } else if (layout_name == "compact") { - layout_height = 1; - } else { - m_canvas->print(0, 0, "INVALID ui.torrent_list.layout '%s'", layout_name.c_str()); - return; - } - typedef std::pair Range; Range range = rak::advance_bidirectional(m_view->begin_visible(), m_view->focus() != m_view->end_visible() ? m_view->focus() : m_view->begin_visible(), m_view->end_visible(), - m_canvas->height() / layout_height); + page_size(layout_name)); // Make sure we properly fill out the last lines so it looks like // there are more torrents, yet don't hide it if we got the last one diff --git a/src/display/window_download_list.h b/src/display/window_download_list.h index 8e15cac9..5b704846 100644 --- a/src/display/window_download_list.h +++ b/src/display/window_download_list.h @@ -55,6 +55,9 @@ public: void set_view(core::View* l); + int page_size(const std::string layout_name); + int page_size(); + private: core::View* m_view; diff --git a/src/ui/element_download_list.cc b/src/ui/element_download_list.cc index 90a769ab..5c92984c 100644 --- a/src/ui/element_download_list.cc +++ b/src/ui/element_download_list.cc @@ -1,39 +1,3 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - #include "config.h" #include @@ -55,8 +19,8 @@ namespace ui { ElementDownloadList::ElementDownloadList() : - m_window(NULL), - m_view(NULL) { + m_window(NULL), + m_view(NULL) { receive_change_view("main"); @@ -67,40 +31,42 @@ ElementDownloadList::ElementDownloadList() : m_bindings['\x04'] = std::bind(&ElementDownloadList::receive_command, this, "branch=d.state=,d.stop=,d.erase="); m_bindings['\x0B'] = std::bind(&ElementDownloadList::receive_command, this, "d.ignore_commands.set=1; d.stop=; d.close="); m_bindings['\x12'] = std::bind(&ElementDownloadList::receive_command, this, "d.complete.set=0; d.check_hash="); - m_bindings['\x05'] = std::bind(&ElementDownloadList::receive_command, this, - "f.multicall=,f.set_create_queued=0,f.set_resize_queued=0; print=\"Queued create/resize of files in torrent.\""); + m_bindings['\x05'] = std::bind(&ElementDownloadList::receive_command, this, "f.multicall=,f.set_create_queued=0,f.set_resize_queued=0; print=\"Queued create/resize of files in torrent.\""); - m_bindings['+'] = std::bind(&ElementDownloadList::receive_next_priority, this); - m_bindings['-'] = std::bind(&ElementDownloadList::receive_prev_priority, this); - m_bindings['T'-'@']= std::bind(&ElementDownloadList::receive_cycle_throttle, this); - m_bindings['I'] = std::bind(&ElementDownloadList::receive_command, this, - "branch=d.ignore_commands=," - "{d.ignore_commands.set=0, print=\"Torrent set to heed commands.\"}," - "{d.ignore_commands.set=1, print=\"Torrent set to ignore commands.\"}"); - m_bindings['B'-'@']= std::bind(&ElementDownloadList::receive_command, this, - "branch=d.is_active=," - "{print=\"Cannot enable initial seeding on an active download.\"}," - "{d.connection_seed.set=initial_seed, print=\"Enabled initial seeding for the selected download.\"}"); + m_bindings['+'] = std::bind(&ElementDownloadList::receive_next_priority, this); + m_bindings['-'] = std::bind(&ElementDownloadList::receive_prev_priority, this); + m_bindings['T' - '@'] = std::bind(&ElementDownloadList::receive_cycle_throttle, this); + m_bindings['I'] = std::bind(&ElementDownloadList::receive_command, this, "branch=d.ignore_commands=," + "{d.ignore_commands.set=0, print=\"Torrent set to heed commands.\"}," + "{d.ignore_commands.set=1, print=\"Torrent set to ignore commands.\"}"); + m_bindings['B' - '@'] = std::bind(&ElementDownloadList::receive_command, this, "branch=d.is_active=," + "{print=\"Cannot enable initial seeding on an active download.\"}," + "{d.connection_seed.set=initial_seed, print=\"Enabled initial seeding for the selected download.\"}"); - m_bindings['U'] = std::bind(&ElementDownloadList::receive_command, this, - "d.delete_tied=; print=\"Cleared tied to file association for the selected download.\""); + m_bindings['U'] = std::bind(&ElementDownloadList::receive_command, this, "d.delete_tied=; print=\"Cleared tied to file association for the selected download.\""); // These should also be commands. - m_bindings['1'] = std::bind(&ElementDownloadList::receive_change_view, this, "main"); - m_bindings['2'] = std::bind(&ElementDownloadList::receive_change_view, this, "name"); - m_bindings['3'] = std::bind(&ElementDownloadList::receive_change_view, this, "started"); - m_bindings['4'] = std::bind(&ElementDownloadList::receive_change_view, this, "stopped"); - m_bindings['5'] = std::bind(&ElementDownloadList::receive_change_view, this, "complete"); - m_bindings['6'] = std::bind(&ElementDownloadList::receive_change_view, this, "incomplete"); - m_bindings['7'] = std::bind(&ElementDownloadList::receive_change_view, this, "hashing"); - m_bindings['8'] = std::bind(&ElementDownloadList::receive_change_view, this, "seeding"); - m_bindings['9'] = std::bind(&ElementDownloadList::receive_change_view, this, "leeching"); - m_bindings['0'] = std::bind(&ElementDownloadList::receive_change_view, this, "active"); + m_bindings['1'] = std::bind(&ElementDownloadList::receive_change_view, this, "main"); + m_bindings['2'] = std::bind(&ElementDownloadList::receive_change_view, this, "name"); + m_bindings['3'] = std::bind(&ElementDownloadList::receive_change_view, this, "started"); + m_bindings['4'] = std::bind(&ElementDownloadList::receive_change_view, this, "stopped"); + m_bindings['5'] = std::bind(&ElementDownloadList::receive_change_view, this, "complete"); + m_bindings['6'] = std::bind(&ElementDownloadList::receive_change_view, this, "incomplete"); + m_bindings['7'] = std::bind(&ElementDownloadList::receive_change_view, this, "hashing"); + m_bindings['8'] = std::bind(&ElementDownloadList::receive_change_view, this, "seeding"); + m_bindings['9'] = std::bind(&ElementDownloadList::receive_change_view, this, "leeching"); + m_bindings['0'] = std::bind(&ElementDownloadList::receive_change_view, this, "active"); - m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementDownloadList::receive_prev, this); + m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementDownloadList::receive_prev, this); m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = std::bind(&ElementDownloadList::receive_next, this); - m_bindings['L'] = std::bind(&ElementDownloadList::toggle_layout, this); + m_bindings[KEY_PPAGE] = m_bindings['U' - '@'] = [this] { receive_pageprev(); }; + m_bindings[KEY_NPAGE] = m_bindings['H' - '@'] = [this] { receive_pagenext(); }; + + m_bindings[KEY_HOME] = m_bindings['A' - '@'] = [this] { receive_home(); }; + m_bindings[KEY_END] = m_bindings['E' - '@'] = [this] { receive_end(); }; + + m_bindings['L'] = std::bind(&ElementDownloadList::toggle_layout, this); } void @@ -172,6 +138,41 @@ ElementDownloadList::receive_prev() { m_view->set_last_changed(); } +int +ElementDownloadList::page_size() { + int rpc_page_size = rpc::call_command_value("ui.focus.page_size"); + if (rpc_page_size > 0) + return rpc_page_size; + int auto_page_size = m_window->page_size() - 1; + if (auto_page_size > 0) + return auto_page_size; + return 50; +} + +void +ElementDownloadList::receive_pagenext() { + m_view->next_focus(page_size()); + m_view->set_last_changed(); +} + +void +ElementDownloadList::receive_pageprev() { + m_view->prev_focus(page_size()); + m_view->set_last_changed(); +} + +void +ElementDownloadList::receive_home() { + m_view->set_focus(m_view->begin_visible()); + m_view->set_last_changed(); +} + +void +ElementDownloadList::receive_end() { + m_view->set_focus(m_view->end_visible() - 1); + m_view->set_last_changed(); +} + void ElementDownloadList::receive_next_priority() { if (m_view->focus() == m_view->end_visible()) @@ -222,12 +223,10 @@ ElementDownloadList::receive_change_view(const std::string& name) { std::string old_name = view() ? view()->name() : ""; if (!old_name.empty()) - rpc::commands.call_catch("event.view.hide", rpc::make_target(), name, - "View hide event action failed: "); + rpc::commands.call_catch("event.view.hide", rpc::make_target(), name, "View hide event action failed: "); set_view(*itr); if (!old_name.empty()) - rpc::commands.call_catch("event.view.show", rpc::make_target(), old_name, - "View show event action failed: "); + rpc::commands.call_catch("event.view.show", rpc::make_target(), old_name, "View show event action failed: "); } void @@ -240,4 +239,4 @@ ElementDownloadList::toggle_layout() { rpc::call_command("ui.torrent_list.layout.set", "full"); } } -} +} // namespace ui diff --git a/src/ui/element_download_list.h b/src/ui/element_download_list.h index 5bf4f08f..67585dbc 100644 --- a/src/ui/element_download_list.h +++ b/src/ui/element_download_list.h @@ -1,43 +1,6 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - #ifndef RTORRENT_UI_ELEMENT_DOWNLOAD_LIST_H #define RTORRENT_UI_ELEMENT_DOWNLOAD_LIST_H -#include "core/download_list.h" #include "display/window_download_list.h" #include "element_base.h" @@ -45,7 +8,7 @@ class Control; namespace core { - class View; +class View; } namespace ui { @@ -56,34 +19,41 @@ public: ElementDownloadList(); - void activate(display::Frame* frame, bool focus = true); - void disable(); + void activate(display::Frame* frame, bool focus = true); + void disable(); - core::View* view() { return m_view; } - void set_view(core::View* l); + core::View* view() { return m_view; } + void set_view(core::View* l); - void receive_command(const char* cmd); + void receive_command(const char* cmd); - void receive_next(); - void receive_prev(); + void receive_next(); + void receive_prev(); - void receive_stop_download(); - void receive_close_download(); + int page_size(); + void receive_pagenext(); + void receive_pageprev(); - void receive_next_priority(); - void receive_prev_priority(); + void receive_home(); + void receive_end(); - void receive_cycle_throttle(); + void receive_stop_download(); + void receive_close_download(); - void receive_change_view(const std::string& name); + void receive_next_priority(); + void receive_prev_priority(); - void toggle_layout(); + void receive_cycle_throttle(); + + void receive_change_view(const std::string& name); + + void toggle_layout(); private: - WDownloadList* m_window; - core::View* m_view; + WDownloadList* m_window; + core::View* m_view; }; -} +} // namespace ui #endif From 6d8c214d0973342023fe750bf1b543b66ec22755 Mon Sep 17 00:00:00 2001 From: kannibalox Date: Thu, 26 Dec 2024 17:44:01 -0500 Subject: [PATCH 9/9] Manually include config.h for clang-tidy Specifically this fixes errors related to undefined macros in headers, since those aren't recorded in compile_commands.json --- .github/workflows/PR.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/PR.yml b/.github/workflows/PR.yml index 67382f29..118ff4d6 100644 --- a/.github/workflows/PR.yml +++ b/.github/workflows/PR.yml @@ -54,7 +54,7 @@ jobs: mkdir clang-tidy-result - name: Analyze run: | - git diff -U0 "$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}")" | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml + git diff -U0 "$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}")" | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml "-extra-arg=-include/${PWD}/config.h" - name: Save PR metadata run: | echo "${{ github.event.number }}" > clang-tidy-result/pr-id.txt