#include "ThreadCatalogModel.h" #include #include #include #include #include #include #include ThreadCatalogModel::ThreadCatalogModel() { update(); } ThreadCatalogModel::~ThreadCatalogModel() { } void ThreadCatalogModel::set_board(const String& board) { if (m_board == board) return; m_board = board; update(); } void ThreadCatalogModel::update() { CHttpRequest request; request.set_url(String::format("http://a.4cdn.org/%s/catalog.json", m_board.characters())); if (m_pending_job) m_pending_job->cancel(); m_pending_job = request.schedule(); if (on_load_started) on_load_started(); m_pending_job->on_finish = [this](bool success) { auto* response = m_pending_job->response(); dbg() << "Catalog download finished, success=" << success << ", response=" << response; if (!success) { if (on_load_finished) on_load_finished(false); return; } dbg() << "Catalog payload size: " << response->payload().size(); auto json = JsonValue::from_string(response->payload()); if (json.is_array()) { JsonArray new_catalog; for (auto& page : json.as_array().values()) { if (!page.is_object()) continue; auto threads_value = page.as_object().get("threads"); if (!threads_value.is_array()) continue; for (auto& thread : threads_value.as_array().values()) { new_catalog.append(thread); } } m_catalog = move(new_catalog); } did_update(); if (on_load_finished) on_load_finished(true); }; } int ThreadCatalogModel::row_count(const GModelIndex&) const { return m_catalog.size(); } String ThreadCatalogModel::column_name(int column) const { switch (column) { case Column::ThreadNumber: return "#"; case Column::Subject: return "Subject"; case Column::Text: return "Text"; case Column::ReplyCount: return "Replies"; case Column::ImageCount: return "Images"; case Column::PostTime: return "Time"; default: ASSERT_NOT_REACHED(); } } GModel::ColumnMetadata ThreadCatalogModel::column_metadata(int column) const { switch (column) { case Column::ThreadNumber: return { 70, TextAlignment::CenterRight }; case Column::Subject: return { 170, TextAlignment::CenterLeft }; case Column::Text: return { 270, TextAlignment::CenterLeft }; case Column::ReplyCount: return { 45, TextAlignment::CenterRight }; case Column::ImageCount: return { 40, TextAlignment::CenterRight }; case Column::PostTime: return { 120, TextAlignment::CenterLeft }; default: ASSERT_NOT_REACHED(); } } GVariant ThreadCatalogModel::data(const GModelIndex& index, Role role) const { auto& thread = m_catalog.at(index.row()).as_object(); if (role == Role::Display) { switch (index.column()) { case Column::ThreadNumber: return thread.get("no").to_u32(); case Column::Subject: return thread.get("sub").as_string_or({}); case Column::Text: return thread.get("com").as_string_or({}); case Column::ReplyCount: return thread.get("replies").to_u32(); case Column::ImageCount: return thread.get("images").to_u32(); case Column::PostTime: return thread.get("now").to_string(); default: ASSERT_NOT_REACHED(); } } return {}; }