Kstars

addcatalogobject.cpp
1/*
2 SPDX-FileCopyrightText: 2021 Valentin Boettcher <hiro at protagon.space; @hiro98:tchncs.de>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "addcatalogobject.h"
8#include "ui_addcatalogobject.h"
9#include "kstars_debug.h"
10
11#include <QInputDialog>
12#include <QPushButton>
13
15 : QDialog(parent), ui(new Ui::AddCatalogObject), m_object{ obj }
16{
17 ui->setupUi(this);
18 ui->ra->setUnits(dmsBox::HOURS);
19 fill_form_from_object();
20
22 [&](const auto &name) { m_object.setName(name); });
23
24 connect(ui->long_name, &QLineEdit::textChanged,
25 [&](const auto &name) { m_object.setLongName(name); });
26
27 connect(ui->catalog_identifier, &QLineEdit::textChanged,
28 [&](const auto &ident) { m_object.setCatalogIdentifier(ident); });
29
30 connect(ui->type, QOverload<int>::of(&QComboBox::currentIndexChanged),
31 [&](const auto index) {
32 if (index > SkyObject::TYPE_UNKNOWN)
33 m_object.setType(SkyObject::TYPE_UNKNOWN);
34
35 m_object.setType(index);
36
37 refresh_flux();
38 });
39
40 auto validateAndStoreCoordinates = [&]() {
41 bool raOk(false), decOk(false);
42 auto ra = ui->ra->createDms(&raOk);
43 auto dec = ui->dec->createDms(&decOk);
44 auto* okButton = ui->buttonBox->button(QDialogButtonBox::Ok);
45 Q_ASSERT(!!okButton);
46 okButton->setEnabled(raOk && decOk);
47 if (raOk && decOk) {
48 m_object.setRA0(ra);
49 m_object.setDec0(dec);
50 }
51 };
52
53 connect(ui->ra, &dmsBox::textChanged, validateAndStoreCoordinates);
54 connect(ui->dec, &dmsBox::textChanged, validateAndStoreCoordinates);
55
56 auto updateMag = [&]()
57 {
58 m_object.setMag(
59 ui->magUnknown->isChecked() ? NaN::f : static_cast<float>(ui->mag->value()));
60 };
61 connect(ui->mag, QOverload<double>::of(&QDoubleSpinBox::valueChanged), updateMag);
62 connect(ui->magUnknown, &QCheckBox::stateChanged, updateMag);
63
64 connect(ui->maj, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
65 [&](const auto value) { m_object.setMaj(static_cast<float>(value)); });
66
67 connect(ui->min, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
68 [&](const auto value) { m_object.setMin(static_cast<float>(value)); });
69
70 connect(ui->flux, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
71 [&](const auto value) { m_object.setFlux(static_cast<float>(value)); });
72
73 connect(ui->position_angle, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
74 [&](const auto value) { m_object.setPA(value); });
75
76 connect(ui->guessFromTextButton, &QPushButton::clicked, [this]() { this->guess_form_contents_from_text(); });
77}
78
79AddCatalogObject::~AddCatalogObject()
80{
81 delete ui;
82}
83
84void AddCatalogObject::fill_form_from_object()
85{
86 if (m_object.hasName()) // N.B. Avoid filling name fields with "unnamed"
87 ui->name->setText(m_object.name());
88 if (m_object.hasLongName())
89 ui->long_name->setText(m_object.longname());
90 ui->catalog_identifier->setText(m_object.catalogIdentifier());
91
92 for (int k = 0; k < SkyObject::NUMBER_OF_KNOWN_TYPES; ++k)
93 {
94 ui->type->addItem(SkyObject::typeName(k));
95 }
96 ui->type->addItem(SkyObject::typeName(SkyObject::TYPE_UNKNOWN));
97 ui->type->setCurrentIndex((int)(m_object.type()));
98
99 dms ra0 = m_object.ra0();
100 dms dec0 = m_object.dec0(); // Make a copy to avoid overwriting by signal-slot connection
101 ui->ra->show(ra0);
102 ui->dec->show(dec0);
103 if (std::isnan(m_object.mag()))
104 {
105 ui->magUnknown->setChecked(true);
106 }
107 else
108 {
109 ui->mag->setValue(m_object.mag());
110 ui->magUnknown->setChecked(false);
111 }
112 ui->flux->setValue(m_object.flux());
113 ui->position_angle->setValue(m_object.pa());
114 ui->maj->setValue(m_object.a());
115 ui->min->setValue(m_object.b());
116 refresh_flux();
117}
118
119void AddCatalogObject::refresh_flux()
120{
121 ui->flux->setEnabled(m_object.type() == SkyObject::RADIO_SOURCE);
122
123 if (!ui->flux->isEnabled())
124 ui->flux->setValue(0);
125}
126
127void AddCatalogObject::guess_form_contents_from_text()
128{
129 bool accepted = false;
131 this,
132 i18n("Guess object data from text"),
133 i18n("Copy-paste a text blurb with data on the object, and KStars will try to guess the contents of the fields from the text. The result is just a guess, so please verify the coordinates and the other information."),
134 QString(),
135 &accepted);
136 if (accepted && !text.isEmpty())
137 {
138 guess_form_contents_from_text(text);
139 }
140}
141
142void AddCatalogObject::guess_form_contents_from_text(QString text)
143{
144 // Parse text to fill in the entries in the form, using regexes to
145 // guess the field values
146
147 // TODO: Guess type from catalog name if the type match failed
148
149 QRegularExpression matchJ2000Line("^(.*)(?:J2000|ICRS|FK5|\\(2000(?:\\.0)?\\))(.*)$");
150 matchJ2000Line.setPatternOptions(QRegularExpression::MultilineOption);
151 QRegularExpression matchCoords("(?:^|[^-\\d])([-+]?\\d\\d?)(?:h ?|d ?|[^\\d]?° ?|:| )(\\d\\d)(?:m ?|\' ?|’ ?|′ "
152 "?|:| )(\\d\\d(?:\\.\\d+)?)?(?:s|\"|\'\'|”|″)?\\b");
153 QRegularExpression matchCoords2("J?\\d{6,6}[-+]\\d{6,6}");
154 QRegularExpression findMag1(
155 "(?:[mM]ag(?:nitudes?)?\\s*(?:\\([vV]\\))?|V(?=\\b))(?:\\s*=|:)?\\s*(-?\\d{1,2}(?:\\.\\d{1,3})?)");
156 QRegularExpression findMag2("\\b(-?\\d{1,2}\\.\\d{1,3})?\\s*(?:[mM]ag|V|B)\\b");
157 QRegularExpression findSize1("\\b(\\d{1,3}(?:\\.\\d{1,2})?)\\s*(°|\'|\"|\'\')?\\s*[xX×]\\s*(\\d{1,3}(?:\\.\\d{1,2})"
158 "?)\\s*(°|\'|\"|\'\')?\\b");
159 QRegularExpression findSize2("\\b(?:[Ss]ize|[Dd]imensions?|[Dd]iameter)[: "
160 "](?:\\([vV]\\))?\\s*(\\d{1,3}(?:\\.\\d{1,2})?)\\s*(°|\'|\"|\'\')?\\b");
161 QRegularExpression findMajorAxis("\\b[Mm]ajor\\s*[Aa]xis:?\\s*(\\d{1,3}(?:\\.\\d{1,2})?)\\s*(°|\'|\"|\'\')?\\b");
162 QRegularExpression findMinorAxis("\\b[Mm]inor\\s*[Aa]xis:?\\s*(\\d{1,3}(?:\\.\\d{1,2})?)\\s*(°|\'|\"|\'\')?\\b");
163 QRegularExpression findPA(
164 "\\b(?:[Pp]osition *[Aa]ngle|PA|[pP]\\.[aA]\\.):?\\s*(\\d{1,3}(\\.\\d{1,2})?)(?:°|[Ddeg])?\\b");
165 QRegularExpression findName1(
166 "\\b(?:(?:[nN]ames?|NAMES?)[: ]|[iI]dent(?:ifier)?:|[dD]esignation:)\\h*\"?([-+\'A-Za-z0-9 ]*)\"?\\b");
167 QStringList catalogNames;
168 catalogNames << "NGC"
169 << "IC"
170 << "M"
171 << "PGC"
172 << "UGC"
173 << "UGCA"
174 << "MCG"
175 << "ESO"
176 << "SDSS"
177 << "LEDA"
178 << "IRAS"
179 << "PNG"
180 << "Abell"
181 << "ACO"
182 << "HCG"
183 << "CGCG"
184 << "[IV]+ ?Zw"
185 << "Hickson"
186 << "AGC"
187 << "2MASS"
188 << "RCS2"
189 << "Terzan"
190 << "PN [A-Z0-9]"
191 << "VV"
192 << "PK"
193 << "GSC2"
194 << "LBN"
195 << "LDN"
196 << "Caldwell"
197 << "HIP"
198 << "AM"
199 << "vdB"
200 << "Barnard"
201 << "Shkh?"
202 << "KTG"
203 << "Palomar"
204 << "KPG"
205 << "CGPG"
206 << "TYC"
207 << "Arp"
208 << "Minkowski"
209 << "KUG"
210 << "DDO"
211 ;
213 objectTypes.append({"[Op]pen ?[Cc]luster|OCL|\\*Cl|Cl\\*|OpC|Cl\\?|Open Cl\\.", SkyObject::OPEN_CLUSTER});
214 objectTypes.append({"Globular ?Cluster|GlC|GCl|Glob\\. Cl\\.|Globular|Gl\\?", SkyObject::GLOBULAR_CLUSTER});
215 objectTypes.append({"(?:[Gg]as(?:eous)?|Diff(?:\\.|use)?|Emission|Ref(?:\\.|lection)?) ?[Nn]eb(?:ula|\\.)?|Neb|RfN|HII|GNe", SkyObject::GASEOUS_NEBULA});
216 objectTypes.append({"PN|PNe|Pl\\.? ?[Nn]eb\\.?|(?:[Pp]re[- ]?)[Pp]lanetary|PPNe|PPN|pA\\*|post[- ]?AGB", SkyObject::PLANETARY_NEBULA});
217 objectTypes.append({"SNR|[Ss]upernova ?[Rr]em(?:\\.|nant)?|SNRem(?:\\.|nant)?", SkyObject::SUPERNOVA_REMNANT});
218 objectTypes.append({"Gxy?|HIIG|H2G|[bB]CG|SBG|AGN|EmG|LINER|LIRG|GiG|GinP", SkyObject::GALAXY});
219 objectTypes.append({"Ast\\.?|Asterism", SkyObject::ASTERISM});
220 objectTypes.append({"ClG|GrG|CGG|[Gg](?:ala)?xy ?(?:[Gg]roup|[Cc]luster|[Pp]air|[Tt]rio|[Tt]riple)|GClus|GGrp|GGroup|GClstr|GPair|GTrpl|GTrio", SkyObject::GALAXY_CLUSTER});
221 objectTypes.append({"ISM|DNeb?|[dD](?:k\\.?|ark) ?[Nn]eb(?:ula|\\.)?", SkyObject::DARK_NEBULA});
222 objectTypes.append({"QSO|[qQ]uasar", SkyObject::QUASAR});
223 objectTypes.append({"(?:[Dd]ouble|[Dd]bl\\.?|[Tt]riple|[Mm]ult(?:iple|\\.)? ?[Ss]tar)|\\*\\*|Mult\\.? ?\\*", SkyObject::MULT_STAR});
224 objectTypes.append({"[nN]ebula", SkyObject::GASEOUS_NEBULA}); // Catch all nebula
225 objectTypes.append({"[gG]alaxy", SkyObject::GALAXY}); // Catch all galaxy
226
227 QRegularExpression findName2("\\b(" + catalogNames.join("|") + ")\\s+(J?[-+0-9\\.]+[A-Da-h]?)\\b");
228 QRegularExpression findName3("\\b([A-Za-z]+[0-9]?)\\s+(J?[-+0-9]+[A-Da-h]?)\\b");
229
230 // FIXME: This code will clean up by a lot if std::optional<> can be used
231 QString coordText;
232 bool coordsFound = false,
233 magFound = false,
234 sizeFound = false,
235 nameFound = false,
236 positionAngleFound = false,
237 catalogDetermined = false,
238 typeFound = false;
239
240 dms RA, Dec;
241 float mag = NaN::f;
242 float majorAxis = NaN::f;
243 float minorAxis = NaN::f;
244 float positionAngle = 0;
246 QString catalogName;
247 QString catalogIdentifier;
248 SkyObject::TYPE type = SkyObject::TYPE_UNKNOWN;
249
250 // Note: The following method is a proxy to support older versions of Qt.
251 // In Qt 5.5 and above, the QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) method obviates the need for the following.
252 auto indexOf = [](const QString & s, const QRegularExpression & regExp, int from, QRegularExpressionMatch * m) -> int
253 {
254 *m = regExp.match(s, from);
255 return m->capturedStart(0);
256 };
257
258 auto countNonOverlappingMatches = [indexOf](const QString & string, const QRegularExpression & regExp,
259 QStringList *list = nullptr) -> int
260 {
261 int count = 0;
262 int matchIndex = -1;
263 int lastMatchLength = 1;
265 while ((matchIndex = indexOf(string, regExp, matchIndex + lastMatchLength, &rmatch)) >= 0)
266 {
267 ++count;
268 lastMatchLength = rmatch.captured(0).length();
269 if (list)
270 list->append(rmatch.captured(0));
271 }
272 return count;
273 };
274
276 int nonOverlappingMatchCount;
277 std::size_t coordTextIndex = 0;
278 if ((nonOverlappingMatchCount = countNonOverlappingMatches(text, matchCoords)) == 2)
279 {
280 coordText = text;
281 }
282 else if (nonOverlappingMatchCount > 2)
283 {
284 qCDebug(KSTARS) << "Found more than 2 coordinate matches. Trying to match J2000 line.";
285 if (indexOf(text, matchJ2000Line, 0, &rmatch) >= 0)
286 {
287 coordTextIndex = indexOf(text, matchJ2000Line, 0, &rmatch);
288 coordText = rmatch.captured(1) + rmatch.captured(2);
289 qCDebug(KSTARS) << "Found a J2000 line match: " << coordText;
290 }
291 }
292
293 if (!coordText.isEmpty())
294 {
295 int coord1 = indexOf(coordText, matchCoords, 0, &rmatch);
296 if (coord1 >= 0) {
297 std::size_t length1 = rmatch.captured(0).length();
298 RA = dms(rmatch.captured(1) + ' ' + rmatch.captured(2) + ' ' + rmatch.captured(3), false);
299 int coord2 = indexOf(coordText, matchCoords, coord1 + length1, &rmatch);
300 if (coord2 >= 0) {
301 Dec = dms(rmatch.captured(1) + ' ' + rmatch.captured(2) + ' ' + rmatch.captured(3), true);
302 qCDebug(KSTARS) << "Extracted coordinates: " << RA.toHMSString() << " " << Dec.toDMSString();
303 coordsFound = true;
304
305 // Remove the coordinates from the original string so subsequent tasks don't confuse it
306 std::size_t length2 = rmatch.captured(0).length();
307 qCDebug(KSTARS) << "Eliminating text: " << text.midRef(coordTextIndex + coord1, length1) << " and " << text.midRef(coordTextIndex + coord2, length2);
308 text.replace(coordTextIndex + coord1, length1, "\n");
309 text.replace(coordTextIndex + coord2 - length1 + 1, length2, "\n");
310 qCDebug(KSTARS) << "Text now: " << text;
311 }
312 }
313 }
314 else
315 {
316 if (text.contains(matchCoords2, &rmatch))
317 {
318 QString matchString = rmatch.captured(0);
319 QRegularExpression extractCoords2("(\\d\\d)(\\d\\d)(\\d\\d)([-+]\\d\\d)(\\d\\d)(\\d\\d)");
320 Q_ASSERT(matchString.contains(extractCoords2, &rmatch));
321 RA = dms(rmatch.captured(1) + ' ' + rmatch.captured(2) + ' ' + rmatch.captured(3), false);
322 Dec = dms(rmatch.captured(4) + ' ' + rmatch.captured(5) + ' ' + rmatch.captured(6), true);
323 coordsFound = true;
324
325 // Remove coordinates to avoid downstream confusion with it
326 qCDebug(KSTARS) << "Eliminating text: " << text.midRef(rmatch.capturedStart(), rmatch.captured(0).length());
327 text.replace(rmatch.capturedStart(), rmatch.captured(0).length(), "\n");
328 qCDebug(KSTARS) << "Text now: " << text;
329 }
330 else
331 {
332 QStringList matches;
333 qCDebug(KSTARS) << "Could not extract RA/Dec. Found " << countNonOverlappingMatches(text, matchCoords, &matches)
334 << " coordinate matches:";
335 qCDebug(KSTARS) << matches;
336 }
337 }
338
339 // Type determination: Support full names of types, or SIMBAD/NED shorthands
340 for (const auto& p : objectTypes)
341 {
342 QRegularExpression findType("\\b(?:" + p.first + ")\\b");
343 if (text.contains(findType, &rmatch)) {
344 type = p.second;
345 typeFound = true;
346 qCDebug(KSTARS) << "Found Type: " << SkyObject::typeName(p.second);
347 qCDebug(KSTARS) << "Eliminating text: " << text.midRef(rmatch.capturedStart(), rmatch.captured(0).length());
348 text.replace(rmatch.capturedStart(), rmatch.captured(0).length(), "\n"); // Remove to avoid downstream confusion
349 qCDebug(KSTARS) << "Text now: " << text;
350 break;
351 }
352 }
353 if (!typeFound) {
354 qCDebug(KSTARS) << "Type not found";
355 }
356
357 nameFound = true;
358 catalogDetermined = true; // Transition to std::optional with C++17
359 if (text.contains(findName1, &rmatch)) // Explicit name search
360 {
361 qCDebug(KSTARS) << "Found explicit name field: " << rmatch.captured(1) << " in text " << rmatch.captured(0);
362 name = rmatch.captured(1);
363 catalogDetermined = false;
364 }
365 else if (text.contains(findName2, &rmatch))
366 {
367 catalogDetermined = true;
368 catalogName = rmatch.captured(1);
369 catalogIdentifier = rmatch.captured(2);
370 name = catalogName + ' ' + catalogIdentifier;
371 qCDebug(KSTARS) << "Found known catalog field: " << name
372 << " in text " << rmatch.captured(0);
373 }
374 else if (text.contains(findName3, &rmatch))
375 {
376 // N.B. This case is not strong enough to assume catalog name was found correctly
377 name = rmatch.captured(1) + ' ' + rmatch.captured(2);
378 qCDebug(KSTARS) << "Found something that looks like a catalog designation: "
379 << name << " in text " << rmatch.captured(0);
380 }
381 else
382 {
383 qCDebug(KSTARS) << "Could not find name.";
384 nameFound = false;
385 catalogDetermined = false;
386 }
387
388 magFound = true;
389 if (text.contains(findMag1, &rmatch))
390 {
391 qCDebug(KSTARS) << "Found magnitude: " << rmatch.captured(1) << " in text " << rmatch.captured(0);
392 mag = rmatch.captured(1).toFloat();
393 }
394 else if (text.contains(findMag2, &rmatch))
395 {
396 qCDebug(KSTARS) << "Found magnitude: " << rmatch.captured(1) << " in text " << rmatch.captured(0);
397 mag = rmatch.captured(1).toFloat();
398 }
399 else
400 {
401 qCDebug(KSTARS) << "Could not find magnitude.";
402 magFound = false;
403 }
404
405 sizeFound = true;
406 if (text.contains(findSize1, &rmatch))
407 {
408 qCDebug(KSTARS) << "Found size: " << rmatch.captured(1) << " x " << rmatch.captured(3) << " with units "
409 << rmatch.captured(4) << " in text " << rmatch.captured(0);
410 majorAxis = rmatch.captured(1).toFloat();
411 QString unitText2;
412 if (rmatch.captured(2).isEmpty())
413 {
414 unitText2 = rmatch.captured(4);
415 }
416 else
417 {
418 unitText2 = rmatch.captured(2);
419 }
420
421 if (unitText2.contains("°"))
422 majorAxis *= 60;
423 else if (unitText2.contains("\"") || unitText2.contains("\'\'"))
424 majorAxis /= 60;
425
426 minorAxis = rmatch.captured(3).toFloat();
427 if (rmatch.captured(4).contains("°"))
428 minorAxis *= 60;
429 else if (rmatch.captured(4).contains("\"") || rmatch.captured(4).contains("\'\'"))
430 minorAxis /= 60;
431 qCDebug(KSTARS) << "Major axis = " << majorAxis << "; minor axis = " << minorAxis << " in arcmin";
432 }
433 else if (text.contains(findSize2, &rmatch))
434 {
435 majorAxis = rmatch.captured(1).toFloat();
436 if (rmatch.captured(2).contains("°"))
437 majorAxis *= 60;
438 else if (rmatch.captured(2).contains("\"") || rmatch.captured(2).contains("\'\'"))
439 majorAxis /= 60;
440 minorAxis = majorAxis;
441 }
442 else if (text.contains(findMajorAxis, &rmatch))
443 {
444 majorAxis = rmatch.captured(1).toFloat();
445 if (rmatch.captured(2).contains("°"))
446 majorAxis *= 60;
447 else if (rmatch.captured(2).contains("\"") || rmatch.captured(2).contains("\'\'"))
448 majorAxis /= 60;
449 minorAxis = majorAxis;
450 if (text.contains(findMinorAxis, &rmatch))
451 {
452 minorAxis = rmatch.captured(1).toFloat();
453 if (rmatch.captured(2).contains("°"))
454 minorAxis *= 60;
455 else if (rmatch.captured(2).contains("\"") || rmatch.captured(2).contains("\'\'"))
456 minorAxis /= 60;
457 }
458 }
459
460 else
461 {
462 qCDebug(KSTARS)
463 << "Could not find size."; // FIXME: Improve to include separate major and minor axis matches, and size matches for round objects.
464 sizeFound = false;
465 }
466
467 positionAngleFound = true;
468 if (text.contains(findPA, &rmatch))
469 {
470 qCDebug(KSTARS) << "Found position angle: " << rmatch.captured(1) << " in text " << rmatch.captured(0);
471 positionAngle = rmatch.captured(1).toFloat();
472 }
473 else
474 {
475 qCDebug(KSTARS) << "Could not find position angle.";
476 positionAngleFound = false;
477 }
478
479 if (typeFound)
480 ui->type->setCurrentIndex((int)type);
481 if (nameFound)
482 ui->name->setText(name);
483 if (magFound)
484 {
485 ui->mag->setValue(mag);
486 ui->magUnknown->setChecked(false);
487 } else
488 {
489 ui->magUnknown->setChecked(true);
490 }
491 if (coordsFound)
492 {
493 ui->ra->show(RA);
494 ui->dec->show(Dec);
495 }
496 if (positionAngleFound)
497 ui->position_angle->setValue(positionAngle);
498 if (sizeFound)
499 {
500 ui->maj->setValue(majorAxis);
501 ui->min->setValue(minorAxis);
502 }
503 if (catalogDetermined)
504 {
505 ui->catalog_identifier->setText(catalogIdentifier);
506 }
507 refresh_flux();
508}
A simple data entry dialog to create and edit objects in CatalogDB catalogs.
AddCatalogObject(QWidget *parent, const CatalogObject &obj={})
A simple container object to hold the minimum information for a Deep Sky Object to be drawn on the sk...
float flux() const
float a() const
const QString & catalogIdentifier() const
void setMag(const double mag)
Set the magnitude of the object.
double pa() const override
float b() const
virtual QString name(void) const
Definition skyobject.h:145
virtual QString longname(void) const
Definition skyobject.h:164
int type(void) const
Definition skyobject.h:188
QString typeName() const
float mag() const
Definition skyobject.h:206
TYPE
The type classification of the SkyObject.
Definition skyobject.h:112
const CachingDms & ra0() const
Definition skypoint.h:251
void setRA0(dms r)
Sets RA0, the catalog Right Ascension.
Definition skypoint.h:94
const CachingDms & dec0() const
Definition skypoint.h:257
void setDec0(dms d)
Sets Dec0, the catalog Declination.
Definition skypoint.h:119
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
Definition dms.cpp:287
const QString toHMSString(const bool machineReadable=false, const bool highPrecision=false) const
Definition dms.cpp:378
QString i18n(const char *text, const TYPE &arg...)
QString name(GameStandardAction id)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
void clicked(bool checked)
void stateChanged(int state)
void currentIndexChanged(int index)
void accepted()
void valueChanged(double d)
QString getMultiLineText(QWidget *parent, const QString &title, const QString &label, const QString &text, bool *ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
void textChanged(const QString &text)
void append(QList< T > &&value)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString captured(QStringView name) const const
qsizetype capturedStart(QStringView name) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype length() const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
float toFloat(bool *ok) const const
QString join(QChar separator) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:59:51 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.