Kstars

exporteyepieceview.cpp
1 /*
2  SPDX-FileCopyrightText: 2016 Akarsh Simha <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "exporteyepieceview.h"
8 
9 #include "dms.h"
10 #include "eyepiecefield.h"
11 #include "kstarsdata.h"
12 #include "Options.h"
13 #include "skypoint.h"
14 
15 #include <QComboBox>
16 #include <QDialogButtonBox>
17 #include <QFileDialog>
18 #include <QHBoxLayout>
19 #include <QLabel>
20 #include <QPainter>
21 #include <QPixmap>
22 #include <QVBoxLayout>
23 #include <QWidget>
24 
25 ExportEyepieceView::ExportEyepieceView(const SkyPoint *_sp, const KStarsDateTime &dt, const QPixmap *renderImage,
26  const QPixmap *renderChart, QWidget *parent)
27  : QDialog(parent), m_dt(dt)
28 {
29 #ifdef Q_OS_OSX
31 #endif
32  m_sp.reset(new SkyPoint(*_sp)); // Work on a copy.
33 
34  Q_ASSERT(renderChart);
35  m_renderChart.reset(new QPixmap(*renderChart));
36 
37  if (renderImage != nullptr)
38  m_renderImage.reset(new QPixmap(*renderImage));
39 
40  setWindowTitle(i18nc("@title:window", "Export eyepiece view"));
41 
42  QWidget *mainWidget = new QWidget(this);
43  QVBoxLayout *mainLayout = new QVBoxLayout;
44  mainLayout->addWidget(mainWidget);
45  setLayout(mainLayout);
46 
48  mainLayout->addWidget(buttonBox);
49  connect(buttonBox, SIGNAL(rejected()), this, SLOT(slotCloseDialog()));
50  connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotSaveImage()));
51 
52  QVBoxLayout *rows = new QVBoxLayout;
53  mainWidget->setLayout(rows);
54 
55  QLabel *tickInfoLabel = new QLabel(i18n("Overlay orientation vs. time ticks: "), this);
56  m_tickConfigCombo = new QComboBox(this);
57  m_tickConfigCombo->addItem(i18n("None"));
58  m_tickConfigCombo->addItem(i18n("Towards Zenith"));
59  m_tickConfigCombo->addItem(i18n("Dobsonian View"));
60 
61  QHBoxLayout *optionsLayout = new QHBoxLayout;
62  optionsLayout->addWidget(tickInfoLabel);
63  optionsLayout->addWidget(m_tickConfigCombo);
64  optionsLayout->addStretch();
65  rows->addLayout(optionsLayout);
66 
67  m_tickWarningLabel = new QLabel(this);
68  rows->addWidget(m_tickWarningLabel);
69 
70  m_outputDisplay = new QLabel;
71  m_outputDisplay->setBackgroundRole(QPalette::Base);
72  m_outputDisplay->setScaledContents(false);
73  m_outputDisplay->setMinimumWidth(400);
75  rows->addWidget(m_outputDisplay);
76 
77  connect(m_tickConfigCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotOverlayTicks(int)));
78  connect(m_tickConfigCombo, SIGNAL(activated(int)), this, SLOT(slotOverlayTicks(int)));
79 
80  render();
81  show();
82 }
83 
85 {
86  m_tickConfig = tickConfig;
87  if (tickConfig == 0)
88  m_tickWarningLabel->setText(QString());
89  else if (tickConfig == 1)
90  m_tickWarningLabel->setText(i18n("Note: This overlay makes sense only if the view was generated in alt/az mode "
91  "with a preset such as Refractor or Vanilla"));
92  else if (tickConfig == 2)
93  m_tickWarningLabel->setText(i18n("Note: This overlay makes sense only if the view was generated in alt/az "
94  "mode with a preset such as Dobsonian"));
95  render();
96 }
97 
98 void ExportEyepieceView::render()
99 {
100  float baseWidth = m_renderChart->width();
101  float baseHeight = m_renderChart->height();
102 
103  if (m_renderImage.get() != nullptr)
104  m_output = QImage(int(baseWidth * 2.25), int(baseHeight),
105  QImage::Format_ARGB32); // 0.25 * baseWidth gap between the images
106  else
107  m_output = QImage(int(baseWidth), int(baseHeight), QImage::Format_ARGB32);
108 
109  m_output.fill(Qt::white);
110  QPainter op(&m_output);
111  op.drawPixmap(QPointF(0, 0), *m_renderChart);
112  if (m_renderImage.get() != nullptr)
113  op.drawPixmap(QPointF(baseWidth * 1.25, 0), *m_renderImage);
114 
115  if (m_tickConfig != 0 && Options::useAltAz()) // FIXME: this is very skymap-state-heavy for my happiness --asimha
116  {
117  // we must draw ticks
118  QImage tickOverlay(baseWidth, baseHeight, QImage::Format_ARGB32);
119  tickOverlay.fill(Qt::transparent);
120 
121  QPainter p(&tickOverlay);
122  p.setPen(Qt::red); // FIXME: Determine color depending on situation, or make it configurable
123  double rEnd = 0.85 * (baseWidth / 2.);
124  double rStart = 0.8 * (baseWidth / 2.);
125  QFont font;
126  font.setPixelSize((rEnd - rStart));
127  p.setFont(font);
128 
129  GeoLocation *geo = KStarsData::Instance()->geo();
130  double alt0 = m_sp->alt().Degrees(); // altitude when hour = 0, i.e. at m_dt (see below).
131  dms northAngle0 = EyepieceField::findNorthAngle(m_sp.get(), geo->lat());
132 
133  for (float hour = -3.5; hour <= 3.5; hour += 0.5)
134  {
135  dms rotation; // rotation
136 
137  // FIXME: Code duplication : code duplicated from EyepieceField. This should really be a member of SkyPoint or something.
138  SkyPoint sp = SkyPoint::timeTransformed(m_sp.get(), m_dt, geo, hour);
139  double alt = sp.alt().Degrees();
140  dms northAngle = EyepieceField::findNorthAngle(&sp, geo->lat());
141 
142  rotation = (northAngle - northAngle0);
143  if (m_tickConfig == 2)
144  {
145  // Dobsonian: add additional CW rotation by altitude, but compensate for the fact that we've already rotated by alt0
146  rotation = rotation - dms((alt - alt0));
147  }
148  rotation = rotation.reduce();
149  p.save();
150  p.translate(baseWidth / 2.0, baseHeight / 2.0);
151  p.rotate(-(rotation.Degrees() + 90.0));
152  p.drawLine(QPointF(rStart, 0), QPointF(rEnd, 0));
153  QTime ct = geo->UTtoLT(m_dt.addSecs(3600.0 * hour)).time();
154  p.drawText(QPointF(rEnd + 0.01 * baseWidth, 0), QString::asprintf("%02d:%02d", ct.hour(), ct.minute()));
155  p.restore();
156  }
157  p.end();
158  op.drawImage(QPointF(0, 0), tickOverlay);
159  if (m_renderImage.get() != nullptr)
160  {
161  op.drawImage(QPointF(baseWidth * 1.25, 0), tickOverlay);
162  }
163  }
164  op.end();
165 
166  m_outputDisplay->setPixmap((QPixmap::fromImage(m_output))
167  .scaled(m_outputDisplay->width(), m_outputDisplay->height(), Qt::KeepAspectRatio,
169 }
170 
172 {
173  // does nothing at the moment. TODO: Implement.
174  QString fileName = QFileDialog::getSaveFileName(this, i18nc("@title:window", "Save Image as"), QString(),
175  i18n("Image files (*.png *.jpg *.xpm *.bmp *.gif)"));
176  if (!fileName.isEmpty())
177  {
178  m_output.save(fileName);
179  slotCloseDialog();
180  }
181 }
182 
184 {
185  hide();
186  deleteLater();
187 }
const dms & alt() const
Definition: skypoint.h:281
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
void setText(const QString &)
QWidget(QWidget *parent, Qt::WindowFlags f)
static SkyPoint timeTransformed(const SkyPoint *p, const KStarsDateTime &dt, const GeoLocation *geo, const double hour=0)
returns a time-transformed SkyPoint.
Definition: skypoint.cpp:1121
void fill(uint pixelValue)
void setSizePolicy(QSizePolicy)
void setScaledContents(bool)
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
void slotCloseDialog()
Closes the dialog, and sets up deleteLater() so that the dialog is destructed.
void addStretch(int stretch)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KStarsDateTime addSecs(double s) const
void hide()
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
ExportEyepieceView(const SkyPoint *_sp, const KStarsDateTime &dt, const QPixmap *renderImage, const QPixmap *renderChart, QWidget *parent=nullptr)
Constructor.
void deleteLater()
void rejected()
KeepAspectRatio
QString i18n(const char *text, const TYPE &arg...)
void setWindowFlags(Qt::WindowFlags type)
void slotSaveImage()
Save the image (export), and then close the dialog by calling slotCloseDialog()
bool isEmpty() const const
GeoLocation * geo()
Definition: kstarsdata.h:229
void setWindowTitle(const QString &)
void slotOverlayTicks(int overlayType)
Change the tick overlay scheme.
void setBackgroundRole(QPalette::ColorRole role)
GeoCoordinates geo(const QVariant &location)
int hour() const const
void show()
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:37
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
const double & Degrees() const
Definition: dms.h:141
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void addItem(const QString &text, const QVariant &userData)
void setMinimumWidth(int minw)
void addLayout(QLayout *layout, int stretch)
const dms reduce() const
return the equivalent angle between 0 and 360 degrees.
Definition: dms.cpp:251
QString asprintf(const char *cformat,...)
void setLayout(QLayout *layout)
SmoothTransformation
void setPixmap(const QPixmap &)
int minute() const const
bool save(const QString &fileName, const char *format, int quality) const const
Relevant data about an observing location on Earth.
Definition: geolocation.h:27
static dms findNorthAngle(const SkyPoint *sp, const dms *lat)
Finds the angle between "up" (i.e.
void accepted()
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sun Aug 14 2022 04:13:55 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.