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
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 {
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{
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:172
static KStarsDateTime currentDateTime()
static KStars * Instance()
Definition kstars.h:121
Dialog for changing the geographic location of the observer.
Jason Harris.
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
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)
QString name(GameStandardAction id)
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)
QStringView country(QStringView ifopt)
KGuiItem overwrite()
KGuiItem save()
KGuiItem discard()
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)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
void clear()
qsizetype count() const const
iterator insert(const_iterator before, parameter_type value)
bool isEmpty() const const
T & last()
void removeAt(qsizetype i)
T takeAt(qsizetype i)
value_type takeFirst()
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
QString arg(Args &&... args) const const
void clear()
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
qsizetype length() 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
void setRootIsDecorated(bool show)
void setColumnWidth(int column, int width)
QTreeWidgetItem * currentItem() const const
QTreeWidgetItem * topLevelItem(int index) 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
void clear()
QString fileName(ComponentFormattingOptions options) const const
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
bool isEmpty() const const
bool isLocalFile() const const
bool isValid() const const
QString toLocalFile() const const
QString url(FormattingOptions options) const const
bool close()
void setEnabled(bool)
QFontMetrics fontMetrics() const const
void show()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.