Kstars

scriptbuilder.cpp
1/*
2 SPDX-FileCopyrightText: 2003 Jason Harris <kstars@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "scriptbuilder.h"
8
9#include "kspaths.h"
10#include "scriptfunction.h"
11#include "kstars.h"
12#include "kstarsdata.h"
13#include "skymap.h"
14#include "ksnotification.h"
15#include "kstarsdatetime.h"
16#include "dialogs/finddialog.h"
17#include "dialogs/locationdialog.h"
18#include "widgets/dmsbox.h"
19#include "widgets/timespinbox.h"
20#include "widgets/timestepbox.h"
21
22#include <KLocalizedString>
23#include <KMessageBox>
24#include <KIO/StoredTransferJob>
25#include <KIO/CopyJob>
26#include <KJob>
27
28#include <QApplication>
29#include <QFontMetrics>
30#include <QTreeWidget>
31#include <QTextStream>
32#include <QFileDialog>
33#include <QStandardPaths>
34#include <QTemporaryFile>
35#include <QProcess>
36#include <QDebug>
37
38#include <sys/stat.h>
39
40OptionsTreeViewWidget::OptionsTreeViewWidget(QWidget *p) : QFrame(p)
41{
42 setupUi(this);
43}
44
45OptionsTreeView::OptionsTreeView(QWidget *p) : QDialog(p)
46{
47 otvw.reset(new OptionsTreeViewWidget(this));
48
49 QVBoxLayout *mainLayout = new QVBoxLayout;
50
51 mainLayout->addWidget(otvw.get());
52 setLayout(mainLayout);
53
54 setWindowTitle(i18nc("@title:window", "Options"));
55
57 mainLayout->addWidget(buttonBox);
58 connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
59 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
60
61 setModal(false);
62}
63
64void OptionsTreeView::resizeColumns()
65{
66 //Size each column to the maximum width of items in that column
67 int maxwidth[3] = { 0, 0, 0 };
68 QFontMetrics qfm = optionsList()->fontMetrics();
69
70 for (int i = 0; i < optionsList()->topLevelItemCount(); ++i)
71 {
72 QTreeWidgetItem *topitem = optionsList()->topLevelItem(i);
73 topitem->setExpanded(true);
74
75 for (int j = 0; j < topitem->childCount(); ++j)
76 {
77 QTreeWidgetItem *child = topitem->child(j);
78
79 for (int icol = 0; icol < 3; ++icol)
80 {
81 child->setExpanded(true);
82
83 int w = qfm.horizontalAdvance(child->text(icol)) + 4;
84
85 if (icol == 0)
86 {
87 w += 2 * optionsList()->indentation();
88 }
89
90 if (w > maxwidth[icol])
91 {
92 maxwidth[icol] = w;
93 }
94 }
95 }
96 }
97
98 for (int icol = 0; icol < 3; ++icol)
99 {
100 //DEBUG
101 qDebug() << Q_FUNC_INFO << QString("max width of column %1: %2").arg(icol).arg(maxwidth[icol]);
102
103 optionsList()->setColumnWidth(icol, maxwidth[icol]);
104 }
105}
106
107ScriptNameWidget::ScriptNameWidget(QWidget *p) : QFrame(p)
108{
109 setupUi(this);
110}
111
112ScriptNameDialog::ScriptNameDialog(QWidget *p) : QDialog(p)
113{
114#ifdef Q_OS_MACOS
115 setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
116#endif
117 snw = new ScriptNameWidget(this);
118
119 QVBoxLayout *mainLayout = new QVBoxLayout;
120
121 mainLayout->addWidget(snw);
122 setLayout(mainLayout);
123
124 setWindowTitle(i18nc("@title:window", "Script Data"));
125
127 mainLayout->addWidget(buttonBox);
128 connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
129 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
130
131 okB = buttonBox->button(QDialogButtonBox::Ok);
132
133 connect(snw->ScriptName, SIGNAL(textChanged(QString)), this, SLOT(slotEnableOkButton()));
134}
135
136ScriptNameDialog::~ScriptNameDialog()
137{
138 delete snw;
139}
140
141void ScriptNameDialog::slotEnableOkButton()
142{
143 okB->setEnabled(!snw->ScriptName->text().isEmpty());
144}
145
146ScriptBuilderUI::ScriptBuilderUI(QWidget *p) : QFrame(p)
147{
148 setupUi(this);
149}
150
151ScriptBuilder::ScriptBuilder(QWidget *parent)
152 : QDialog(parent), UnsavedChanges(false), checkForChanges(true), currentFileURL(), currentDir(QDir::homePath()),
153 currentScriptName(), currentAuthor()
154{
155#ifdef Q_OS_MACOS
156 setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
157#endif
158 sb = new ScriptBuilderUI(this);
159
160 QVBoxLayout *mainLayout = new QVBoxLayout;
161
162 mainLayout->addWidget(sb);
163 setLayout(mainLayout);
164
165 setWindowTitle(i18nc("@title:window", "Script Builder"));
166
168 mainLayout->addWidget(buttonBox);
169 connect(buttonBox, SIGNAL(rejected()), this, SLOT(slotClose()));
170
171 sb->FuncDoc->setTextInteractionFlags(Qt::NoTextInteraction);
172
173 //Initialize function templates and descriptions
174 KStarsFunctionList.append(new ScriptFunction("lookTowards",
175 i18n("Point the display at the specified location. %1 can be the name "
176 "of an object, a cardinal point on the compass, or 'zenith'.",
177 QString("dir")),
178 false, "QString", "dir"));
179 KStarsFunctionList.append(new ScriptFunction(
180 "addLabel", i18n("Add a name label to the object named %1.", QString("name")), false, "QString", "name"));
181 KStarsFunctionList.append(
182 new ScriptFunction("removeLabel", i18n("Remove the name label from the object named %1.", QString("name")),
183 false, "QString", "name"));
184 KStarsFunctionList.append(new ScriptFunction(
185 "addTrail", i18n("Add a trail to the solar system body named %1.", QString("name")), false, "QString", "name"));
186 KStarsFunctionList.append(new ScriptFunction(
187 "removeTrail", i18n("Remove the trail from the solar system body named %1.", QString("name")), false, "QString",
188 "name"));
189 KStarsFunctionList.append(new ScriptFunction("setRaDec",
190 i18n("Point the display at the specified RA/Dec coordinates. RA is "
191 "expressed in Hours; Dec is expressed in Degrees."),
192 false, "double", "ra", "double", "dec"));
193 KStarsFunctionList.append(new ScriptFunction(
194 "setAltAz",
195 i18n("Point the display at the specified Alt/Az coordinates. Alt and Az are expressed in Degrees."), false,
196 "double", "alt", "double", "az"));
197 KStarsFunctionList.append(new ScriptFunction("zoomIn", i18n("Increase the display Zoom Level."), false));
198 KStarsFunctionList.append(new ScriptFunction("zoomOut", i18n("Decrease the display Zoom Level."), false));
199 KStarsFunctionList.append(
200 new ScriptFunction("defaultZoom", i18n("Set the display Zoom Level to its default value."), false));
201 KStarsFunctionList.append(
202 new ScriptFunction("zoom", i18n("Set the display Zoom Level manually."), false, "double", "z"));
203 KStarsFunctionList.append(
204 new ScriptFunction("setLocalTime", i18n("Set the system clock to the specified Local Time."), false, "int",
205 "year", "int", "month", "int", "day", "int", "hour", "int", "minute", "int", "second"));
206 KStarsFunctionList.append(new ScriptFunction(
207 "waitFor", i18n("Pause script execution for specified number of seconds."), false, "double", "sec"));
208 KStarsFunctionList.append(new ScriptFunction("waitForKey",
209 i18n("Halt script execution until the specified key is pressed. Only "
210 "single-key strokes are possible; use 'space' for the spacebar."),
211 false, "QString", "key"));
212 KStarsFunctionList.append(new ScriptFunction(
213 "setTracking", i18n("Set whether the display is tracking the current location."), false, "bool", "track"));
214 KStarsFunctionList.append(new ScriptFunction(
215 "changeViewOption", i18n("Change view option named %1 to value %2.", QString("opName"), QString("opValue")),
216 false, "QString", "opName", "QString", "opValue"));
217 KStarsFunctionList.append(new ScriptFunction(
218 "setGeoLocation", i18n("Set the geographic location to the city specified by city, province and country."),
219 false, "QString", "cityName", "QString", "provinceName", "QString", "countryName"));
220 KStarsFunctionList.append(new ScriptFunction(
221 "setColor", i18n("Set the color named %1 to the value %2.", QString("colorName"), QString("value")), false,
222 "QString", "colorName", "QString", "value"));
223 KStarsFunctionList.append(new ScriptFunction("loadColorScheme", i18n("Load the color scheme specified by name."),
224 false, "QString", "name"));
225 KStarsFunctionList.append(
226 new ScriptFunction("exportImage", i18n("Export the sky image to the file, with specified width and height."),
227 false, "QString", "fileName", "int", "width", "int", "height"));
228 KStarsFunctionList.append(
229 new ScriptFunction("printImage",
230 i18n("Print the sky image to a printer or file. If %1 is true, it will show the print "
231 "dialog. If %2 is true, it will use the Star Chart color scheme for printing.",
232 QString("usePrintDialog"), QString("useChartColors")),
233 false, "bool", "usePrintDialog", "bool", "useChartColors"));
234 SimClockFunctionList.append(new ScriptFunction("stop", i18n("Halt the simulation clock."), true));
235 SimClockFunctionList.append(new ScriptFunction("start", i18n("Start the simulation clock."), true));
236 SimClockFunctionList.append(new ScriptFunction("setClockScale",
237 i18n("Set the timescale of the simulation clock to specified scale. "
238 " 1.0 means real-time; 2.0 means twice real-time; etc."),
239 true, "double", "scale"));
240
241 // JM: We're using QTreeWdiget for Qt4 now
242 QTreeWidgetItem *kstars_tree = new QTreeWidgetItem(sb->FunctionTree, QStringList("KStars"));
243 QTreeWidgetItem *simclock_tree = new QTreeWidgetItem(sb->FunctionTree, QStringList("SimClock"));
244
245 for (auto &item : KStarsFunctionList)
246 new QTreeWidgetItem(kstars_tree, QStringList(item->prototype()));
247
248 for (auto &item : SimClockFunctionList)
249 new QTreeWidgetItem(simclock_tree, QStringList(item->prototype()));
250
251 kstars_tree->sortChildren(0, Qt::AscendingOrder);
252 simclock_tree->sortChildren(0, Qt::AscendingOrder);
253
254 sb->FunctionTree->setColumnCount(1);
255 sb->FunctionTree->setHeaderLabels(QStringList(i18n("Functions")));
256 sb->FunctionTree->setSortingEnabled(false);
257
258 //Add icons to Push Buttons
259 sb->NewButton->setIcon(QIcon::fromTheme("document-new"));
260 sb->OpenButton->setIcon(QIcon::fromTheme("document-open"));
261 sb->SaveButton->setIcon(QIcon::fromTheme("document-save"));
262 sb->SaveAsButton->setIcon(
263 QIcon::fromTheme("document-save-as"));
264 sb->RunButton->setIcon(QIcon::fromTheme("system-run"));
265 sb->CopyButton->setIcon(QIcon::fromTheme("view-refresh"));
266 sb->AddButton->setIcon(QIcon::fromTheme("go-previous"));
267 sb->RemoveButton->setIcon(QIcon::fromTheme("go-next"));
268 sb->UpButton->setIcon(QIcon::fromTheme("go-up"));
269 sb->DownButton->setIcon(QIcon::fromTheme("go-down"));
270
271 sb->NewButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
272 sb->OpenButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
273 sb->SaveButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
274 sb->SaveAsButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
275 sb->RunButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
276 sb->CopyButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
277 sb->AddButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
278 sb->RemoveButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
279 sb->UpButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
280 sb->DownButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
281
282 //Prepare the widget stack
283 argBlank = new QWidget();
284 argLookToward = new ArgLookToward(sb->ArgStack);
285 argFindObject = new ArgFindObject(sb->ArgStack); //shared by Add/RemoveLabel and Add/RemoveTrail
286 argSetRaDec = new ArgSetRaDec(sb->ArgStack);
287 argSetAltAz = new ArgSetAltAz(sb->ArgStack);
288 argSetLocalTime = new ArgSetLocalTime(sb->ArgStack);
289 argWaitFor = new ArgWaitFor(sb->ArgStack);
290 argWaitForKey = new ArgWaitForKey(sb->ArgStack);
291 argSetTracking = new ArgSetTrack(sb->ArgStack);
292 argChangeViewOption = new ArgChangeViewOption(sb->ArgStack);
293 argSetGeoLocation = new ArgSetGeoLocation(sb->ArgStack);
294 argTimeScale = new ArgTimeScale(sb->ArgStack);
295 argZoom = new ArgZoom(sb->ArgStack);
296 argExportImage = new ArgExportImage(sb->ArgStack);
297 argPrintImage = new ArgPrintImage(sb->ArgStack);
298 argSetColor = new ArgSetColor(sb->ArgStack);
299 argLoadColorScheme = new ArgLoadColorScheme(sb->ArgStack);
300
301 sb->ArgStack->addWidget(argBlank);
302 sb->ArgStack->addWidget(argLookToward);
303 sb->ArgStack->addWidget(argFindObject);
304 sb->ArgStack->addWidget(argSetRaDec);
305 sb->ArgStack->addWidget(argSetAltAz);
306 sb->ArgStack->addWidget(argSetLocalTime);
307 sb->ArgStack->addWidget(argWaitFor);
308 sb->ArgStack->addWidget(argWaitForKey);
309 sb->ArgStack->addWidget(argSetTracking);
310 sb->ArgStack->addWidget(argChangeViewOption);
311 sb->ArgStack->addWidget(argSetGeoLocation);
312 sb->ArgStack->addWidget(argTimeScale);
313 sb->ArgStack->addWidget(argZoom);
314 sb->ArgStack->addWidget(argExportImage);
315 sb->ArgStack->addWidget(argPrintImage);
316 sb->ArgStack->addWidget(argSetColor);
317 sb->ArgStack->addWidget(argLoadColorScheme);
318
319 sb->ArgStack->setCurrentIndex(0);
320
321 snd = new ScriptNameDialog(KStars::Instance());
322 otv = new OptionsTreeView(KStars::Instance());
323
324 otv->resize(sb->width(), 0.5 * sb->height());
325
326 initViewOptions();
327 otv->resizeColumns();
328
329 //connect widgets in ScriptBuilderUI
330 connect(sb->FunctionTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(slotAddFunction()));
331 connect(sb->FunctionTree, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(slotShowDoc()));
332 connect(sb->UpButton, SIGNAL(clicked()), this, SLOT(slotMoveFunctionUp()));
333 connect(sb->ScriptListBox, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(slotArgWidget()));
334 connect(sb->DownButton, SIGNAL(clicked()), this, SLOT(slotMoveFunctionDown()));
335 connect(sb->CopyButton, SIGNAL(clicked()), this, SLOT(slotCopyFunction()));
336 connect(sb->RemoveButton, SIGNAL(clicked()), this, SLOT(slotRemoveFunction()));
337 connect(sb->NewButton, SIGNAL(clicked()), this, SLOT(slotNew()));
338 connect(sb->OpenButton, SIGNAL(clicked()), this, SLOT(slotOpen()));
339 connect(sb->SaveButton, SIGNAL(clicked()), this, SLOT(slotSave()));
340 connect(sb->SaveAsButton, SIGNAL(clicked()), this, SLOT(slotSaveAs()));
341 connect(sb->AddButton, SIGNAL(clicked()), this, SLOT(slotAddFunction()));
342 connect(sb->RunButton, SIGNAL(clicked()), this, SLOT(slotRunScript()));
343
344 //Connections for Arg Widgets
345 connect(argSetGeoLocation->FindCityButton, SIGNAL(clicked()), this, SLOT(slotFindCity()));
346 connect(argLookToward->FindButton, SIGNAL(clicked()), this, SLOT(slotFindObject()));
347 connect(argChangeViewOption->TreeButton, SIGNAL(clicked()), this, SLOT(slotShowOptions()));
348 connect(argFindObject->FindButton, SIGNAL(clicked()), this, SLOT(slotFindObject()));
349
350 connect(argLookToward->FocusEdit, SIGNAL(editTextChanged(QString)), this, SLOT(slotLookToward()));
351 connect(argFindObject->NameEdit, SIGNAL(textChanged(QString)), this, SLOT(slotArgFindObject()));
352 connect(argSetRaDec->RABox, SIGNAL(textChanged(QString)), this, SLOT(slotRa()));
353 connect(argSetRaDec->DecBox, SIGNAL(textChanged(QString)), this, SLOT(slotDec()));
354 connect(argSetAltAz->AltBox, SIGNAL(textChanged(QString)), this, SLOT(slotAlt()));
355 connect(argSetAltAz->AzBox, SIGNAL(textChanged(QString)), this, SLOT(slotAz()));
356 connect(argSetLocalTime->DateWidget, SIGNAL(dateChanged(QDate)), this, SLOT(slotChangeDate()));
357 connect(argSetLocalTime->TimeBox, SIGNAL(timeChanged(QTime)), this, SLOT(slotChangeTime()));
358 connect(argWaitFor->DelayBox, SIGNAL(valueChanged(int)), this, SLOT(slotWaitFor()));
359 connect(argWaitForKey->WaitKeyEdit, SIGNAL(textChanged(QString)), this, SLOT(slotWaitForKey()));
360 connect(argSetTracking->CheckTrack, SIGNAL(stateChanged(int)), this, SLOT(slotTracking()));
361 connect(argChangeViewOption->OptionName, SIGNAL(activated(QString)), this, SLOT(slotViewOption()));
362 connect(argChangeViewOption->OptionValue, SIGNAL(textChanged(QString)), this, SLOT(slotViewOption()));
363 connect(argSetGeoLocation->CityName, SIGNAL(textChanged(QString)), this, SLOT(slotChangeCity()));
364 connect(argSetGeoLocation->ProvinceName, SIGNAL(textChanged(QString)), this, SLOT(slotChangeProvince()));
365 connect(argSetGeoLocation->CountryName, SIGNAL(textChanged(QString)), this, SLOT(slotChangeCountry()));
366 connect(argTimeScale->TimeScale, SIGNAL(scaleChanged(float)), this, SLOT(slotTimeScale()));
367 connect(argZoom->ZoomBox, SIGNAL(textChanged(QString)), this, SLOT(slotZoom()));
368 connect(argExportImage->ExportFileName, SIGNAL(textChanged(QString)), this, SLOT(slotExportImage()));
369 connect(argExportImage->ExportWidth, SIGNAL(valueChanged(int)), this, SLOT(slotExportImage()));
370 connect(argExportImage->ExportHeight, SIGNAL(valueChanged(int)), this, SLOT(slotExportImage()));
371 connect(argPrintImage->UsePrintDialog, SIGNAL(toggled(bool)), this, SLOT(slotPrintImage()));
372 connect(argPrintImage->UseChartColors, SIGNAL(toggled(bool)), this, SLOT(slotPrintImage()));
373 connect(argSetColor->ColorName, SIGNAL(activated(QString)), this, SLOT(slotChangeColorName()));
374 connect(argSetColor->ColorValue, SIGNAL(changed(QColor)), this, SLOT(slotChangeColor()));
375 connect(argLoadColorScheme->SchemeList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(slotLoadColorScheme()));
376
377 //disable some buttons
378 sb->CopyButton->setEnabled(false);
379 sb->AddButton->setEnabled(false);
380 sb->RemoveButton->setEnabled(false);
381 sb->UpButton->setEnabled(false);
382 sb->DownButton->setEnabled(false);
383 sb->SaveButton->setEnabled(false);
384 sb->SaveAsButton->setEnabled(false);
385 sb->RunButton->setEnabled(false);
386}
387
388ScriptBuilder::~ScriptBuilder()
389{
390 while (!KStarsFunctionList.isEmpty())
391 delete KStarsFunctionList.takeFirst();
392
393 while (!SimClockFunctionList.isEmpty())
394 delete SimClockFunctionList.takeFirst();
395
396 while (!ScriptList.isEmpty())
397 delete ScriptList.takeFirst();
398}
399
400void ScriptBuilder::initViewOptions()
401{
402 otv->optionsList()->setRootIsDecorated(true);
403 QStringList fields;
404
405 //InfoBoxes
406 opsGUI = new QTreeWidgetItem(otv->optionsList(), QStringList(i18n("InfoBoxes")));
407 fields << "ShowInfoBoxes" << i18n("Toggle display of all InfoBoxes") << i18n("bool");
408 new QTreeWidgetItem(opsGUI, fields);
409 fields.clear();
410 fields << "ShowTimeBox" << i18n("Toggle display of Time InfoBox") << i18n("bool");
411 new QTreeWidgetItem(opsGUI, fields);
412 fields.clear();
413 fields << "ShowGeoBox" << i18n("Toggle display of Geographic InfoBox") << i18n("bool");
414 new QTreeWidgetItem(opsGUI, fields);
415 fields.clear();
416 fields << "ShowFocusBox" << i18n("Toggle display of Focus InfoBox") << i18n("bool");
417 new QTreeWidgetItem(opsGUI, fields);
418 fields.clear();
419 fields << "ShadeTimeBox" << i18n("(un)Shade Time InfoBox") << i18n("bool");
420 new QTreeWidgetItem(opsGUI, fields);
421 fields.clear();
422 fields << "ShadeGeoBox" << i18n("(un)Shade Geographic InfoBox") << i18n("bool");
423 new QTreeWidgetItem(opsGUI, fields);
424 fields.clear();
425 fields << "ShadeFocusBox" << i18n("(un)Shade Focus InfoBox") << i18n("bool");
426 new QTreeWidgetItem(opsGUI, fields);
427 fields.clear();
428
429 argChangeViewOption->OptionName->addItem("ShowInfoBoxes");
430 argChangeViewOption->OptionName->addItem("ShowTimeBox");
431 argChangeViewOption->OptionName->addItem("ShowGeoBox");
432 argChangeViewOption->OptionName->addItem("ShowFocusBox");
433 argChangeViewOption->OptionName->addItem("ShadeTimeBox");
434 argChangeViewOption->OptionName->addItem("ShadeGeoBox");
435 argChangeViewOption->OptionName->addItem("ShadeFocusBox");
436
437 //Toolbars
438 opsToolbar = new QTreeWidgetItem(otv->optionsList(), QStringList(i18n("Toolbars")));
439 fields << "ShowMainToolBar" << i18n("Toggle display of main toolbar") << i18n("bool");
440 new QTreeWidgetItem(opsToolbar, fields);
441 fields.clear();
442 fields << "ShowViewToolBar" << i18n("Toggle display of view toolbar") << i18n("bool");
443 new QTreeWidgetItem(opsToolbar, fields);
444 fields.clear();
445
446 argChangeViewOption->OptionName->addItem("ShowMainToolBar");
447 argChangeViewOption->OptionName->addItem("ShowViewToolBar");
448
449 //Show Objects
450 opsShowObj = new QTreeWidgetItem(otv->optionsList(), QStringList(i18n("Show Objects")));
451 fields << "ShowStars" << i18n("Toggle display of Stars") << i18n("bool");
452 new QTreeWidgetItem(opsShowObj, fields);
453 fields.clear();
454 fields << "ShowDeepSky" << i18n("Toggle display of all deep-sky objects") << i18n("bool");
455 new QTreeWidgetItem(opsShowObj, fields);
456 fields.clear();
457 new QTreeWidgetItem(opsShowObj, fields);
458 fields.clear();
459 new QTreeWidgetItem(opsShowObj, fields);
460 fields.clear();
461 fields << "ShowSolarSystem" << i18n("Toggle display of all solar system bodies") << i18n("bool");
462 new QTreeWidgetItem(opsShowObj, fields);
463 fields.clear();
464 fields << "ShowSun" << i18n("Toggle display of Sun") << i18n("bool");
465 new QTreeWidgetItem(opsShowObj, fields);
466 fields.clear();
467 fields << "ShowMoon" << i18n("Toggle display of Moon") << i18n("bool");
468 new QTreeWidgetItem(opsShowObj, fields);
469 fields.clear();
470 fields << "ShowMercury" << i18n("Toggle display of Mercury") << i18n("bool");
471 new QTreeWidgetItem(opsShowObj, fields);
472 fields.clear();
473 fields << "ShowVenus" << i18n("Toggle display of Venus") << i18n("bool");
474 new QTreeWidgetItem(opsShowObj, fields);
475 fields.clear();
476 fields << "ShowMars" << i18n("Toggle display of Mars") << i18n("bool");
477 new QTreeWidgetItem(opsShowObj, fields);
478 fields.clear();
479 fields << "ShowJupiter" << i18n("Toggle display of Jupiter") << i18n("bool");
480 new QTreeWidgetItem(opsShowObj, fields);
481 fields.clear();
482 fields << "ShowSaturn" << i18n("Toggle display of Saturn") << i18n("bool");
483 new QTreeWidgetItem(opsShowObj, fields);
484 fields.clear();
485 fields << "ShowUranus" << i18n("Toggle display of Uranus") << i18n("bool");
486 new QTreeWidgetItem(opsShowObj, fields);
487 fields.clear();
488 fields << "ShowNeptune" << i18n("Toggle display of Neptune") << i18n("bool");
489 new QTreeWidgetItem(opsShowObj, fields);
490 //fields.clear();
491 //fields << "ShowPluto" << i18n( "Toggle display of Pluto" ) << i18n( "bool" );
492 //new QTreeWidgetItem( opsShowObj, fields );
493 fields.clear();
494 fields << "ShowAsteroids" << i18n("Toggle display of Asteroids") << i18n("bool");
495 new QTreeWidgetItem(opsShowObj, fields);
496 fields.clear();
497 fields << "ShowComets" << i18n("Toggle display of Comets") << i18n("bool");
498 new QTreeWidgetItem(opsShowObj, fields);
499 fields.clear();
500
501 argChangeViewOption->OptionName->addItem("ShowStars");
502 argChangeViewOption->OptionName->addItem("ShowDeepSky");
503 argChangeViewOption->OptionName->addItem("ShowSolarSystem");
504 argChangeViewOption->OptionName->addItem("ShowSun");
505 argChangeViewOption->OptionName->addItem("ShowMoon");
506 argChangeViewOption->OptionName->addItem("ShowMercury");
507 argChangeViewOption->OptionName->addItem("ShowVenus");
508 argChangeViewOption->OptionName->addItem("ShowMars");
509 argChangeViewOption->OptionName->addItem("ShowJupiter");
510 argChangeViewOption->OptionName->addItem("ShowSaturn");
511 argChangeViewOption->OptionName->addItem("ShowUranus");
512 argChangeViewOption->OptionName->addItem("ShowNeptune");
513 //argChangeViewOption->OptionName->addItem( "ShowPluto" );
514 argChangeViewOption->OptionName->addItem("ShowAsteroids");
515 argChangeViewOption->OptionName->addItem("ShowComets");
516
517 opsShowOther = new QTreeWidgetItem(otv->optionsList(), QStringList(i18n("Show Other")));
518 fields << "ShowCLines" << i18n("Toggle display of constellation lines") << i18n("bool");
519 new QTreeWidgetItem(opsShowOther, fields);
520 fields.clear();
521 fields << "ShowCBounds" << i18n("Toggle display of constellation boundaries") << i18n("bool");
522 new QTreeWidgetItem(opsShowOther, fields);
523 fields.clear();
524 fields << "ShowCNames" << i18n("Toggle display of constellation names") << i18n("bool");
525 new QTreeWidgetItem(opsShowOther, fields);
526 fields.clear();
527 fields << "ShowMilkyWay" << i18n("Toggle display of Milky Way") << i18n("bool");
528 new QTreeWidgetItem(opsShowOther, fields);
529 fields.clear();
530 fields << "ShowGrid" << i18n("Toggle display of the coordinate grid") << i18n("bool");
531 new QTreeWidgetItem(opsShowOther, fields);
532 fields.clear();
533 fields << "ShowEquator" << i18n("Toggle display of the celestial equator") << i18n("bool");
534 new QTreeWidgetItem(opsShowOther, fields);
535 fields.clear();
536 fields << "ShowEcliptic" << i18n("Toggle display of the ecliptic") << i18n("bool");
537 new QTreeWidgetItem(opsShowOther, fields);
538 fields.clear();
539 fields << "ShowHorizon" << i18n("Toggle display of the horizon line") << i18n("bool");
540 new QTreeWidgetItem(opsShowOther, fields);
541 fields.clear();
542 fields << "ShowGround" << i18n("Toggle display of the opaque ground") << i18n("bool");
543 new QTreeWidgetItem(opsShowOther, fields);
544 fields.clear();
545 fields << "ShowStarNames" << i18n("Toggle display of star name labels") << i18n("bool");
546 new QTreeWidgetItem(opsShowOther, fields);
547 fields.clear();
548 fields << "ShowStarMagnitudes" << i18n("Toggle display of star magnitude labels") << i18n("bool");
549 new QTreeWidgetItem(opsShowOther, fields);
550 fields.clear();
551 fields << "ShowAsteroidNames" << i18n("Toggle display of asteroid name labels") << i18n("bool");
552 new QTreeWidgetItem(opsShowOther, fields);
553 fields.clear();
554 fields << "ShowCometNames" << i18n("Toggle display of comet name labels") << i18n("bool");
555 new QTreeWidgetItem(opsShowOther, fields);
556 fields.clear();
557 fields << "ShowPlanetNames" << i18n("Toggle display of planet name labels") << i18n("bool");
558 new QTreeWidgetItem(opsShowOther, fields);
559 fields.clear();
560 fields << "ShowPlanetImages" << i18n("Toggle display of planet images") << i18n("bool");
561 new QTreeWidgetItem(opsShowOther, fields);
562 fields.clear();
563
564 argChangeViewOption->OptionName->addItem("ShowCLines");
565 argChangeViewOption->OptionName->addItem("ShowCBounds");
566 argChangeViewOption->OptionName->addItem("ShowCNames");
567 argChangeViewOption->OptionName->addItem("ShowMilkyWay");
568 argChangeViewOption->OptionName->addItem("ShowGrid");
569 argChangeViewOption->OptionName->addItem("ShowEquator");
570 argChangeViewOption->OptionName->addItem("ShowEcliptic");
571 argChangeViewOption->OptionName->addItem("ShowHorizon");
572 argChangeViewOption->OptionName->addItem("ShowGround");
573 argChangeViewOption->OptionName->addItem("ShowStarNames");
574 argChangeViewOption->OptionName->addItem("ShowStarMagnitudes");
575 argChangeViewOption->OptionName->addItem("ShowAsteroidNames");
576 argChangeViewOption->OptionName->addItem("ShowCometNames");
577 argChangeViewOption->OptionName->addItem("ShowPlanetNames");
578 argChangeViewOption->OptionName->addItem("ShowPlanetImages");
579
580 opsCName = new QTreeWidgetItem(otv->optionsList(), QStringList(i18n("Constellation Names")));
581 fields << "UseLatinConstellNames" << i18n("Show Latin constellation names") << i18n("bool");
582 new QTreeWidgetItem(opsCName, fields);
583 fields.clear();
584 fields << "UseLocalConstellNames" << i18n("Show constellation names in local language") << i18n("bool");
585 new QTreeWidgetItem(opsCName, fields);
586 fields.clear();
587 fields << "UseAbbrevConstellNames" << i18n("Show IAU-standard constellation abbreviations") << i18n("bool");
588 new QTreeWidgetItem(opsCName, fields);
589 fields.clear();
590
591 argChangeViewOption->OptionName->addItem("UseLatinConstellNames");
592 argChangeViewOption->OptionName->addItem("UseLocalConstellNames");
593 argChangeViewOption->OptionName->addItem("UseAbbrevConstellNames");
594
595 opsHide = new QTreeWidgetItem(otv->optionsList(), QStringList(i18n("Hide Items")));
596 fields << "HideOnSlew" << i18n("Toggle whether objects hidden while slewing display") << i18n("bool");
597 new QTreeWidgetItem(opsHide, fields);
598 fields.clear();
599 fields << "SlewTimeScale" << i18n("Timestep threshold (in seconds) for hiding objects") << i18n("double");
600 new QTreeWidgetItem(opsHide, fields);
601 fields.clear();
602 fields << "HideStars" << i18n("Hide faint stars while slewing?") << i18n("bool");
603 new QTreeWidgetItem(opsHide, fields);
604 fields.clear();
605 fields << "HidePlanets" << i18n("Hide solar system bodies while slewing?") << i18n("bool");
606 new QTreeWidgetItem(opsHide, fields);
607 fields.clear();
608 fields << "HideMilkyWay" << i18n("Hide Milky Way while slewing?") << i18n("bool");
609 new QTreeWidgetItem(opsHide, fields);
610 fields.clear();
611 fields << "HideCNames" << i18n("Hide constellation names while slewing?") << i18n("bool");
612 new QTreeWidgetItem(opsHide, fields);
613 fields.clear();
614 fields << "HideCLines" << i18n("Hide constellation lines while slewing?") << i18n("bool");
615 new QTreeWidgetItem(opsHide, fields);
616 fields.clear();
617 fields << "HideCBounds" << i18n("Hide constellation boundaries while slewing?") << i18n("bool");
618 new QTreeWidgetItem(opsHide, fields);
619 fields.clear();
620 fields << "HideGrid" << i18n("Hide coordinate grid while slewing?") << i18n("bool");
621 new QTreeWidgetItem(opsHide, fields);
622 fields.clear();
623
624 argChangeViewOption->OptionName->addItem("HideOnSlew");
625 argChangeViewOption->OptionName->addItem("SlewTimeScale");
626 argChangeViewOption->OptionName->addItem("HideStars");
627 argChangeViewOption->OptionName->addItem("HidePlanets");
628 argChangeViewOption->OptionName->addItem("HideMilkyWay");
629 argChangeViewOption->OptionName->addItem("HideCNames");
630 argChangeViewOption->OptionName->addItem("HideCLines");
631 argChangeViewOption->OptionName->addItem("HideCBounds");
632 argChangeViewOption->OptionName->addItem("HideGrid");
633
634 opsSkymap = new QTreeWidgetItem(otv->optionsList(), QStringList(i18n("Skymap Options")));
635 fields << "UseAltAz" << i18n("Use Horizontal coordinates? (otherwise, use Equatorial)") << i18n("bool");
636 new QTreeWidgetItem(opsSkymap, fields);
637 fields.clear();
638 fields << "ZoomFactor" << i18n("Set the Zoom Factor") << i18n("double");
639 new QTreeWidgetItem(opsSkymap, fields);
640 fields.clear();
641 fields << "FOVName" << i18n("Select angular size for the FOV symbol (in arcmin)") << i18n("double");
642 new QTreeWidgetItem(opsSkymap, fields);
643 fields.clear();
644 fields << "FOVShape" << i18n("Select shape for the FOV symbol (0=Square, 1=Circle, 2=Crosshairs, 4=Bullseye)")
645 << i18n("int");
646 new QTreeWidgetItem(opsSkymap, fields);
647 fields.clear();
648 fields << "FOVColor" << i18n("Select color for the FOV symbol") << i18n("string");
649 new QTreeWidgetItem(opsSkymap, fields);
650 fields.clear();
651 fields << "UseAnimatedSlewing" << i18n("Use animated slewing? (otherwise, \"snap\" to new focus)") << i18n("bool");
652 new QTreeWidgetItem(opsSkymap, fields);
653 fields.clear();
654 fields << "UseRefraction" << i18n("Correct for atmospheric refraction?") << i18n("bool");
655 new QTreeWidgetItem(opsSkymap, fields);
656 fields.clear();
657 fields << "UseAutoLabel" << i18n("Automatically attach name label to centered object?") << i18n("bool");
658 new QTreeWidgetItem(opsSkymap, fields);
659 fields.clear();
660 fields << "UseHoverLabel" << i18n("Attach temporary name label when hovering mouse over an object?")
661 << i18n("bool");
662 new QTreeWidgetItem(opsSkymap, fields);
663 fields.clear();
664 fields << "UseAutoTrail" << i18n("Automatically add trail to centered solar system body?") << i18n("bool");
665 new QTreeWidgetItem(opsSkymap, fields);
666 fields.clear();
667 fields << "FadePlanetTrails" << i18n("Planet trails fade to sky color? (otherwise color is constant)")
668 << i18n("bool");
669 new QTreeWidgetItem(opsSkymap, fields);
670 fields.clear();
671
672 argChangeViewOption->OptionName->addItem("UseAltAz");
673 argChangeViewOption->OptionName->addItem("ZoomFactor");
674 argChangeViewOption->OptionName->addItem("FOVName");
675 argChangeViewOption->OptionName->addItem("FOVSize");
676 argChangeViewOption->OptionName->addItem("FOVShape");
677 argChangeViewOption->OptionName->addItem("FOVColor");
678 argChangeViewOption->OptionName->addItem("UseRefraction");
679 argChangeViewOption->OptionName->addItem("UseAutoLabel");
680 argChangeViewOption->OptionName->addItem("UseHoverLabel");
681 argChangeViewOption->OptionName->addItem("UseAutoTrail");
682 argChangeViewOption->OptionName->addItem("AnimateSlewing");
683 argChangeViewOption->OptionName->addItem("FadePlanetTrails");
684
685 opsLimit = new QTreeWidgetItem(otv->optionsList(), QStringList(i18n("Limits")));
686 /*
687 fields << "magLimitDrawStar" << i18n( "magnitude of faintest star drawn on map when zoomed in" ) << i18n( "double" );
688 new QTreeWidgetItem( opsLimit, fields );
689 fields.clear();
690 fields << "magLimitDrawStarZoomOut" << i18n( "magnitude of faintest star drawn on map when zoomed out" ) << i18n( "double" );
691 new QTreeWidgetItem( opsLimit, fields );
692 fields.clear();
693 */
694
695 // TODO: We have disabled the following two features. Enable them when feasible...
696 /*
697 fields << "magLimitDrawDeepSky" << i18n( "magnitude of faintest nonstellar object drawn on map when zoomed in" ) << i18n( "double" );
698 new QTreeWidgetItem( opsLimit, fields );
699 fields.clear();
700 fields << "magLimitDrawDeepSkyZoomOut" << i18n( "magnitude of faintest nonstellar object drawn on map when zoomed out" ) << i18n( "double" );
701 new QTreeWidgetItem( opsLimit, fields );
702 fields.clear();
703 */
704
705 //FIXME: This description is incorrect! Fix after strings freeze
706 fields << "starLabelDensity" << i18n("magnitude of faintest star labeled on map") << i18n("double");
707 new QTreeWidgetItem(opsLimit, fields);
708 fields.clear();
709 fields << "magLimitHideStar" << i18n("magnitude of brightest star hidden while slewing") << i18n("double");
710 new QTreeWidgetItem(opsLimit, fields);
711 fields.clear();
712 fields << "magLimitAsteroid" << i18n("magnitude of faintest asteroid drawn on map") << i18n("double");
713 new QTreeWidgetItem(opsLimit, fields);
714 fields.clear();
715 //FIXME: This description is incorrect! Fix after strings freeze
716 fields << "asteroidLabelDensity" << i18n("magnitude of faintest asteroid labeled on map") << i18n("double");
717 new QTreeWidgetItem(opsLimit, fields);
718 fields.clear();
719 fields << "maxRadCometName" << i18n("comets nearer to the Sun than this (in AU) are labeled on map")
720 << i18n("double");
721 new QTreeWidgetItem(opsLimit, fields);
722 fields.clear();
723
724 // argChangeViewOption->OptionName->addItem( "magLimitDrawStar" );
725 // argChangeViewOption->OptionName->addItem( "magLimitDrawStarZoomOut" );
726 argChangeViewOption->OptionName->addItem("magLimitDrawDeepSky");
727 argChangeViewOption->OptionName->addItem("magLimitDrawDeepSkyZoomOut");
728 argChangeViewOption->OptionName->addItem("starLabelDensity");
729 argChangeViewOption->OptionName->addItem("magLimitHideStar");
730 argChangeViewOption->OptionName->addItem("magLimitAsteroid");
731 argChangeViewOption->OptionName->addItem("asteroidLabelDensity");
732 argChangeViewOption->OptionName->addItem("maxRadCometName");
733
734 //init the list of color names and values
735 for (unsigned int i = 0; i < KStarsData::Instance()->colorScheme()->numberOfColors(); ++i)
736 {
737 argSetColor->ColorName->addItem(KStarsData::Instance()->colorScheme()->nameAt(i));
738 }
739
740 //init list of color scheme names
741 argLoadColorScheme->SchemeList->addItem(i18nc("use default color scheme", "Default Colors"));
742 argLoadColorScheme->SchemeList->addItem(i18nc("use 'star chart' color scheme", "Star Chart"));
743 argLoadColorScheme->SchemeList->addItem(i18nc("use 'night vision' color scheme", "Night Vision"));
744 argLoadColorScheme->SchemeList->addItem(i18nc("use 'moonless night' color scheme", "Moonless Night"));
745
746 QFile file;
747 QString line;
748 //determine filename in local user KDE directory tree.
749 file.setFileName(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "colors.dat"));
750 if (file.open(QIODevice::ReadOnly))
751 {
752 QTextStream stream(&file);
753
754 while (!stream.atEnd())
755 {
756 line = stream.readLine();
757 argLoadColorScheme->SchemeList->addItem(line.left(line.indexOf(':')));
758 }
759 file.close();
760 }
761}
762
763//Slots defined in ScriptBuilderUI
764void ScriptBuilder::slotNew()
765{
766 saveWarning();
767 if (!UnsavedChanges)
768 {
769 ScriptList.clear();
770 sb->ScriptListBox->clear();
771 sb->ArgStack->setCurrentWidget(argBlank);
772
773 sb->CopyButton->setEnabled(false);
774 sb->RemoveButton->setEnabled(false);
775 sb->RunButton->setEnabled(false);
776 sb->SaveAsButton->setEnabled(false);
777
778 currentFileURL.clear();
779 currentScriptName.clear();
780 }
781}
782
783void ScriptBuilder::slotOpen()
784{
785 saveWarning();
786
787 QString fname;
788 QTemporaryFile tmpfile;
789 tmpfile.open();
790
791 if (!UnsavedChanges)
792 {
793 currentFileURL = QFileDialog::getOpenFileUrl(
794 KStars::Instance(), QString(), QUrl(currentDir),
795 "*.kstars|" + i18nc("Filter by file type: KStars Scripts.", "KStars Scripts (*.kstars)"));
796
797 if (currentFileURL.isValid())
798 {
799 currentDir = currentFileURL.toLocalFile();
800
801 ScriptList.clear();
802 sb->ScriptListBox->clear();
803 sb->ArgStack->setCurrentWidget(argBlank);
804
805 if (currentFileURL.isLocalFile())
806 {
807 fname = currentFileURL.toLocalFile();
808 }
809 else
810 {
811 fname = tmpfile.fileName();
812 if (KIO::copy(currentFileURL, QUrl(fname))->exec() == false)
813 //if ( ! KIO::NetAccess::download( currentFileURL, fname, (QWidget*) 0 ) )
814 KSNotification::sorry(i18n("Could not download remote file."), i18n("Download Error"));
815 }
816
817 QFile f(fname);
818 if (!f.open(QIODevice::ReadOnly))
819 {
820 KSNotification::sorry(i18n("Could not open file %1.", f.fileName()), i18n("Could Not Open File"));
821 currentFileURL.clear();
822 return;
823 }
824
825 QTextStream istream(&f);
826 readScript(istream);
827
828 f.close();
829 }
830 else if (!currentFileURL.url().isEmpty())
831 {
832 KSNotification::sorry(i18n("Invalid URL: %1", currentFileURL.url()), i18n("Invalid URL"));
833 currentFileURL.clear();
834 }
835 }
836}
837
838void ScriptBuilder::slotSave()
839{
840 QString fname;
841 QTemporaryFile tmpfile;
842 tmpfile.open();
843
844 if (currentScriptName.isEmpty())
845 {
846 //Get Script Name and Author info
847 if (snd->exec() == QDialog::Accepted)
848 {
849 currentScriptName = snd->scriptName();
850 currentAuthor = snd->authorName();
851 }
852 else
853 {
854 return;
855 }
856 }
857
858 bool newFilename = false;
859 if (currentFileURL.isEmpty())
860 {
861 currentFileURL = QFileDialog::getSaveFileUrl(
862 KStars::Instance(), QString(), QUrl(currentDir),
863 "*.kstars|" + i18nc("Filter by file type: KStars Scripts.", "KStars Scripts (*.kstars)"));
864 newFilename = true;
865 }
866
867 if (currentFileURL.isValid())
868 {
869 currentDir = currentFileURL.toLocalFile();
870
871 if (currentFileURL.isLocalFile())
872 {
873 fname = currentFileURL.toLocalFile();
874
875 //Warn user if file exists
876 if (newFilename == true && QFile::exists(currentFileURL.toLocalFile()))
877 {
878 int r = KMessageBox::warningContinueCancel(static_cast<QWidget *>(parent()),
879 i18n("A file named \"%1\" already exists. "
880 "Overwrite it?",
881 currentFileURL.fileName()),
882 i18n("Overwrite File?"), KStandardGuiItem::overwrite());
883
884 if (r == KMessageBox::Cancel)
885 return;
886 }
887 }
888 else
889 {
890 fname = tmpfile.fileName();
891 }
892
893 if (fname.right(7).toLower() != ".kstars")
894 fname += ".kstars";
895
896 QFile f(fname);
897 if (!f.open(QIODevice::WriteOnly))
898 {
899 QString message = i18n("Could not open file %1.", f.fileName());
900 KSNotification::sorry(message, i18n("Could Not Open File"));
901 currentFileURL.clear();
902 return;
903 }
904
905 QTextStream ostream(&f);
906 writeScript(ostream);
907 f.close();
908
909#ifndef _WIN32
910 //set rwx for owner, rx for group, rx for other
911 chmod(fname.toLatin1(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
912#endif
913
914 if (tmpfile.fileName() == fname)
915 {
916 //need to upload to remote location
917 //if ( ! KIO::NetAccess::upload( tmpfile.fileName(), currentFileURL, (QWidget*) 0 ) )
918 if (KIO::storedHttpPost(&tmpfile, currentFileURL)->exec() == false)
919 {
920 QString message = i18n("Could not upload image to remote location: %1", currentFileURL.url());
921 KSNotification::sorry(message, i18n("Could not upload file"));
922 }
923 }
924
925 setUnsavedChanges(false);
926 }
927 else
928 {
929 QString message = i18n("Invalid URL: %1", currentFileURL.url());
930 KSNotification::sorry(message, i18n("Invalid URL"));
931 currentFileURL.clear();
932 }
933}
934
935void ScriptBuilder::slotSaveAs()
936{
937 currentFileURL.clear();
938 currentScriptName.clear();
939 slotSave();
940}
941
942void ScriptBuilder::saveWarning()
943{
944 if (UnsavedChanges)
945 {
946 QString caption = i18n("Save Changes to Script?");
947 QString message = i18n("The current script has unsaved changes. Would you like to save before closing it?");
948 int ans =
950 if (ans == KMessageBox::Continue)
951 {
952 slotSave();
953 setUnsavedChanges(false);
954 }
955 else if (ans == KMessageBox::Cancel)
956 {
957 setUnsavedChanges(false);
958 }
959
960 //Do nothing if 'cancel' selected
961 }
962}
963
964void ScriptBuilder::slotRunScript()
965{
966 //hide window while script runs
967 // If this is uncommented, the program hangs before the script is executed. Why?
968 // hide();
969
970 //Save current script to a temporary file, then execute that file.
971 //For some reason, I can't use KTempFile here! If I do, then the temporary script
972 //is not executable. Bizarre...
973 //KTempFile tmpfile;
974 //QString fname = tmpfile.name();
975 QString fname = QDir::tempPath() + QDir::separator() + "kstars-tempscript";
976
977 QFile f(fname);
978 if (f.exists())
979 f.remove();
980 if (!f.open(QIODevice::WriteOnly))
981 {
982 QString message = i18n("Could not open file %1.", f.fileName());
983 KSNotification::sorry(message, i18n("Could Not Open File"));
984 currentFileURL.clear();
985 return;
986 }
987
988 QTextStream ostream(&f);
989 writeScript(ostream);
990 f.close();
991
992#ifndef _WIN32
993 //set rwx for owner, rx for group, rx for other
994 chmod(QFile::encodeName(f.fileName()), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
995#endif
996
997 QProcess p;
998#ifdef Q_OS_MACOS
999 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
1000 QString path = env.value("PATH", "");
1001 env.insert("PATH", "/usr/local/bin:" + QCoreApplication::applicationDirPath() + ':' + path);
1002 p.setProcessEnvironment(env);
1003#endif
1004 QStringList arguments;
1005 p.start(f.fileName(), arguments);
1006
1007 if (!p.waitForStarted())
1008 qDebug() << Q_FUNC_INFO << "Process did not start.";
1009
1010 while (!p.waitForFinished(10))
1011 {
1012 qApp->processEvents(); //otherwise tempfile may get deleted before script completes.
1013 if (p.state() != QProcess::Running)
1014 break;
1015 }
1016 //delete temp file
1017 if (f.exists())
1018 f.remove();
1019
1020 //uncomment if 'hide()' is uncommented...
1021 // show();
1022}
1023
1024/*
1025 This can't work anymore and is also not portable in any way :(
1026*/
1027void ScriptBuilder::writeScript(QTextStream &ostream)
1028{
1029 // FIXME Without --print-reply, the dbus-send doesn't do anything, why??
1030 QString dbus_call = "dbus-send --dest=org.kde.kstars --print-reply ";
1031 QString main_method = "/KStars org.kde.kstars.";
1032 QString clock_method = "/KStars/SimClock org.kde.kstars.SimClock.";
1033
1034 //Write script header
1035 ostream << "#!/bin/bash\n";
1036 ostream << "#KStars DBus script: " << currentScriptName << '\n';
1037 ostream << "#by " << currentAuthor << '\n';
1038 ostream << "#last modified: " << KStarsDateTime::currentDateTime().toString(Qt::ISODate) << '\n';
1039 ostream << "#\n";
1040
1041 foreach (ScriptFunction *sf, ScriptList)
1042 {
1043 if (!sf->valid())
1044 continue;
1045
1046 if (sf->isClockFunction())
1047 {
1048 ostream << dbus_call << clock_method << sf->scriptLine() << '\n';
1049 }
1050 else
1051 {
1052 ostream << dbus_call << main_method << sf->scriptLine() << '\n';
1053 }
1054 }
1055
1056 //Write script footer
1057 ostream << "##\n";
1058 ostream.flush();
1059}
1060
1061void ScriptBuilder::readScript(QTextStream &istream)
1062{
1063 QString line;
1064 QString service_name = "org.kde.kstars.";
1065 QString fn_name;
1066
1067 while (!istream.atEnd())
1068 {
1069 line = istream.readLine();
1070
1071 //look for name of script
1072 if (line.contains("#KStars DBus script: "))
1073 currentScriptName = line.mid(21).trimmed();
1074
1075 //look for author of scriptbuilder
1076 if (line.contains("#by "))
1077 currentAuthor = line.mid(4).trimmed();
1078
1079 //Actual script functions
1080 if (line.left(4) == "dbus")
1081 {
1082 //is ClockFunction?
1083 if (line.contains("SimClock"))
1084 {
1085 service_name += "SimClock.";
1086 }
1087
1088 //remove leading dbus prefix
1089 line = line.mid(line.lastIndexOf(service_name) + service_name.count());
1090
1091 fn_name = line.left(line.indexOf(' '));
1092
1093 line = line.mid(line.indexOf(' ') + 1);
1094
1095 //construct a stringlist that is fcn name and its arg name/value pairs
1096 QStringList fn;
1097
1098 // If the function lacks any arguments, do not attempt to split
1099 // if (fn_name != line)
1100 // fn = line.split(' ');
1101
1102 if (parseFunction(fn_name, line))
1103 {
1104 sb->ScriptListBox->addItem(ScriptList.last()->name());
1105 // Initially, any read script is valid!
1106 ScriptList.last()->setValid(true);
1107 }
1108 else
1109 qWarning() << i18n("Could not parse script. Line was: %1", line);
1110
1111 } // end if left(4) == "dcop"
1112 } // end while !atEnd()
1113
1114 //Select first item in sb->ScriptListBox
1115 if (sb->ScriptListBox->count())
1116 {
1117 sb->ScriptListBox->setCurrentItem(nullptr);
1118 slotArgWidget();
1119 }
1120}
1121
1122bool ScriptBuilder::parseFunction(const QString &fn_name, const QString &fn_args)
1123{
1124 // clean up the string list first if needed
1125 // We need to perform this in case we havea quoted string "NGC 3000" because this will counted
1126 // as two arguments, and it should be counted as one.
1127 // bool foundQuote(false), quoteProcessed(false);
1128 // QString cur, arg;
1129 // QStringList::iterator it;
1130
1131 // for (it = fn.begin(); it != fn.end(); ++it)
1132 // {
1133 // cur = (*it);
1134
1135 // cur = cur.mid(cur.indexOf(":") + 1).remove('\'');
1136
1137 // (*it) = cur;
1138
1139 // if (cur.startsWith('\"'))
1140 // {
1141 // arg += cur.rightRef(cur.length() - 1);
1142 // arg += ' ';
1143 // foundQuote = true;
1144 // quoteProcessed = true;
1145 // }
1146 // else if (cur.endsWith('\"'))
1147 // {
1148 // arg += cur.leftRef(cur.length() - 1);
1149 // arg += '\'';
1150 // foundQuote = false;
1151 // }
1152 // else if (foundQuote)
1153 // {
1154 // arg += cur;
1155 // arg += ' ';
1156 // }
1157 // else
1158 // {
1159 // arg += cur;
1160 // arg += '\'';
1161 // }
1162 // }
1163
1164 // if (quoteProcessed)
1165 // fn = arg.split(' ', QString::SkipEmptyParts);
1166
1167 QRegularExpression re("(?<=:)[^:\\s]*");
1168 QRegularExpressionMatchIterator i = re.globalMatch(fn_args);
1169 QStringList fn;
1170 while (i.hasNext())
1171 {
1172 QRegularExpressionMatch match = i.next();
1173 fn << match.captured(0).remove("\"");
1174 };
1175
1176 //loop over known functions to find a name match
1177 for (auto &sf : KStarsFunctionList)
1178 {
1179 if (fn_name == sf->name())
1180 {
1181 // if (fn_name == "setGeoLocation")
1182 // {
1183 // ScriptList.append(new ScriptFunction(sf));
1184 // ScriptList.last()->setArg(0, fn[0]);
1185 // ScriptList.last()->setArg(1, fn[1]);
1186 // ScriptList.last()->setArg(2, fn[2]);
1187 // }
1188 // else if (fn.count() != sf->numArgs())
1189 // return false;
1190
1191 ScriptList.append(new ScriptFunction(sf));
1192
1193 for (int i = 0; i < sf->numArgs(); ++i)
1194 ScriptList.last()->setArg(i, fn[i]);
1195
1196 return true;
1197 }
1198
1199 foreach (ScriptFunction *sf, SimClockFunctionList)
1200 {
1201 if (fn_name == sf->name())
1202 {
1203 if (fn.count() != sf->numArgs())
1204 return false;
1205
1206 ScriptList.append(new ScriptFunction(sf));
1207
1208 for (int i = 0; i < sf->numArgs(); ++i)
1209 ScriptList.last()->setArg(i, fn[i]);
1210
1211 return true;
1212 }
1213 }
1214 }
1215
1216 //if we get here, no function-name match was found
1217 return false;
1218}
1219
1220void ScriptBuilder::setUnsavedChanges(bool b)
1221{
1222 if (checkForChanges)
1223 {
1224 UnsavedChanges = b;
1225 sb->SaveButton->setEnabled(b);
1226 }
1227}
1228
1229void ScriptBuilder::slotCopyFunction()
1230{
1231 if (!UnsavedChanges)
1232 setUnsavedChanges(true);
1233
1234 int Pos = sb->ScriptListBox->currentRow() + 1;
1235 ScriptList.insert(Pos, new ScriptFunction(ScriptList[Pos - 1]));
1236 //copy ArgVals
1237 for (int i = 0; i < ScriptList[Pos - 1]->numArgs(); ++i)
1238 ScriptList[Pos]->setArg(i, ScriptList[Pos - 1]->argVal(i));
1239
1240 sb->ScriptListBox->insertItem(Pos, ScriptList[Pos]->name());
1241 //sb->ScriptListBox->setSelected( Pos, true );
1242 sb->ScriptListBox->setCurrentRow(Pos);
1243 slotArgWidget();
1244}
1245
1246void ScriptBuilder::slotRemoveFunction()
1247{
1248 setUnsavedChanges(true);
1249
1250 int Pos = sb->ScriptListBox->currentRow();
1251 ScriptList.removeAt(Pos);
1252 sb->ScriptListBox->takeItem(Pos);
1253 if (sb->ScriptListBox->count() == 0)
1254 {
1255 sb->ArgStack->setCurrentWidget(argBlank);
1256 sb->CopyButton->setEnabled(false);
1257 sb->RemoveButton->setEnabled(false);
1258 sb->RunButton->setEnabled(false);
1259 sb->SaveAsButton->setEnabled(false);
1260 }
1261 else
1262 {
1263 //sb->ScriptListBox->setSelected( Pos, true );
1264 if (Pos == sb->ScriptListBox->count())
1265 {
1266 Pos = Pos - 1;
1267 }
1268 sb->ScriptListBox->setCurrentRow(Pos);
1269 }
1270 slotArgWidget();
1271}
1272
1273void ScriptBuilder::slotAddFunction()
1274{
1275 ScriptFunction *found = nullptr;
1276 QTreeWidgetItem *currentItem = sb->FunctionTree->currentItem();
1277
1278 if (currentItem == nullptr || currentItem->parent() == nullptr)
1279 return;
1280
1281 for (auto &sc : KStarsFunctionList)
1282 {
1283 if (sc->prototype() == currentItem->text(0))
1284 {
1285 found = sc;
1286 break;
1287 }
1288 }
1289
1290 for (auto &sc : SimClockFunctionList)
1291 {
1292 if (sc->prototype() == currentItem->text(0))
1293 {
1294 found = sc;
1295 break;
1296 }
1297 }
1298
1299 if (found == nullptr)
1300 return;
1301
1302 setUnsavedChanges(true);
1303
1304 int Pos = sb->ScriptListBox->currentRow() + 1;
1305
1306 ScriptList.insert(Pos, new ScriptFunction(found));
1307 sb->ScriptListBox->insertItem(Pos, ScriptList[Pos]->name());
1308 sb->ScriptListBox->setCurrentRow(Pos);
1309 slotArgWidget();
1310}
1311
1312void ScriptBuilder::slotMoveFunctionUp()
1313{
1314 if (sb->ScriptListBox->currentRow() > 0)
1315 {
1316 setUnsavedChanges(true);
1317
1318 //QString t = sb->ScriptListBox->currentItem()->text();
1319 QString t = sb->ScriptListBox->currentItem()->text();
1320 unsigned int n = sb->ScriptListBox->currentRow();
1321
1322 ScriptFunction *tmp = ScriptList.takeAt(n);
1323 ScriptList.insert(n - 1, tmp);
1324
1325 sb->ScriptListBox->takeItem(n);
1326 sb->ScriptListBox->insertItem(n - 1, t);
1327 sb->ScriptListBox->setCurrentRow(n - 1);
1328 slotArgWidget();
1329 }
1330}
1331
1332void ScriptBuilder::slotMoveFunctionDown()
1333{
1334 if (sb->ScriptListBox->currentRow() > -1 && sb->ScriptListBox->currentRow() < ((int)sb->ScriptListBox->count()) - 1)
1335 {
1336 setUnsavedChanges(true);
1337
1338 QString t = sb->ScriptListBox->currentItem()->text();
1339 unsigned int n = sb->ScriptListBox->currentRow();
1340
1341 ScriptFunction *tmp = ScriptList.takeAt(n);
1342 ScriptList.insert(n + 1, tmp);
1343
1344 sb->ScriptListBox->takeItem(n);
1345 sb->ScriptListBox->insertItem(n + 1, t);
1346 sb->ScriptListBox->setCurrentRow(n + 1);
1347 slotArgWidget();
1348 }
1349}
1350
1351void ScriptBuilder::slotArgWidget()
1352{
1353 //First, setEnabled on buttons that act on the selected script function
1354 if (sb->ScriptListBox->currentRow() == -1) //no selection
1355 {
1356 sb->CopyButton->setEnabled(false);
1357 sb->RemoveButton->setEnabled(false);
1358 sb->UpButton->setEnabled(false);
1359 sb->DownButton->setEnabled(false);
1360 }
1361 else if (sb->ScriptListBox->count() == 1) //only one item, so disable up/down buttons
1362 {
1363 sb->CopyButton->setEnabled(true);
1364 sb->RemoveButton->setEnabled(true);
1365 sb->UpButton->setEnabled(false);
1366 sb->DownButton->setEnabled(false);
1367 }
1368 else if (sb->ScriptListBox->currentRow() == 0) //first item selected
1369 {
1370 sb->CopyButton->setEnabled(true);
1371 sb->RemoveButton->setEnabled(true);
1372 sb->UpButton->setEnabled(false);
1373 sb->DownButton->setEnabled(true);
1374 }
1375 else if (sb->ScriptListBox->currentRow() == ((int)sb->ScriptListBox->count()) - 1) //last item selected
1376 {
1377 sb->CopyButton->setEnabled(true);
1378 sb->RemoveButton->setEnabled(true);
1379 sb->UpButton->setEnabled(true);
1380 sb->DownButton->setEnabled(false);
1381 }
1382 else //other item selected
1383 {
1384 sb->CopyButton->setEnabled(true);
1385 sb->RemoveButton->setEnabled(true);
1386 sb->UpButton->setEnabled(true);
1387 sb->DownButton->setEnabled(true);
1388 }
1389
1390 //RunButton and SaveAs button enabled when script not empty.
1391 if (sb->ScriptListBox->count())
1392 {
1393 sb->RunButton->setEnabled(true);
1394 sb->SaveAsButton->setEnabled(true);
1395 }
1396 else
1397 {
1398 sb->RunButton->setEnabled(false);
1399 sb->SaveAsButton->setEnabled(false);
1400 setUnsavedChanges(false);
1401 }
1402
1403 //Display the function's arguments widget
1404 if (sb->ScriptListBox->currentRow() > -1 && sb->ScriptListBox->currentRow() < ((int)sb->ScriptListBox->count()))
1405 {
1406 unsigned int n = sb->ScriptListBox->currentRow();
1407 ScriptFunction *sf = ScriptList.at(n);
1408
1409 checkForChanges = false; //Don't signal unsaved changes
1410
1411 if (sf->name() == "lookTowards")
1412 {
1413 sb->ArgStack->setCurrentWidget(argLookToward);
1414 QString s = sf->argVal(0);
1415 argLookToward->FocusEdit->setEditText(s);
1416 }
1417 else if (sf->name() == "addLabel" || sf->name() == "removeLabel" || sf->name() == "addTrail" ||
1418 sf->name() == "removeTrail")
1419 {
1420 sb->ArgStack->setCurrentWidget(argFindObject);
1421 QString s = sf->argVal(0);
1422 argFindObject->NameEdit->setText(s);
1423 }
1424 else if (sf->name() == "setRaDec")
1425 {
1426 bool ok(false);
1427 double r(0.0), d(0.0);
1428 dms ra(0.0);
1429
1430 sb->ArgStack->setCurrentWidget(argSetRaDec);
1431
1432 ok = !sf->argVal(0).isEmpty();
1433 if (ok)
1434 r = sf->argVal(0).toDouble(&ok);
1435 else
1436 argSetRaDec->RABox->clear();
1437 if (ok)
1438 {
1439 ra.setH(r);
1440 argSetRaDec->RABox->show(ra);
1441 }
1442
1443 ok = !sf->argVal(1).isEmpty();
1444 if (ok)
1445 d = sf->argVal(1).toDouble(&ok);
1446 else
1447 argSetRaDec->DecBox->clear();
1448 if (ok)
1449 argSetRaDec->DecBox->show(dms(d));
1450 }
1451 else if (sf->name() == "setAltAz")
1452 {
1453 bool ok(false);
1454 double x(0.0), y(0.0);
1455
1456 sb->ArgStack->setCurrentWidget(argSetAltAz);
1457
1458 ok = !sf->argVal(0).isEmpty();
1459 if (ok)
1460 y = sf->argVal(0).toDouble(&ok);
1461 else
1462 argSetAltAz->AzBox->clear();
1463 if (ok)
1464 argSetAltAz->AltBox->show(dms(y));
1465 else
1466 argSetAltAz->AltBox->clear();
1467
1468 ok = !sf->argVal(1).isEmpty();
1469 x = sf->argVal(1).toDouble(&ok);
1470 if (ok)
1471 argSetAltAz->AzBox->show(dms(x));
1472 }
1473 else if (sf->name() == "zoomIn")
1474 {
1475 sb->ArgStack->setCurrentWidget(argBlank);
1476 //no Args
1477 }
1478 else if (sf->name() == "zoomOut")
1479 {
1480 sb->ArgStack->setCurrentWidget(argBlank);
1481 //no Args
1482 }
1483 else if (sf->name() == "defaultZoom")
1484 {
1485 sb->ArgStack->setCurrentWidget(argBlank);
1486 //no Args
1487 }
1488 else if (sf->name() == "zoom")
1489 {
1490 sb->ArgStack->setCurrentWidget(argZoom);
1491 bool ok(false);
1492 /*double z = */ sf->argVal(0).toDouble(&ok);
1493 if (ok)
1494 argZoom->ZoomBox->setText(sf->argVal(0));
1495 else
1496 argZoom->ZoomBox->setText("2000.");
1497 }
1498 else if (sf->name() == "exportImage")
1499 {
1500 sb->ArgStack->setCurrentWidget(argExportImage);
1501 argExportImage->ExportFileName->setUrl(QUrl::fromUserInput(sf->argVal(0)));
1502 bool ok(false);
1503 int w = 0, h = 0;
1504 w = sf->argVal(1).toInt(&ok);
1505 if (ok)
1506 h = sf->argVal(2).toInt(&ok);
1507 if (ok)
1508 {
1509 argExportImage->ExportWidth->setValue(w);
1510 argExportImage->ExportHeight->setValue(h);
1511 }
1512 else
1513 {
1514 argExportImage->ExportWidth->setValue(SkyMap::Instance()->width());
1515 argExportImage->ExportHeight->setValue(SkyMap::Instance()->height());
1516 }
1517 }
1518 else if (sf->name() == "printImage")
1519 {
1520 if (sf->argVal(0) == i18n("true"))
1521 argPrintImage->UsePrintDialog->setChecked(true);
1522 else
1523 argPrintImage->UsePrintDialog->setChecked(false);
1524 if (sf->argVal(1) == i18n("true"))
1525 argPrintImage->UseChartColors->setChecked(true);
1526 else
1527 argPrintImage->UseChartColors->setChecked(false);
1528 }
1529 else if (sf->name() == "setLocalTime")
1530 {
1531 sb->ArgStack->setCurrentWidget(argSetLocalTime);
1532 bool ok(false);
1533 int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0;
1534
1535 year = sf->argVal(0).toInt(&ok);
1536 if (ok)
1537 month = sf->argVal(1).toInt(&ok);
1538 if (ok)
1539 day = sf->argVal(2).toInt(&ok);
1540 if (ok)
1541 argSetLocalTime->DateWidget->setDate(QDate(year, month, day));
1542 else
1543 argSetLocalTime->DateWidget->setDate(QDate::currentDate());
1544
1545 hour = sf->argVal(3).toInt(&ok);
1546 if (sf->argVal(3).isEmpty())
1547 ok = false;
1548 if (ok)
1549 min = sf->argVal(4).toInt(&ok);
1550 if (ok)
1551 sec = sf->argVal(5).toInt(&ok);
1552 if (ok)
1553 argSetLocalTime->TimeBox->setTime(QTime(hour, min, sec));
1554 else
1555 argSetLocalTime->TimeBox->setTime(QTime(QTime::currentTime()));
1556 }
1557 else if (sf->name() == "waitFor")
1558 {
1559 sb->ArgStack->setCurrentWidget(argWaitFor);
1560 bool ok(false);
1561 int sec = sf->argVal(0).toInt(&ok);
1562 if (ok)
1563 argWaitFor->DelayBox->setValue(sec);
1564 else
1565 argWaitFor->DelayBox->setValue(0);
1566 }
1567 else if (sf->name() == "waitForKey")
1568 {
1569 sb->ArgStack->setCurrentWidget(argWaitForKey);
1570 if (sf->argVal(0).length() == 1 || sf->argVal(0).toLower() == "space")
1571 argWaitForKey->WaitKeyEdit->setText(sf->argVal(0));
1572 else
1573 argWaitForKey->WaitKeyEdit->setText(QString());
1574 }
1575 else if (sf->name() == "setTracking")
1576 {
1577 sb->ArgStack->setCurrentWidget(argSetTracking);
1578 if (sf->argVal(0) == i18n("true"))
1579 argSetTracking->CheckTrack->setChecked(true);
1580 else
1581 argSetTracking->CheckTrack->setChecked(false);
1582 }
1583 else if (sf->name() == "changeViewOption")
1584 {
1585 sb->ArgStack->setCurrentWidget(argChangeViewOption);
1586 argChangeViewOption->OptionName->setCurrentIndex(argChangeViewOption->OptionName->findText(sf->argVal(0)));
1587 argChangeViewOption->OptionValue->setText(sf->argVal(1));
1588 }
1589 else if (sf->name() == "setGeoLocation")
1590 {
1591 sb->ArgStack->setCurrentWidget(argSetGeoLocation);
1592 argSetGeoLocation->CityName->setText(sf->argVal(0));
1593 argSetGeoLocation->ProvinceName->setText(sf->argVal(1));
1594 argSetGeoLocation->CountryName->setText(sf->argVal(2));
1595 }
1596 else if (sf->name() == "setColor")
1597 {
1598 sb->ArgStack->setCurrentWidget(argSetColor);
1599 if (sf->argVal(0).isEmpty())
1600 sf->setArg(0, "SkyColor"); //initialize default value
1601 argSetColor->ColorName->setCurrentIndex(
1602 argSetColor->ColorName->findText(KStarsData::Instance()->colorScheme()->nameFromKey(sf->argVal(0))));
1603 argSetColor->ColorValue->setColor(QColor(sf->argVal(1).remove('\\')));
1604 }
1605 else if (sf->name() == "loadColorScheme")
1606 {
1607 sb->ArgStack->setCurrentWidget(argLoadColorScheme);
1608 argLoadColorScheme->SchemeList->setCurrentItem(
1609 argLoadColorScheme->SchemeList->findItems(sf->argVal(0).remove('\"'), Qt::MatchExactly).at(0));
1610 }
1611 else if (sf->name() == "stop")
1612 {
1613 sb->ArgStack->setCurrentWidget(argBlank);
1614 //no Args
1615 }
1616 else if (sf->name() == "start")
1617 {
1618 sb->ArgStack->setCurrentWidget(argBlank);
1619 //no Args
1620 }
1621 else if (sf->name() == "setClockScale")
1622 {
1623 sb->ArgStack->setCurrentWidget(argTimeScale);
1624 bool ok(false);
1625 double ts = sf->argVal(0).toDouble(&ok);
1626 if (ok)
1627 argTimeScale->TimeScale->tsbox()->changeScale(float(ts));
1628 else
1629 argTimeScale->TimeScale->tsbox()->changeScale(0.0);
1630 }
1631
1632 checkForChanges = true; //signal unsaved changes if the argument widgets are changed
1633 }
1634}
1635
1636void ScriptBuilder::slotShowDoc()
1637{
1638 ScriptFunction *found = nullptr;
1639 QTreeWidgetItem *currentItem = sb->FunctionTree->currentItem();
1640
1641 if (currentItem == nullptr || currentItem->parent() == nullptr)
1642 return;
1643
1644 for (auto &sc : KStarsFunctionList)
1645 {
1646 if (sc->prototype() == currentItem->text(0))
1647 {
1648 found = sc;
1649 break;
1650 }
1651 }
1652
1653 for (auto &sc : SimClockFunctionList)
1654 {
1655 if (sc->prototype() == currentItem->text(0))
1656 {
1657 found = sc;
1658 break;
1659 }
1660 }
1661
1662 if (found == nullptr)
1663 {
1664 sb->AddButton->setEnabled(false);
1665 qWarning() << i18n("Function index out of bounds.");
1666 return;
1667 }
1668
1669 sb->AddButton->setEnabled(true);
1670 sb->FuncDoc->setHtml(found->description());
1671}
1672
1673//Slots for Arg Widgets
1674void ScriptBuilder::slotFindCity()
1675{
1676 QPointer<LocationDialog> ld = new LocationDialog(this);
1677
1678 if (ld->exec() == QDialog::Accepted)
1679 {
1680 if (ld->selectedCity())
1681 {
1682 // set new location names
1683 argSetGeoLocation->CityName->setText(ld->selectedCityName());
1684 if (!ld->selectedProvinceName().isEmpty())
1685 {
1686 argSetGeoLocation->ProvinceName->setText(ld->selectedProvinceName());
1687 }
1688 else
1689 {
1690 argSetGeoLocation->ProvinceName->clear();
1691 }
1692 argSetGeoLocation->CountryName->setText(ld->selectedCountryName());
1693
1694 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1695 if (sf->name() == "setGeoLocation")
1696 {
1697 setUnsavedChanges(true);
1698
1699 sf->setArg(0, ld->selectedCityName());
1700 sf->setArg(1, ld->selectedProvinceName());
1701 sf->setArg(2, ld->selectedCountryName());
1702 }
1703 else
1704 {
1705 warningMismatch("setGeoLocation");
1706 }
1707 }
1708 }
1709 delete ld;
1710}
1711
1712void ScriptBuilder::slotFindObject()
1713{
1714 if (FindDialog::Instance()->exec() == QDialog::Accepted && FindDialog::Instance()->targetObject())
1715 {
1716 setUnsavedChanges(true);
1717
1718 if (sender() == argLookToward->FindButton)
1719 argLookToward->FocusEdit->setEditText(FindDialog::Instance()->targetObject()->name());
1720 else
1721 argFindObject->NameEdit->setText(FindDialog::Instance()->targetObject()->name());
1722 }
1723}
1724
1725void ScriptBuilder::slotShowOptions()
1726{
1727 //Show tree-view of view options
1728 if (otv->exec() == QDialog::Accepted)
1729 {
1730 argChangeViewOption->OptionName->setCurrentIndex(
1731 argChangeViewOption->OptionName->findText(otv->optionsList()->currentItem()->text(0)));
1732 }
1733}
1734
1735void ScriptBuilder::slotLookToward()
1736{
1737 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1738
1739 if (sf->name() == "lookTowards")
1740 {
1741 setUnsavedChanges(true);
1742
1743 sf->setArg(0, argLookToward->FocusEdit->currentText());
1744 sf->setValid(true);
1745 }
1746 else
1747 {
1748 warningMismatch("lookTowards");
1749 }
1750}
1751
1752void ScriptBuilder::slotArgFindObject()
1753{
1754 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1755
1756 if (sf->name() == "addLabel" || sf->name() == "removeLabel" || sf->name() == "addTrail" ||
1757 sf->name() == "removeTrail")
1758 {
1759 setUnsavedChanges(true);
1760
1761 sf->setArg(0, argFindObject->NameEdit->text());
1762 sf->setValid(true);
1763 }
1764 else
1765 {
1766 warningMismatch(sf->name());
1767 }
1768}
1769
1770void ScriptBuilder::slotRa()
1771{
1772 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1773
1774 if (sf->name() == "setRaDec")
1775 {
1776 //do nothing if box is blank (because we could be clearing boxes while switching argWidgets)
1777 if (argSetRaDec->RABox->text().isEmpty())
1778 return;
1779
1780 bool ok(false);
1781 dms ra = argSetRaDec->RABox->createDms(&ok);
1782 if (ok)
1783 {
1784 setUnsavedChanges(true);
1785
1786 sf->setArg(0, QString("%1").arg(ra.Hours()));
1787 if (!sf->argVal(1).isEmpty())
1788 sf->setValid(true);
1789 }
1790 else
1791 {
1792 sf->setArg(0, QString());
1793 sf->setValid(false);
1794 }
1795 }
1796 else
1797 {
1798 warningMismatch("setRaDec");
1799 }
1800}
1801
1802void ScriptBuilder::slotDec()
1803{
1804 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1805
1806 if (sf->name() == "setRaDec")
1807 {
1808 //do nothing if box is blank (because we could be clearing boxes while switching argWidgets)
1809 if (argSetRaDec->DecBox->text().isEmpty())
1810 return;
1811
1812 bool ok(false);
1813 dms dec = argSetRaDec->DecBox->createDms(&ok);
1814 if (ok)
1815 {
1816 setUnsavedChanges(true);
1817
1818 sf->setArg(1, QString("%1").arg(dec.Degrees()));
1819 if (!sf->argVal(0).isEmpty())
1820 sf->setValid(true);
1821 }
1822 else
1823 {
1824 sf->setArg(1, QString());
1825 sf->setValid(false);
1826 }
1827 }
1828 else
1829 {
1830 warningMismatch("setRaDec");
1831 }
1832}
1833
1834void ScriptBuilder::slotAz()
1835{
1836 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1837
1838 if (sf->name() == "setAltAz")
1839 {
1840 //do nothing if box is blank (because we could be clearing boxes while switching argWidgets)
1841 if (argSetAltAz->AzBox->text().isEmpty())
1842 return;
1843
1844 bool ok(false);
1845 dms az = argSetAltAz->AzBox->createDms(&ok);
1846 if (ok)
1847 {
1848 setUnsavedChanges(true);
1849 sf->setArg(1, QString("%1").arg(az.Degrees()));
1850 if (!sf->argVal(0).isEmpty())
1851 sf->setValid(true);
1852 }
1853 else
1854 {
1855 sf->setArg(1, QString());
1856 sf->setValid(false);
1857 }
1858 }
1859 else
1860 {
1861 warningMismatch("setAltAz");
1862 }
1863}
1864
1865void ScriptBuilder::slotAlt()
1866{
1867 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1868
1869 if (sf->name() == "setAltAz")
1870 {
1871 //do nothing if box is blank (because we could be clearing boxes while switching argWidgets)
1872 if (argSetAltAz->AltBox->text().isEmpty())
1873 return;
1874
1875 bool ok(false);
1876 dms alt = argSetAltAz->AltBox->createDms(&ok);
1877 if (ok)
1878 {
1879 setUnsavedChanges(true);
1880
1881 sf->setArg(0, QString("%1").arg(alt.Degrees()));
1882 if (!sf->argVal(1).isEmpty())
1883 sf->setValid(true);
1884 }
1885 else
1886 {
1887 sf->setArg(0, QString());
1888 sf->setValid(false);
1889 }
1890 }
1891 else
1892 {
1893 warningMismatch("setAltAz");
1894 }
1895}
1896
1897void ScriptBuilder::slotChangeDate()
1898{
1899 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1900
1901 if (sf->name() == "setLocalTime")
1902 {
1903 setUnsavedChanges(true);
1904
1905 QDate date = argSetLocalTime->DateWidget->date();
1906
1907 sf->setArg(0, QString("%1").arg(date.year()));
1908 sf->setArg(1, QString("%1").arg(date.month()));
1909 sf->setArg(2, QString("%1").arg(date.day()));
1910 if (!sf->argVal(3).isEmpty())
1911 sf->setValid(true);
1912 }
1913 else
1914 {
1915 warningMismatch("setLocalTime");
1916 }
1917}
1918
1919void ScriptBuilder::slotChangeTime()
1920{
1921 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1922
1923 if (sf->name() == "setLocalTime")
1924 {
1925 setUnsavedChanges(true);
1926
1927 QTime time = argSetLocalTime->TimeBox->time();
1928
1929 sf->setArg(3, QString("%1").arg(time.hour()));
1930 sf->setArg(4, QString("%1").arg(time.minute()));
1931 sf->setArg(5, QString("%1").arg(time.second()));
1932 if (!sf->argVal(0).isEmpty())
1933 sf->setValid(true);
1934 }
1935 else
1936 {
1937 warningMismatch("setLocalTime");
1938 }
1939}
1940
1941void ScriptBuilder::slotWaitFor()
1942{
1943 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1944
1945 if (sf->name() == "waitFor")
1946 {
1947 bool ok(false);
1948 int delay = argWaitFor->DelayBox->text().toInt(&ok);
1949
1950 if (ok)
1951 {
1952 setUnsavedChanges(true);
1953
1954 sf->setArg(0, QString("%1").arg(delay));
1955 sf->setValid(true);
1956 }
1957 else
1958 {
1959 sf->setValid(false);
1960 }
1961 }
1962 else
1963 {
1964 warningMismatch("waitFor");
1965 }
1966}
1967
1968void ScriptBuilder::slotWaitForKey()
1969{
1970 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1971
1972 if (sf->name() == "waitForKey")
1973 {
1974 QString sKey = argWaitForKey->WaitKeyEdit->text().trimmed();
1975
1976 //DCOP script can only use single keystrokes; make sure entry is either one character,
1977 //or the word 'space'
1978 if (sKey.length() == 1 || sKey == "space")
1979 {
1980 setUnsavedChanges(true);
1981
1982 sf->setArg(0, sKey);
1983 sf->setValid(true);
1984 }
1985 else
1986 {
1987 sf->setValid(false);
1988 }
1989 }
1990 else
1991 {
1992 warningMismatch("waitForKey");
1993 }
1994}
1995
1996void ScriptBuilder::slotTracking()
1997{
1998 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
1999
2000 if (sf->name() == "setTracking")
2001 {
2002 setUnsavedChanges(true);
2003
2004 sf->setArg(0, (argSetTracking->CheckTrack->isChecked() ? i18n("true") : i18n("false")));
2005 sf->setValid(true);
2006 }
2007 else
2008 {
2009 warningMismatch("setTracking");
2010 }
2011}
2012
2013void ScriptBuilder::slotViewOption()
2014{
2015 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2016
2017 if (sf->name() == "changeViewOption")
2018 {
2019 if (argChangeViewOption->OptionName->currentIndex() >= 0 && argChangeViewOption->OptionValue->text().length())
2020 {
2021 setUnsavedChanges(true);
2022
2023 sf->setArg(0, argChangeViewOption->OptionName->currentText());
2024 sf->setArg(1, argChangeViewOption->OptionValue->text());
2025 sf->setValid(true);
2026 }
2027 else
2028 {
2029 sf->setValid(false);
2030 }
2031 }
2032 else
2033 {
2034 warningMismatch("changeViewOption");
2035 }
2036}
2037
2038void ScriptBuilder::slotChangeCity()
2039{
2040 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2041
2042 if (sf->name() == "setGeoLocation")
2043 {
2044 QString city = argSetGeoLocation->CityName->text();
2045
2046 if (city.length())
2047 {
2048 setUnsavedChanges(true);
2049
2050 sf->setArg(0, city);
2051 if (sf->argVal(2).length())
2052 sf->setValid(true);
2053 }
2054 else
2055 {
2056 sf->setArg(0, QString());
2057 sf->setValid(false);
2058 }
2059 }
2060 else
2061 {
2062 warningMismatch("setGeoLocation");
2063 }
2064}
2065
2066void ScriptBuilder::slotChangeProvince()
2067{
2068 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2069
2070 if (sf->name() == "setGeoLocation")
2071 {
2072 QString province = argSetGeoLocation->ProvinceName->text();
2073
2074 if (province.length())
2075 {
2076 setUnsavedChanges(true);
2077
2078 sf->setArg(1, province);
2079 if (sf->argVal(0).length() && sf->argVal(2).length())
2080 sf->setValid(true);
2081 }
2082 else
2083 {
2084 sf->setArg(1, QString());
2085 //might not be invalid
2086 }
2087 }
2088 else
2089 {
2090 warningMismatch("setGeoLocation");
2091 }
2092}
2093
2094void ScriptBuilder::slotChangeCountry()
2095{
2096 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2097
2098 if (sf->name() == "setGeoLocation")
2099 {
2100 QString country = argSetGeoLocation->CountryName->text();
2101
2102 if (country.length())
2103 {
2104 setUnsavedChanges(true);
2105
2106 sf->setArg(2, country);
2107 if (sf->argVal(0).length())
2108 sf->setValid(true);
2109 }
2110 else
2111 {
2112 sf->setArg(2, QString());
2113 sf->setValid(false);
2114 }
2115 }
2116 else
2117 {
2118 warningMismatch("setGeoLocation");
2119 }
2120}
2121
2122void ScriptBuilder::slotTimeScale()
2123{
2124 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2125
2126 if (sf->name() == "setClockScale")
2127 {
2128 setUnsavedChanges(true);
2129
2130 sf->setArg(0, QString("%1").arg(argTimeScale->TimeScale->tsbox()->timeScale()));
2131 sf->setValid(true);
2132 }
2133 else
2134 {
2135 warningMismatch("setClockScale");
2136 }
2137}
2138
2139void ScriptBuilder::slotZoom()
2140{
2141 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2142
2143 if (sf->name() == "zoom")
2144 {
2145 setUnsavedChanges(true);
2146
2147 bool ok(false);
2148 argZoom->ZoomBox->text().toDouble(&ok);
2149 if (ok)
2150 {
2151 sf->setArg(0, argZoom->ZoomBox->text());
2152 sf->setValid(true);
2153 }
2154 }
2155 else
2156 {
2157 warningMismatch("zoom");
2158 }
2159}
2160
2161void ScriptBuilder::slotExportImage()
2162{
2163 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2164
2165 if (sf->name() == "exportImage")
2166 {
2167 setUnsavedChanges(true);
2168
2169 sf->setArg(0, argExportImage->ExportFileName->url().url());
2170 sf->setArg(1, QString("%1").arg(argExportImage->ExportWidth->value()));
2171 sf->setArg(2, QString("%1").arg(argExportImage->ExportHeight->value()));
2172 sf->setValid(true);
2173 }
2174 else
2175 {
2176 warningMismatch("exportImage");
2177 }
2178}
2179
2180void ScriptBuilder::slotPrintImage()
2181{
2182 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2183
2184 if (sf->name() == "printImage")
2185 {
2186 setUnsavedChanges(true);
2187
2188 sf->setArg(0, (argPrintImage->UsePrintDialog->isChecked() ? i18n("true") : i18n("false")));
2189 sf->setArg(1, (argPrintImage->UseChartColors->isChecked() ? i18n("true") : i18n("false")));
2190 sf->setValid(true);
2191 }
2192 else
2193 {
2194 warningMismatch("exportImage");
2195 }
2196}
2197
2198void ScriptBuilder::slotChangeColorName()
2199{
2200 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2201
2202 if (sf->name() == "setColor")
2203 {
2204 setUnsavedChanges(true);
2205
2206 argSetColor->ColorValue->setColor(KStarsData::Instance()->colorScheme()->colorAt(argSetColor->ColorName->currentIndex()));
2207 sf->setArg(0, KStarsData::Instance()->colorScheme()->keyAt(argSetColor->ColorName->currentIndex()));
2208 QString cname(argSetColor->ColorValue->color().name());
2209 //if ( cname.at(0) == '#' ) cname = "\\" + cname; //prepend a "\" so bash doesn't think we have a comment
2210 sf->setArg(1, cname);
2211 sf->setValid(true);
2212 }
2213 else
2214 {
2215 warningMismatch("setColor");
2216 }
2217}
2218
2219void ScriptBuilder::slotChangeColor()
2220{
2221 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2222
2223 if (sf->name() == "setColor")
2224 {
2225 setUnsavedChanges(true);
2226
2227 sf->setArg(0, KStarsData::Instance()->colorScheme()->keyAt(argSetColor->ColorName->currentIndex()));
2228 QString cname(argSetColor->ColorValue->color().name());
2229 //if ( cname.at(0) == '#' ) cname = "\\" + cname; //prepend a "\" so bash doesn't think we have a comment
2230 sf->setArg(1, cname);
2231 sf->setValid(true);
2232 }
2233 else
2234 {
2235 warningMismatch("setColor");
2236 }
2237}
2238
2239void ScriptBuilder::slotLoadColorScheme()
2240{
2241 ScriptFunction *sf = ScriptList[sb->ScriptListBox->currentRow()];
2242
2243 if (sf->name() == "loadColorScheme")
2244 {
2245 setUnsavedChanges(true);
2246
2247 sf->setArg(0, '\"' + argLoadColorScheme->SchemeList->currentItem()->text() + '\"');
2248 sf->setValid(true);
2249 }
2250 else
2251 {
2252 warningMismatch("loadColorScheme");
2253 }
2254}
2255
2256void ScriptBuilder::slotClose()
2257{
2258 saveWarning();
2259
2260 if (!UnsavedChanges)
2261 {
2262 ScriptList.clear();
2263 sb->ScriptListBox->clear();
2264 sb->ArgStack->setCurrentWidget(argBlank);
2265 close();
2266 }
2267}
2268
2269//TODO JM: INDI Scripting to be included in KDE 4.1
2270
2271#if 0
2272void ScriptBuilder::slotINDIStartDeviceName()
2273{
2274 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2275
2276 if ( sf->name() == "startINDI" )
2277 {
2278 setUnsavedChanges( true );
2279
2280 sf->setArg(0, argStartINDI->deviceName->text());
2281 sf->setArg(1, argStartINDI->LocalButton->isChecked() ? "true" : "false");
2282 sf->setValid(true);
2283 }
2284 else
2285 {
2286 warningMismatch( "startINDI" );
2287 }
2288
2289}
2290
2291void ScriptBuilder::slotINDIStartDeviceMode()
2292{
2293
2294 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2295
2296 if ( sf->name() == "startINDI" )
2297 {
2298 setUnsavedChanges( true );
2299
2300 sf->setArg(1, argStartINDI->LocalButton->isChecked() ? "true" : "false");
2301 sf->setValid(true);
2302 }
2303 else
2304 {
2305 warningMismatch( "startINDI" );
2306 }
2307
2308}
2309
2310void ScriptBuilder::slotINDISetDevice()
2311{
2312
2313 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2314
2315 if ( sf->name() == "setINDIDevice" )
2316 {
2317 setUnsavedChanges( true );
2318
2319 sf->setArg(0, argSetDeviceINDI->deviceName->text());
2320 sf->setValid(true);
2321 }
2322 else
2323 {
2324 warningMismatch( "startINDI" );
2325 }
2326}
2327
2328void ScriptBuilder::slotINDIShutdown()
2329{
2330
2331 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2332
2333 if ( sf->name() == "shutdownINDI" )
2334 {
2335 if (argShutdownINDI->deviceName->text().isEmpty())
2336 {
2337 sf->setValid(false);
2338 return;
2339 }
2340
2341 if (sf->argVal(0) != argShutdownINDI->deviceName->text())
2342 setUnsavedChanges( true );
2343
2344 sf->setArg(0, argShutdownINDI->deviceName->text());
2345 sf->setValid(true);
2346 }
2347 else
2348 {
2349 warningMismatch( "shutdownINDI" );
2350 }
2351
2352}
2353
2354void ScriptBuilder::slotINDISwitchDeviceConnection()
2355{
2356
2357 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2358
2359 if ( sf->name() == "switchINDI" )
2360 {
2361
2362 if (sf->argVal(0) != (argSwitchINDI->OnButton->isChecked() ? "true" : "false"))
2363 setUnsavedChanges( true );
2364
2365 sf->setArg(0, argSwitchINDI->OnButton->isChecked() ? "true" : "false");
2366 sf->setValid(true);
2367 }
2368 else
2369 {
2370 warningMismatch( "switchINDI" );
2371 }
2372
2373}
2374
2375void ScriptBuilder::slotINDISetPortDevicePort()
2376{
2377 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2378
2379 if ( sf->name() == "setINDIPort" )
2380 {
2381
2382 if (argSetPortINDI->devicePort->text().isEmpty())
2383 {
2384 sf->setValid(false);
2385 return;
2386 }
2387
2388 if (sf->argVal(0) != argSetPortINDI->devicePort->text())
2389 setUnsavedChanges( true );
2390
2391 sf->setArg(0, argSetPortINDI->devicePort->text());
2392 sf->setValid(true);
2393 }
2394 else
2395 {
2396 warningMismatch( "setINDIPort" );
2397 }
2398
2399}
2400
2401void ScriptBuilder::slotINDISetTargetCoordDeviceRA()
2402{
2403 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2404
2405 if ( sf->name() == "setINDITargetCoord" )
2406 {
2407 //do nothing if box is blank (because we could be clearing boxes while switching argWidgets)
2408 if ( argSetTargetCoordINDI->RABox->text().isEmpty() )
2409 {
2410 sf->setValid(false);
2411 return;
2412 }
2413
2414 bool ok(false);
2415 dms ra = argSetTargetCoordINDI->RABox->createDms(&ok);
2416 if ( ok )
2417 {
2418
2419 if (sf->argVal(0) != QString( "%1" ).arg( ra.Hours() ))
2420 setUnsavedChanges( true );
2421
2422 sf->setArg( 0, QString( "%1" ).arg( ra.Hours() ) );
2423 if ( ( ! sf->argVal(1).isEmpty() ))
2424 sf->setValid( true );
2425 else
2426 sf->setValid(false);
2427
2428 }
2429 else
2430 {
2431 sf->setArg( 0, QString() );
2432 sf->setValid( false );
2433 }
2434 }
2435 else
2436 {
2437 warningMismatch( "setINDITargetCoord" );
2438 }
2439
2440}
2441
2442void ScriptBuilder::slotINDISetTargetCoordDeviceDEC()
2443{
2444 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2445
2446 if ( sf->name() == "setINDITargetCoord" )
2447 {
2448 //do nothing if box is blank (because we could be clearing boxes while switching argWidgets)
2449 if ( argSetTargetCoordINDI->DecBox->text().isEmpty() )
2450 {
2451 sf->setValid(false);
2452 return;
2453 }
2454
2455 bool ok(false);
2456 dms dec = argSetTargetCoordINDI->DecBox->createDms(&ok);
2457 if ( ok )
2458 {
2459
2460 if (sf->argVal(1) != QString( "%1" ).arg( dec.Degrees() ))
2461 setUnsavedChanges( true );
2462
2463 sf->setArg( 1, QString( "%1" ).arg( dec.Degrees() ) );
2464 if ( ( ! sf->argVal(0).isEmpty() ))
2465 sf->setValid( true );
2466 else
2467 sf->setValid(false);
2468
2469 }
2470 else
2471 {
2472 sf->setArg( 1, QString() );
2473 sf->setValid( false );
2474 }
2475 }
2476 else
2477 {
2478 warningMismatch( "setINDITargetCoord" );
2479 }
2480
2481}
2482
2483void ScriptBuilder::slotINDIsetCoreProperty(SequenceJob::SJ_TargetName,TargetName()
2484{
2485
2486 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2487
2488 if ( sf->name() == "setINDITargetName" )
2489 {
2490 if (argsetCoreProperty(SequenceJob::SJ_TargetName,INDI->targetName->text().isEmpty())
2491 {
2492 sf->setValid(false);
2493 return;
2494 }
2495
2496 if (sf->argVal(0) != argsetCoreProperty(SequenceJob::SJ_TargetName,INDI->targetName->text())
2497 setUnsavedChanges( true );
2498
2499 sf->setArg(0, argsetCoreProperty(SequenceJob::SJ_TargetName,INDI->targetName->text());
2500 sf->setValid(true);
2501 }
2502 else
2503 {
2504 warningMismatch( "setINDITargetName" );
2505 }
2506
2507}
2508
2509void ScriptBuilder::slotINDISetActionName()
2510{
2511 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2512
2513 if ( sf->name() == "setINDIAction" )
2514 {
2515 if (argSetActionINDI->actionName->text().isEmpty())
2516 {
2517 sf->setValid(false);
2518 return;
2519 }
2520
2521 if (sf->argVal(0) != argSetActionINDI->actionName->text())
2522 setUnsavedChanges( true );
2523
2524 sf->setArg(0, argSetActionINDI->actionName->text());
2525 sf->setValid(true);
2526 }
2527 else
2528 {
2529 warningMismatch( "setINDIAction" );
2530 }
2531
2532}
2533
2534void ScriptBuilder::slotINDIWaitForActionName()
2535{
2536 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2537
2538 if ( sf->name() == "waitForINDIAction" )
2539 {
2540 if (argWaitForActionINDI->actionName->text().isEmpty())
2541 {
2542 sf->setValid(false);
2543 return;
2544 }
2545
2546 if (sf->argVal(0) != argWaitForActionINDI->actionName->text())
2547 setUnsavedChanges( true );
2548
2549 sf->setArg(0, argWaitForActionINDI->actionName->text());
2550 sf->setValid(true);
2551 }
2552 else
2553 {
2554 warningMismatch( "waitForINDIAction" );
2555 }
2556
2557}
2558
2559void ScriptBuilder::slotINDISetFocusSpeed()
2560{
2561 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2562
2563 if ( sf->name() == "setINDIFocusSpeed" )
2564 {
2565
2566 if (sf->argVal(0).toInt() != argSetFocusSpeedINDI->speedIN->value())
2567 setUnsavedChanges( true );
2568
2569 sf->setArg(0, QString("%1").arg(argSetFocusSpeedINDI->speedIN->value()));
2570 sf->setValid(true);
2571 }
2572 else
2573 {
2574 warningMismatch( "setINDIFocusSpeed" );
2575 }
2576
2577}
2578
2579void ScriptBuilder::slotINDIStartFocusDirection()
2580{
2581 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2582
2583 if ( sf->name() == "startINDIFocus" )
2584 {
2585 if (sf->argVal(0) != argStartFocusINDI->directionCombo->currentText())
2586 setUnsavedChanges( true );
2587
2588 sf->setArg(0, argStartFocusINDI->directionCombo->currentText());
2589 sf->setValid(true);
2590 }
2591 else
2592 {
2593 warningMismatch( "startINDIFocus" );
2594 }
2595
2596}
2597
2598void ScriptBuilder::slotINDISetFocusTimeout()
2599{
2600 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2601
2602 if ( sf->name() == "setINDIFocusTimeout" )
2603 {
2604 if (sf->argVal(0).toInt() != argSetFocusTimeoutINDI->timeOut->value())
2605 setUnsavedChanges( true );
2606
2607 sf->setArg(0, QString("%1").arg(argSetFocusTimeoutINDI->timeOut->value()));
2608 sf->setValid(true);
2609 }
2610 else
2611 {
2612 warningMismatch( "setINDIFocusTimeout" );
2613 }
2614
2615}
2616
2617void ScriptBuilder::slotINDISetGeoLocationDeviceLong()
2618{
2619 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2620
2621 if ( sf->name() == "setINDIGeoLocation" )
2622 {
2623 //do nothing if box is blank (because we could be clearing boxes while switching argWidgets)
2624 if ( argSetGeoLocationINDI->longBox->text().isEmpty())
2625 {
2626 sf->setValid(false);
2627 return;
2628 }
2629
2630 bool ok(false);
2631 dms longitude = argSetGeoLocationINDI->longBox->createDms(&ok);
2632 if ( ok )
2633 {
2634
2635 if (sf->argVal(0) != QString( "%1" ).arg( longitude.Degrees()))
2636 setUnsavedChanges( true );
2637
2638 sf->setArg( 0, QString( "%1" ).arg( longitude.Degrees() ) );
2639 if ( ! sf->argVal(1).isEmpty() )
2640 sf->setValid( true );
2641 else
2642 sf->setValid(false);
2643
2644 }
2645 else
2646 {
2647 sf->setArg( 0, QString() );
2648 sf->setValid( false );
2649 }
2650 }
2651 else
2652 {
2653 warningMismatch( "setINDIGeoLocation" );
2654 }
2655
2656}
2657
2658void ScriptBuilder::slotINDISetGeoLocationDeviceLat()
2659{
2660 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2661
2662 if ( sf->name() == "setINDIGeoLocation" )
2663 {
2664 //do nothing if box is blank (because we could be clearing boxes while switching argWidgets)
2665 if ( argSetGeoLocationINDI->latBox->text().isEmpty() )
2666 {
2667 sf->setValid(false);
2668 return;
2669 }
2670
2671 bool ok(false);
2672 dms latitude = argSetGeoLocationINDI->latBox->createDms(&ok);
2673 if ( ok )
2674 {
2675
2676 if (sf->argVal(1) != QString( "%1" ).arg( latitude.Degrees()))
2677 setUnsavedChanges( true );
2678
2679 sf->setArg( 1, QString( "%1" ).arg( latitude.Degrees() ) );
2680 if ( ! sf->argVal(0).isEmpty() )
2681 sf->setValid( true );
2682 else
2683 sf->setValid(false);
2684
2685 }
2686 else
2687 {
2688 sf->setArg( 1, QString() );
2689 sf->setValid( false );
2690 }
2691 }
2692 else
2693 {
2694 warningMismatch( "setINDIGeoLocation" );
2695 }
2696
2697}
2698
2699void ScriptBuilder::slotINDIStartExposureTimeout()
2700{
2701 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2702
2703 if ( sf->name() == "startINDIExposure" )
2704 {
2705
2706 if (sf->argVal(0).toInt() != argStartExposureINDI->timeOut->value())
2707 setUnsavedChanges( true );
2708
2709 sf->setArg(0, QString("%1").arg(argStartExposureINDI->timeOut->value()));
2710 sf->setValid(true);
2711 }
2712 else
2713 {
2714 warningMismatch( "startINDIExposure" );
2715 }
2716
2717}
2718
2719void ScriptBuilder::slotINDISetUTC()
2720{
2721 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2722
2723 if ( sf->name() == "setINDIUTC" )
2724 {
2725
2726 if (argSetUTCINDI->UTC->text().isEmpty())
2727 {
2728 sf->setValid(false);
2729 return;
2730 }
2731
2732 if (sf->argVal(0) != argSetUTCINDI->UTC->text())
2733 setUnsavedChanges( true );
2734
2735 sf->setArg(0, argSetUTCINDI->UTC->text());
2736 sf->setValid(true);
2737 }
2738 else
2739 {
2740 warningMismatch( "setINDIUTC" );
2741 }
2742
2743}
2744
2745void ScriptBuilder::slotINDISetScopeAction()
2746{
2747 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2748
2749 if ( sf->name() == "setINDIScopeAction" )
2750 {
2751
2752 if (sf->argVal(0) != argSetScopeActionINDI->actionCombo->currentText())
2753 setUnsavedChanges( true );
2754
2755 sf->setArg(0, argSetScopeActionINDI->actionCombo->currentText());
2756 sf->setINDIProperty("CHECK");
2757 sf->setValid(true);
2758 }
2759 else
2760 {
2761 warningMismatch( "setINDIScopeAction" );
2762 }
2763
2764}
2765
2766void ScriptBuilder::slotINDISetFrameType()
2767{
2768 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2769
2770 if ( sf->name() == "setINDIFrameType" )
2771 {
2772
2773 if (sf->argVal(0) != argSetFrameTypeINDI->typeCombo->currentText())
2774 setUnsavedChanges( true );
2775
2776 sf->setArg(0, argSetFrameTypeINDI->typeCombo->currentText());
2777 sf->setValid(true);
2778 }
2779 else
2780 {
2781 warningMismatch( "setINDIFrameType" );
2782 }
2783
2784}
2785
2786void ScriptBuilder::slotINDISetCCDTemp()
2787{
2788 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2789
2790 if ( sf->name() == "setINDICCDTemp" )
2791 {
2792
2793 if (sf->argVal(0).toInt() != argSetCCDTempINDI->temp->value())
2794 setUnsavedChanges( true );
2795
2796 sf->setArg(0, QString("%1").arg(argSetCCDTempINDI->temp->value()));
2797 sf->setValid(true);
2798 }
2799 else
2800 {
2801 warningMismatch( "setINDICCDTemp" );
2802 }
2803
2804}
2805
2806void ScriptBuilder::slotINDISetFilterNum()
2807{
2808
2809 ScriptFunction * sf = ScriptList[ sb->ScriptListBox->currentRow() ];
2810
2811 if ( sf->name() == "setINDIFilterNum" )
2812 {
2813
2814 if (sf->argVal(0).toInt() != argSetFilterNumINDI->filter_num->value())
2815 setUnsavedChanges( true );
2816
2817 sf->setArg(0, QString("%1").arg(argSetFilterNumINDI->filter_num->value()));
2818 sf->setValid(true);
2819 }
2820 else
2821 {
2822 warningMismatch( "setINDIFilterNum" );
2823 }
2824
2825
2826}
2827#endif
2828
2829void ScriptBuilder::warningMismatch(const QString &expected) const
2830{
2831 qWarning() << i18n("Mismatch between function and Arg widget (expected %1.)", QString(expected));
2832}
unsigned int numberOfColors() const
ColorScheme * colorScheme()
Definition kstarsdata.h:180
static KStarsDateTime currentDateTime()
static KStars * Instance()
Definition kstars.h:122
Jason Harris.
double Hours() const
Definition dms.h:168
const double & Degrees() const
Definition dms.h:141
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
KIOCORE_EXPORT ChmodJob * chmod(const KFileItemList &lstItems, int permissions, int mask, const QString &newOwner, const QString &newGroup, bool recursive, JobFlags flags=DefaultFlags)
KIOCORE_EXPORT StoredTransferJob * storedHttpPost(const QByteArray &arr, const QUrl &url, JobFlags flags=DefaultFlags)
KIOCORE_EXPORT CopyJob * copy(const QList< QUrl > &src, const QUrl &dest, JobFlags flags=DefaultFlags)
QString path(const QString &relativePath)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
QString name(StandardAction id)
KGuiItem overwrite()
KGuiItem save()
KGuiItem discard()
KI18NLOCALEDATA_EXPORT KCountry country(const char *ianaId)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
QString applicationDirPath()
QDate currentDate()
int day() const const
int month() const const
int year() const const
QString toString(QStringView format, QCalendar cal) const const
virtual int exec()
QPushButton * button(StandardButton which) const const
QChar separator()
QString tempPath()
QByteArray encodeName(const QString &fileName)
bool exists() const const
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
void setFileName(const QString &name)
virtual void close() override
QUrl getOpenFileUrl(QWidget *parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, Options options, const QStringList &supportedSchemes)
QUrl getSaveFileUrl(QWidget *parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, Options options, const QStringList &supportedSchemes)
int horizontalAdvance(QChar ch) const const
QIcon fromTheme(const QString &name)
qsizetype count() const const
QObject * parent() const const
QObject * sender() const const
void setProcessEnvironment(const QProcessEnvironment &environment)
void start(OpenMode mode)
QProcess::ProcessState state() const const
bool waitForFinished(int msecs)
bool waitForStarted(int msecs)
void insert(const QProcessEnvironment &e)
QProcessEnvironment systemEnvironment()
QString value(const QString &name, const QString &defaultValue) const const
QRegularExpressionMatch next()
qsizetype count() const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
QString left(qsizetype n) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString right(qsizetype n) const const
double toDouble(bool *ok) const const
int toInt(bool *ok, int base) const const
QByteArray toLatin1() const const
QString toLower() const const
QString trimmed() const const
MatchExactly
AscendingOrder
NoTextInteraction
WA_LayoutUsesWidgetRect
QTextStream & dec(QTextStream &stream)
virtual QString fileName() const const override
bool atEnd() const const
void flush()
QString readLine(qint64 maxlen)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QTime currentTime()
int hour() const const
int minute() const const
int second() const const
QTreeWidgetItem * child(int index) const const
int childCount() const const
QTreeWidgetItem * parent() const const
void setExpanded(bool expand)
void sortChildren(int column, Qt::SortOrder order)
QString text(int column) const const
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
QWidget(QWidget *parent, Qt::WindowFlags f)
bool close()
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 31 2025 11:53:51 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.