From 7a632771151cc641096c786933b651ee0f57784b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 5 Aug 2019 18:43:36 +0200 Subject: ChanViewer: Fetch the list of boards and allow switching the board We put the list of boards in a combo box and allow the user to switch boards that way. :^) --- Applications/ChanViewer/BoardListModel.cpp | 90 ++++++++++++++++++++++++++ Applications/ChanViewer/BoardListModel.h | 27 ++++++++ Applications/ChanViewer/Makefile | 1 + Applications/ChanViewer/ThreadCatalogModel.cpp | 10 ++- Applications/ChanViewer/ThreadCatalogModel.h | 3 + Applications/ChanViewer/main.cpp | 15 +++++ 6 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 Applications/ChanViewer/BoardListModel.cpp create mode 100644 Applications/ChanViewer/BoardListModel.h (limited to 'Applications') diff --git a/Applications/ChanViewer/BoardListModel.cpp b/Applications/ChanViewer/BoardListModel.cpp new file mode 100644 index 0000000000..bb326d94db --- /dev/null +++ b/Applications/ChanViewer/BoardListModel.cpp @@ -0,0 +1,90 @@ +#include "BoardListModel.h" +#include +#include +#include +#include +#include +#include +#include + +BoardListModel::BoardListModel() +{ + update(); +} + +BoardListModel::~BoardListModel() +{ +} + +void BoardListModel::update() +{ + CHttpRequest request; + request.set_hostname("a.4cdn.org"); + request.set_path("/boards.json"); + + auto* job = request.schedule(); + + job->on_finish = [job, this](bool success) { + auto* response = job->response(); + dbg() << "Board list download finished, success=" << success << ", response=" << response; + + if (!success) + return; + + dbg() << "Board list payload size: " << response->payload().size(); + + auto json = JsonValue::from_string(response->payload()); + + if (json.is_object()) { + auto new_boards = json.as_object().get("boards"); + if (new_boards.is_array()) + m_boards = move(new_boards.as_array()); + } + + did_update(); + }; +} + +int BoardListModel::row_count(const GModelIndex&) const +{ + return m_boards.size(); +} + +String BoardListModel::column_name(int column) const +{ + switch (column) { + case Column::Board: + return "Board"; + default: + ASSERT_NOT_REACHED(); + } +} + +GModel::ColumnMetadata BoardListModel::column_metadata([[maybe_unused]] int column) const +{ + return {}; +} + +GVariant BoardListModel::data(const GModelIndex& index, Role role) const +{ + auto& board = m_boards.at(index.row()).as_object(); + if (role == Role::Display) { + switch (index.column()) { + case Column::Board: + return String::format("/%s/ - %s", + board.get("board").to_string().characters(), + board.get("title").to_string().characters()); + default: + ASSERT_NOT_REACHED(); + } + } + if (role == Role::Custom) { + switch (index.column()) { + case Column::Board: + return board.get("board").to_string(); + default: + ASSERT_NOT_REACHED(); + } + } + return {}; +} diff --git a/Applications/ChanViewer/BoardListModel.h b/Applications/ChanViewer/BoardListModel.h new file mode 100644 index 0000000000..13a997c85e --- /dev/null +++ b/Applications/ChanViewer/BoardListModel.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +class BoardListModel final : public GModel { +public: + enum Column { + Board, + __Count, + }; + + static NonnullRefPtr create() { return adopt(*new BoardListModel); } + virtual ~BoardListModel() override; + + virtual int row_count(const GModelIndex& = GModelIndex()) const override; + virtual int column_count(const GModelIndex& = GModelIndex()) const override { return Column::__Count; } + virtual String column_name(int) const override; + virtual ColumnMetadata column_metadata(int) const override; + virtual GVariant data(const GModelIndex&, Role = Role::Display) const override; + virtual void update() override; + +private: + BoardListModel(); + + JsonArray m_boards; +}; diff --git a/Applications/ChanViewer/Makefile b/Applications/ChanViewer/Makefile index 65d01b6065..c31011fcf4 100755 --- a/Applications/ChanViewer/Makefile +++ b/Applications/ChanViewer/Makefile @@ -2,6 +2,7 @@ include ../../Makefile.common OBJS = \ ThreadCatalogModel.o \ + BoardListModel.o \ main.o APP = ChanViewer diff --git a/Applications/ChanViewer/ThreadCatalogModel.cpp b/Applications/ChanViewer/ThreadCatalogModel.cpp index 264ac20760..828e314410 100644 --- a/Applications/ChanViewer/ThreadCatalogModel.cpp +++ b/Applications/ChanViewer/ThreadCatalogModel.cpp @@ -16,11 +16,19 @@ 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_hostname("a.4cdn.org"); - request.set_path("/g/catalog.json"); + request.set_path(String::format("/%s/catalog.json", m_board.characters())); auto* job = request.schedule(); diff --git a/Applications/ChanViewer/ThreadCatalogModel.h b/Applications/ChanViewer/ThreadCatalogModel.h index d39c232d06..a2b03cddde 100644 --- a/Applications/ChanViewer/ThreadCatalogModel.h +++ b/Applications/ChanViewer/ThreadCatalogModel.h @@ -25,8 +25,11 @@ public: virtual GVariant data(const GModelIndex&, Role = Role::Display) const override; virtual void update() override; + void set_board(const String&); + private: ThreadCatalogModel(); + String m_board { "g" }; JsonArray m_catalog; }; diff --git a/Applications/ChanViewer/main.cpp b/Applications/ChanViewer/main.cpp index fe4a8bf422..851903e7eb 100644 --- a/Applications/ChanViewer/main.cpp +++ b/Applications/ChanViewer/main.cpp @@ -1,7 +1,9 @@ +#include "BoardListModel.h" #include "ThreadCatalogModel.h" #include #include #include +#include #include #include @@ -16,11 +18,24 @@ int main(int argc, char** argv) auto* widget = new GWidget; window->set_main_widget(widget); + widget->set_fill_with_background_color(true); widget->set_layout(make(Orientation::Vertical)); + auto* board_combo = new GComboBox(widget); + board_combo->set_only_allow_values_from_model(true); + board_combo->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); + board_combo->set_preferred_size(0, 20); + board_combo->set_model(BoardListModel::create()); + auto* catalog_view = new GTableView(widget); catalog_view->set_model(ThreadCatalogModel::create()); + board_combo->on_change = [&] (auto&, const GModelIndex& index) { + auto selected_board = board_combo->model()->data(index, GModel::Role::Custom); + ASSERT(selected_board.is_string()); + static_cast(catalog_view->model())->set_board(selected_board.to_string()); + }; + window->show(); return app.exec(); -- cgit v1.2.3