1 /*
2  * Stellarium
3  * Copyright (C) 2008 Fabien Chereau
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18 */
19 
20 
21 #include "StelDialog.hpp"
22 #include "StelDialog_p.hpp"
23 #include "StelMainView.hpp"
24 #include "StelGui.hpp"
25 #include "StelActionMgr.hpp"
26 #include "StelPropertyMgr.hpp"
27 #include "StelTranslator.hpp"
28 #include "StelModuleMgr.hpp"
29 
30 #include <QDebug>
31 #include <QAbstractButton>
32 #include <QComboBox>
33 #include <QDialog>
34 #include <QGraphicsSceneWheelEvent>
35 #include <QMetaProperty>
36 #include <QStyleOptionGraphicsItem>
37 #include <QSlider>
38 #include <QSpinBox>
39 #include <QDoubleSpinBox>
40 #include <QLineEdit>
41 #include <QScroller>
42 #include <QToolButton>
43 #include <QColorDialog>
44 #include <QMessageBox>
45 
StelDialog(QString dialogName,QObject * parent)46 StelDialog::StelDialog(QString dialogName, QObject* parent)
47 	: QObject(parent)
48 	, dialog(Q_NULLPTR)
49 	, proxy(Q_NULLPTR)
50 	, dialogName(dialogName)
51 {
52 	if (parent == Q_NULLPTR)
53 		setParent(StelMainView::getInstance().getGuiWidget());
54 
55 	connect(&StelApp::getInstance(), SIGNAL(fontChanged(QFont)), this, SLOT(handleFontChanged()));
56 	connect(&StelApp::getInstance(), SIGNAL(guiFontSizeChanged(int)), this, SLOT(handleFontChanged()));
57 }
58 
~StelDialog()59 StelDialog::~StelDialog()
60 {
61 }
62 
close()63 void StelDialog::close()
64 {
65 	setVisible(false);
66 }
67 
styleChanged()68 void StelDialog::styleChanged()
69 {
70 	// Nothing for now
71 }
72 
visible() const73 bool StelDialog::visible() const
74 {
75 	return dialog!=Q_NULLPTR && dialog->isVisible();
76 }
77 
setVisible(bool v)78 void StelDialog::setVisible(bool v)
79 {
80 	if (v)
81 	{
82 		StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
83 		QSize screenSize = StelMainView::getInstance().size();
84 		// If dialog size is very large and we move to a computer with much smaller screen, this should create the dialog with reasonable better size.
85 		QSize maxSize = 0.95*screenSize;
86 		if (dialog)
87 		{
88 			// reload stylesheet, in case size changed!
89 			if (gui)
90 				dialog->setStyleSheet(gui->getStelStyle().qtStyleSheet);
91 			dialog->show();
92 			StelMainView::getInstance().scene()->setActiveWindow(proxy);
93 			// If the main window has been resized, it is possible the dialog
94 			// will be off screen.  Check for this and move it to a visible
95 			// position if necessary
96 			QPointF newPos = proxy->pos();
97 			if (newPos.x()>=screenSize.width())
98 				newPos.setX(screenSize.width() - dialog->size().width());
99 			if (newPos.y()>=screenSize.height())
100 				newPos.setY(screenSize.height() - dialog->size().height());
101 			if (newPos != dialog->pos())
102 				proxy->setPos(newPos);
103 		}
104 		else
105 		{
106 			QGraphicsWidget* parent = qobject_cast<QGraphicsWidget*>(this->parent());
107 			dialog = new QDialog(Q_NULLPTR);
108 			// dialog->setParent(parent);
109 			//dialog->setAttribute(Qt::WA_OpaquePaintEvent, true);
110 			connect(dialog, SIGNAL(rejected()), this, SLOT(close()));
111 			createDialogContent();
112 			if (gui)
113 				dialog->setStyleSheet(gui->getStelStyle().qtStyleSheet);
114 			// Ensure that tooltip get rendered in red in night mode.
115 			connect(&StelApp::getInstance(), SIGNAL(visionNightModeChanged(bool)), this, SLOT(updateNightModeProperty(bool)));
116 			updateNightModeProperty(StelApp::getInstance().getVisionModeNight());
117 
118 			proxy = new CustomProxy(parent, Qt::Tool);
119 			proxy->setWidget(dialog);
120 			QSizeF size = proxy->size();
121 
122 			connect(proxy, SIGNAL(sizeChanged(QSizeF)), this, SLOT(handleDialogSizeChanged(QSizeF)));
123 
124 			int newX, newY;
125 			// Retrieve panel locations from config.ini, but shift if required to a visible position.
126 			// else centre dialog according to current window size.
127 			QSettings *conf=StelApp::getInstance().getSettings();
128 			Q_ASSERT(conf);
129 			QString confNamePt="DialogPositions/" + dialogName;
130 			QString storedPosString=conf->value(confNamePt,
131 							    QString("%1,%2")
132 							    .arg(static_cast<int>((screenSize.width()  - size.width() )/2))
133 							    .arg(static_cast<int>((screenSize.height() - size.height())/2)))
134 					.toString();
135 			QStringList posList=storedPosString.split(",");
136 			if (posList.length()==2)
137 			{
138 				newX=posList.at(0).toInt();
139 				newY=posList.at(1).toInt();
140 			}
141 			else	// in case there is an invalid string?
142 			{
143 				newX=static_cast<int>((screenSize.width()  - size.width() )/2);
144 				newY=static_cast<int>((screenSize.height() - size.height())/2);
145 			}
146 
147 			if (newX>=screenSize.width())
148 				newX= (screenSize.width()  - dialog->size().width());
149 			if (newY>=screenSize.height())
150 				newY= (screenSize.height() - dialog->size().height());
151 
152 			// Make sure that the window's title bar is accessible
153 			if (newY <-0)
154 				newY = 0;
155 			proxy->setPos(newX, newY);
156 			// Invisible frame around the window to make resizing easier
157 			// (this also changes the bounding rectangle size)
158 			proxy->setWindowFrameMargins(7,0,7,7);
159 
160 			// Retrieve stored panel sizes, scale panel up if it was stored larger than default.
161 			QString confNameSize="DialogSizes/" + dialogName;
162 			QString storedSizeString=conf->value(confNameSize, QString("0,0")).toString();
163 			QStringList sizeList=storedSizeString.split(",");
164 			if (sizeList.length()==2)
165 			{
166 				newX=sizeList.at(0).toInt();
167 				newY=sizeList.at(1).toInt();
168 			}
169 			else	// in case there is an invalid string?
170 			{
171 				newX=0;
172 				newY=0;
173 			}
174 			// resize only if number was valid and larger than default loaded size.
175 			if ( (newX>=proxy->size().width()) || (newY>=proxy->size().height()) )
176 			{
177 				//qDebug() << confNameSize << ": resize from" << proxy->size().width() << "x" << proxy->size().height() << "to " << storedSizeString;
178 				proxy->resize(qMax(static_cast<qreal>(newX), proxy->size().width()), qMax(static_cast<qreal>(newY), proxy->size().height()));
179 			}
180 			if(proxy->size().width() > maxSize.width() || proxy->size().height() > maxSize.height())
181 			{
182 				proxy->resize(qMin(static_cast<qreal>(maxSize.width()), proxy->size().width()), qMin(static_cast<qreal>(maxSize.height()), proxy->size().height()));
183 			}
184 			handleDialogSizeChanged(proxy->size()); // This may trigger internal updates in subclasses. E.g. LocationPanel location arrow.
185 
186 			proxy->setZValue(100);
187 			StelMainView::getInstance().scene()->setActiveWindow(proxy);
188 		}
189 		proxy->setFocus();
190 	}
191 	else
192 	{
193 		dialog->hide();
194 		//proxy->clearFocus();
195 		StelMainView::getInstance().focusSky();
196 	}
197 	emit visibleChanged(v);
198 }
199 
handleFontChanged()200 void StelDialog::handleFontChanged()
201 {
202 	if (dialog && dialog->isVisible())
203 	{
204 		// reload stylesheet, in case size or font changed!
205 		StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
206 		if (gui)
207 			dialog->setStyleSheet(gui->getStelStyle().qtStyleSheet);
208 	}
209 }
210 
connectCheckBox(QAbstractButton * checkBox,const QString & actionName)211 void StelDialog::connectCheckBox(QAbstractButton *checkBox, const QString &actionName)
212 {
213 	StelAction* action = StelApp::getInstance().getStelActionManager()->findAction(actionName);
214 	connectCheckBox(checkBox,action);
215 }
216 
connectCheckBox(QAbstractButton * checkBox,StelAction * action)217 void StelDialog::connectCheckBox(QAbstractButton *checkBox, StelAction *action)
218 {
219 	Q_ASSERT(action);
220 	checkBox->setChecked(action->isChecked());
221 	connect(action, SIGNAL(toggled(bool)), checkBox, SLOT(setChecked(bool)));
222 	connect(checkBox, SIGNAL(toggled(bool)), action, SLOT(setChecked(bool)));
223 }
224 
connectIntProperty(QLineEdit * lineEdit,const QString & propName)225 void StelDialog::connectIntProperty(QLineEdit* lineEdit, const QString& propName)
226 {
227 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
228 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
229 
230 	//use a proxy for the connection
231 	new QLineEditStelPropertyConnectionHelper(prop,lineEdit);
232 }
233 
connectIntProperty(QSpinBox * spinBox,const QString & propName)234 void StelDialog::connectIntProperty(QSpinBox *spinBox, const QString &propName)
235 {
236 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
237 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
238 
239 	//use a proxy for the connection
240 	new QSpinBoxStelPropertyConnectionHelper(prop,spinBox);
241 }
242 
connectIntProperty(QComboBox * comboBox,const QString & propName)243 void StelDialog::connectIntProperty(QComboBox *comboBox, const QString &propName)
244 {
245 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
246 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
247 
248 	//use a proxy for the connection
249 	new QComboBoxStelPropertyConnectionHelper(prop,comboBox);
250 }
251 
connectIntProperty(QSlider * slider,const QString & propName,int minValue,int maxValue)252 void StelDialog::connectIntProperty(QSlider *slider, const QString &propName,int minValue, int maxValue)
253 {
254 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
255 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
256 
257 	//The connection is handled by a helper class. It is automatically destroyed when the slider is destroyed.
258 	new QSliderStelPropertyConnectionHelper(prop,minValue,maxValue,slider);
259 }
260 
connectDoubleProperty(QDoubleSpinBox * spinBox,const QString & propName)261 void StelDialog::connectDoubleProperty(QDoubleSpinBox *spinBox, const QString &propName)
262 {
263 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
264 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
265 
266 	//use a proxy for the connection
267 	new QDoubleSpinBoxStelPropertyConnectionHelper(prop,spinBox);
268 }
269 
connectDoubleProperty(AngleSpinBox * spinBox,const QString & propName)270 void StelDialog::connectDoubleProperty(AngleSpinBox *spinBox, const QString &propName)
271 {
272 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
273 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
274 
275 	//use a proxy for the connection
276 	new AngleSpinBoxStelPropertyConnectionHelper(prop,spinBox);
277 }
278 
connectDoubleProperty(QSlider * slider,const QString & propName,double minValue,double maxValue)279 void StelDialog::connectDoubleProperty(QSlider *slider, const QString &propName,double minValue, double maxValue)
280 {
281 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
282 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
283 
284 	//The connection is handled by a helper class. It is automatically destroyed when the slider is destroyed.
285 	new QSliderStelPropertyConnectionHelper(prop,minValue,maxValue,slider);
286 }
287 
connectStringProperty(QComboBox * comboBox,const QString & propName)288 void StelDialog::connectStringProperty(QComboBox *comboBox, const QString &propName)
289 {
290 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
291 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
292 
293 	//use a proxy for the connection
294 	new QComboBoxStelStringPropertyConnectionHelper(prop,comboBox);
295 }
296 
connectStringProperty(QLineEdit * lineEdit,const QString & propName)297 void StelDialog::connectStringProperty(QLineEdit *lineEdit, const QString &propName)
298 {
299 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
300 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
301 
302 	//use a proxy for the connection
303 	new QLineEditStelPropertyConnectionHelper(prop,lineEdit);
304 }
305 
connectBoolProperty(QAbstractButton * checkBox,const QString & propName)306 void StelDialog::connectBoolProperty(QAbstractButton *checkBox, const QString &propName)
307 {
308 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
309 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
310 
311 	new QAbstractButtonStelPropertyConnectionHelper(prop,checkBox);
312 }
313 
connectBoolProperty(QGroupBox * checkBox,const QString & propName)314 void StelDialog::connectBoolProperty(QGroupBox *checkBox, const QString &propName)
315 {
316 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propName);
317 	Q_ASSERT_X(prop,"StelDialog", "StelProperty does not exist");
318 
319 	new QGroupBoxStelPropertyConnectionHelper(prop,checkBox);
320 }
321 
askConfirmation()322 bool StelDialog::askConfirmation()
323 {
324 	return (QMessageBox::warning(&StelMainView::getInstance(), q_("Attention!"), q_("Are you sure? This will delete your customized data."), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes);
325 }
326 
connectColorButton(QToolButton * toolButton,QString propertyName,QString iniName,QString moduleName)327 void StelDialog::connectColorButton(QToolButton *toolButton, QString propertyName, QString iniName, QString moduleName)
328 {
329 	toolButton->setProperty("propName", propertyName);
330 	toolButton->setProperty("iniName", iniName);
331 	toolButton->setProperty("moduleName", moduleName);
332 	StelProperty* prop = StelApp::getInstance().getStelPropertyManager()->getProperty(propertyName);
333 	QColor color=prop->getValue().value<Vec3f>().toQColor();
334 	// Use style sheet to create a nice button :)
335 	toolButton->setStyleSheet("QToolButton { background-color:" + color.name() + "; }");
336 	toolButton->setFixedSize(QSize(18, 18));
337 
338 	connect(toolButton, SIGNAL(released()), this, SLOT(askColor()));
339 }
340 
askColor()341 void StelDialog::askColor()
342 {
343 	// Only work if connected from a QToolButton
344 	if (!sender())
345 	{
346 		qWarning() << "askColor(): No sender? Ignoring.";
347 		Q_ASSERT(0);
348 		return;
349 	}
350 	if (QString(sender()->metaObject()->className()) != QString("QToolButton"))
351 	{
352 		qWarning() << "Sender not a QToolButton but a |" << sender()->metaObject()->className() << "|! ColorButton not set up properly! Ignoring.";
353 		Q_ASSERT(0);
354 		return;
355 	}
356 	QString propName=sender()->property("propName").toString();
357 	QString iniName=sender()->property("iniName").toString();
358 	QString moduleName=sender()->property("moduleName").toString(); // optional
359 	if ((propName.isEmpty()) || (iniName.isEmpty()))
360 	{
361 		qWarning() << "ColorButton not set up properly! Ignoring.";
362 		Q_ASSERT(0);
363 		return;
364 	}
365 	Vec3d vColor = StelApp::getInstance().getStelPropertyManager()->getProperty(propName)->getValue().value<Vec3f>().toVec3d();
366 	QColor color = vColor.toQColor();
367 	QColor c = QColorDialog::getColor(color, &StelMainView::getInstance() , q_(static_cast<QToolButton*>(QObject::sender())->toolTip()));
368 	if (c.isValid())
369 	{
370 		vColor = Vec3d(c.redF(), c.greenF(), c.blueF());
371 		StelApp::getInstance().getStelPropertyManager()->setStelPropertyValue(propName, QVariant::fromValue(Vec3f(c.redF(), c.greenF(), c.blueF())));
372 		if (moduleName.isEmpty())
373 			StelApp::getInstance().getSettings()->setValue(iniName, vColor.toStr());
374 		else
375 		{
376 			StelModule *module=StelApp::getInstance().getModuleMgr().getModule(moduleName);
377 			QSettings *settings=module->getSettings();
378 			Q_ASSERT(settings);
379 			settings->setValue(iniName, vColor.toStr());
380 		}
381 		static_cast<QToolButton*>(QObject::sender())->setStyleSheet("QToolButton { background-color:" + c.name() + "; }");
382 	}
383 }
384 
enableKineticScrolling(bool b)385 void StelDialog::enableKineticScrolling(bool b)
386 {
387 	if (kineticScrollingList.length()==0) return;
388 	if (b)
389 	{
390 		for (auto* w : kineticScrollingList)
391 		{
392 			QScroller::grabGesture(w, QScroller::LeftMouseButtonGesture);
393 			QScroller::scroller(w); // WHAT DOES THIS DO? We don't use the return value.
394 		}
395 	}
396 	else
397 	{
398 		for (auto* w : kineticScrollingList)
399 		{
400 			QScroller::ungrabGesture(w);
401 			// QScroller::scroller(w);
402 		}
403 	}
404 }
405 
updateNightModeProperty(bool n)406 void StelDialog::updateNightModeProperty(bool n)
407 {
408 	dialog->setProperty("nightMode", n);
409 }
410 
handleMovedTo(QPoint newPos)411 void StelDialog::handleMovedTo(QPoint newPos)
412 {
413 	QSettings *conf=StelApp::getInstance().getSettings();
414 	Q_ASSERT(conf);
415 	conf->setValue("DialogPositions/" + dialogName, QString("%1,%2").arg(newPos.x()).arg(newPos.y()));
416 }
417 
handleDialogSizeChanged(QSizeF size)418 void StelDialog::handleDialogSizeChanged(QSizeF size)
419 {
420 	QSettings *conf=StelApp::getInstance().getSettings();
421 	Q_ASSERT(conf);
422 	conf->setValue("DialogSizes/" + dialogName, QString("%1,%2").arg(static_cast<int>(size.width())).arg(static_cast<int>(size.height())));
423 }
424 
425 
426 //// --- Implementation of StelDialog_p.hpp classes follow ---
427 
QAbstractButtonStelPropertyConnectionHelper(StelProperty * prop,QAbstractButton * button)428 QAbstractButtonStelPropertyConnectionHelper::QAbstractButtonStelPropertyConnectionHelper(StelProperty *prop, QAbstractButton *button)
429 	:StelPropertyProxy(prop,button), button(button)
430 {
431 	QVariant val = prop->getValue();
432 	bool ok = val.canConvert<bool>();
433 	Q_ASSERT_X(ok,"QAbstractButtonStelPropertyConnectionHelper","Can not convert to bool datatype");
434 	Q_UNUSED(ok);
435 	onPropertyChanged(val);
436 
437 	//in this direction, we can directly connect because Qt supports QVariant slots with the new syntax
438 	connect(button, &QAbstractButton::toggled, prop, &StelProperty::setValue);
439 }
440 
onPropertyChanged(const QVariant & value)441 void QAbstractButtonStelPropertyConnectionHelper::onPropertyChanged(const QVariant &value)
442 {
443 	//block signals to prevent sending the valueChanged signal, changing the property again
444 	bool b = button->blockSignals(true);
445 	button->setChecked(value.toBool());
446 	button->blockSignals(b);
447 }
448 
QGroupBoxStelPropertyConnectionHelper(StelProperty * prop,QGroupBox * box)449 QGroupBoxStelPropertyConnectionHelper::QGroupBoxStelPropertyConnectionHelper(StelProperty *prop, QGroupBox *box)
450 	:StelPropertyProxy(prop,box), box(box)
451 {
452 	QVariant val = prop->getValue();
453 	bool ok = val.canConvert<bool>();
454 	Q_ASSERT_X(ok,"QGroupBoxStelPropertyConnectionHelper","Can not convert to bool datatype");
455 	Q_UNUSED(ok);
456 	onPropertyChanged(val);
457 
458 	//in this direction, we can directly connect because Qt supports QVariant slots with the new syntax
459 	connect(box, &QGroupBox::toggled, prop, &StelProperty::setValue);
460 }
461 
onPropertyChanged(const QVariant & value)462 void QGroupBoxStelPropertyConnectionHelper::onPropertyChanged(const QVariant &value)
463 {
464 	//block signals to prevent sending the valueChanged signal, changing the property again
465 	bool b = box->blockSignals(true);
466 	box->setChecked(value.toBool());
467 	box->blockSignals(b);
468 }
469 
QComboBoxStelPropertyConnectionHelper(StelProperty * prop,QComboBox * combo)470 QComboBoxStelPropertyConnectionHelper::QComboBoxStelPropertyConnectionHelper(StelProperty *prop, QComboBox *combo)
471 	:StelPropertyProxy(prop,combo), combo(combo)
472 {
473 	QVariant val = prop->getValue();
474 	bool ok = val.canConvert<int>();
475 	Q_ASSERT_X(ok,"QComboBoxStelPropertyConnectionHelper","Can not convert to int datatype");
476 	Q_UNUSED(ok);
477 	onPropertyChanged(val);
478 
479 	//in this direction, we can directly connect because Qt supports QVariant slots with the new syntax
480 	connect(combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),prop,&StelProperty::setValue);
481 }
482 
onPropertyChanged(const QVariant & value)483 void QComboBoxStelPropertyConnectionHelper::onPropertyChanged(const QVariant &value)
484 {
485 	//block signals to prevent sending the valueChanged signal, changing the property again
486 	bool b = combo->blockSignals(true);
487 	combo->setCurrentIndex(value.toInt());
488 	combo->blockSignals(b);
489 }
QComboBoxStelStringPropertyConnectionHelper(StelProperty * prop,QComboBox * combo)490 QComboBoxStelStringPropertyConnectionHelper::QComboBoxStelStringPropertyConnectionHelper(StelProperty *prop, QComboBox *combo)
491 	:StelPropertyProxy(prop,combo), combo(combo)
492 {
493 	QVariant val = prop->getValue();
494 	bool ok = val.canConvert<QString>();
495 	Q_ASSERT_X(ok,"QComboBoxStelStringPropertyConnectionHelper","Can not convert to QString datatype");
496 	Q_UNUSED(ok);
497 	onPropertyChanged(val);
498 
499 	//in this direction, we can directly connect because Qt supports QVariant slots with the new syntax
500 	connect(combo, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),prop,&StelProperty::setValue);
501 }
502 
onPropertyChanged(const QVariant & value)503 void QComboBoxStelStringPropertyConnectionHelper::onPropertyChanged(const QVariant &value)
504 {
505 	//block signals to prevent sending the valueChanged signal, changing the property again
506 	bool b = combo->blockSignals(true);
507 	combo->setCurrentText(value.toString());
508 	combo->blockSignals(b);
509 }
510 
QLineEditStelPropertyConnectionHelper(StelProperty * prop,QLineEdit * edit)511 QLineEditStelPropertyConnectionHelper::QLineEditStelPropertyConnectionHelper(StelProperty *prop, QLineEdit *edit)
512 	:StelPropertyProxy(prop,edit), edit(edit)
513 {
514 	QVariant val = prop->getValue();
515 	bool ok = val.canConvert<int>();
516 	Q_ASSERT_X(ok,"QLineEditStelPropertyConnectionHelper","Can not convert to int datatype");
517 	Q_UNUSED(ok);
518 	onPropertyChanged(val);
519 
520 	//in this direction, we can directly connect because Qt supports QVariant slots with the new syntax
521 	connect(edit, static_cast<void (QLineEdit::*)(const QString&)>(&QLineEdit::textEdited),prop,&StelProperty::setValue);
522 }
523 
onPropertyChanged(const QVariant & value)524 void QLineEditStelPropertyConnectionHelper::onPropertyChanged(const QVariant &value)
525 {
526 	//block signals to prevent sending the valueChanged signal, changing the property again
527 	bool b = edit->blockSignals(true);
528 	edit->setText(value.toString());
529 	edit->blockSignals(b);
530 }
531 
QSpinBoxStelPropertyConnectionHelper(StelProperty * prop,QSpinBox * spin)532 QSpinBoxStelPropertyConnectionHelper::QSpinBoxStelPropertyConnectionHelper(StelProperty *prop, QSpinBox *spin)
533 	:StelPropertyProxy(prop,spin), spin(spin)
534 {
535 	QVariant val = prop->getValue();
536 	bool ok = val.canConvert<int>();
537 	Q_ASSERT_X(ok,"QSpinBoxStelPropertyConnectionHelper","Can not convert to int datatype");
538 	Q_UNUSED(ok);
539 	onPropertyChanged(val);
540 
541 	//in this direction, we can directly connect because Qt supports QVariant slots with the new syntax
542 	connect(spin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),prop,&StelProperty::setValue);
543 }
544 
onPropertyChanged(const QVariant & value)545 void QSpinBoxStelPropertyConnectionHelper::onPropertyChanged(const QVariant &value)
546 {
547 	//block signals to prevent sending the valueChanged signal, changing the property again
548 	bool b = spin->blockSignals(true);
549 	spin->setValue(value.toInt());
550 	spin->blockSignals(b);
551 }
552 
QDoubleSpinBoxStelPropertyConnectionHelper(StelProperty * prop,QDoubleSpinBox * spin)553 QDoubleSpinBoxStelPropertyConnectionHelper::QDoubleSpinBoxStelPropertyConnectionHelper(StelProperty *prop, QDoubleSpinBox *spin)
554 	:StelPropertyProxy(prop,spin), spin(spin)
555 {
556 	QVariant val = prop->getValue();
557 	bool ok = val.canConvert<double>();
558 	Q_ASSERT_X(ok,"QDoubleSpinBoxStelPropertyConnectionHelper","Can not convert to double datatype");
559 	Q_UNUSED(ok);
560 	onPropertyChanged(val);
561 
562 	//in this direction, we can directly connect because Qt supports QVariant slots with the new syntax
563 	connect(spin, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),prop,&StelProperty::setValue);
564 }
565 
onPropertyChanged(const QVariant & value)566 void QDoubleSpinBoxStelPropertyConnectionHelper::onPropertyChanged(const QVariant &value)
567 {
568 	//block signals to prevent sending the valueChanged signal, changing the property again
569 	bool b = spin->blockSignals(true);
570 	spin->setValue(value.toDouble());
571 	spin->blockSignals(b);
572 }
573 
AngleSpinBoxStelPropertyConnectionHelper(StelProperty * prop,AngleSpinBox * spin)574 AngleSpinBoxStelPropertyConnectionHelper::AngleSpinBoxStelPropertyConnectionHelper(StelProperty *prop, AngleSpinBox *spin)
575 	:StelPropertyProxy(prop,spin), spin(spin)
576 {
577 	QVariant val = prop->getValue();
578 	bool ok = val.canConvert<double>();
579 	Q_ASSERT_X(ok,"AngleSpinBoxStelPropertyConnectionHelper","Can not convert to double datatype");
580 	Q_UNUSED(ok);
581 	onPropertyChanged(val);
582 
583 	//in this direction, we can directly connect because Qt supports QVariant slots with the new syntax
584 	connect(spin, static_cast<void (AngleSpinBox::*)(double)>(&AngleSpinBox::valueChangedDeg),prop,&StelProperty::setValue);
585 }
586 
onPropertyChanged(const QVariant & value)587 void AngleSpinBoxStelPropertyConnectionHelper::onPropertyChanged(const QVariant &value)
588 {
589 	//block signals to prevent sending the valueChanged signal, changing the property again
590 	bool b = spin->blockSignals(true);
591 	spin->setDegrees(value.toDouble());
592 	spin->blockSignals(b);
593 }
594 
595 
QSliderStelPropertyConnectionHelper(StelProperty * prop,double minValue,double maxValue,QSlider * slider)596 QSliderStelPropertyConnectionHelper::QSliderStelPropertyConnectionHelper(StelProperty *prop, double minValue, double maxValue, QSlider *slider)
597 	: StelPropertyProxy(prop,slider),slider(slider),minValue(minValue),maxValue(maxValue)
598 {
599 	QVariant val = prop->getValue();
600 	bool ok = val.canConvert<double>();
601 	Q_ASSERT_X(ok,"QSliderStelPropertyConnectionHelper","Can not convert to double datatype");
602 	Q_UNUSED(ok);
603 
604 	dRange = maxValue - minValue;
605 	onPropertyChanged(val);
606 
607 	connect(slider,SIGNAL(valueChanged(int)),this,SLOT(sliderIntValueChanged(int)));
608 }
609 
QSliderStelPropertyConnectionHelper(StelProperty * prop,int minValue,int maxValue,QSlider * slider)610 QSliderStelPropertyConnectionHelper::QSliderStelPropertyConnectionHelper(StelProperty *prop, int minValue, int maxValue, QSlider *slider)
611 	: StelPropertyProxy(prop,slider),slider(slider),minValue(minValue),maxValue(maxValue)
612 {
613 	QVariant val = prop->getValue();
614 	bool ok = val.canConvert<double>();
615 	Q_ASSERT_X(ok,"QSliderStelPropertyConnectionHelper","Can not convert to double datatype");
616 	Q_UNUSED(ok);
617 
618 	dRange = maxValue - minValue;
619 	onPropertyChanged(val);
620 
621 	connect(slider,SIGNAL(valueChanged(int)),this,SLOT(sliderIntValueChanged(int)));
622 }
sliderIntValueChanged(int val)623 void QSliderStelPropertyConnectionHelper::sliderIntValueChanged(int val)
624 {
625 	double dVal = ((val - slider->minimum()) / static_cast<double>(slider->maximum() - slider->minimum())) * dRange + minValue;
626 	prop->setValue(dVal);
627 }
628 
onPropertyChanged(const QVariant & val)629 void QSliderStelPropertyConnectionHelper::onPropertyChanged(const QVariant& val)
630 {
631 	double dVal = val.toDouble();
632 	int iRange = slider->maximum() - slider->minimum();
633 	int iVal = qRound(((dVal - minValue)/dRange) * iRange + slider->minimum());
634 	bool b = slider->blockSignals(true);
635 	slider->setValue(iVal);
636 	slider->blockSignals(b);
637 }
638