From 1f6c21080da3f591461bc5399693281e436d3a3b Mon Sep 17 00:00:00 2001 From: Suraj Yadav Date: Tue, 9 Jul 2024 19:08:22 +0000 Subject: [PATCH] Changes for linux build (#13) * Changes for Building on fedora * Added build step for linux * Added build step for linux * Added build step for linux * Added build step for linux * Changes for Building on fedora * Github Action Changes * Test release * Test release * Reset release --- .github/workflows/ci.yml | 44 +++++------ .github/workflows/setup/action.yaml | 25 +++++++ .vscode/launch.json | 16 ---- CMakeLists.txt | 109 +++++++++++++++------------- include/comic_gallery.hpp | 3 +- include/comic_viewer.hpp | 1 + include/image_utils.hpp | 2 + src/archive.cpp | 5 +- src/comic.cpp | 12 +-- src/comic_gallery.cpp | 32 +++++--- src/comic_viewer.cpp | 11 ++- src/image_utils.cpp | 8 ++ src/main.cpp | 21 +++--- 13 files changed, 171 insertions(+), 118 deletions(-) create mode 100644 .github/workflows/setup/action.yaml delete mode 100644 .vscode/launch.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c6ffad..1ba76cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,9 @@ on: - '!master' tags: - '**' # matches every tag +defaults: + run: + shell: bash jobs: build-windows: env: @@ -16,38 +19,37 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 - - uses: actions/github-script@v6 + - uses: './.github/workflows/setup' with: - script: | - core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); - core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); - - name: Setup OpenCppCoverage and add to PATH - id: setup_opencppcoverage - run: | - choco install OpenCppCoverage -y - echo "C:\Program Files\OpenCppCoverage" >> $env:GITHUB_PATH - - name: cmake configure - run: | - $env:CMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" - cmake -B build -S . - - name: cmake test - run: cmake --build build --target coverage - - name: cmake build - run: cmake --build build --target package --config Release - - uses: actions/upload-artifact@v3 - if: startsWith(github.ref, 'refs/tags/v') + zip-output: windows-zip + build-linux: + env: + VCPKG_DEFAULT_TRIPLET: x64-linux + VCPKG_BINARY_SOURCES: clear;x-gha,readwrite + runs-on: ubuntu-latest + steps: + - name: Install wxWidgets + run: sudo apt update && sudo apt install -y x11-xserver-utils libxi-dev libxtst-dev python3-jinja2 libxrandr-dev + - uses: actions/checkout@v3 with: - name: windows-zip - path: build/comic_reader-*.zip + fetch-depth: 0 + - uses: './.github/workflows/setup' + with: + zip-output: linux-zip + create-release: if: startsWith(github.ref, 'refs/tags/v') needs: - build-windows + - build-linux runs-on: macos-latest steps: - uses: actions/download-artifact@v3 with: name: windows-zip + - uses: actions/download-artifact@v3 + with: + name: linux-zip - run: ls - uses: marvinpinto/action-automatic-releases@latest with: diff --git a/.github/workflows/setup/action.yaml b/.github/workflows/setup/action.yaml new file mode 100644 index 0000000..e7fae08 --- /dev/null +++ b/.github/workflows/setup/action.yaml @@ -0,0 +1,25 @@ +name: 'Build' +inputs: + zip-output: + required: true +runs: + using: "composite" + steps: + - uses: actions/github-script@v6 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + - name: cmake configure + shell: bash + run: | + export CMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake + cmake -B build -S . || cat build/vcpkg_installed/vcpkg/issue_body.md + - name: cmake build + shell: bash + run: cmake --build build --target package --config Release + - uses: actions/upload-artifact@v3 + if: startsWith(github.ref, 'refs/tags/v') + with: + name: ${{ inputs.zip-output }} + path: build/comic_reader-*.zip diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index ac269f3..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "(Windows) Launch", - "type": "cppvsdbg", - "request": "launch", - "program": "${workspaceFolder}/build/comic_reader", - "cwd": "${workspaceFolder}", - "preLaunchTask": "Build" - } - ] -} diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cba932..7b0f8f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,80 +6,87 @@ parse_git_tag() project(comic_reader LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") +set(CMAKE_EXPORT_COMPILE_COMMANDS + ON + CACHE INTERNAL "") find_package(LibArchive REQUIRED) find_package(Tweeny CONFIG REQUIRED) find_package(WebP CONFIG REQUIRED) find_package(wxWidgets CONFIG REQUIRED) -add_library(common_lib STATIC - src/archive.cpp - src/comic_gallery.cpp - src/comic_viewer.cpp - src/comic.cpp - src/fuzzy.cpp - src/image_utils.cpp - src/viewport.cpp - src/wxUtil.cpp -) -target_link_libraries(common_lib PUBLIC - LibArchive::LibArchive - tweeny - WebP::webp - wx::core -) +add_library( + common_lib STATIC + src/archive.cpp + src/comic_gallery.cpp + src/comic_viewer.cpp + src/comic.cpp + src/fuzzy.cpp + src/image_utils.cpp + src/viewport.cpp + src/wxUtil.cpp) + +target_link_libraries(common_lib PUBLIC LibArchive::LibArchive tweeny + WebP::webp wx::core) + target_include_directories(common_lib PUBLIC "${CMAKE_SOURCE_DIR}/include") add_executable(comic_reader WIN32 src/main.cpp) target_link_libraries(comic_reader PRIVATE common_lib) if(MSVC) - add_definitions(-D_CRT_SECURE_NO_WARNINGS) - target_sources(comic_reader PRIVATE resource/main.rc resource/main.manifest) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + target_sources(comic_reader PRIVATE resource/main.rc resource/main.manifest) endif() -if(MSVC) - set(CPACK_GENERATOR "ZIP") - install(TARGETS comic_reader - RUNTIME_DEPENDENCIES - PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-" "hvsifiletrust" "pdmutilities" - POST_EXCLUDE_REGEXES ".*system32/.*\\.dll" - RUNTIME DESTINATION . - ) - set(CPACK_PACKAGE_VERSION ${VERSION_STRING}) - include(CPack) -endif() +set(CPACK_GENERATOR "ZIP") +install( + TARGETS comic_reader + RUNTIME_DEPENDENCIES + PRE_EXCLUDE_REGEXES + "api-ms-" + "ext-ms-" + "hvsifiletrust" + "pdmutilities" + POST_EXCLUDE_REGEXES + ".*system32/.*\\.dll" + RUNTIME DESTINATION .) +set(CPACK_PACKAGE_VERSION ${VERSION_STRING}) +include(CPack) # Setup Test, coverage and benchmarks find_package(benchmark CONFIG REQUIRED) find_package(GTest CONFIG REQUIRED) -SET(TEST_SRCS - src/archive_test.cpp - src/comic_test.cpp - src/fuzzy_test.cpp - src/lru_test.cpp -) +set(TEST_SRCS src/archive_test.cpp src/comic_test.cpp src/fuzzy_test.cpp + src/lru_test.cpp) add_executable(tests ${TEST_SRCS}) -target_link_libraries(tests PRIVATE - common_lib GTest::gtest benchmark::benchmark GTest::gtest_main) +target_link_libraries(tests PRIVATE common_lib GTest::gtest + benchmark::benchmark GTest::gtest_main) add_executable(benchmarks ${TEST_SRCS}) -target_link_libraries(benchmarks PRIVATE - common_lib GTest::gtest benchmark::benchmark benchmark::benchmark_main) +target_link_libraries( + benchmarks PRIVATE common_lib GTest::gtest benchmark::benchmark + benchmark::benchmark_main) if(MSVC) - add_custom_target( - coverage - OpenCppCoverage - -q --export_type cobertura:${CMAKE_BINARY_DIR}/cov.xml - --sources $ - --sources $ - --modules $ - --cover_children -- $ --gtest_output=xml:${CMAKE_BINARY_DIR}/test.xml - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - DEPENDS tests - ) + add_custom_target( + coverage + OpenCppCoverage + -q + --export_type + cobertura:${CMAKE_BINARY_DIR}/cov.xml + --sources + $ + --sources + $ + --modules + $ + --cover_children + -- + $ + --gtest_output=xml:${CMAKE_BINARY_DIR}/test.xml + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + DEPENDS tests) endif() diff --git a/include/comic_gallery.hpp b/include/comic_gallery.hpp index c86ed41..6f1b8bd 100644 --- a/include/comic_gallery.hpp +++ b/include/comic_gallery.hpp @@ -24,7 +24,7 @@ class ComicGallery : public wxPanel { void OnComicAddition(wxCommandEvent& evt); void OnPaint(wxPaintEvent& evt); void OnSize(wxSizeEvent& event); - void AddComic(std::filesystem::path path); + bool AddComic(std::filesystem::path path); void verify(const wxGraphicsContext* g, int index); @@ -35,4 +35,5 @@ class ComicGallery : public wxPanel { void loadComics(std::vector paths); void HandleInput(Navigation input, char ch = ' '); Comic& currentComic() { return comics[index]; } + int length() const; }; diff --git a/include/comic_viewer.hpp b/include/comic_viewer.hpp index 5f3ba03..3baa90d 100644 --- a/include/comic_viewer.hpp +++ b/include/comic_viewer.hpp @@ -50,6 +50,7 @@ class ComicViewer : public wxPanel { void OnLeftUp(wxMouseEvent&); void OnSize(wxSizeEvent&); void OnCaptureLost(wxMouseCaptureLostEvent&); + void OnClose(wxCloseEvent&); void StartPan(const wxPoint2DDouble&, PanSource); void ProcessPan(const wxPoint2DDouble&, bool, PanSource); diff --git a/include/image_utils.hpp b/include/image_utils.hpp index cf4c041..b323e3f 100644 --- a/include/image_utils.hpp +++ b/include/image_utils.hpp @@ -25,4 +25,6 @@ class ImagePool { bool addImage(const std::filesystem::path& filepath); const wxSize size(int index); const wxBitmap& bitmap(int index); + auto empty() const { return paths.empty() || bitmaps.empty(); } + void clear(); }; diff --git a/src/archive.cpp b/src/archive.cpp index 187ce2b..8c41e60 100644 --- a/src/archive.cpp +++ b/src/archive.cpp @@ -14,8 +14,9 @@ ArchiveFile::ArchiveFile(struct archive* ap, archive_entry* e) : archivePtr(ap), entry(e) {} std::filesystem::path ArchiveFile::path() const { - return std::filesystem::path(archive_entry_pathname(entry)) - .make_preferred(); + auto p = archive_entry_pathname(entry); + if (p == nullptr) { return ""; } + return std::filesystem::path(p).make_preferred(); } int64_t ArchiveFile::size() const { return archive_entry_size(entry); } diff --git a/src/comic.cpp b/src/comic.cpp index fe2ff39..7070100 100644 --- a/src/comic.cpp +++ b/src/comic.cpp @@ -8,10 +8,12 @@ #include "image_utils.hpp" #include "util.hpp" -const int THUMB_DIM = (std::min)( - wxSystemSettings::GetMetric(wxSYS_SCREEN_X), - wxSystemSettings::GetMetric(wxSYS_SCREEN_Y)); - +int GET_THUMB_DIM() { + const static int THUMB_DIM = (std::min)( + wxSystemSettings::GetMetric(wxSYS_SCREEN_X), + wxSystemSettings::GetMetric(wxSYS_SCREEN_Y)); + return THUMB_DIM; +} const std::filesystem::path cacheDirectory = std::filesystem::temp_directory_path() / "comicReaderCache"; @@ -39,7 +41,7 @@ Comic::Comic(const std::filesystem::path& comicPath) coverPage = getCoverPath(comicPath, fullPath); file.writeContent(coverPage); }); - saveThumbnail(coverPage, coverPage, THUMB_DIM); + saveThumbnail(coverPage, coverPage, GET_THUMB_DIM()); } int Comic::length() const { return size; }; diff --git a/src/comic_gallery.cpp b/src/comic_gallery.cpp index fce601f..ae1dff6 100644 --- a/src/comic_gallery.cpp +++ b/src/comic_gallery.cpp @@ -26,7 +26,7 @@ ComicGallery::ComicGallery( GALLERY_UPDATE_ID); SetBackgroundStyle(wxBG_STYLE_PAINT); - SetBackgroundColour(wxColour(25, 25, 25, 1)); + SetBackgroundColour(wxColour(25, 25, 25)); loadComics(paths); } @@ -40,10 +40,14 @@ ComicGallery::~ComicGallery() { } } -void ComicGallery::AddComic(std::filesystem::path path) { +bool ComicGallery::AddComic(std::filesystem::path path) { Comic c(path); - pool.addImage(c.coverPage); - comics.push_back(c); + if (c.length() > 0) { + pool.addImage(c.coverPage); + comics.push_back(c); + return true; + } + return false; } void ComicGallery::loadComics(std::vector paths) { @@ -54,18 +58,22 @@ void ComicGallery::loadComics(std::vector paths) { paths.erase(std::unique(paths.begin(), paths.end()), paths.end()); comics.reserve(paths.size()); - AddComic(paths.front()); + auto offset = 0u; + for (; offset < paths.size(); ++offset) { + if (AddComic(paths[offset])) { break; } + } workInBackground.store(false); if (!paths.empty()) { workInBackground.store(true); - loader = std::async([paths, this]() { - for (auto i = 1u; i < paths.size(); ++i) { + loader = std::async([paths, offset, this]() { + for (auto i = offset + 1; i < paths.size(); ++i) { if (!workInBackground.load()) { return; } - AddComic(paths[i]); - GetEventHandler()->AddPendingEvent(wxCommandEvent( - wxEVT_COMMAND_TEXT_UPDATED, GALLERY_UPDATE_ID)); + if (AddComic(paths[i])) { + GetEventHandler()->AddPendingEvent(wxCommandEvent( + wxEVT_COMMAND_TEXT_UPDATED, GALLERY_UPDATE_ID)); + }; } workInBackground.store(false); }); @@ -90,7 +98,7 @@ void ComicGallery::OnPaint(wxPaintEvent& event) { dc.Clear(); // direct2d renderer - wxGraphicsRenderer* d2dr = wxGraphicsRenderer::GetDirect2DRenderer(); + wxGraphicsRenderer* d2dr = wxGraphicsRenderer::GetDefaultRenderer(); wxGraphicsContext* gc = d2dr->CreateContext(dc); if (gc) { @@ -237,3 +245,5 @@ void ComicGallery::HandleInput(Navigation input, char ch) { }); } } + +int ComicGallery::length() const { return comics.size(); }; diff --git a/src/comic_viewer.cpp b/src/comic_viewer.cpp index 5433de6..ac6a78d 100644 --- a/src/comic_viewer.cpp +++ b/src/comic_viewer.cpp @@ -15,8 +15,9 @@ ComicViewer::ComicViewer(wxWindow* parent, Comic& comic) Bind(wxEVT_LEFT_DOWN, &ComicViewer::OnLeftDown, this); Bind(wxEVT_LEFT_DCLICK, &ComicViewer::OnLeftDClick, this); Bind(wxEVT_SIZE, &ComicViewer::OnSize, this); + Bind(wxEVT_CLOSE_WINDOW, &ComicViewer::OnClose, this); SetBackgroundStyle(wxBG_STYLE_PAINT); - SetBackgroundColour(wxColour(25, 25, 25, 1)); + SetBackgroundColour(wxColour(25, 25, 25)); } void ComicViewer::load() { @@ -26,19 +27,25 @@ void ComicViewer::load() { for (auto& page : comic.pages) { pool.addImage(page); } } +void ComicViewer::OnClose(wxCloseEvent& event) { + comic.unload(); + pool.clear(); +} + bool ComicViewer::verify(const wxGraphicsContext* gc, int i) { if (i < 0 || i >= comic.length()) { return false; } return true; } void ComicViewer::OnPaint(wxPaintEvent& event) { + if (pool.empty()) { return; } if (comic.pages.empty()) { return; } wxAutoBufferedPaintDC dc(this); dc.Clear(); // direct2d renderer - wxGraphicsRenderer* d2dr = wxGraphicsRenderer::GetDirect2DRenderer(); + wxGraphicsRenderer* d2dr = wxGraphicsRenderer::GetDefaultRenderer(); wxGraphicsContext* gc = d2dr->CreateContext(dc); if (gc) { diff --git a/src/image_utils.cpp b/src/image_utils.cpp index ffe4177..dae1563 100644 --- a/src/image_utils.cpp +++ b/src/image_utils.cpp @@ -49,6 +49,7 @@ wxImage load(const std::filesystem::path& file) { bool saveThumbnail( const std::filesystem::path& src, const std::filesystem::path& dest, const int MAX_DIM) { + if (!std::filesystem::exists(src)) { return false; } auto img = load(src); int W = MAX_DIM, H = MAX_DIM; @@ -104,3 +105,10 @@ const wxBitmap& ImagePool::bitmap(int index) { load(index); return bitmaps[index]; } + +void ImagePool::clear() { + int size = static_cast(bitmaps.size()); + for (int i = 0; i < size; i++) { unload(i); } + paths.clear(); + bitmaps.clear(); +} diff --git a/src/main.cpp b/src/main.cpp index 610907a..f19b123 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,9 +21,9 @@ class MyApp : public wxApp { wxIMPLEMENT_APP(MyApp); class MyFrame : public wxFrame { - ComicGallery* comicGallery; - ComicViewer* comicViewer; - wxSizer* sizer; + ComicGallery* comicGallery = nullptr; + ComicViewer* comicViewer = nullptr; + wxSizer* sizer = nullptr; void OnKeyDown(wxKeyEvent& event); @@ -43,17 +43,16 @@ bool MyApp::OnInit() { ::wxInitAllImageHandlers(); auto frame = new MyFrame(); +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) frame->SetIcon(wxICON(app_icon)); +#endif frame->Show(true); frame->LoadComic(); frame->SetTitle(DEFAULT_FRAME_TITLE); return true; } -MyFrame::MyFrame() - : wxFrame(nullptr, wxID_ANY, ""), - comicGallery(nullptr), - comicViewer(nullptr) { +MyFrame::MyFrame() : wxFrame(nullptr, wxID_ANY, "") { Bind(wxEVT_CHAR_HOOK, &MyFrame::OnKeyDown, this); } @@ -69,7 +68,7 @@ void MyFrame::OnKeyDown(wxKeyEvent& event) { case WXK_ESCAPE: sizer->Remove(1); sizer->Show(size_t(0)); - comicViewer->Destroy(); + comicViewer->Close(); comicViewer = nullptr; comicGallery->currentComic().unload(); Layout(); @@ -96,7 +95,7 @@ void MyFrame::OnKeyDown(wxKeyEvent& event) { new ComicViewer(this, comicGallery->currentComic()); comicViewer->load(); } catch (const std::exception& e) { - comicViewer->Destroy(); + comicViewer->Close(); comicViewer = nullptr; wxMessageBox(e.what(), "Error while opening comic"); return; @@ -137,6 +136,10 @@ void MyFrame::LoadComic() { sizer = new wxBoxSizer(wxVERTICAL); comicGallery = new ComicGallery(this, paths); + if (comicGallery->length() == 0) { + wxMessageBox("No Valid Comic file found"); + Close(); + } sizer->Add(comicGallery, wxSizerFlags(1).Expand()); SetSizer(sizer);