Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
af8be50
add resource downloading table - minimal implementation
jw098 Mar 15, 2026
34fd060
move ResourceDownloadTable.h to ResourceDownload folder
jw098 Mar 15, 2026
14bb494
add DownloadButton and DownloadButtonWidget
jw098 Mar 15, 2026
9c8044d
add Delete Button
jw098 Mar 15, 2026
9bb0892
add_rows_from_resource_list_json
jw098 Mar 16, 2026
98aee6c
refactor so that we keep a handle on m_resources and m_resource_rows.
jw098 Mar 16, 2026
4c1d407
check if resource is downloaded
jw098 Mar 17, 2026
6554806
check if downloaded. add "Version" column
jw098 Mar 17, 2026
60c4024
add DOWNLOADED_RESOURCE_PATH()
jw098 Mar 17, 2026
f7a6652
initial implementation of updating "Version" column on a separate thr…
jw098 Mar 17, 2026
e582f0f
initialize worker thread outside of constructor
jw098 Mar 18, 2026
64ae1e6
convert member fields to PIMPL
jw098 Mar 18, 2026
be129ed
add version number to the JSON
jw098 Mar 19, 2026
058e8c1
update version_num, version_status for each row
jw098 Mar 19, 2026
b136c2f
refactor Row class into its own file
jw098 Mar 20, 2026
767d148
clicking Download button disables it until action is done
jw098 Mar 20, 2026
008317c
add download pop-up
jw098 Mar 21, 2026
881349b
move functions to Helper class to avoid circular dependency. lazy ini…
jw098 Mar 24, 2026
d30759c
cleanup headers
jw098 Mar 24, 2026
18362a0
print to console when throwing ParseException
jw098 Mar 25, 2026
1736cb8
update exception handling within the thread. add predownload_warning_…
jw098 Mar 25, 2026
8b9e41e
FileDownloader::download_file_to_disk
jw098 Mar 26, 2026
fafd581
initial progress bar implementation
jw098 Mar 26, 2026
6d6d9ad
fix Download button
jw098 Mar 27, 2026
2ad2b73
added static progress bar to UI
jw098 Mar 27, 2026
d63ed48
refactor. move functions out of DownloadButton into Row. Move buttons…
jw098 Mar 27, 2026
07450a8
more refactor of ResourceDownloadRow class. pass local_metadata to it…
jw098 Mar 27, 2026
c91ece7
working implementation of Progress bar. fix inheritance for DownloadW…
jw098 Mar 27, 2026
5e9d39d
download failed pop-up if internet disconnected.
jw098 Mar 27, 2026
ee4fd7e
delete folder prior to downloading. create parent directory during th…
jw098 Mar 31, 2026
a154fbe
catch errors with get_resource_version_num()
jw098 Mar 31, 2026
0b4a5f9
add unzip progress bar
jw098 Mar 31, 2026
17a280d
minor UI changes with the progress bar
jw098 Mar 31, 2026
eaa37db
minor fix
jw098 Mar 31, 2026
d9012ca
update the Version and Downloaded column after downloading
jw098 Apr 1, 2026
918f18f
add cancel button
jw098 Apr 1, 2026
7889422
add cancel callback to download routine
jw098 Apr 1, 2026
8913a4b
add cancel callback to unzip function
jw098 Apr 2, 2026
4196b88
refactor: move logic from DownloadButton class to DownloadRow class.
jw098 Apr 2, 2026
a61d90b
implement delete action for Delete button
jw098 Apr 2, 2026
861031d
unzip routine will throw OperationCancelledException if cancelled. an…
jw098 Apr 3, 2026
8620003
adjust logic that updates button state
jw098 Apr 3, 2026
30adc57
update UI state for progress bar
jw098 Apr 4, 2026
3821cc0
adjust text and width of buttons
jw098 Apr 4, 2026
bd42eca
get SHA 256 after each download
jw098 Apr 8, 2026
9ab8984
compare with expected hash
jw098 Apr 8, 2026
ab0a65e
minior UI changes. update file size in table to KiB/MiB/GiB.
jw098 Apr 8, 2026
fccc36a
minor changes
jw098 Apr 8, 2026
be7f2ab
remove tabs
jw098 Apr 8, 2026
e29ba6c
fix build
jw098 Apr 8, 2026
66dca0d
fix build
jw098 Apr 9, 2026
a3d376f
use Filesystem::Path instead of implicitly using std::filesystem
jw098 Apr 9, 2026
0932d46
fix build
jw098 Apr 9, 2026
4b82781
draft: use CancellableScope
jw098 Apr 11, 2026
80e2d68
move thread into DownloadThread class
jw098 Apr 14, 2026
bdcf4bc
refactor DownloadThread and its lifetime
jw098 Apr 16, 2026
0f3578c
update initialization of DownloadThread to use factory method to ensu…
jw098 Apr 16, 2026
df47629
fix ResourceDownload buttons, which fixes the issue with blank box in…
jw098 Apr 16, 2026
741d1c6
add missing semicolon
jw098 Apr 17, 2026
92621b6
add DownloadListener. first step of migration away from Qt signals
jw098 Apr 17, 2026
772573e
remove Qt signals from DownloadRow. remove slots from DownloadWidget
jw098 Apr 18, 2026
e9d4712
fix build
jw098 Apr 18, 2026
d2f708a
minor refactor
jw098 Apr 18, 2026
0e07929
update table labels
jw098 Apr 18, 2026
8e09153
minor
jw098 Apr 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Common/Cpp/Exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ std::string Exception::to_str() const{
}


ParseException::ParseException(std::string message_string)
: m_message(std::move(message_string))
{
std::string str = ParseException::name();
str += ": " + message();
std::cerr << str << std::endl;
}



FileException::FileException(Logger* logger, const char* location, std::string message_string, std::string file)
Expand Down
2 changes: 1 addition & 1 deletion Common/Cpp/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class OperationCancelledException : public Exception{
class ParseException : public Exception{
public:
ParseException() = default;
ParseException(std::string message) : m_message(std::move(message)) {}
ParseException(std::string message);
virtual const char* name() const override{ return "ParseException"; }
virtual std::string message() const override{ return m_message; }
protected:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ GlobalSettings::GlobalSettings()
PA_ADD_OPTION(TEMP_FOLDER);
PA_ADD_OPTION(THEME);
PA_ADD_OPTION(USE_PADDLE_OCR);
PA_ADD_OPTION(RESOURCE_DOWNLOAD_TABLE);
PA_ADD_OPTION(WINDOW_SIZE);
PA_ADD_OPTION(LOG_WINDOW_SIZE);
PA_ADD_OPTION(LOG_WINDOW_STARTUP);
Expand Down
2 changes: 2 additions & 0 deletions SerialPrograms/Source/CommonFramework/GlobalSettingsPanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "Common/Cpp/Options/StringOption.h"
#include "CommonFramework/Panels/SettingsPanel.h"
#include "CommonFramework/Panels/PanelTools.h"
#include "CommonFramework/ResourceDownload/ResourceDownloadTable.h"

//#include <iostream>
//using std::cout;
Expand Down Expand Up @@ -124,6 +125,7 @@ class GlobalSettings : public BatchOption, private ConfigOption::Listener, priva

Pimpl<ThemeSelectorOption> THEME;
BooleanCheckBoxOption USE_PADDLE_OCR;
ResourceDownloadTable RESOURCE_DOWNLOAD_TABLE;
Pimpl<ResolutionOption> WINDOW_SIZE;
Pimpl<ResolutionOption> LOG_WINDOW_SIZE;
BooleanCheckBoxOption LOG_WINDOW_STARTUP;
Expand Down
4 changes: 4 additions & 0 deletions SerialPrograms/Source/CommonFramework/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ const std::string& RESOURCE_PATH(){
static std::string path = get_resource_path();
return path;
}
const std::string& DOWNLOADED_RESOURCE_PATH(){
static std::string path = RUNTIME_BASE_PATH() + "DownloadedResources/";
return path;
}
const std::string& TRAINING_PATH(){
static std::string path = get_training_path();
return path;
Expand Down
4 changes: 4 additions & 0 deletions SerialPrograms/Source/CommonFramework/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ const std::string& USER_FILE_PATH();
// Resource folder path. Resources include JSON files, images, sound files and others required by
// various automation programs.
const std::string& RESOURCE_PATH();

// Folder path that holds Downloaded resources
const std::string& DOWNLOADED_RESOURCE_PATH();

// Hold ML training data.
const std::string& TRAINING_PATH();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "Common/Cpp/Containers/Pimpl.tpp"
#include "Common/Cpp/Json/JsonValue.h"
#include "Common/Cpp/Concurrency/SpinLock.h"
#include "LabelCellOption.h"

//#include <iostream>
Expand All @@ -17,7 +18,7 @@ namespace PokemonAutomation{


struct LabelCellOption::Data{
// mutable SpinLock m_lock;
mutable SpinLock m_lock;
std::string m_text;
// ImageRGB32 m_icon_owner;
ImageViewRGB32 m_icon;
Expand Down Expand Up @@ -80,6 +81,7 @@ LabelCellOption::LabelCellOption(
// : m_data(CONSTRUCT_TOKEN, std::move(text), std::move(icon))
//{}
const std::string& LabelCellOption::text() const{
ReadSpinLock lg(m_data->m_lock);
return m_data->m_text;
}
const ImageViewRGB32& LabelCellOption::icon() const{
Expand All @@ -94,6 +96,18 @@ JsonValue LabelCellOption::to_json() const{
return JsonValue();
}

void LabelCellOption::set_text(std::string x){
// sanitize(x);
{
WriteSpinLock lg(m_data->m_lock);
if (m_data->m_text == x){
return;
}
m_data->m_text = std::move(x);
}
report_value_changed(this);
}




Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class LabelCellOption : public ConfigOptionImpl<LabelCellOption>{
const ImageViewRGB32& icon() const;
Resolution resolution() const;

void set_text(std::string x);

virtual void load_json(const JsonValue& json) override;
virtual JsonValue to_json() const override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ LabelCellWidget::~LabelCellWidget(){
LabelCellWidget::LabelCellWidget(QWidget& parent, LabelCellOption& value)
: QWidget(&parent)
, ConfigWidget(value, *this)
// , m_value(value)
, m_value(value)
{
QHBoxLayout* layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
Expand All @@ -49,6 +49,17 @@ LabelCellWidget::LabelCellWidget(QWidget& parent, LabelCellOption& value)
layout->addWidget(m_text, 1);
// text->setTextInteractionFlags(Qt::TextBrowserInteraction);
// m_text->setOpenExternalLinks(true);

m_value.add_listener(*this);
}

void LabelCellWidget::update_value(){
m_text->setText(QString::fromStdString(m_value.text()));
}
void LabelCellWidget::on_config_value_changed(void* object){
QMetaObject::invokeMethod(m_text, [this]{
update_value();
}, Qt::QueuedConnection);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ class LabelCellWidget : public QWidget, public ConfigWidget{
~LabelCellWidget();
LabelCellWidget(QWidget& parent, LabelCellOption& value);

virtual void update_value() override;
virtual void on_config_value_changed(void* object) override;

private:
// LabelCellOption& m_value;
LabelCellOption& m_value;
QLabel* m_icon = nullptr;
QLabel* m_text;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/* Resource Download Helpers
*
* From: https://github.com/PokemonAutomation/
*
*/

#include "CommonFramework/Globals.h"
#include "CommonFramework/Logging/Logger.h"
// #include "CommonFramework/Tools/GlobalThreadPools.h"
#include "CommonFramework/Tools/FileDownloader.h"
#include "CommonFramework/Exceptions/OperationFailedException.h"
#include "Common/Cpp/Json/JsonArray.h"
#include "Common/Cpp/Json/JsonObject.h"
#include "Common/Cpp/Filesystem.h"
#include "ResourceDownloadHelpers.h"

// #include <filesystem>
// #include <thread>
// #include <unordered_set>

#include <iostream>
using std::cout;
using std::endl;

namespace PokemonAutomation{


ResourceType get_resource_type_from_string(std::string type){
if (type == "ZippedFolder"){
return ResourceType::ZIP_FILE;
}else{
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "get_resource_type_from_string: Unknown string.");
}

}

std::vector<DownloadedResourceMetadata> deserialize_resource_list_json(const JsonValue& json){
std::vector<DownloadedResourceMetadata> resources;

try{
const JsonObject& obj = json.to_object_throw();
const JsonArray& resource_list = obj.get_array_throw("resourceList");
for (const JsonValue& resource_val : resource_list){
const JsonObject& resource_obj = resource_val.to_object_throw();

std::string resource_name = resource_obj.get_string_throw("resourceName");
std::optional<uint16_t> version_num = (uint16_t)resource_obj.get_integer_throw("version");
ResourceType resource_type = get_resource_type_from_string(resource_obj.get_string_throw("Type"));
size_t compressed_bytes = (size_t)resource_obj.get_integer_throw("CompressedBytes");
size_t decompressed_bytes = (size_t)resource_obj.get_integer_throw("DecompressedBytes");
std::string url = resource_obj.get_string_throw("URL");
std::string sha_256 = resource_obj.get_string_throw("SHA_256");

DownloadedResourceMetadata resource = {
resource_name,
version_num,
resource_type,
compressed_bytes,
decompressed_bytes,
url,
sha_256
};

resources.emplace_back(std::move(resource));

}

}catch (ParseException&){
std::cerr << "JSON parsing error. Given JSON file doesn't match the expected format." << endl;
// throw ParseException("JSON parsing error. Given JSON file doesn't match the expected format.");
return std::vector<DownloadedResourceMetadata>();
}

return resources;
}


const std::vector<DownloadedResourceMetadata>& local_resource_download_list(){
// cout << "local_resource_download_list" << endl;
static std::vector<DownloadedResourceMetadata> local_resources = deserialize_resource_list_json(load_json_file(RESOURCE_PATH() + "ResourceDownloadList.json"));

return local_resources;
}


JsonValue fetch_resource_download_list_json_from_remote(){
Logger& logger = global_logger_tagged();
JsonValue json =
FileDownloader::download_json_file(
logger,
"https://raw.githubusercontent.com/jw098/Packages/refs/heads/download/Resources/ResourceDownloadList.json"
);

return json;
}

const JsonValue& remote_resource_download_list_json(){
static const JsonValue json = fetch_resource_download_list_json_from_remote();

return json;
}

const std::vector<DownloadedResourceMetadata>& remote_resource_download_list(){
// cout << "remote_resource_download_list" << endl;
static std::vector<DownloadedResourceMetadata> remote_resources = deserialize_resource_list_json(remote_resource_download_list_json());

return remote_resources;
}

std::optional<uint16_t> get_resource_version_num(Filesystem::Path folder_path){
try{
std::string file_name = folder_path.string() + "/version.json";
const JsonValue& json = load_json_file(file_name);

const JsonObject& obj = json.to_object_throw();
uint16_t version_num = (uint16_t)obj.get_integer_throw("version");
return version_num;
}catch(...){
std::cerr << "Unable to determine the version number from version.json." << endl;
return std::nullopt;
}

}

ResourceVersionStatus get_version_status(uint16_t expected_version_num, std::optional<uint16_t> current_version_num){
if (!current_version_num.has_value()){
return ResourceVersionStatus::NOT_APPLICABLE;
}

if (current_version_num < expected_version_num){
return ResourceVersionStatus::OUTDATED;
}else if (current_version_num == expected_version_num){
return ResourceVersionStatus::CURRENT;
}else{ // current > expected
return ResourceVersionStatus::FUTURE_VERSION;
}
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* Resource Download Helpers
*
* From: https://github.com/PokemonAutomation/
*
*/

#ifndef PokemonAutomation_ResourceDownloadHelpers_H
#define PokemonAutomation_ResourceDownloadHelpers_H

#include <string>
#include <optional>


namespace PokemonAutomation{

namespace Filesystem{
class Path;
}


enum class ResourceType{
ZIP_FILE,
};

struct DownloadedResourceMetadata{
std::string resource_name;
std::optional<uint16_t> version_num;
ResourceType resource_type;
size_t size_compressed_bytes;
size_t size_decompressed_bytes;
std::string url;
std::string sha_256;
};

enum class ResourceVersionStatus{
CURRENT,
OUTDATED, // still used, but newer version available
FUTURE_VERSION, // current version number is greater than the expected version number
NOT_APPLICABLE, // resource not downloaded locally, so can't get its version
// RETIRED, // no longer used
// BLANK, // not yet fetched version info from remote
};

enum class RemoteMetadataStatus{
UNINITIALIZED,
NOT_AVAILABLE,
AVAILABLE,
};
struct RemoteMetadata {
RemoteMetadataStatus status = RemoteMetadataStatus::UNINITIALIZED;
DownloadedResourceMetadata metadata;
};


const std::vector<DownloadedResourceMetadata>& local_resource_download_list();
const std::vector<DownloadedResourceMetadata>& remote_resource_download_list();
std::optional<uint16_t> get_resource_version_num(Filesystem::Path folder_path);
ResourceVersionStatus get_version_status(uint16_t expected_version_num, std::optional<uint16_t> current_version_num);

}
#endif
Loading