diff --git a/kstars/auxiliary/fov.cpp b/kstars/auxiliary/fov.cpp index a864be9d0..b32205d12 100644 --- a/kstars/auxiliary/fov.cpp +++ b/kstars/auxiliary/fov.cpp @@ -1,406 +1,412 @@ /*************************************************************************** fov.cpp - description ------------------- begin : Fri 05 Sept 2003 copyright : (C) 2003 by Jason Harris email : kstars@30doradus.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "fov.h" #include "geolocation.h" #include "kspaths.h" #ifndef KSTARS_LITE #include "kstars.h" #endif #include "kstarsdata.h" #include "Options.h" #include "skymap.h" #include "projections/projector.h" #include "fovadaptor.h" #include #include #include #include #include #include QList FOVManager::m_FOVs; int FOV::m_ID=1; FOVManager::~FOVManager() { qDeleteAll(m_FOVs); } QList FOVManager::defaults() { QList fovs; fovs << new FOV(i18nc("use field-of-view for binoculars", "7x35 Binoculars"), 558, 558, 0, 0, 0, FOV::CIRCLE, "#AAAAAA") << new FOV(i18nc("use a Telrad field-of-view indicator", "Telrad"), 30, 30, 0, 0, 0, FOV::BULLSEYE, "#AA0000") << new FOV(i18nc("use 1-degree field-of-view indicator", "One Degree"), 60, 60, 0, 0, 0, FOV::CIRCLE, "#AAAAAA") << new FOV(i18nc("use HST field-of-view indicator", "HST WFPC2"), 2.4, 2.4, 0, 0, 0, FOV::SQUARE, "#AAAAAA") << new FOV(i18nc("use Radiotelescope HPBW", "30m at 1.3cm"), 1.79, 1.79, 0, 0, 0, FOV::SQUARE, "#AAAAAA"); return fovs; } bool FOVManager::save() { QFile f; // TODO: Move FOVs to user database instead of file!! f.setFileName(KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "fov.dat"); if (!f.open(QIODevice::WriteOnly)) { qDebug() << "Could not open fov.dat."; return false; } QTextStream ostream(&f); foreach (FOV *fov, m_FOVs) { ostream << fov->name() << ':' << fov->sizeX() << ':' << fov->sizeY() << ':' << fov->offsetX() << ':' << fov->offsetY() << ':' << fov->PA() << ':' << QString::number(fov->shape()) << ':' << fov->color() << ':' << (fov->lockCelestialPole() ? 1 : 0) << endl; } f.close(); return true; } const QList &FOVManager::readFOVs() { qDeleteAll(m_FOVs); m_FOVs.clear(); QFile f; f.setFileName(KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "fov.dat"); if (!f.exists()) { m_FOVs = defaults(); save(); return m_FOVs; } if (f.open(QIODevice::ReadOnly)) { QTextStream istream(&f); while (!istream.atEnd()) { QStringList fields = istream.readLine().split(':'); bool ok; QString name, color; float sizeX, sizeY, xoffset, yoffset, rot; bool lockedCP = false; FOV::Shape shape; if (fields.count() >= 8) { name = fields[0]; sizeX = fields[1].toFloat(&ok); if (!ok) { return m_FOVs; } sizeY = fields[2].toFloat(&ok); if (!ok) { return m_FOVs; } xoffset = fields[3].toFloat(&ok); if (!ok) { return m_FOVs; } yoffset = fields[4].toFloat(&ok); if (!ok) { return m_FOVs; } rot = fields[5].toFloat(&ok); if (!ok) { return m_FOVs; } shape = static_cast(fields[6].toInt(&ok)); if (!ok) { return m_FOVs; } color = fields[7]; if (fields.count() == 9) lockedCP = (fields[8].toInt(&ok) == 1); } else { continue; } m_FOVs.append(new FOV(name, sizeX, sizeY, xoffset, yoffset, rot, shape, color, lockedCP)); } } return m_FOVs; } void FOVManager::releaseCache() { qDeleteAll(m_FOVs); m_FOVs.clear(); } FOV::FOV(const QString &n, float a, float b, float xoffset, float yoffset, float rot, Shape sh, const QString &col, bool useLockedCP) : QObject() { + qRegisterMetaType("FOV::Shape"); + qDBusRegisterMetaType(); + new FovAdaptor(this); QDBusConnection::sessionBus().registerObject(QString("/KStars/FOV/%1").arg(getID()) , this); m_name = n; m_sizeX = a; m_sizeY = (b < 0.0) ? a : b; m_offsetX = xoffset; m_offsetY = yoffset; m_PA = rot; m_shape = sh; m_color = col; m_northPA = 0; m_center.setRA(0); m_center.setDec(0); m_imageDisplay = false; m_lockCelestialPole = useLockedCP; } FOV::FOV() : QObject() { + qRegisterMetaType("FOV::Shape"); + qDBusRegisterMetaType(); + new FovAdaptor(this); QDBusConnection::sessionBus().registerObject(QString("/KStars/FOV/%1").arg(getID()) , this); m_name = i18n("No FOV"); m_color = "#FFFFFF"; m_sizeX = m_sizeY = 0; m_shape = SQUARE; m_imageDisplay = false; m_lockCelestialPole = false; } FOV::FOV(const FOV &other) : QObject() { m_name = other.m_name; m_color = other.m_color; m_sizeX = other.m_sizeX; m_sizeY = other.m_sizeY; m_shape = other.m_shape; m_offsetX= other.m_offsetX; m_offsetY= other.m_offsetY; m_PA = other.m_PA; m_imageDisplay = other.m_imageDisplay; m_lockCelestialPole = other.m_lockCelestialPole; } void FOV::sync(const FOV &other) { m_name = other.m_name; m_color = other.m_color; m_sizeX = other.m_sizeX; m_sizeY = other.m_sizeY; m_shape = other.m_shape; m_offsetX= other.m_offsetX; m_offsetY= other.m_offsetY; m_PA = other.m_PA; m_imageDisplay = other.m_imageDisplay; m_lockCelestialPole = other.m_lockCelestialPole; } void FOV::draw(QPainter &p, float zoomFactor) { // Do not draw empty FOVs if (m_sizeX == 0 || m_sizeY == 0) return; p.setPen(QColor(color())); p.setBrush(Qt::NoBrush); p.setRenderHint(QPainter::Antialiasing, Options::useAntialias()); float pixelSizeX = sizeX() * zoomFactor / 57.3 / 60.0; float pixelSizeY = sizeY() * zoomFactor / 57.3 / 60.0; float offsetXPixelSize = offsetX() * zoomFactor / 57.3 / 60.0; float offsetYPixelSize = offsetY() * zoomFactor / 57.3 / 60.0; p.save(); if (m_center.ra().Degrees() > 0) { m_center.EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat()); QPointF skypoint_center = KStars::Instance()->map()->projector()->toScreen(&m_center); p.translate(skypoint_center.toPoint()); } else p.translate(p.viewport().center()); p.translate(offsetXPixelSize, offsetYPixelSize); p.rotate( (m_PA - m_northPA) * -1); QPointF center(0, 0); switch (shape()) { case SQUARE: { QRect targetRect(center.x() - pixelSizeX / 2, center.y() - pixelSizeY / 2, pixelSizeX, pixelSizeY); if (m_imageDisplay) p.drawImage(targetRect, m_image); p.drawRect(targetRect); p.drawRect(center.x(), center.y() - (3 * pixelSizeY / 5), pixelSizeX / 40, pixelSizeX / 10); p.drawLine(center.x() - pixelSizeX / 30, center.y() - (3 * pixelSizeY / 5), center.x() + pixelSizeX / 20, center.y() - (3 * pixelSizeY / 5)); p.drawLine(center.x() - pixelSizeX / 30, center.y() - (3 * pixelSizeY / 5), center.x() + pixelSizeX / 70, center.y() - (0.7 * pixelSizeY)); p.drawLine(center.x() + pixelSizeX / 20, center.y() - (3 * pixelSizeY / 5), center.x() + pixelSizeX / 70, center.y() - (0.7 * pixelSizeY)); int fontSize = pixelSizeX / 15; if (fontSize <= 4) break; QFont font = p.font(); font.setPixelSize(fontSize); p.setFont(font); QRect nameRect(targetRect.topLeft().x(), targetRect.topLeft().y()-(pixelSizeY/8), targetRect.width()/2, pixelSizeX / 10); p.drawText(nameRect, Qt::AlignCenter, name()); QRect sizeRect(targetRect.center().x(), targetRect.topLeft().y()-(pixelSizeY/8), targetRect.width()/2, pixelSizeX / 10); p.drawText(sizeRect, Qt::AlignCenter, QString("%1'x%2'").arg(QString::number(m_sizeX, 'f', 1), QString::number(m_sizeY, 'f', 1))); } break; case CIRCLE: p.drawEllipse(center, pixelSizeX / 2, pixelSizeY / 2); break; case CROSSHAIRS: //Draw radial lines p.drawLine(center.x() + 0.5 * pixelSizeX, center.y(), center.x() + 1.5 * pixelSizeX, center.y()); p.drawLine(center.x() - 0.5 * pixelSizeX, center.y(), center.x() - 1.5 * pixelSizeX, center.y()); p.drawLine(center.x(), center.y() + 0.5 * pixelSizeY, center.x(), center.y() + 1.5 * pixelSizeY); p.drawLine(center.x(), center.y() - 0.5 * pixelSizeY, center.x(), center.y() - 1.5 * pixelSizeY); //Draw circles at 0.5 & 1 degrees p.drawEllipse(center, 0.5 * pixelSizeX, 0.5 * pixelSizeY); p.drawEllipse(center, pixelSizeX, pixelSizeY); break; case BULLSEYE: p.drawEllipse(center, 0.5 * pixelSizeX, 0.5 * pixelSizeY); p.drawEllipse(center, 2.0 * pixelSizeX, 2.0 * pixelSizeY); p.drawEllipse(center, 4.0 * pixelSizeX, 4.0 * pixelSizeY); break; case SOLIDCIRCLE: { QColor colorAlpha = color(); colorAlpha.setAlpha(127); p.setBrush(QBrush(colorAlpha)); p.drawEllipse(center, pixelSizeX / 2, pixelSizeY / 2); p.setBrush(Qt::NoBrush); break; } default:; } p.restore(); } void FOV::draw(QPainter &p, float x, float y) { float xfactor = x / sizeX() * 57.3 * 60.0; float yfactor = y / sizeY() * 57.3 * 60.0; float zoomFactor = std::min(xfactor, yfactor); switch (shape()) { case CROSSHAIRS: zoomFactor /= 3; break; case BULLSEYE: zoomFactor /= 8; break; default:; } draw(p, zoomFactor); } SkyPoint FOV::center() const { return m_center; } void FOV::setCenter(const SkyPoint ¢er) { m_center = center; } float FOV::northPA() const { return m_northPA; } void FOV::setNorthPA(float northPA) { m_northPA = northPA; } void FOV::setImage(const QImage &image) { m_image = image; } void FOV::setImageDisplay(bool value) { m_imageDisplay = value; } bool FOV::lockCelestialPole() const { return m_lockCelestialPole; } void FOV::setLockCelestialPole(bool lockCelestialPole) { m_lockCelestialPole = lockCelestialPole; } QDBusArgument &operator<<(QDBusArgument &argument, const FOV::Shape& source) { argument.beginStructure(); argument << static_cast(source); argument.endStructure(); return argument; } const QDBusArgument &operator>>(const QDBusArgument &argument, FOV::Shape &dest) { int a; argument.beginStructure(); argument >> a; argument.endStructure(); dest = static_cast(a); return argument; } diff --git a/kstars/auxiliary/fov.h b/kstars/auxiliary/fov.h index b7953f560..f192ee7a7 100644 --- a/kstars/auxiliary/fov.h +++ b/kstars/auxiliary/fov.h @@ -1,189 +1,189 @@ /*************************************************************************** fov.h - description ------------------- begin : Fri 05 Sept 2003 copyright : (C) 2003 by Jason Harris email : kstars@30doradus.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #pragma once #include "skypoint.h" #include #include #include #include class QPainter; /** * @class FOV * A simple class encapsulating a Field-of-View symbol * * The FOV size, shape, name, and color can be customized. The rotation is by default 0 degrees East Of North. * @author Jason Harris * @author Jasem Mutlaq * @version 1.1 */ class FOV : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.kstars.fov") Q_PROPERTY(QString name MEMBER m_name) - Q_PROPERTY(Shape shape MEMBER m_shape) + Q_PROPERTY(FOV::Shape shape MEMBER m_shape) Q_PROPERTY(float sizeX MEMBER m_sizeX) Q_PROPERTY(float sizeY MEMBER m_sizeY) Q_PROPERTY(float offsetX MEMBER m_offsetX) Q_PROPERTY(float offsetY MEMBER m_offsetY) Q_PROPERTY(float PA MEMBER m_PA) Q_PROPERTY(QString color MEMBER m_color) Q_PROPERTY(bool cpLock MEMBER m_lockCelestialPole) public: enum Shape { SQUARE, CIRCLE, CROSSHAIRS, BULLSEYE, SOLIDCIRCLE, UNKNOWN }; /** Default constructor */ FOV(); FOV(const QString &name, float a, float b = -1, float xoffset = 0, float yoffset = 0, float rot = 0, Shape shape = SQUARE, const QString &color = "#FFFFFF", bool useLockedCP = false); FOV(const FOV &other); void sync(const FOV &other); inline Q_SCRIPTABLE QString name() const { return m_name; } void setName(const QString &n) { m_name = n; } - inline Shape shape() const { return m_shape; } - void setShape(Shape s) { m_shape = s; } + inline FOV::Shape shape() const { return m_shape; } + void setShape(FOV::Shape s) { m_shape = s; } //void setShape(int s); inline float sizeX() const { return m_sizeX; } inline float sizeY() const { return m_sizeY; } void setSize(float s) { m_sizeX = m_sizeY = s; } void setSize(float sx, float sy) { m_sizeX = sx; m_sizeY = sy; } void setOffset(float fx, float fy) { m_offsetX = fx; m_offsetY = fy; } inline float offsetX() const { return m_offsetX; } inline float offsetY() const { return m_offsetY; } // Position Angle void setPA(float rt) { m_PA = rt; } inline float PA() const { return m_PA; } inline QString color() const { return m_color; } void setColor(const QString &c) { m_color = c; } /** * @short draw the FOV symbol on a QPainter * @param p reference to the target QPainter. The painter should already be started. * @param zoomFactor is zoom factor as in SkyMap. */ void draw(QPainter &p, float zoomFactor); /** * @short draw FOV symbol so it will be inside a rectangle * @param p reference to the target QPainter. The painter should already be started. * @param x is X size of rectangle * @param y is Y size of rectangle */ void draw(QPainter &p, float x, float y); SkyPoint center() const; void setCenter(const SkyPoint ¢er); float northPA() const; void setNorthPA(float northPA); void setImage(const QImage &image); void setImageDisplay(bool value); bool lockCelestialPole() const; void setLockCelestialPole(bool lockCelestialPole); private: QString m_name, m_color; - Shape m_shape; + FOV::Shape m_shape; float m_sizeX { 0 }, m_sizeY { 0 }; float m_offsetX { 0 }, m_offsetY { 0 }; float m_PA { 0 }; float m_northPA { 0 }; SkyPoint m_center; QImage m_image; bool m_imageDisplay { false }; bool m_lockCelestialPole { false }; static int getID() { return m_ID++; } static int m_ID; }; /** * @class FOVManager * A simple class handling FOVs. * @note Should migrate this from file (fov.dat) to using the user sqlite database * @author Jasem Mutlaq * @version 1.0 */ class FOVManager { public: /** @short Read list of FOVs from "fov.dat" */ static const QList &readFOVs(); /** @short Release the FOV cache */ static void releaseCache(); static void addFOV(FOV *newFOV) { Q_ASSERT(newFOV); m_FOVs.append(newFOV); } static void removeFOV(FOV *fov) { Q_ASSERT(fov); m_FOVs.removeOne(fov); } static const QList &getFOVs() { return m_FOVs; } /** @short Write list of FOVs to "fov.dat" */ static bool save(); private: FOVManager() = default; ~FOVManager(); /** @short Fill list with default FOVs*/ static QList defaults(); static QList m_FOVs; }; // Shape Q_DECLARE_METATYPE(FOV::Shape) QDBusArgument &operator<<(QDBusArgument &argument, const FOV::Shape& source); const QDBusArgument &operator>>(const QDBusArgument &argument, FOV::Shape &dest);