7#include "catalogcsvimport.h"
9#include "ui_catalogcsvimport.h"
22const std::vector<std::pair<QString, std::tuple<QString, QString, bool>>> fields{
23 {
"Type", {
"",
"",
true } },
24 {
"Right Ascension", {
"",
"",
false } },
25 {
"Declination", {
"",
"",
false } },
26 {
"Magnitude", {
"",
"",
false } },
27 {
"Name", {
"",
"",
false } },
28 {
"Long Name", {
"",
"",
true } },
29 {
"Identifier", {
"",
"",
true } },
30 {
"Major Axis", {
"",
"arcmin",
true } },
31 {
"Minor Axis", {
"",
"arcmin",
true } },
32 {
"Position Angle", {
"",
"°",
true } },
33 {
"Flux", {
"",
"",
true } },
42 for (
int i = 0; i < SkyObject::TYPE::NUMBER_OF_KNOWN_TYPES; i++)
48 pLayout->addWidget(pCombo);
49 pWidget->setLayout(pLayout);
54CatalogCSVImport::CatalogCSVImport(
QWidget *parent)
55 :
QDialog(parent), ui(new Ui::CatalogCSVImport)
60 ui->separator->setText(
QString(default_separator));
61 ui->comment_prefix->setText(
QString(default_comment));
63 ui->preview->setModel(&m_preview_model);
64 ui->preview->horizontalHeader()->setSectionResizeMode(
65 QHeaderView::ResizeMode::Stretch);
68 &CatalogCSVImport::select_file);
71 &CatalogCSVImport::type_table_add_map);
74 &CatalogCSVImport::read_objects);
77 &CatalogCSVImport::type_table_remove_map);
80 read_n_objects(default_preview_size);
81 m_preview_model.setObjects(m_objects);
84 init_column_mapping();
87 for (
auto *box : { ui->ra_units, ui->dec_units })
89 box->addItem(
i18n(
"Degrees"));
90 box->addItem(
i18n(
"Hours"));
94CatalogCSVImport::~CatalogCSVImport()
99void CatalogCSVImport::select_file()
102 QString(
"CSV") +
i18n(
"File") + QString(
" (*.csv);;") +
103 i18n(
"Any File") + QString(
" (*);;"));
105 dialog.setDefaultSuffix(
"csv");
110 const auto &fileName = dialog.selectedUrls().value(0).toLocalFile();
116 i18n(
"Could not open the csv file.<br>It does not exist."));
121 if (ui->separator->text().length() < 1)
123 ui->separator->setText(QString(default_separator));
126 if (ui->comment_prefix->text().length() < 1)
128 ui->separator->setText(QString(default_separator));
131 const auto &separator = ui->separator->text();
132 const auto &comment_prefix = ui->comment_prefix->text();
134 ui->file_path_label->setText(fileName);
136 m_doc.Load(fileName.toStdString(), rapidcsv::LabelParams(),
137 rapidcsv::SeparatorParams(separator[0].toLatin1(),
true),
138 rapidcsv::ConverterParams(
false),
139 rapidcsv::LineReaderParams(
true, comment_prefix[0].toLatin1()));
141 init_mapping_selectors();
144void CatalogCSVImport::reset_mapping()
146 ui->column_mapping->setEnabled(
false);
147 ui->preview_button->setEnabled(
false);
148 ui->obj_count->setEnabled(
false);
150 ui->buttonBox->buttons()[0]->setEnabled(
false);
153void CatalogCSVImport::init_mapping_selectors()
155 const auto &columns = m_doc.GetColumnNames();
157 for (
const auto &field : fields)
159 const auto can_be_ignored = std::get<2>(field.second);
160 auto *selector = m_selectors[field.first];
164 selector->setMaxCount(columns.size() + (can_be_ignored ? 0 : 1));
167 selector->addItem(
i18n(
"Ignore"), -2);
170 for (
const auto &col : columns)
171 selector->addItem(col.c_str(), i++);
174 ui->column_mapping->setEnabled(
true);
175 ui->buttonBox->buttons()[0]->setEnabled(
true);
176 ui->obj_count->setEnabled(
true);
177 ui->preview_button->setEnabled(
true);
178 ui->obj_count->setText(
i18np(
"%1 Object",
"%1 Objects", m_doc.GetRowCount()));
181void CatalogCSVImport::init_type_table()
183 auto *
const table = ui->type_table;
184 table->setHorizontalHeaderLabels(QStringList() <<
i18n(
"Text") <<
i18n(
"Type"));
186 table->setColumnCount(2);
187 table->setRowCount(1);
188 auto *item =
new QTableWidgetItem{
i18n(
"default") };
190 table->setItem(0, 0, item);
192 table->setCellWidget(0, 1, type_selector_widget());
193 table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::Stretch);
196void CatalogCSVImport::type_table_add_map()
198 auto *
const table = ui->type_table;
199 const auto cur_row = table->rowCount();
201 table->setRowCount(cur_row + 1);
202 table->setItem(cur_row, 0,
new QTableWidgetItem{
"" });
203 table->setCellWidget(cur_row, 1, type_selector_widget());
206void CatalogCSVImport::type_table_remove_map()
208 auto *
const table = ui->type_table;
210 for (
const auto *item : table->selectedItems())
212 const auto row = item->row();
214 table->removeRow(row);
218CatalogCSVImport::type_map CatalogCSVImport::get_type_mapping()
220 auto *
const table = ui->type_table;
223 for (
int i = 0; i <= table->rowCount(); i++)
225 const auto *key = table->item(i, 0);
226 const auto *
type = table->cellWidget(i, 1);
228 if (key ==
nullptr || type ==
nullptr)
232 dynamic_cast<QComboBox *
>(
type->layout()->itemAt(0)->widget())
240void CatalogCSVImport::init_column_mapping()
242 auto *cmapping =
new QFormLayout();
243 for (
const auto &field : fields)
246 const auto &tooltip = std::get<0>(field.second);
247 const auto &unit = std::get<1>(field.second);
249 if (unit.length() > 0)
250 name += QString(
" [%1]").
arg(unit);
252 auto *
label =
new QLabel(name);
253 label->setToolTip(tooltip);
255 auto *selector =
new QComboBox();
256 selector->setEditable(
true);
257 m_selectors[field.first] = selector;
259 cmapping->addRow(label, selector);
262 ui->column_mapping->setLayout(cmapping);
265CatalogCSVImport::column_map CatalogCSVImport::get_column_mapping()
267 CatalogCSVImport::column_map
map{};
268 const auto &names = m_doc.GetColumnNames();
270 for (
const auto &item : m_selectors)
273 const auto *selector = item.second;
274 auto selected_value = selector->currentData().
toInt();
277 if (selected_value >= 0 &&
278 (selector->currentText() != names[selected_value].c_str()))
281 val_string = selector->currentText();
288 map[
name] = { selected_value, val_string };
294void CatalogCSVImport::read_n_objects(
size_t n)
296 const auto &type_map = get_type_mapping();
297 const auto &column_map = get_column_mapping();
301 m_objects.reserve(std::min(m_doc.GetRowCount(), n));
304 const auto make_getter = [
this, &column_map](
const QString &field,
auto def) {
305 const auto &conf = column_map.at(field);
306 const auto &default_val = get_default(conf, def);
307 const auto index = conf.first;
309 std::function<
decltype(def)(
const size_t)> getter;
311 getter = [=](
const size_t row) {
314 return m_doc.GetCell<
decltype(def)>(index, row);
322 getter = [=](
const size_t) {
return default_val; };
327 const auto make_coord_getter = [
this, &column_map](
const QString &field,
auto def,
329 const auto &conf = column_map.at(field);
330 const auto default_val =
331 (unit == coord_unit::deg) ?
332 get_default<typed_dms<coord_unit::deg>>(column_map.at(field), { def })
334 get_default<typed_dms<coord_unit::hours>>(column_map.at(field), { def })
336 const auto index = conf.first;
338 std::function<
decltype(def)(
const size_t)> getter;
341 if (unit == coord_unit::deg)
342 getter = [=](
const size_t row) {
345 return m_doc.GetCell<typed_dms<coord_unit::deg>>(index, row).data;
353 getter = [=](
const size_t row) {
356 return m_doc.GetCell<typed_dms<coord_unit::hours>>(index, row)
366 getter = [=](
const size_t) {
return default_val; };
371 const auto ra_type =
static_cast<coord_unit
>(ui->ra_units->currentIndex());
372 const auto dec_type =
static_cast<coord_unit
>(ui->dec_units->currentIndex());
374 const auto get_ra = make_coord_getter(
"Right Ascension",
defaults.ra(), ra_type);
375 const auto get_dec = make_coord_getter(
"Declination",
defaults.dec(), dec_type);
376 const auto get_mag = make_getter(
"Magnitude",
defaults.mag());
377 const auto get_name = make_getter(
"Name",
defaults.name());
378 const auto get_type = make_getter(
"Type", std::string{
"default" });
379 const auto get_long_name = make_getter(
"Long Name",
defaults.name());
380 const auto get_identifier = make_getter(
"Identifier",
defaults.catalogIdentifier());
381 const auto get_a = make_getter(
"Major Axis",
defaults.a());
382 const auto get_b = make_getter(
"Minor Axis",
defaults.b());
383 const auto get_pa = make_getter(
"Position Angle",
defaults.pa());
384 const auto get_flux = make_getter(
"Flux",
defaults.flux());
386 for (
size_t i = 0; i < std::min(m_doc.GetRowCount(), n); i++)
388 const auto &raw_type = get_type(i);
390 const auto type = parse_type(raw_type, type_map);
392 const auto ra = get_ra(i);
393 const auto dec = get_dec(i);
394 const auto mag = get_mag(i);
395 const auto name = get_name(i);
396 const auto long_name = get_long_name(i);
397 const auto identifier = get_identifier(i);
398 const auto a = get_a(i);
399 const auto b = get_b(i);
400 const auto pa = get_pa(i);
401 const auto flux = get_flux(i);
403 m_objects.emplace_back(CatalogObject::oid{},
type, ra,
dec, mag,
name, long_name,
404 identifier, -1, a, b, pa, flux);
409 const type_map &type_map)
411 if (type_map.count(type) == 0)
412 return type_map.at(
"default");
414 return type_map.at(type);
static QString typeName(const int t)
TYPE
The type classification of the SkyObject.
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString name(GameStandardAction id)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
QString label(StandardShortcut id)
bool exists() const const
StandardButton warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
QString arg(Args &&... args) const const
QString first(qsizetype n) const const
int toInt(bool *ok, int base) const const
QTextStream & dec(QTextStream &stream)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setContentsMargins(const QMargins &margins)