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