• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

kstars

  • sources
  • kde-4.12
  • kdeedu
  • kstars
  • datahandlers
catalogdb.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  catalogDB.cpp - K Desktop Planetarium
3  -------------------
4  begin : 2012/03/08
5  copyright : (C) 2012 by Rishab Arora
6  email : ra.rishab@gmail.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "datahandlers/catalogdb.h"
19 #include "kstars/version.h"
20 
21 
22 bool CatalogDB::Initialize() {
23  skydb_ = QSqlDatabase::addDatabase("QSQLITE", "skydb");
24  QString dbfile = KStandardDirs::locateLocal("appdata",
25  QString("skycomponents.db"));
26  QFile testdb(dbfile);
27  bool first_run = false;
28  if (!testdb.exists()) {
29  kDebug()<< i18n("DSO DB does not exist!");
30  first_run = true;
31  }
32  skydb_.setDatabaseName(dbfile);
33  if (!skydb_.open()) {
34  kWarning() << i18n("Unable to open DSO database file!");
35  kWarning() << LastError();
36  } else {
37  kDebug() << i18n("Opened the DSO Database. Ready!");
38  if (first_run == true) {
39  FirstRun();
40  }
41  }
42  skydb_.close();
43  return true;
44 }
45 
46 void CatalogDB::FirstRun() {
47  kWarning() << i18n("Rebuilding Additional Sky Catalog Database");
48  QVector<QString> tables;
49  tables.append("CREATE TABLE Version ("
50  "Version CHAR DEFAULT NULL)");
51  tables.append("INSERT INTO Version VALUES (\"" KSTARS_VERSION "\")");
52  tables.append("CREATE TABLE ObjectDesignation ("
53  "id INTEGER NOT NULL DEFAULT NULL PRIMARY KEY,"
54  "id_Catalog INTEGER DEFAULT NULL REFERENCES Catalog (id),"
55  "UID_DSO INTEGER DEFAULT NULL REFERENCES DSO (UID),"
56  "LongName MEDIUMTEXT DEFAULT NULL,"
57  "IDNumber INTEGER DEFAULT NULL,"
58  "Trixel INTEGER NULL)");
59  // TODO(kstar): `Trixel` int(11) NOT NULL COMMENT 'Trixel Number'
60  // For Future safety
61 
62  tables.append("CREATE TABLE Catalog ("
63  "id INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT,"
64  "Name CHAR NOT NULL DEFAULT 'NULL',"
65  "Prefix CHAR DEFAULT 'NULL',"
66  "Color CHAR DEFAULT '#CC0000',"
67  "Epoch FLOAT DEFAULT 2000.0,"
68  "Author CHAR DEFAULT NULL,"
69  "License MEDIUMTEXT DEFAULT NULL,"
70  "FluxFreq CHAR DEFAULT 'NULL',"
71  "FluxUnit CHAR DEFAULT 'NULL')");
72 
73  tables.append("CREATE TABLE DSO ("
74  "UID INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT,"
75  "RA DOUBLE NOT NULL DEFAULT 0.0,"
76  "Dec DOUBLE DEFAULT 0.0,"
77  //"RA CHAR NOT NULL DEFAULT 'NULL',"
78  //"Dec CHAR NOT NULL DEFAULT 'NULL',"
79  "Type INTEGER DEFAULT NULL,"
80  "Magnitude DECIMAL DEFAULT NULL,"
81  "PositionAngle INTEGER DEFAULT NULL,"
82  "MajorAxis FLOAT NOT NULL DEFAULT NULL,"
83  "MinorAxis FLOAT DEFAULT NULL,"
84  "Flux FLOAT DEFAULT NULL,"
85  "Add1 VARCHAR DEFAULT NULL,"
86  "Add2 INTEGER DEFAULT NULL,"
87  "Add3 INTEGER DEFAULT NULL,"
88  "Add4 INTEGER DEFAULT NULL)");
89 
90  for (int i = 0; i < tables.count(); ++i) {
91  QSqlQuery query(skydb_);
92  if (!query.exec(tables[i])) {
93  kDebug() << query.lastError();
94  }
95  }
96  return;
97 }
98 
99 
100 CatalogDB::~CatalogDB() {
101  skydb_.close();
102 }
103 
104 
105 QSqlError CatalogDB::LastError() {
106  // error description is in QSqlError::text()
107  return skydb_.lastError();
108 }
109 
110 
111 QStringList* CatalogDB::Catalogs() {
112  RefreshCatalogList();
113  return &catalog_list_;
114 }
115 
116 
117 void CatalogDB::RefreshCatalogList() {
118  catalog_list_.clear();
119  skydb_.open();
120  QSqlTableModel catalog(0, skydb_);
121  catalog.setTable("Catalog");
122  catalog.select();
123 
124  for (int i = 0; i < catalog.rowCount(); ++i) {
125  QSqlRecord record = catalog.record(i);
126  QString name = record.value("Name").toString();
127  catalog_list_.append(name);
128 // QString author = record.value("Author").toString();
129 // QString license = record.value("License").toString();
130 // QString compiled_by = record.value("CompiledBy").toString();
131 // QString prefix = record.value("Prefix").toString();
132  }
133 
134  catalog.clear();
135  skydb_.close();
136 }
137 
138 
139 int CatalogDB::FindCatalog(const QString& catalog_name) {
140  skydb_.open();
141  QSqlTableModel catalog(0, skydb_);
142 
143  catalog.setTable("Catalog");
144  catalog.setFilter("Name LIKE \'" + catalog_name + "\'");
145  catalog.select();
146 
147  int catalog_count = catalog.rowCount();
148  QSqlRecord record = catalog.record(0);
149 
150  int returnval = -1;
151  if (catalog_count > 0)
152  returnval = record.value("id").toInt();
153 
154  catalog.clear();
155  skydb_.close();
156 
157  return returnval;
158 }
159 
160 
161 void CatalogDB::AddCatalog(const CatalogData& catalog_data) {
162  skydb_.open();
163  QSqlTableModel cat_entry(0, skydb_);
164  cat_entry.setTable("Catalog");
165 
166  int row = 0;
167  cat_entry.insertRows(row, 1);
168  // row(0) is autoincerement ID
169  cat_entry.setData(cat_entry.index(row, 1), catalog_data.catalog_name);
170  cat_entry.setData(cat_entry.index(row, 2), catalog_data.prefix);
171  cat_entry.setData(cat_entry.index(row, 3), catalog_data.color);
172  cat_entry.setData(cat_entry.index(row, 4), catalog_data.epoch);
173  cat_entry.setData(cat_entry.index(row, 5), catalog_data.author);
174  cat_entry.setData(cat_entry.index(row, 6), catalog_data.license);
175  cat_entry.setData(cat_entry.index(row, 7), catalog_data.fluxfreq);
176  cat_entry.setData(cat_entry.index(row, 8), catalog_data.fluxunit);
177 
178  cat_entry.submitAll();
179 
180  cat_entry.clear();
181  skydb_.close();
182 }
183 
184 void CatalogDB::RemoveCatalog(const QString& catalog_name) {
185  // Part 1 Clear DSO Entries
186  ClearDSOEntries(FindCatalog(catalog_name));
187 
188  skydb_.open();
189  QSqlTableModel catalog(0, skydb_);
190 
191  // Part 2 Clear Catalog Table
192  catalog.setTable("Catalog");
193  catalog.setFilter("Name LIKE \'" + catalog_name + "\'");
194  catalog.select();
195 
196  catalog.removeRows(0, catalog.rowCount());
197  catalog.submitAll();
198 
199  catalog.clear();
200  skydb_.close();
201 
202  RefreshCatalogList();
203 }
204 
205 void CatalogDB::ClearDSOEntries(int catalog_id) {
206  skydb_.open();
207 
208  QStringList del_query;
209 
210  // FIXME(spacetime): Only delete from DSO if removed from all Designations
211  // del_query.append("DELETE FROM DSO WHERE UID IN (SELECT UID_DSO FROM "
212  // "ObjectDesignation WHERE id_Catalog = " +
213  // QString::number(catalog_id) + ")");
214 
215  del_query.append("DELETE FROM ObjectDesignation WHERE id_Catalog = " +
216  QString::number(catalog_id));
217 
218  for (int i = 0; i < del_query.count(); ++i) {
219  QSqlQuery query(skydb_);
220  if (!query.exec(del_query[i])) {
221  kDebug() << query.lastError();
222  }
223  }
224 
225  skydb_.close();
226 }
227 
228 int CatalogDB::FindFuzzyEntry(const double ra, const double dec,
229  const double magnitude) {
230  /*
231  * FIXME (spacetime): Match the incoming entry with the ones from the db
232  * with certain fuzz. If found, store it in rowuid
233  * This Fuzz has not been established after due discussion
234  */
235  skydb_.open();
236  QSqlTableModel dsoentries(0, skydb_);
237 
238  QString filter =
239  "((RA - " + QString().setNum(ra) + ") between -0.0016 and 0.0016) and "
240  "((Dec - " + QString().setNum(dec) + ") between -0.0016 and 0.0016) and"
241  "((Magnitude - " + QString().setNum(magnitude) + ") between -0.1 and 0.1)";
242 // kDebug() << filter;
243  dsoentries.setTable("DSO");
244  dsoentries.setFilter(filter);
245  dsoentries.select();
246 
247  int entry_count = dsoentries.rowCount();
248  QSqlRecord record = dsoentries.record(0);
249 
250  int returnval = -1;
251  if (entry_count > 0)
252  returnval = record.value("UID").toInt();
253 
254  dsoentries.clear();
255  skydb_.close();
256 // kDebug() << returnval;
257  return returnval;
258 }
259 
260 
261 void CatalogDB::AddEntry(const CatalogEntryData& catalog_entry) {
262  // Verification step
263  // If RA, Dec are Null, it denotes an invalid object and should not be written
264 
265  if (catalog_entry.ra == KSParser::EBROKEN_DOUBLE ||
266  catalog_entry.ra == 0.0 ||
267  catalog_entry.dec == KSParser::EBROKEN_DOUBLE ||
268  catalog_entry.dec == 0.0) {
269  kDebug() << "Attempt to add incorrect ra & dec with ID:"
270  << catalog_entry.ID << " Long Name: "
271  << catalog_entry.long_name;
272  return;
273  }
274  // Part 1: Adding in DSO table
275  // I will not use QSQLTableModel as I need to execute a query to find
276  // out the lastInsertId
277 
278  // Part 2: Fuzzy Match or Create New Entry
279  int rowuid = FindFuzzyEntry(catalog_entry.ra, catalog_entry.dec,
280  catalog_entry.magnitude);
281  int catid;
282 
283  skydb_.open();
284  if ( rowuid == -1) { //i.e. No fuzzy match found. Proceed to add new entry
285  QSqlQuery add_query(skydb_);
286  add_query.prepare("INSERT INTO DSO (RA, Dec, Type, Magnitude, PositionAngle,"
287  " MajorAxis, MinorAxis, Flux) VALUES (:RA, :Dec, :Type,"
288  " :Magnitude, :PositionAngle, :MajorAxis, :MinorAxis,"
289  " :Flux)");
290  add_query.bindValue("RA", catalog_entry.ra);
291  add_query.bindValue("Dec", catalog_entry.dec);
292  add_query.bindValue("Type", catalog_entry.type);
293  add_query.bindValue("Magnitude", catalog_entry.magnitude);
294  add_query.bindValue("PositionAngle", catalog_entry.position_angle);
295  add_query.bindValue("MajorAxis", catalog_entry.major_axis);
296  add_query.bindValue("MinorAxis", catalog_entry.minor_axis);
297  add_query.bindValue("Flux", catalog_entry.flux);
298  if (!add_query.exec()) {
299  kWarning() << "Custom Catalog Insert Query FAILED!";
300  kWarning() << add_query.lastQuery();
301  }
302 
303  // Find UID of the Row just added
304  rowuid = add_query.lastInsertId().toInt();
305  add_query.clear();
306  }
307 
308  /* TODO(spacetime)
309  * Possible Bugs in QSQL Db with SQLite
310  * 1) Unless the db is closed and opened again, the next queries
311  * fail.
312  * 2) unless I clear the resources, db close fails. The doc says
313  * this is to be rarely used.
314  */
315 
316  // Find ID of catalog
317  skydb_.close();
318  catid = FindCatalog(catalog_entry.catalog_name);
319 
320  // Part 3: Add in Object Designation
321  skydb_.open();
322  QSqlQuery add_od(skydb_);
323  add_od.prepare("INSERT INTO ObjectDesignation (id_Catalog, UID_DSO, LongName"
324  ", IDNumber) VALUES (:catid, :rowuid, :longname, :id)");
325  add_od.bindValue("catid", catid);
326  add_od.bindValue("rowuid", rowuid);
327  add_od.bindValue("longname", catalog_entry.long_name);
328  add_od.bindValue("id", catalog_entry.ID);
329  if (!add_od.exec()) {
330  kWarning() << add_od.lastQuery();
331  kWarning() << skydb_.lastError();
332  }
333  add_od.clear();
334 
335  skydb_.close();
336 }
337 
338 
339 bool CatalogDB::AddCatalogContents(const QString& fname) {
340  QDir::setCurrent(QDir::homePath()); // for files with relative path
341  QString filename = fname;
342  // If the filename begins with "~", replace the "~" with the user's home
343  // directory (otherwise, the file will not successfully open)
344  if (filename.at(0) == '~')
345  filename = QDir::homePath() + filename.mid(1, filename.length());
346 
347  QFile ccFile(filename);
348 
349  if (ccFile.open(QIODevice::ReadOnly)) {
350  QStringList columns; // list of data column descriptors in the header
351  QString catalog_name;
352  char delimiter;
353 
354  QTextStream stream(&ccFile);
355  // TODO(spacetime) : Decide appropriate number of lines to be read
356  QStringList lines;
357  for (int times = 10; times >= 0 && !stream.atEnd(); --times)
358  lines.append(stream.readLine());
359  /*WAS
360  * = stream.readAll().split('\n', QString::SkipEmptyParts);
361  * Memory Hog!
362  */
363 
364  if (lines.size() < 1 ||
365  !ParseCatalogInfoToDB(lines, columns, catalog_name, delimiter)) {
366  kWarning() << "Issue in catalog file header: " << filename;
367  ccFile.close();
368  return false;
369  }
370  ccFile.close();
371  // The entry in the Catalog table is now ready!
372 
373  /*
374  * Now 'Columns' should be a StringList of the Header contents
375  * Hence, we 1) Convert the Columns to a KSParser compatible format
376  * 2) Use KSParser to read stuff and store in DB
377  */
378 
379  // Part 1) Conversion to KSParser compatible format
380  QList< QPair<QString, KSParser::DataTypes> > sequence =
381  buildParserSequence(columns);
382 
383  // Part 2) Read file and store into DB
384  KSParser catalog_text_parser(filename, '#', sequence, delimiter);
385 
386  QHash<QString, QVariant> row_content;
387  while (catalog_text_parser.HasNextRow()) {
388  row_content = catalog_text_parser.ReadNextRow();
389 
390  CatalogEntryData catalog_entry;
391 
392  dms read_ra(row_content["RA"].toString(), false);
393  dms read_dec(row_content["Dc"].toString(), true);
394  kDebug()<<row_content["Nm"].toString();
395  catalog_entry.catalog_name = catalog_name;
396  catalog_entry.ID = row_content["ID"].toInt();
397  catalog_entry.long_name = row_content["Nm"].toString();
398  catalog_entry.ra = read_ra.Degrees();
399  catalog_entry.dec = read_dec.Degrees();
400  catalog_entry.type = row_content["Tp"].toInt();
401  catalog_entry.magnitude = row_content["Mg"].toFloat();
402  catalog_entry.position_angle = row_content["PA"].toFloat();
403  catalog_entry.major_axis = row_content["Mj"].toFloat();
404  catalog_entry.minor_axis = row_content["Mn"].toFloat();
405  catalog_entry.flux = row_content["Flux"].toFloat();
406 
407  AddEntry(catalog_entry);
408  }
409  }
410  return true;
411 }
412 
413 
414 bool CatalogDB::ParseCatalogInfoToDB(const QStringList &lines,
415  QStringList &columns,
416  QString &catalog_name,
417  char &delimiter) {
418 /*
419 * Most of the code here is by Thomas Kabelmann from customcatalogcomponent.cpp
420 * (now catalogcomponent.cpp)
421 *
422 * I have modified the already existing code into this method
423 * -- Rishab Arora (spacetime)
424 */
425  bool foundDataColumns = false; // set to true if description of data
426  // columns found
427  int ncol = 0;
428 
429  QStringList errs;
430  QString catPrefix, catColor, catFluxFreq, catFluxUnit;
431  float catEpoch;
432  bool showerrs = false;
433 
434  catalog_name.clear();
435  catPrefix.clear();
436  catColor.clear();
437  catFluxFreq.clear();
438  catFluxUnit.clear();
439  catEpoch = 0.;
440  delimiter = '\0';
441 
442  int i = 0;
443  for (; i < lines.size(); ++i) {
444  QString d(lines.at(i)); // current data line
445  if (d.left(1) != "#") break; // no longer in header!
446 
447  int idelimiter = d.indexOf("# Delimiter: ");
448  int iname = d.indexOf("# Name: ");
449  int iprefix = d.indexOf("# Prefix: ");
450  int icolor = d.indexOf("# Color: ");
451  int iepoch = d.indexOf("# Epoch: ");
452  int ifluxfreq = d.indexOf("# Flux Frequency: ");
453  int ifluxunit = d.indexOf("# Flux Unit: ");
454 
455  if (idelimiter == 0) { // line contains delimiter
456  idelimiter = d.indexOf(":") + 2;
457  kWarning() << idelimiter << d;
458  if (delimiter == '\0') {
459  delimiter = d.mid(idelimiter).at(0).toAscii();
460  } else { // duplicate name in header
461  if (showerrs)
462  errs.append(i18n("Parsing header: ") +
463  i18n("Extra Delimiter field in header: %1."
464  " Will be ignored", d.mid(idelimiter)));
465  }
466  } else if (iname == 0) { // line contains catalog name
467  iname = d.indexOf(":")+2;
468  if (catalog_name.isEmpty()) {
469  catalog_name = d.mid(iname);
470  } else { // duplicate name in header
471  if (showerrs)
472  errs.append(i18n("Parsing header: ") +
473  i18n("Extra Name field in header: %1."
474  " Will be ignored", d.mid(iname)));
475  }
476  } else if (iprefix == 0) { // line contains catalog prefix
477  iprefix = d.indexOf(":")+2;
478  if (catPrefix.isEmpty()) {
479  catPrefix = d.mid(iprefix);
480  } else { // duplicate prefix in header
481  if (showerrs)
482  errs.append(i18n("Parsing header: ") +
483  i18n("Extra Prefix field in header: %1."
484  " Will be ignored", d.mid(iprefix)));
485  }
486  } else if (icolor == 0) { // line contains catalog prefix
487  icolor = d.indexOf(":")+2;
488  if (catColor.isEmpty()) {
489  catColor = d.mid(icolor);
490  } else { // duplicate prefix in header
491  if (showerrs)
492  errs.append(i18n("Parsing header: ") +
493  i18n("Extra Color field in header: %1."
494  " Will be ignored", d.mid(icolor)));
495  }
496  } else if (iepoch == 0) { // line contains catalog epoch
497  iepoch = d.indexOf(":")+2;
498  if (catEpoch == 0.) {
499  bool ok(false);
500  catEpoch = d.mid(iepoch).toFloat(&ok);
501  if (!ok) {
502  if (showerrs)
503  errs.append(i18n("Parsing header: ") +
504  i18n("Could not convert Epoch to float: "
505  "%1. Using 2000. instead",
506  d.mid(iepoch)));
507  catEpoch = 2000.; // adopt default value
508  }
509  }
510  } else if (ifluxfreq == 0) { // line contains catalog flux frequnecy
511  ifluxfreq = d.indexOf(":")+2;
512  if (catFluxFreq.isEmpty()) {
513  catFluxFreq = d.mid(ifluxfreq);
514  } else { // duplicate prefix in header
515  if (showerrs)
516  errs.append(i18n("Parsing header: ") +
517  i18n("Extra Flux Frequency field in header:"
518  " %1. Will be ignored",
519  d.mid(ifluxfreq)));
520  }
521  } else if (ifluxunit == 0) {
522  // line contains catalog flux unit
523  ifluxunit = d.indexOf(":") + 2;
524 
525  if (catFluxUnit.isEmpty()) {
526  catFluxUnit = d.mid(ifluxunit);
527  } else { // duplicate prefix in header
528  if (showerrs)
529  errs.append(i18n("Parsing header: ") +
530  i18n("Extra Flux Unit field in "
531  "header: %1. Will be ignored",
532  d.mid(ifluxunit)));
533  }
534  } else if (!foundDataColumns) { // don't try to parse data column
535  // descriptors if we already found them
536  columns.clear();
537 
538  // Chomp off leading "#" character
539  d = d.remove('#');
540 
541  // split on whitespace
542  QStringList fields = d.split(' ', QString::SkipEmptyParts);
543 
544  // we need a copy of the master list of data fields, so we can
545  // remove fields from it as they are encountered in the "fields" list.
546  // this allows us to detect duplicate entries
547  QStringList master(fields);
548 
549  for (int j = 0; j < fields.size(); ++j) {
550  QString s(fields.at(j));
551  if (master.contains(s)) {
552  // add the data field
553  columns.append(s);
554 
555  // remove the field from the master list and inc the
556  // count of "good" columns (unless field is "Ignore")
557  if (s != "Ig") {
558  master.removeAt(master.indexOf(s));
559  ncol++;
560  }
561  } else if (fields.contains(s)) { // duplicate field
562  fields.append("Ig"); // ignore the duplicate column
563  if (showerrs)
564  errs.append(i18n("Parsing header: ") +
565  i18n("Duplicate data field descriptor "
566  "\"%1\" will be ignored", s));
567  } else { // Invalid field
568  fields.append("Ig"); // ignore the invalid column
569  if (showerrs)
570  errs.append(i18n("Parsing header: ") +
571  i18n("Invalid data field descriptor "
572  "\"%1\" will be ignored", s));
573  }
574  }
575 
576  if (ncol) foundDataColumns = true;
577  }
578  }
579 
580  // For backward compatibility of old catalogs. No delimiter -> assume space
581  if (delimiter == '\0')
582  delimiter = ' ';
583 
584  if (!foundDataColumns) {
585  if (showerrs)
586  errs.append(i18n("Parsing header: ") +
587  i18n("No valid column descriptors found. Exiting"));
588  return false;
589  }
590 
591  if (i == lines.size()) {
592  if (showerrs) errs.append(i18n("Parsing header: ") +
593  i18n("No data lines found after"
594  " header. Exiting."));
595  return false;
596  } else {
597  // Make sure Name, Prefix, Color and Epoch were set
598  if (catalog_name.isEmpty()) {
599  if (showerrs) errs.append(i18n("Parsing header: ") +
600  i18n("No Catalog Name specified;"
601  " setting to \"Custom\""));
602  catalog_name = i18n("Custom");
603  }
604  if (catPrefix.isEmpty()) {
605  if (showerrs) errs.append(i18n("Parsing header: ") +
606  i18n("No Catalog Prefix specified"
607  "; setting to \"CC\""));
608  catPrefix = "CC";
609  }
610  if (catColor.isEmpty()) {
611  if (showerrs) errs.append(i18n("Parsing header: ") +
612  i18n("No Catalog Color specified"
613  "; setting to Red"));
614  catColor = "#CC0000";
615  }
616  if (catEpoch == 0.) {
617  if (showerrs) errs.append(i18n("Parsing header: ") +
618  i18n("No Catalog Epoch specified"
619  "; assuming 2000."));
620  catEpoch = 2000.;
621  }
622 
623  // Detect a duplicate catalog name
624  if (FindCatalog(catalog_name) != -1) {
625  if (KMessageBox::warningYesNo(0,
626  i18n("A catalog of the same name already exists. "
627  "Overwrite contents? If you press yes, the"
628  " new catalog will erase the old one!"),
629  i18n("Overwrite Existing Catalog"))
630  == KMessageBox::No) {
631  KMessageBox::information(0, "Catalog addition cancelled.");
632  return false;
633  } else {
634  RemoveCatalog(catalog_name);
635  }
636  }
637 
638  // Everything OK. Make a new Catalog entry in DB
639  CatalogData new_catalog;
640 
641  new_catalog.catalog_name = catalog_name;
642  new_catalog.prefix = catPrefix;
643  new_catalog.color = catColor;
644  new_catalog.epoch = catEpoch;
645  new_catalog.fluxfreq = catFluxFreq;
646  new_catalog.fluxunit = catFluxUnit;
647 
648  AddCatalog(new_catalog);
649 
650  return true;
651  }
652 }
653 
654 void CatalogDB::GetCatalogData(const QString& catalog_name,
655  CatalogData& load_catalog) {
656  skydb_.open();
657  QSqlTableModel catalog(0, skydb_);
658  catalog.setTable("Catalog");
659  catalog.setFilter("Name LIKE \'" + catalog_name + "\'");
660  catalog.select();
661 
662  QSqlRecord record = catalog.record(0);
663  load_catalog.prefix = record.value("Prefix").toString();
664  load_catalog.color = record.value("Color").toString();
665  load_catalog.fluxfreq = record.value("FluxFreq").toString();
666  load_catalog.fluxunit = record.value("FluxUnit").toString();
667  load_catalog.epoch = record.value("Epoch").toFloat();
668 
669  catalog.clear();
670  skydb_.close();
671 }
672 
673 
674 void CatalogDB::GetAllObjects(const QString &catalog,
675  QList< SkyObject* > &sky_list,
676  QList < QPair <int, QString> > &object_names,
677  CatalogComponent *catalog_ptr) {
678  sky_list.clear();
679  QString selected_catalog = QString::number(FindCatalog(catalog));
680  skydb_.open();
681  QSqlQuery get_query(skydb_);
682  get_query.prepare("SELECT Epoch, Type, RA, Dec, Magnitude, Prefix, "
683  "IDNumber, LongName, MajorAxis, MinorAxis, "
684  "PositionAngle, Flux FROM ObjectDesignation JOIN DSO "
685  "JOIN Catalog WHERE Catalog.id = :catID AND "
686  "ObjectDesignation.id_Catalog = Catalog.id AND "
687  "ObjectDesignation.UID_DSO = DSO.UID");
688  get_query.bindValue("catID", selected_catalog);
689 
690 // kWarning() << get_query.lastQuery();
691 // kWarning() << get_query.lastError();
692 // kWarning() << FindCatalog(catalog);
693 
694  if (!get_query.exec()) {
695  kWarning() << get_query.lastQuery();
696  kWarning() << get_query.lastError();
697  }
698 
699  while (get_query.next()) {
700 
701  int cat_epoch = get_query.value(0).toInt();
702  unsigned char iType = get_query.value(1).toInt();
703  dms RA(get_query.value(2).toDouble());
704  dms Dec(get_query.value(3).toDouble());
705  float mag = get_query.value(4).toFloat();
706  QString catPrefix = get_query.value(5).toString();
707  int id_number_in_catalog = get_query.value(6).toInt();
708  QString lname = get_query.value(7).toString();
709  float a = get_query.value(8).toFloat();
710  float b = get_query.value(9).toFloat();
711  float PA = get_query.value(10).toFloat();
712  float flux = get_query.value(11).toFloat();
713 
714  QString name = catPrefix + ' ' + QString::number(id_number_in_catalog);
715  SkyPoint t;
716  t.set(RA, Dec);
717 
718  if (cat_epoch == 1950) {
719  // Assume B1950 epoch
720  t.B1950ToJ2000(); // t.ra() and t.dec() are now J2000.0
721  // coordinates
722  } else if (cat_epoch == 2000) {
723  // Do nothing
724  { }
725  } else {
726  // FIXME: What should we do?
727  // FIXME: This warning will be printed for each line in the
728  // catalog rather than once for the entire catalog
729  kWarning() << "Unknown epoch while dealing with custom "
730  "catalog. Will ignore the epoch and assume"
731  " J2000.0";
732  }
733 
734  RA = t.ra();
735  Dec = t.dec();
736 
737  if (iType == 0) { // Add a star
738  StarObject *o = new StarObject(RA, Dec, mag, lname);
739  sky_list.append(o);
740  } else { // Add a deep-sky object
741  DeepSkyObject *o = new DeepSkyObject(iType, RA, Dec, mag,
742  name, QString(), lname,
743  catPrefix, a, b, -PA);
744  o->setFlux(flux);
745  o->setCustomCatalog(catalog_ptr);
746 
747  sky_list.append(o);
748 
749  // Add name to the list of object names
750  if (!name.isEmpty()) {
751  object_names.append(qMakePair<int,QString>(iType, name));
752  }
753  }
754 
755  if (!lname.isEmpty() && lname != name) {
756  object_names.append(qMakePair<int,QString>(iType, lname));
757  }
758  }
759 
760  get_query.clear();
761  skydb_.close();
762 }
763 
764 
765 QList< QPair<QString, KSParser::DataTypes> > CatalogDB::
766  buildParserSequence(const QStringList& Columns) {
767  QList< QPair<QString, KSParser::DataTypes> > sequence;
768  QStringList::const_iterator iter = Columns.begin();
769 
770  while (iter != Columns.end()) {
771  // Available Types: ID RA Dc Tp Nm Mg Flux Mj Mn PA Ig
772  KSParser::DataTypes current_type;
773 
774  if (*iter == QString("ID"))
775  current_type = KSParser::D_QSTRING;
776  else if (*iter == QString("RA"))
777  current_type = KSParser::D_QSTRING;
778  else if (*iter == QString("Dc"))
779  current_type = KSParser::D_QSTRING;
780  else if (*iter == QString("Tp"))
781  current_type = KSParser::D_INT;
782  else if (*iter == QString("Nm"))
783  current_type = KSParser::D_QSTRING;
784  else if (*iter == QString("Mg"))
785  current_type = KSParser::D_FLOAT;
786  else if (*iter == QString("Flux"))
787  current_type = KSParser::D_FLOAT;
788  else if (*iter == QString("Mj"))
789  current_type = KSParser::D_FLOAT;
790  else if (*iter == QString("Mn"))
791  current_type = KSParser::D_FLOAT;
792  else if (*iter == QString("PA"))
793  current_type = KSParser::D_FLOAT;
794  else if (*iter == QString("Ig"))
795  current_type = KSParser::D_SKIP;
796 
797  sequence.append(qMakePair(*iter, current_type));
798  ++iter;
799  }
800 
801  return sequence;
802 }
SkyPoint::ra
const dms & ra() const
Definition: skypoint.h:171
KSParser::HasNextRow
bool HasNextRow()
Returns True if there are more rows to be read.
Definition: ksparser.cpp:218
SkyPoint::set
void set(const dms &r, const dms &d)
Sets RA, Dec and RA0, Dec0 according to arguments.
Definition: skypoint.cpp:46
CatalogData::author
QString author
Definition: catalogdata.h:47
CatalogDB::AddCatalogContents
bool AddCatalogContents(const QString &filename)
Add contents of custom catalog to the program database.
Definition: catalogdb.cpp:339
KSParser
Generic class for text file parsers used in KStars.
Definition: ksparser.h:49
CatalogEntryData
Class to store details of a Catalog Entry.
Definition: catalogentrydata.h:59
dms::Degrees
const double & Degrees() const
Definition: dms.h:98
CatalogEntryData::magnitude
float magnitude
Definition: catalogentrydata.h:67
CatalogDB::GetAllObjects
void GetAllObjects(const QString &catalog_name, QList< SkyObject * > &sky_list, QList< QPair< int, QString > > &object_names, CatalogComponent *catalog_pointer)
Creates objects of type SkyObject and assigns them to references.
Definition: catalogdb.cpp:674
KSParser::EBROKEN_DOUBLE
static const double EBROKEN_DOUBLE
These are the values used in case of error in conversion.
Definition: ksparser.h:54
CatalogData::epoch
float epoch
Definition: catalogdata.h:44
CatalogDB::AddEntry
void AddEntry(const CatalogEntryData &catalog_entry)
Used to add a cross referenced entry into the database.
Definition: catalogdb.cpp:261
CatalogDB::RefreshCatalogList
void RefreshCatalogList()
Rechecks the database and builds the Catalog listing.
Definition: catalogdb.cpp:117
KSParser::DataTypes
DataTypes
DataTypes for building sequence D_QSTRING QString Type D_INT Integer Type D_FLOAT Floating Point Type...
Definition: ksparser.h:67
DeepSkyObject::setCustomCatalog
void setCustomCatalog(CatalogComponent *s)
Set the reference to the custom catalog component, if any.
Definition: deepskyobject.h:112
CatalogEntryData::flux
float flux
Definition: catalogentrydata.h:71
CatalogEntryData::ID
int ID
Definition: catalogentrydata.h:62
CatalogData::fluxfreq
QString fluxfreq
Definition: catalogdata.h:45
CatalogDB::Catalogs
QStringList * Catalogs()
Accessor for list of all available catalogs in db.
Definition: catalogdb.cpp:111
SkyPoint
The sky coordinates of a point in the sky.
Definition: skypoint.h:50
CatalogEntryData::minor_axis
float minor_axis
Definition: catalogentrydata.h:70
CatalogData::color
QString color
Definition: catalogdata.h:43
CatalogEntryData::ra
double ra
Definition: catalogentrydata.h:64
CatalogData
Add the catalog with given details into the database.
Definition: catalogdata.h:38
KSParser::D_FLOAT
Definition: ksparser.h:70
CatalogEntryData::catalog_name
QString catalog_name
Definition: catalogentrydata.h:61
CatalogComponent
Represents a custom user-defined catalog.
Definition: catalogcomponent.h:39
CatalogData::prefix
QString prefix
Definition: catalogdata.h:42
dms
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:42
SkyPoint::dec
const dms & dec() const
Definition: skypoint.h:174
KSParser::D_INT
Definition: ksparser.h:69
CatalogDB::~CatalogDB
~CatalogDB()
Attempt to close database and remove reference from the DB List.
Definition: catalogdb.cpp:100
DeepSkyObject
Provides all necessary information about a deep-sky object: data inherited from SkyObject (coordinate...
Definition: deepskyobject.h:43
CatalogEntryData::position_angle
int position_angle
Definition: catalogentrydata.h:68
QTextStream
CatalogDB::Initialize
bool Initialize()
Initializes the database and sets up pointers to Catalog DB Performs the following actions: ...
Definition: catalogdb.cpp:22
CatalogData::fluxunit
QString fluxunit
Definition: catalogdata.h:46
NaN::d
const double d
Definition: nan.h:35
CatalogEntryData::dec
double dec
Definition: catalogentrydata.h:65
CatalogData::license
QString license
Definition: catalogdata.h:48
DeepSkyObject::setFlux
void setFlux(const float &f)
Set the integrated flux value of the object.
Definition: deepskyobject.h:122
CatalogEntryData::type
int type
Definition: catalogentrydata.h:66
CatalogDB::GetCatalogData
void GetCatalogData(const QString &catalog_name, CatalogData &catalog_data)
Get information about the catalog like Prefix etc.
Definition: catalogdb.cpp:654
CatalogEntryData::long_name
QString long_name
Definition: catalogentrydata.h:63
KSParser::ReadNextRow
QHash< QString, QVariant > ReadNextRow()
Generic function used to read the next row of a text file.
Definition: ksparser.cpp:56
catalogdb.h
StarObject
This is a subclass of SkyObject.
Definition: starobject.h:41
KSParser::D_SKIP
Definition: ksparser.h:72
KSParser::D_QSTRING
Definition: ksparser.h:68
CatalogEntryData::major_axis
float major_axis
Definition: catalogentrydata.h:69
SkyPoint::B1950ToJ2000
void B1950ToJ2000(void)
Exact precession from Besselian epoch 1950 to epoch J2000.
Definition: skypoint.cpp:480
CatalogData::catalog_name
QString catalog_name
Definition: catalogdata.h:41
QList
CatalogDB::FindFuzzyEntry
int FindFuzzyEntry(const double ra, const double dec, const double magnitude)
returns the id of the row if it matches with certain fuzz.
Definition: catalogdb.cpp:228
CatalogDB::RemoveCatalog
void RemoveCatalog(const QString &catalog_name)
Removes the catalog from the database and refreshes the listing.
Definition: catalogdb.cpp:184
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:36:19 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kstars

Skip menu "kstars"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal