mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-03 18:19:38 -06:00
Implement save to CSV (without validation)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user