#include #include #include #include "../file.h" #include "../logcat_entry.h" #include "export.h" enum class ExportAmount : int { All, Filtered, }; static inline void export_logcat_entries(const LogcatEntries& logcat_entries, ExportAmount export_amount, bool export_buffers, File& file); static inline void export_logcat_entries_to_clipboard(const LogcatEntries& logcat_entries, ExportAmount export_amount, bool export_buffers); static void export_logcat_entries(const LogcatEntries& logcat_entries, ExportAmount export_amount, bool export_buffers, auto cb); static inline std::optional save_file_picker(); void export_fragment(const LogcatEntries& logcat_entries) { static ExportAmount export_amount = ExportAmount::Filtered; static bool export_buffers = true; ImGui::RadioButton("Export all entries", reinterpret_cast(&export_amount), static_cast(ExportAmount::All)); ImGui::RadioButton("Export filtered entries", reinterpret_cast(&export_amount), static_cast(ExportAmount::Filtered)); ImGui::Checkbox("Export buffers", &export_buffers); ImGui::Separator(); if (ImGui::Button("Export to File")) { std::optional file = save_file_picker(); if (file) { ImGui::CloseCurrentPopup(); try { export_logcat_entries(logcat_entries, export_amount, export_buffers, *file); } catch (const std::exception& e) { log(std::string("Failed to export logcat entries: ") + e.what()); } } } ImGui::SameLine(); if (ImGui::Button("Export to Clipboard")) { ImGui::CloseCurrentPopup(); try { export_logcat_entries_to_clipboard(logcat_entries, export_amount, export_buffers); } catch (const std::exception& e) { log(std::string("Failed to export logcat entries: ") + e.what()); } } } static inline void export_logcat_entries(const LogcatEntries& logcat_entries, ExportAmount export_amount, bool export_buffers, File& file) { export_logcat_entries(logcat_entries, export_amount, export_buffers, [&](std::string line) { file.write(std::move(line)); file.write("\n", 1); }); } static inline void export_logcat_entries_to_clipboard(const LogcatEntries& logcat_entries, ExportAmount export_amount, bool export_buffers) { std::string text; export_logcat_entries(logcat_entries, export_amount, export_buffers, [&](std::string line) { text += std::move(line); text += '\n'; }); ImGui::SetClipboardText(text.c_str()); } static void export_logcat_entries(const LogcatEntries& logcat_entries, ExportAmount export_amount, bool export_buffers, auto cb) { size_t size; const LogcatEntry& (LogcatEntries::*get_fn)(size_t) const; unsigned int buffers_printed = 0; std::optional last_buffer; switch (export_amount) { case ExportAmount::All: size = logcat_entries.size_all(); get_fn = &LogcatEntries::at_all; break; case ExportAmount::Filtered: size = logcat_entries.size_filtered(); get_fn = &LogcatEntries::at_filtered; break; } for (size_t i = 0; i < size; i++) { const LogcatEntry& entry = (logcat_entries.*get_fn)(i); if (export_buffers && (!last_buffer || *last_buffer != entry.buffer)) { const char* prefix = buffers_printed & static_cast(entry.buffer) ? "switch to" : "beginning of"; cb(std::string("--------- ") + prefix + ' ' + to_string_lower(entry.buffer)); buffers_printed |= static_cast(entry.buffer); last_buffer = entry.buffer; } cb(to_string(entry)); } } static inline std::optional save_file_picker() { nfdchar_t* path; nfdfilteritem_t filters[1] = {{"Log file", "log"}}; nfdresult_t res = NFD_SaveDialog(&path, filters, 1, nullptr, "logcat.log"); if (res == NFD_OKAY) { try { File file(path, "w"); NFD_FreePath(path); return file; } catch (const std::exception& e) { NFD_FreePath(path); log(std::string("Failed to open file from file picker: ") + e.what()); } } else if (res == NFD_CANCEL) { // dialog was canceled, shrug } else { // ignore error when failing to open the file picker } return std::nullopt; }