Implement save to CSV (without validation)

This commit is contained in:
Emma Broman
2024-09-06 11:09:51 +02:00
parent ed1b3f61ae
commit 4e4f688868
4 changed files with 175 additions and 1 deletions

View File

@@ -46,6 +46,7 @@
#include <limits>
#include <string>
#include <string_view>
#include <variant>
namespace {
constexpr std::string_view _loggerCat = "ExoplanetsDataLoader";
@@ -461,4 +462,49 @@ std::vector<ExoplanetItem> DataLoader::loadData(const DataSettings& settings) {
return planets;
}
void DataLoader::saveData(const std::filesystem::path& targetPath,
const std::vector<ExoplanetItem>& allItems,
const std::vector<size_t>& indices,
const std::vector<ColumnKey>& columns)
{
// TODO: verify csv ending
std::fstream f(targetPath, std::ios::out);
if (!f.is_open()) {
LERROR(std::format("Failed writing data to file: '{}'", targetPath));
return;
}
if (!columns.empty()) {
f << ghoul::join(columns, ",") << std::endl;
}
else {
std::string line;
for (auto [key, _] : allItems.front().dataColumns) {
line += key + ",";
}
f << line.substr(0, line.size() - 1) << std::endl;
}
for (const size_t& i : indices) {
const ExoplanetItem& item = allItems[i];
std::string line;
for (auto [_, value] : item.dataColumns) {
if (std::holds_alternative<float>(value)) {
float v = std::get<float>(value);
line += std::isnan(v) ? "" : ghoul::to_string(v);
}
else {
line += std::get<std::string>(value);
}
line += ",";
}
f << line.substr(0, line.size() - 1) << std::endl;
}
// TODO: handle indices empty
}
} // namespace openspace::exoplanets

View File

@@ -37,6 +37,20 @@ public:
static DataSettings loadDataSettingsFromJson();
static std::vector<ExoplanetItem> loadData(const DataSettings& settings);
/**
* Save data to a CSV file.
*
* \param targetPath the filepath for where to save the dataset
* \param allItems the list of data items in the loaded dataset
* \param indices the indices which to save. If empty, save all
* \param columns the list of names for the columns to save in the dataset.
* If empty, save all
*/
static void saveData(const std::filesystem::path& targetPath,
const std::vector<ExoplanetItem>& allItems,
const std::vector<size_t>& indices = {},
const std::vector<ColumnKey>& columns = {});
};
} // namespace openspace::exoplanets

View File

@@ -526,6 +526,8 @@ void DataViewer::render() {
handleDoubleClickHoveredPlanet(hoveredPlanet);
if (ImGui::BeginMainMenuBar()) {
renderFileMenu();
if (ImGui::BeginMenu("Windows")) {
ImGui::MenuItem("Table", NULL, &showTable);
ImGui::MenuItem("Filters", NULL, &showFilterSettingsWindow);
@@ -689,7 +691,7 @@ void DataViewer::renderTableWindow(bool *open) {
// Search table
static char searchString[128] = "";
ImGui::InputTextWithHint(
ImGui::InputTextWithHint(
"##Query",
"Search for an item by name here...",
searchString,
@@ -1154,6 +1156,117 @@ void DataViewer::updateFilteredRowsProperty(std::optional<std::vector<size_t>> c
}
}
void DataViewer::renderFileMenu() {
static bool showSaveCsvModal = false;
// Menu
if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("New", NULL, false, false)) {
// TODO: Create a settings.json file
}
if (ImGui::MenuItem("Open", NULL, false, false)) {
// TODO: Menu to load a new data file from disk
}
ImGui::MenuItem("Save CSV", NULL, &showSaveCsvModal);
ImGui::SameLine();
view::helper::renderHelpMarker("Save the current filtered data items as a CSV file");
if (ImGui::MenuItem("Save filters", NULL, false, false)) {
// TODO: Menu to save the current set of filters.
// To a settings .json file? Or a completely new file format?
}
ImGui::EndMenu();
}
// Modals for view
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_HorizontalScrollbar;
if (showSaveCsvModal) {
ImGui::OpenPopup("Save CSV");
if (ImGui::BeginPopupModal("Save CSV", NULL, flags)) {
ImGui::Text("Save the currently selected filtering to a CSV file.");
static char name[128] = "";
ImGui::InputText(
"Filename (.csv)",
name,
IM_ARRAYSIZE(name)
);
const char* defaultDir = absPath(
"${MODULE_EXOPLANETSEXPERTTOOL}/data"
).string().c_str();
const float dirTextWidth = ImGui::CalcTextSize(defaultDir).x;
ImGui::SetNextItemWidth(dirTextWidth * 1.3f);
static char dir[256] = "";
ImGui::InputTextWithHint(
"Directory",
defaultDir,
dir,
IM_ARRAYSIZE(dir)
);
static bool incudeAllColumns = true;
ImGui::Checkbox("Include all columns", &incudeAllColumns);
ImGui::SameLine();
view::helper::renderHelpMarker(
"If checked, include all data column in the original data file. "
"Otherwise, only include the selected columns."
);
// TODO: Also add option to save filtering separately
view::helper::renderDescriptiveText(std::format(
"Will save {} rows with {} columns",
_filteredData.size(),
incudeAllColumns ? _data.front().dataColumns.size() :_columns.size()
).c_str());
ImGui::Separator();
// Cancel
ImGuiIO& io = ImGui::GetIO();
if (ImGui::Button("Cancel") ||
ImGui::IsKeyPressed(io.KeyMap[ImGuiKey_Escape]))
{
ImGui::CloseCurrentPopup();
showSaveCsvModal = false;
}
ImGui::SameLine();
// Save
if (ImGui::Button("Save") ||
ImGui::IsKeyPressed(io.KeyMap[ImGuiKey_Enter]))
{
std::filesystem::path fileName = std::filesystem::path(name);
std::filesystem::path directory = std::filesystem::path(dir);
if (directory.empty()) {
directory = std::filesystem::path(defaultDir);
}
if (!fileName.has_extension()) {
fileName.replace_extension("csv");
}
std::filesystem::path path = directory / fileName;
DataLoader::saveData(
path,
_data,
_filteredData,
!incudeAllColumns ? _columns : std::vector<ColumnKey>()
);
ImGui::CloseCurrentPopup();
showSaveCsvModal = false;
}
ImGui::SetItemDefaultFocus();
ImGui::EndPopup();
}
}
}
void DataViewer::renderSettingsMenuContent() {
// OBS! These should match the default settings for the SGNs
static bool useFixedWidth = false;

View File

@@ -123,6 +123,7 @@ private:
void renderPlanetTooltip(int index) const;
void handleDoubleClickHoveredPlanet(int index);
void renderFileMenu();
void renderSettingsMenuContent();
// Write the information about the rendered points to a file