7#include "viewsdialog.h"
11#include <QPainterPath>
12#include <QPainterPathStroker>
13#include <kstars_debug.h>
28 return defaultFlags & (~Qt::ItemIsDropEnabled);
39 ui =
new ViewsDialogUI(
this);
41 setWindowTitle(
i18nc(
"@title:window",
"Manage Sky Map Views"));
45 setLayout(mainLayout);
49 connect(buttonBox, SIGNAL(accepted()),
this, SLOT(accept()));
50 connect(buttonBox, SIGNAL(rejected()),
this, SLOT(
close()));
53 m_model =
new ViewsDialogStringListModel(
this);
55 ui->ViewListBox->setModel(m_model);
58 ui->ViewListBox->setDragDropOverwriteMode(
false);
62 connect(ui->NewButton, SIGNAL(clicked()), SLOT(slotNewView()));
63 connect(ui->EditButton, SIGNAL(clicked()), SLOT(slotEditView()));
64 connect(ui->RemoveButton, SIGNAL(clicked()), SLOT(slotRemoveView()));
68void ViewsDialog::syncModel()
70 QStringList viewNames;
73 viewNames.
append(view.name);
75 m_model->setStringList(viewNames);
78void ViewsDialog::syncFromModel()
81 QHash<QString, SkyMapView> nameToViewMap;
84 nameToViewMap.
insert(view.name, view);
86 QStringList updatedList = m_model->stringList();
88 for (
const auto &view : updatedList)
98 bool enable = current.
isValid();
99 ui->RemoveButton->setEnabled(enable);
100 ui->EditButton->setEnabled(enable);
103void ViewsDialog::slotNewView()
105 QPointer<NewView> newViewDialog =
new NewView(
this);
108 const auto view = newViewDialog->getView();
110 m_model->insertRow(m_model->rowCount());
111 QModelIndex index = m_model->index(m_model->rowCount() - 1, 0);
112 m_model->setData(index, view.name);
113 ui->ViewListBox->setCurrentIndex(index);
115 delete newViewDialog;
118void ViewsDialog::slotEditView()
121 QModelIndex currentIndex = ui->ViewListBox->currentIndex();
124 const QString viewName = m_model->data(currentIndex).toString();
129 qCCritical(KSTARS) <<
"Programming Error";
134 QPointer<NewView> newViewDialog =
new NewView(
this, view);
139 const auto view = newViewDialog->getView();
143 delete newViewDialog;
146void ViewsDialog::slotRemoveView()
148 QModelIndex currentIndex = ui->ViewListBox->currentIndex();
151 const QString viewName = m_model->
data(currentIndex).toString();
154 m_model->removeRow(currentIndex.
row());
160class SliderResetEventFilter :
public QObject
163 SliderResetEventFilter(QSlider *slider,
QObject *
parent =
nullptr)
169 m_slider->installEventFilter(
this);
177 QMouseEvent *mouseEvent =
dynamic_cast<QMouseEvent*
>(
event);
178 Q_ASSERT(!!mouseEvent);
181 m_slider->setValue(0);
205 fieldOfViewSpinBox->addUnit(
"degrees", 1.0);
206 fieldOfViewSpinBox->addUnit(
"arcmin", 1 / 60.);
207 fieldOfViewSpinBox->addUnit(
"arcsec", 1 / 3600.);
208 fieldOfViewSpinBox->doubleSpinBox->setMaximum(600.0);
209 fieldOfViewSpinBox->doubleSpinBox->setMinimum(0.01);
210 fieldOfViewSpinBox->setEnabled(
false);
211 fieldOfViewSpinBox->doubleSpinBox->setValue(1.0);
226 this->updateViewingAnglePreviews();
228 viewingAngleSlider->setValue(0);
238 disableErectObserverCheckBox->setChecked(
true);
239 disableErectObserverCheckBox->setEnabled(
false);
244 disableErectObserverCheckBox->setEnabled(
true);
250 m_topPreview =
new QPixmap(400, 300);
251 m_bottomPreview =
new QPixmap(400, 300);
252 m_observerPixmap =
new QPixmap(
":/images/observer.png");
253 new SliderResetEventFilter(viewingAngleSlider);
258 const auto view = *_view;
259 m_originalName = view.name;
260 viewNameLineEdit->setText(view.name);
261 mountTypeComboBox->setCurrentIndex(view.useAltAz ? 1 : 0);
262 if (view.inverted && view.mirror)
264 invertedMirroredViewType->setChecked(
true);
266 else if (view.inverted)
268 invertedViewType->setChecked(
true);
270 else if (view.mirror)
272 mirroredViewType->setChecked(
true);
276 correctViewType->setChecked(
true);
279 viewingAngleSlider->setValue(view.viewAngle);
280 disableErectObserverCheckBox->setChecked(!view.erectObserver);
281 if (!std::isnan(view.fov))
283 fieldOfViewCheckBox->setChecked(
true);
284 fieldOfViewSpinBox->doubleSpinBox->setValue(view.fov);
293 delete m_bottomPreview;
294 delete m_observerPixmap;
301 view.name = viewNameLineEdit->text();
302 view.useAltAz = (mountTypeComboBox->currentIndex() > 0);
303 view.viewAngle = viewingAngleSlider->value();
304 view.mirror = invertedMirroredViewType->isChecked() || mirroredViewType->isChecked();
305 view.inverted = invertedMirroredViewType->isChecked() || invertedViewType->isChecked();
306 view.fov = fieldOfViewCheckBox->isChecked() ? fieldOfViewSpinBox->value() : NaN::d;
307 view.erectObserver = !(disableErectObserverCheckBox->isChecked());
312void NewView::done(
int r)
316 const QString name = viewNameLineEdit->text();
317 if (name != m_originalName)
322 i18n(
"There already exists a view with the name you attempted to use. Please choose a different name for this view."));
331void NewView::updateViewingAnglePreviews()
333 Q_ASSERT(!!m_topPreview);
334 Q_ASSERT(!!m_bottomPreview);
335 Q_ASSERT(!!m_observerPixmap);
340 float cx = m_topPreview->width() / 2., cy = m_topPreview->height() / 2.;
341 float size = std::min(m_topPreview->width(), m_topPreview->height());
342 float r = 0.75 * (
size / 2.);
343 QPainter p(m_topPreview);
348 p.drawEllipse(QPointF(cx, cy), r, r);
353 p.drawLine(cx - r, cy, cx + r, cy);
354 p.drawLine(cx, cy - r, cx, cy + r);
357 QPainterPathStroker stroker;
359 QPainterPath focuserPath;
360 double theta =
dms::DegToRad * (viewingAngleSlider->value() - 90);
361 focuserPath.
moveTo(cx + (r + 5.) * std::cos(theta), cy + (r + 5.) * std::sin(theta));
362 focuserPath.
lineTo(cx + (r + 25.) * std::cos(theta), cy + (r + 25.) * std::sin(theta));
366 if (!disableErectObserverCheckBox->isChecked() && std::abs(viewingAngleSlider->value()) > 1)
368 p.drawPixmap(QPointF(
369 viewingAngleSlider->value() > 0 ? m_topPreview->width() - m_observerPixmap->width() : 0,
370 m_topPreview->height() - m_observerPixmap->height()),
371 viewingAngleSlider->value() < 0 ?
372 m_observerPixmap->transformed(QTransform(-1, 0, 0, 1, 0, 0)) :
378 viewingAnglePreviewTop->setPixmap(m_topPreview->scaled(viewingAnglePreviewTop->width(), viewingAnglePreviewTop->height(),
384 float cx = m_bottomPreview->width() / 2., cy = m_bottomPreview->height() / 2.;
385 float size = std::min(m_bottomPreview->width(), m_bottomPreview->height());
386 float r = 0.75 * (
size / 2.);
387 QPainter p(m_bottomPreview);
392 p.drawEllipse(QPointF(cx, cy), r, r);
395 QPainterPathStroker stroker;
397 QPainterPath focuserPath;
398 double theta =
dms::DegToRad * (-viewingAngleSlider->value() - 90);
399 focuserPath.
moveTo(cx, cy);
400 focuserPath.
lineTo(cx + 25. * std::cos(theta), cy + 25. * std::sin(theta));
404 if (!disableErectObserverCheckBox->isChecked() && std::abs(viewingAngleSlider->value()) > 1)
406 p.drawPixmap(QPointF(
407 viewingAngleSlider->value() < 0 ? m_bottomPreview->width() - m_observerPixmap->width() : 0,
408 m_bottomPreview->height() - m_observerPixmap->height()),
409 viewingAngleSlider->value() > 0 ?
410 m_observerPixmap->transformed(QTransform(-1, 0, 0, 1, 0, 0)) :
416 viewingAnglePreviewBottom->setPixmap(m_bottomPreview->scaled(
417 viewingAnglePreviewBottom->width(), viewingAnglePreviewBottom->height(),
const SkyMapView getView() const
Return the view struct.
NewView(QWidget *parent=nullptr, std::optional< SkyMapView > view=std::nullopt)
Create new dialog.
static void drop()
Drop the list.
static bool save()
Commit the list of views to the database.
static bool removeView(const QString &name)
Remove a view Note: This is currently an O(N) operation.
static const QList< SkyMapView > & getViews()
Get the list of available views.
static std::optional< SkyMapView > viewNamed(const QString &name)
Get the view with the given name.
static void addView(const SkyMapView &newView)
Add a view.
static constexpr double DegToRad
DegToRad is a const static member equal to the number of radians in one degree (dms::PI/180....
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
void rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
void valueChanged(int value)
void currentIndexChanged(int index)
QDialog(QWidget *parent, Qt::WindowFlags f)
iterator insert(const Key &key, const T &value)
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
void textChanged(const QString &text)
void append(QList< T > &&value)
StandardButton critical(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
bool isValid() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
virtual bool eventFilter(QObject *watched, QEvent *event)
QObject * parent() const const
void lineTo(const QPointF &endPoint)
void moveTo(const QPointF &point)
QPainterPath createStroke(const QPainterPath &path) const const
void setWidth(qreal width)
bool isEmpty() const const
QString number(double n, char format, int precision)
virtual Qt::ItemFlags flags(const QModelIndex &index) const const override
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
Carries parameters of a sky map view.