diff --git a/kstars/auxiliary/xplanetimageviewer.h b/kstars/auxiliary/xplanetimageviewer.h --- a/kstars/auxiliary/xplanetimageviewer.h +++ b/kstars/auxiliary/xplanetimageviewer.h @@ -28,7 +28,6 @@ #include #include #include -#include #include "kstarsdata.h" #include #include @@ -73,12 +72,12 @@ private: //Image related - QPixmap pix; + QPixmap m_Pix; QImage m_Image; //Mouse related - bool mouseButtonDown = false; - QPoint lastMousePoint; + bool m_MouseButtonDown = false; + QPoint m_LastMousePoint; bool event(QEvent *event) override; bool gestureEvent(QGestureEvent *event); void pinchTriggered(QPinchGesture *gesture); @@ -120,83 +119,89 @@ void startXplanet(); private: - /** - * Display the downloaded image. Resize the window to fit the image, If the image is - * larger than the screen, make the image as large as possible while preserving the - * original aspect ratio - */ - bool showImage(); + /** prepares the output file**/ bool setupOutputFile(); - QImage image; + QImage m_Image; /** Save the downloaded image to a local file. */ - void saveFile(QUrl &url); - - QFile file; + void saveFile(const QString & fileName); - QString filename; - - FileDownloader downloadJob; + QFile m_File; XPlanetImageLabel *m_View { nullptr }; QLabel *m_Caption { nullptr }; - QUrl lastURL; + QString m_LastFile; + + QStringList m_ObjectNames; typedef enum { YEARS, MONTHS, DAYS, HOURS, MINS, SECS } timeUnits; void setXPlanetDate(KStarsDateTime time); //XPlanet strings - QString object; - QString origin; - QString date; - QString dateText; + QString m_ObjectName; + QString m_OriginName; + QString m_Date; + QString m_DateText; //XPlanet numbers - int rotation; - int timeUnit; - int radius; - double FOV; - double lat; - double lon; + int m_CurrentObjectIndex { 0 }; + int m_CurrentOriginIndex { 0 }; + int m_Rotation { 0 }; + int m_CurrentTimeUnitIndex { 0 }; + uint32_t m_Radius { 0 }; + double m_FOV { 0 }; + double m_lat { 0 }; + double m_lon { 0 }; + +#ifndef Q_OS_WIN + QFutureWatcher fifoImageLoadWatcher; + QTimer watcherTimeout; +#endif // Time - KStarsDateTime xplanetTime; - bool xplanetRunning = false; + KStarsDateTime m_XPlanetTime {}; + bool m_XPlanetRunning = false; - QComboBox *originSelector {nullptr}; + QComboBox *m_OriginSelector {nullptr}; // Field of view controls - QPushButton *kstarsFOV {nullptr}; - QPushButton *noFOV {nullptr}; - NonLinearDoubleSpinBox *FOVEdit {nullptr}; + QPushButton *m_KStarsFOV {nullptr}; + QPushButton *m_NoFOV {nullptr}; + NonLinearDoubleSpinBox *m_FOVEdit {nullptr}; // Rotation controls - QSpinBox *rotateEdit {nullptr}; + QSpinBox *m_RotateEdit {nullptr}; // Free rotation controls - QLabel *latDisplay {nullptr}; - QLabel *lonDisplay {nullptr}; - QLabel *radDisplay {nullptr}; - QPushButton *freeRotate {nullptr}; + QLabel *m_PositionDisplay {nullptr}; + QPushButton *m_FreeRotate {nullptr}; + bool m_ImageLoadSucceeded = false; // Time controls - QLabel *XPlanetTimeDisplay {nullptr}; - QSlider *timeSlider {nullptr}; - QSpinBox *timeEdit {nullptr}; - QComboBox *timeUnitsSelect {nullptr}; + QLabel *m_XPlanetTimeDisplay {nullptr}; + QSlider *m_TimeSlider {nullptr}; + QSpinBox *m_TimeEdit {nullptr}; + QComboBox *m_TimeUnitsSelect {nullptr}; //Animation controls - QPushButton *runTime {nullptr}; - QTimer *XPlanetTimer {nullptr}; + QPushButton *m_RunTime {nullptr}; + QTimer *m_XPlanetTimer {nullptr}; private slots: + /** + * Display the downloaded image. Resize the window to fit the image, If the image is + * larger than the screen, make the image as large as possible while preserving the + * original aspect ratio + */ + bool showImage(); + // Saves file to disk. void saveFileToDisk(); @@ -212,6 +217,7 @@ void changeXPlanetPosition(QPoint delta); void slotFreeRotate(); void updateStates(); + void updatePositionDisplay(); // Field of View slots void zoomInXPlanetFOV(); @@ -222,8 +228,8 @@ // Time slots void updateXPlanetTime(int timeShift); - void updateXPlanetObject(const QString & obj); - void updateXPlanetOrigin(const QString & obj); + void updateXPlanetObject(int objectIndex); + void updateXPlanetOrigin(int originIndex); void updateXPlanetTimeUnits(int units); void updateXPlanetTimeEdit(); void setXPlanetTime(); @@ -233,5 +239,6 @@ // Animation slots void incrementXPlanetTime(); void toggleXPlanetRun(); + void timeSliderDisplay(int timeShift); }; diff --git a/kstars/auxiliary/xplanetimageviewer.cpp b/kstars/auxiliary/xplanetimageviewer.cpp --- a/kstars/auxiliary/xplanetimageviewer.cpp +++ b/kstars/auxiliary/xplanetimageviewer.cpp @@ -45,6 +45,15 @@ #include #include +typedef enum { +SUN,MERCURY,VENUS, +EARTH,MOON, +MARS,PHOBOS,DEIMOS, +JUPITER,GANYMEDE,IO,CALLISTO,EUROPA, +SATURN,TITAN,MIMAS,ENCELADUS,TETHYS,DIONE,RHEA,HYPERION,IAPETUS,PHOEBE, +URANUS,UMBRIEL,ARIEL,MIRANDA,TITANIA,OBERON, +NEPTUNE,TRITON } objects; + XPlanetImageLabel::XPlanetImageLabel(QWidget *parent) : QFrame(parent) { #ifndef KSTARS_LITE @@ -59,15 +68,15 @@ { #ifndef KSTARS_LITE m_Image = img; - pix = QPixmap::fromImage(m_Image); + m_Pix = QPixmap::fromImage(m_Image); #endif } void XPlanetImageLabel::invertPixels() { #ifndef KSTARS_LITE m_Image.invertPixels(); - pix = QPixmap::fromImage(m_Image.scaled(width(), height(), Qt::KeepAspectRatio)); + m_Pix = QPixmap::fromImage(m_Image.scaled(width(), height(), Qt::KeepAspectRatio)); #endif } @@ -77,24 +86,24 @@ QPainter p; p.begin(this); int x = 0; - if (pix.width() < width()) - x = (width() - pix.width()) / 2; - p.drawPixmap(x, 0, pix); + if (m_Pix.width() < width()) + x = (width() - m_Pix.width()) / 2; + p.drawPixmap(x, 0, m_Pix); p.end(); #endif } void XPlanetImageLabel::resizeEvent(QResizeEvent *event) { - if (event->size() == pix.size()) + if (event->size() == m_Pix.size()) return; - pix = QPixmap::fromImage(m_Image.scaled(event->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + m_Pix = QPixmap::fromImage(m_Image.scaled(event->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); } void XPlanetImageLabel::refreshImage() { - pix = QPixmap::fromImage(m_Image.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + m_Pix = QPixmap::fromImage(m_Image.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); update(); } @@ -142,48 +151,45 @@ void XPlanetImageLabel::mousePressEvent(QMouseEvent *e) { - mouseButtonDown = true; - lastMousePoint = e->globalPos(); + m_MouseButtonDown = true; + m_LastMousePoint = e->globalPos(); e->accept(); } void XPlanetImageLabel::mouseReleaseEvent(QMouseEvent *e) { - mouseButtonDown = false; + m_MouseButtonDown = false; e->accept(); } void XPlanetImageLabel::mouseMoveEvent(QMouseEvent *e) { - if(mouseButtonDown) + if(m_MouseButtonDown) { QPoint newPoint = e->globalPos(); - int dx = newPoint.x() - lastMousePoint.x(); - int dy = newPoint.y() - lastMousePoint.y(); + int dx = newPoint.x() - m_LastMousePoint.x(); + int dy = newPoint.y() - m_LastMousePoint.y(); emit changePosition(QPoint(dx, dy)); - lastMousePoint = newPoint; + m_LastMousePoint = newPoint; } e->accept(); } XPlanetImageViewer::XPlanetImageViewer(const QString &obj, QWidget *parent): QDialog(parent) { #ifndef KSTARS_LITE - lastURL = QUrl::fromLocalFile(QDir::homePath()); + m_LastFile = QDir::homePath(); - object=obj; #ifdef Q_OS_OSX setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); #endif setAttribute(Qt::WA_DeleteOnClose, true); setModal(false); - setWindowTitle(i18n("XPlanet Solar System Simulator: %1", object)); + setWindowTitle(i18n("XPlanet Solar System Simulator: %1", obj)); setXPlanetDate(KStarsData::Instance()->ut()); if (Options::xplanetFOV()) - FOV = KStars::Instance()->map()->fov(); - else - FOV = 0; + m_FOV = KStars::Instance()->map()->fov(); // Create widget QFrame *page = new QFrame(this); @@ -198,67 +204,56 @@ selectorsLayout->setMargin(0); mainLayout->addWidget(selectorsWidget); - QStringList objects; - objects << i18n("Sun") << i18n("Mercury") << i18n("Venus"); - objects << i18n("Earth") << i18n("Moon"); - objects << i18n("Mars") << i18n("Phobos") << i18n("Deimos"); - objects << i18n("Jupiter") << i18n("Ganymede") << i18n("Io") << i18n("Callisto") << i18n("Europa"); - objects << i18n("Saturn") << i18n("Titan") << i18n("Mimas") << i18n("Enceladus") << i18n("Tethys") << i18n("Dione") << i18n("Rhea") << i18n("Hyperion") << i18n("Iapetus") << i18n("Phoebe"); - objects << i18n("Uranus") << i18n("Umbriel") << i18n("Ariel") << i18n("Miranda") << i18n("Titania") << i18n("Oberon"); - objects << i18n("Neptune") << i18n("Triton"); + m_ObjectNames << i18n("Sun") << i18n("Mercury") << i18n("Venus"); + m_ObjectNames << i18n("Earth") << i18n("Moon"); + m_ObjectNames << i18n("Mars") << i18n("Phobos") << i18n("Deimos"); + m_ObjectNames << i18n("Jupiter") << i18n("Ganymede") << i18n("Io") << i18n("Callisto") << i18n("Europa"); + m_ObjectNames << i18n("Saturn") << i18n("Titan") << i18n("Mimas") << i18n("Enceladus") << i18n("Tethys") << i18n("Dione") << i18n("Rhea") << i18n("Hyperion") << i18n("Iapetus") << i18n("Phoebe"); + m_ObjectNames << i18n("Uranus") << i18n("Umbriel") << i18n("Ariel") << i18n("Miranda") << i18n("Titania") << i18n("Oberon"); + m_ObjectNames << i18n("Neptune") << i18n("Triton"); + + m_CurrentObjectIndex = m_ObjectNames.indexOf(obj); + m_ObjectName = m_ObjectNames.at(m_CurrentObjectIndex); QComboBox *objectSelector = new QComboBox(this); - objectSelector->addItems(objects); + objectSelector->addItems(m_ObjectNames); objectSelector->setToolTip(i18n("This allows you to select a new object/target for XPlanet to view")); selectorsLayout->addWidget(objectSelector); - objectSelector->setCurrentIndex(objectSelector->findText(object)); - connect(objectSelector, SIGNAL(currentTextChanged(QString)), this, SLOT(updateXPlanetObject(QString))); + objectSelector->setCurrentIndex(m_CurrentObjectIndex); + connect(objectSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateXPlanetObject(int))); - origin = i18n("Earth"); + m_CurrentOriginIndex = EARTH; + m_OriginName = m_ObjectNames.at(EARTH); selectorsLayout->addWidget(new QLabel(i18n("from"),this)); - originSelector = new QComboBox(this); - originSelector->addItems(objects); - originSelector->setToolTip(i18n("This allows you to select a viewing location")); - selectorsLayout->addWidget(originSelector); - originSelector->setCurrentIndex(originSelector->findText(origin)); - connect(originSelector, SIGNAL(currentTextChanged(QString)), this, SLOT(updateXPlanetOrigin(QString))); + m_OriginSelector = new QComboBox(this); + m_OriginSelector->addItems(m_ObjectNames); + m_OriginSelector->setToolTip(i18n("This allows you to select a viewing location")); + selectorsLayout->addWidget(m_OriginSelector); + m_OriginSelector->setCurrentIndex(EARTH); + connect(m_OriginSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateXPlanetOrigin(int))); - lat = Options::xplanetLatitude().toDouble(); - lon = Options::xplanetLongitude().toDouble(); - radius = 45; + m_lat = Options::xplanetLatitude().toDouble(); + m_lon = Options::xplanetLongitude().toDouble(); + m_Radius = 45; selectorsLayout->addWidget(new QLabel(i18n("Location:"), this)); - latDisplay = new QLabel(this); - latDisplay->setToolTip(i18n("XPlanet Latitude, only valid when viewing the object from the same object")); - latDisplay->setText(QString::number(lat)); - latDisplay->setDisabled(true); - selectorsLayout->addWidget(latDisplay); - - selectorsLayout->addWidget(new QLabel(",", this)); - lonDisplay = new QLabel(this); - lonDisplay->setToolTip(i18n("XPlanet Longitude, only valid when viewing the object from the same object")); - lonDisplay->setText(QString::number(lon)); - lonDisplay->setDisabled(true); - selectorsLayout->addWidget(lonDisplay); - - selectorsLayout->addWidget(new QLabel(",", this)); - radDisplay = new QLabel(this); - radDisplay->setToolTip(i18n("XPlanet object radius in %, only valid when viewing the object from the same object")); - radDisplay->setText(QString::number(radius)); - radDisplay->setDisabled(true); - selectorsLayout->addWidget(radDisplay); - - freeRotate = new QPushButton(this); - freeRotate->setIcon(QIcon::fromTheme("object-rotate-left")); - freeRotate->setAttribute(Qt::WA_LayoutUsesWidgetRect); - freeRotate->setMaximumSize(QSize(32,32)); - freeRotate->setMinimumSize(QSize(32,32)); - freeRotate->setCheckable(true); - freeRotate->setToolTip(i18n("Hover over target and freely rotate view with mouse in XPlanet Viewer")); - selectorsLayout->addWidget(freeRotate); - connect(freeRotate, SIGNAL(clicked()), this, SLOT(slotFreeRotate())); + m_PositionDisplay = new QLabel(this); + m_PositionDisplay->setToolTip(i18n("XPlanet Latitude, Longitude, and object radius in %. This is only valid when viewing the object from the same object")); + updatePositionDisplay(); + m_PositionDisplay->setDisabled(true); + selectorsLayout->addWidget(m_PositionDisplay); + + m_FreeRotate = new QPushButton(this); + m_FreeRotate->setIcon(QIcon::fromTheme("object-rotate-left")); + m_FreeRotate->setAttribute(Qt::WA_LayoutUsesWidgetRect); + m_FreeRotate->setMaximumSize(QSize(32,32)); + m_FreeRotate->setMinimumSize(QSize(32,32)); + m_FreeRotate->setCheckable(true); + m_FreeRotate->setToolTip(i18n("Hover over target and freely rotate view with mouse in XPlanet Viewer")); + selectorsLayout->addWidget(m_FreeRotate); + connect(m_FreeRotate, SIGNAL(clicked()), this, SLOT(slotFreeRotate())); QPushButton *saveB = new QPushButton(this); saveB->setIcon(QIcon::fromTheme("document-save")); @@ -276,48 +271,48 @@ viewControlsLayout->addWidget(new QLabel(i18n("FOV:"), this)); - FOVEdit = new NonLinearDoubleSpinBox(); - FOVEdit->setDecimals(4); + m_FOVEdit = new NonLinearDoubleSpinBox(); + m_FOVEdit->setDecimals(4); QList possibleValues; possibleValues << 0; for(double i=.001;i<100;i*=1.5) possibleValues << i; - FOVEdit->setRecommendedValues(possibleValues); - FOVEdit->setValue(0); - FOVEdit->setToolTip(i18n("Sets the FOV to the Specified value. Note: has no effect if hovering over object.")); - viewControlsLayout->addWidget(FOVEdit); - connect(FOVEdit, SIGNAL(valueChanged(double)), this, SLOT(updateXPlanetFOVEdit())); - - kstarsFOV = new QPushButton(this); - kstarsFOV->setIcon(QIcon::fromTheme("zoom-fit-width")); - kstarsFOV->setAttribute(Qt::WA_LayoutUsesWidgetRect); - kstarsFOV->setMaximumSize(QSize(32,32)); - kstarsFOV->setMinimumSize(QSize(32,32)); - kstarsFOV->setToolTip(i18n("Zoom to the current KStars FOV. Note: has no effect if hovering over object.")); - viewControlsLayout->addWidget(kstarsFOV); - connect(kstarsFOV, SIGNAL(clicked()), this, SLOT(setKStarsXPlanetFOV())); - - noFOV = new QPushButton(this); - noFOV->setIcon(QIcon::fromTheme("system-reboot")); - noFOV->setAttribute(Qt::WA_LayoutUsesWidgetRect); - noFOV->setMaximumSize(QSize(32,32)); - noFOV->setMinimumSize(QSize(32,32)); - noFOV->setToolTip(i18n("Optimum FOV for the target, FOV parameter not specified. Note: has no effect if hovering over object.")); - viewControlsLayout->addWidget(noFOV); - connect(noFOV, SIGNAL(clicked()), this, SLOT(clearXPlanetFOV())); - - rotation = 0; + m_FOVEdit->setRecommendedValues(possibleValues); + m_FOVEdit->setValue(0); + m_FOVEdit->setToolTip(i18n("Sets the FOV to the Specified value. Note: has no effect if hovering over object.")); + viewControlsLayout->addWidget(m_FOVEdit); + connect(m_FOVEdit, SIGNAL(valueChanged(double)), this, SLOT(updateXPlanetFOVEdit())); + + m_KStarsFOV = new QPushButton(this); + m_KStarsFOV->setIcon(QIcon::fromTheme("zoom-fit-width")); + m_KStarsFOV->setAttribute(Qt::WA_LayoutUsesWidgetRect); + m_KStarsFOV->setMaximumSize(QSize(32,32)); + m_KStarsFOV->setMinimumSize(QSize(32,32)); + m_KStarsFOV->setToolTip(i18n("Zoom to the current KStars FOV. Note: has no effect if hovering over object.")); + viewControlsLayout->addWidget(m_KStarsFOV); + connect(m_KStarsFOV, SIGNAL(clicked()), this, SLOT(setKStarsXPlanetFOV())); + + m_NoFOV = new QPushButton(this); + m_NoFOV->setIcon(QIcon::fromTheme("system-reboot")); + m_NoFOV->setAttribute(Qt::WA_LayoutUsesWidgetRect); + m_NoFOV->setMaximumSize(QSize(32,32)); + m_NoFOV->setMinimumSize(QSize(32,32)); + m_NoFOV->setToolTip(i18n("Optimum FOV for the target, FOV parameter not specified. Note: has no effect if hovering over object.")); + viewControlsLayout->addWidget(m_NoFOV); + connect(m_NoFOV, SIGNAL(clicked()), this, SLOT(clearXPlanetFOV())); + + m_Rotation = 0; viewControlsLayout->addWidget(new QLabel(i18n("Rotation:"), this)); - rotateEdit = new QSpinBox(); + m_RotateEdit = new QSpinBox(); - rotateEdit->setRange(-180, 180); - rotateEdit->setValue(0); - rotateEdit->setSingleStep(10); - rotateEdit->setToolTip(i18n("Set the view rotation to the desired angle")); - viewControlsLayout->addWidget(rotateEdit); - connect(rotateEdit, SIGNAL(valueChanged(int)), this, SLOT(updateXPlanetRotationEdit())); + m_RotateEdit->setRange(-180, 180); + m_RotateEdit->setValue(0); + m_RotateEdit->setSingleStep(10); + m_RotateEdit->setToolTip(i18n("Set the view rotation to the desired angle")); + viewControlsLayout->addWidget(m_RotateEdit); + connect(m_RotateEdit, SIGNAL(valueChanged(int)), this, SLOT(updateXPlanetRotationEdit())); QPushButton *invertRotation = new QPushButton(this); invertRotation->setIcon(QIcon::fromTheme("object-flip-vertical")); @@ -361,7 +356,7 @@ mainLayout->addWidget(timeWidget); timeLayout->setMargin(0); - xplanetTime = KStarsData::Instance()->lt(); + m_XPlanetTime = KStarsData::Instance()->lt(); QPushButton *setTime = new QPushButton(this); setTime->setIcon(QIcon::fromTheme("clock")); @@ -381,51 +376,53 @@ timeLayout->addWidget(kstarsTime); connect(kstarsTime, SIGNAL(clicked()), this, SLOT(setXPlanetTimetoKStarsTime())); - XPlanetTimeDisplay = new QLabel(this); - XPlanetTimeDisplay->setToolTip(i18n("Current XPlanet Time")); - timeLayout->addWidget(XPlanetTimeDisplay); - - XPlanetTimeDisplay->setText(xplanetTime.date().toString() + ", " + xplanetTime.time().toString()); - - timeSlider = new QSlider(Qt::Horizontal, this); - timeLayout->addWidget(timeSlider); - timeSlider->setRange(-100, 100); - timeSlider->setToolTip(i18n("This sets the time step from the current XPlanet time, good for viewing events")); - connect(timeSlider, SIGNAL(valueChanged(int)), this, SLOT(updateXPlanetTime(int))); - - timeEdit = new QSpinBox(this); - timeEdit->setRange(-100, 100); - timeEdit->setMaximumWidth(50); - timeEdit->setToolTip(i18n("This sets the time step from the current XPlanet time")); - timeLayout->addWidget(timeEdit); - connect(timeEdit, SIGNAL(valueChanged(int)), this, SLOT(updateXPlanetTimeEdit())); - - timeUnit = MINS; - timeUnitsSelect = new QComboBox(this); - timeLayout->addWidget(timeUnitsSelect); - timeUnitsSelect->addItem(i18n("years")); - timeUnitsSelect->addItem(i18n("months")); - timeUnitsSelect->addItem(i18n("days")); - timeUnitsSelect->addItem(i18n("hours")); - timeUnitsSelect->addItem(i18n("mins")); - timeUnitsSelect->addItem(i18n("secs")); - timeUnitsSelect->setCurrentIndex(MINS); - timeUnitsSelect->setToolTip(i18n("Lets you change the units for the timestep in the animation")); - connect(timeUnitsSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(updateXPlanetTimeUnits(int))); - - XPlanetTimer = new QTimer(this); - XPlanetTimer->setInterval(Options::xplanetAnimationDelay().toInt()); - connect(XPlanetTimer, SIGNAL(timeout()), this, SLOT(incrementXPlanetTime())); - - runTime = new QPushButton(this); - runTime->setIcon(QIcon::fromTheme("media-playback-start")); - runTime->setAttribute(Qt::WA_LayoutUsesWidgetRect); - runTime->setCheckable(true); - runTime->setMaximumSize(QSize(32,32)); - runTime->setMinimumSize(QSize(32,32)); - runTime->setToolTip(i18n("Lets you run the animation")); - timeLayout->addWidget(runTime); - connect(runTime, SIGNAL(clicked()), this, SLOT(toggleXPlanetRun())); + m_XPlanetTimeDisplay = new QLabel(this); + m_XPlanetTimeDisplay->setToolTip(i18n("Current XPlanet Time")); + timeLayout->addWidget(m_XPlanetTimeDisplay); + + m_XPlanetTimeDisplay->setText(i18n("%1, %2", m_XPlanetTime.date().toString() , m_XPlanetTime.time().toString())); + + m_TimeSlider = new QSlider(Qt::Horizontal, this); + m_TimeSlider->setTracking(false); + connect(m_TimeSlider,SIGNAL(sliderMoved(int)),this,SLOT(timeSliderDisplay(int))); + timeLayout->addWidget(m_TimeSlider); + m_TimeSlider->setRange(-100, 100); + m_TimeSlider->setToolTip(i18n("This sets the time step from the current XPlanet time, good for viewing events")); + connect(m_TimeSlider, SIGNAL(valueChanged(int)), this, SLOT(updateXPlanetTime(int))); + + m_TimeEdit = new QSpinBox(this); + m_TimeEdit->setRange(-10000, 10000); + m_TimeEdit->setMaximumWidth(50); + m_TimeEdit->setToolTip(i18n("This sets the time step from the current XPlanet time")); + timeLayout->addWidget(m_TimeEdit); + connect(m_TimeEdit, SIGNAL(valueChanged(int)), this, SLOT(updateXPlanetTimeEdit())); + + m_CurrentTimeUnitIndex = MINS; + m_TimeUnitsSelect = new QComboBox(this); + timeLayout->addWidget(m_TimeUnitsSelect); + m_TimeUnitsSelect->addItem(i18n("years")); + m_TimeUnitsSelect->addItem(i18n("months")); + m_TimeUnitsSelect->addItem(i18n("days")); + m_TimeUnitsSelect->addItem(i18n("hours")); + m_TimeUnitsSelect->addItem(i18n("minutes")); + m_TimeUnitsSelect->addItem(i18n("seconds")); + m_TimeUnitsSelect->setCurrentIndex(MINS); + m_TimeUnitsSelect->setToolTip(i18n("Lets you change the units for the timestep in the animation")); + connect(m_TimeUnitsSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(updateXPlanetTimeUnits(int))); + + m_XPlanetTimer = new QTimer(this); + m_XPlanetTimer->setInterval(Options::xplanetAnimationDelay()); + connect(m_XPlanetTimer, SIGNAL(timeout()), this, SLOT(incrementXPlanetTime())); + + m_RunTime = new QPushButton(this); + m_RunTime->setIcon(QIcon::fromTheme("media-playback-start")); + m_RunTime->setAttribute(Qt::WA_LayoutUsesWidgetRect); + m_RunTime->setCheckable(true); + m_RunTime->setMaximumSize(QSize(32,32)); + m_RunTime->setMinimumSize(QSize(32,32)); + m_RunTime->setToolTip(i18n("Lets you run the animation")); + timeLayout->addWidget(m_RunTime); + connect(m_RunTime, SIGNAL(clicked()), this, SLOT(toggleXPlanetRun())); QPushButton *resetTime = new QPushButton(this); resetTime->setIcon(QIcon::fromTheme("system-reboot")); @@ -441,7 +438,7 @@ m_Caption = new QLabel(page); m_Caption->setAutoFillBackground(true); m_Caption->setFrameShape(QFrame::StyledPanel); - m_Caption->setText(object); + m_Caption->setText(m_ObjectName); // Add layout QVBoxLayout *vlay = new QVBoxLayout(page); vlay->setSpacing(0); @@ -461,13 +458,21 @@ m_Caption->setPalette(p); m_View->setPalette(p); +#ifndef Q_OS_WIN + if(Options::xplanetUseFIFO()) + { + connect(&watcherTimeout,SIGNAL(timeout()),&fifoImageLoadWatcher,SLOT(cancel())); + connect(&fifoImageLoadWatcher,SIGNAL(finished()),this,SLOT(showImage())); + } +#endif + + #ifdef Q_OS_OSX QList qButtons = findChildren(); for (auto &button : qButtons) button->setAutoDefault(false); #endif updateXPlanetTime(0); - startXplanet(); #endif } @@ -478,7 +483,7 @@ void XPlanetImageViewer::startXplanet() { - if(xplanetRunning) + if(m_XPlanetRunning) return; //This means something failed in the file output @@ -513,33 +518,33 @@ QStringList args; //This specifies the object to be viewed - args << "-body" << object.toLower(); + args << "-body" << m_ObjectName.toLower(); //This is the date and time requested - args << "-date" << date; + args << "-date" << m_Date; //This is the glare from the sun args << "-glare" << Options::xplanetGlare(); args << "-base_magnitude" << Options::xplanetMagnitude(); //This is the correction for light's travel time. args << "-light_time"; - args << "-geometry" << Options::xplanetWidth() + 'x' + Options::xplanetHeight(); + args << "-geometry" << QString::number(Options::xplanetWidth()) + 'x' + QString::number(Options::xplanetHeight()); - if(FOV != 0) - args << "-fov" << QString::number(FOV); + if(m_FOV != 0) + args << "-fov" << QString::number(m_FOV); //Need to convert to locale for places that don't use decimals?? //args << "-fov" << fov.setNum(fov());//.replace('.', ','); //This rotates the view for different object angles - args << "-rotate" << QString::number(rotation); + args << "-rotate" << QString::number(m_Rotation); if (Options::xplanetConfigFile()) args << "-config" << Options::xplanetConfigFilePath(); if (Options::xplanetStarmap()) args << "-starmap" << Options::xplanetStarmapPath(); if (Options::xplanetArcFile()) args << "-arc_file" << Options::xplanetArcFilePath(); - if (!file.fileName().isEmpty()) - args << "-output" << file.fileName() << "-quality" << Options::xplanetQuality(); + if (!m_File.fileName().isEmpty()) + args << "-output" << m_File.fileName() << "-quality" << Options::xplanetQuality(); // Labels if (Options::xplanetLabel()) @@ -578,15 +583,15 @@ // This sets the position from which the planet is viewed. // Note that setting Latitude and Longitude means that position above the SAME object - if(object == origin) + if(m_CurrentObjectIndex == m_CurrentOriginIndex) { if (Options::xplanetRandom()) args << "-random"; else - args << "-latitude" << QString::number(lat) << "-longitude" << QString::number(lon) << "-radius" << QString::number(radius); + args << "-latitude" << QString::number(m_lat) << "-longitude" << QString::number(m_lon) << "-radius" << QString::number(m_Radius); } else - args << "-origin" << origin; + args << "-origin" << m_OriginName; // Projection if (Options::xplanetProjection()) @@ -668,348 +673,391 @@ //This prevents it from running forever. args << "-num_times" << "1"; - // Run xplanet - if(Options::xplanetUseFIFO()) - QtConcurrent::run(this, &XPlanetImageViewer::loadImage); + m_XPlanetRunning = true; + m_ImageLoadSucceeded = false; //This will be set to true if it works. + uint32_t timeout = Options::xplanetTimeout(); + + //FIFO files don't work on windows + #ifndef Q_OS_WIN + if(Options::xplanetUseFIFO()) + { + fifoImageLoadWatcher.setFuture(QtConcurrent::run(this, &XPlanetImageViewer::loadImage)); + watcherTimeout.setSingleShot(true); + watcherTimeout.start(timeout); + } + #endif + xplanetProc->start(xPlanetLocation, args); + //Uncomment to print the XPlanet commands to the console // qDebug() << "Run:" << xplanetProc->program() << args.join(" "); - xplanetRunning = true; - bool succeeded = xplanetProc->waitForFinished(Options::xplanetTimeout().toInt()); - xplanetRunning = false; + + bool XPlanetSucceeded = xplanetProc->waitForFinished(timeout); + m_XPlanetRunning = false; + xplanetProc->kill(); //In case it timed out xplanetProc->deleteLater(); - if(succeeded) + if(XPlanetSucceeded) { - if(FOV == 0) - m_Caption->setText(i18n("XPlanet View: ") + object + i18n(" from ") + origin + ", " + dateText); + if(m_FOV == 0) + m_Caption->setText(i18n("XPlanet View: %1 from %2 on %3", m_ObjectName, m_OriginName, m_DateText)); else - m_Caption->setText(i18n("XPlanet View: ") + object + i18n(" from ") + origin + ", " + dateText + i18n(", FOV: ") + QString::number(FOV)); - if(!Options::xplanetUseFIFO()) - loadImage(); - showImage(); - } -} + m_Caption->setText(i18n("XPlanet View: %1 from %2 on %3 at FOV: %4 deg", m_ObjectName, m_OriginName, m_DateText, m_FOV)); + #ifdef Q_OS_WIN + loadImage(); //This will also set imageLoadSucceeded based on whether it worked. + #else + if(Options::xplanetUseFIFO()) + return; //The loading of the image is handled with the watcher + else + loadImage(); //This will also set imageLoadSucceeded based on whether it worked. + #endif -bool XPlanetImageViewer::setupOutputFile() -{ - if(Options::xplanetUseFIFO()) - { - if(file.fileName().contains("/tmp/xplanetfifo") && file.exists()) - return true; - file.setFileName(QString("/tmp/xplanetfifo%1.png").arg(QUuid::createUuid().toString().mid(1, 8))); - int fd =0; - if ((fd = mkfifo(file.fileName().toLatin1(), S_IRUSR | S_IWUSR) < 0)) + if(m_ImageLoadSucceeded) + showImage(); + else { - KMessageBox::error(nullptr, i18n("Error making FIFO file %1: %2.", file.fileName(), strerror(errno))); - return false; + QString text = i18n("Loading of the image of object %1 failed.", m_ObjectName); + KMessageBox::error(this, text); } } else { - QDir writableDir; - QString xPlanetDirPath = KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "xplanet"; - writableDir.mkpath(xPlanetDirPath); - file.setFileName(xPlanetDirPath + QDir::separator() + object + ".png"); + KStars::Instance()->statusBar()->showMessage(i18n("XPlanet failed to generate the image for object %1 before the timeout expired.", m_ObjectName)); + #ifndef Q_OS_WIN + if(Options::xplanetUseFIFO()) + fifoImageLoadWatcher.cancel(); + #endif } +} + +bool XPlanetImageViewer::setupOutputFile() +{ + #ifndef Q_OS_WIN + if(Options::xplanetUseFIFO()) + { + if(m_File.fileName().contains("xplanetfifo") && m_File.exists()) + return true; + QDir kstarsTempDir(KSPaths::writableLocation(QStandardPaths::TempLocation)); + kstarsTempDir.mkdir(kstarsTempDir.absolutePath()); + m_File.setFileName(kstarsTempDir.absolutePath() + QDir::separator() + QString("xplanetfifo%1.png").arg(QUuid::createUuid().toString().mid(1, 8)).toLatin1()); + int mkFifoSuccess = 0; //Note if the return value of the command is 0 it succeeded, -1 means it failed. + if ((mkFifoSuccess = mkfifo(m_File.fileName().toLatin1(), S_IRUSR | S_IWUSR) < 0)) + { + KMessageBox::error(nullptr, i18n("Error making FIFO file %1: %2.", m_File.fileName(), strerror(errno))); + return false; + } + return true; + } + #endif + //If the user is using windows or has not selected to use FIFO, it uses files in the KStars data directory. + QDir writableDir; + QString xPlanetDirPath = KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "xplanet"; + writableDir.mkpath(xPlanetDirPath); + m_File.setFileName(xPlanetDirPath + QDir::separator() + m_ObjectName + ".png"); return true; } void XPlanetImageViewer::zoomInXPlanetFOV() { - if(origin == object) + if(m_CurrentObjectIndex == m_CurrentOriginIndex) { - radius += 5; - radDisplay->setText(QString::number(radius)); + m_Radius += 5; + updatePositionDisplay(); startXplanet(); } else { - FOVEdit->stepDown(); + m_FOVEdit->stepDown(); startXplanet(); } } void XPlanetImageViewer::zoomOutXPlanetFOV() { - if(origin == object) + if(m_CurrentObjectIndex == m_CurrentOriginIndex) { - if(radius > 0) + if(m_Radius > 0) { - radius -= 5; - radDisplay->setText(QString::number(radius)); + m_Radius -= 5; + updatePositionDisplay(); startXplanet(); } } else { - FOVEdit->stepUp(); + m_FOVEdit->stepUp(); startXplanet(); } } +void XPlanetImageViewer::updatePositionDisplay() +{ + m_PositionDisplay->setText(i18n("%1, %2, %3", QString::number(m_lat), QString::number(m_lon), QString::number(m_Radius))); +} + void XPlanetImageViewer::updateXPlanetTime(int timeShift){ KStarsDateTime shiftedXPlanetTime; - switch(timeUnit) + switch(m_CurrentTimeUnitIndex) { case YEARS: - shiftedXPlanetTime = xplanetTime.addDays(timeShift * 365); + shiftedXPlanetTime = m_XPlanetTime.addDays(timeShift * 365); break; case MONTHS: - shiftedXPlanetTime = xplanetTime.addDays(timeShift * 30); + shiftedXPlanetTime = m_XPlanetTime.addDays(timeShift * 30); break; case DAYS: - shiftedXPlanetTime = xplanetTime.addDays(timeShift); + shiftedXPlanetTime = m_XPlanetTime.addDays(timeShift); break; case HOURS: - shiftedXPlanetTime = xplanetTime.addSecs(timeShift * 3600); + shiftedXPlanetTime = m_XPlanetTime.addSecs(timeShift * 3600); break; case MINS: - shiftedXPlanetTime = xplanetTime.addSecs(timeShift * 60); + shiftedXPlanetTime = m_XPlanetTime.addSecs(timeShift * 60); break; case SECS: - shiftedXPlanetTime = xplanetTime.addSecs(timeShift); + shiftedXPlanetTime = m_XPlanetTime.addSecs(timeShift); break; } setXPlanetDate(shiftedXPlanetTime); - dateText = shiftedXPlanetTime.date().toString() + ", " + shiftedXPlanetTime.time().toString(); - timeEdit->setValue(timeShift); - startXplanet(); + m_DateText = i18n("%1, %2", shiftedXPlanetTime.date().toString(), shiftedXPlanetTime.time().toString()); + if(m_TimeEdit->value() != timeShift) + m_TimeEdit->setValue(timeShift); + else + startXplanet(); } -void XPlanetImageViewer::updateXPlanetObject(const QString &obj){ - object = obj; +void XPlanetImageViewer::updateXPlanetObject(int objectIndex){ + m_CurrentObjectIndex = objectIndex; + m_ObjectName = m_ObjectNames.at(objectIndex); - setWindowTitle(i18n("XPlanet Solar System Simulator: %1", object)); - if(freeRotate->isChecked()) - originSelector->setCurrentIndex(originSelector->findText(object)); + setWindowTitle(i18n("XPlanet Solar System Simulator: %1", m_ObjectName)); + if(m_FreeRotate->isChecked()) + m_OriginSelector->setCurrentIndex(m_CurrentObjectIndex); startXplanet(); } -void XPlanetImageViewer::updateXPlanetOrigin(const QString &obj) +void XPlanetImageViewer::updateXPlanetOrigin(int originIndex) { - origin = obj; - if(object == origin) - freeRotate->setChecked(true); + m_CurrentOriginIndex = originIndex; + m_OriginName = m_ObjectNames.at(originIndex); + if(m_CurrentObjectIndex == m_CurrentOriginIndex) + m_FreeRotate->setChecked(true); else - freeRotate->setChecked(false); + m_FreeRotate->setChecked(false); updateStates();//This will update the disabled/enabled states startXplanet(); } void XPlanetImageViewer::changeXPlanetPosition(QPoint delta) { - if(origin == object) + if(m_CurrentObjectIndex == m_CurrentOriginIndex) { - double newLon = lon + delta.x(); - double newLat = lat + delta.y(); + double newLon = m_lon + delta.x(); + double newLat = m_lat + delta.y(); - if(newLat > 90) - newLat = 90; - if(newLat < -90) - newLat = -90; + newLat = qBound(-90.0, newLat, 90.0); - lon = newLon; - lat = newLat; + m_lon = newLon; + m_lat = newLat; - latDisplay->setText(QString::number(lat)); - lonDisplay->setText(QString::number(lon)); + updatePositionDisplay(); startXplanet(); } } void XPlanetImageViewer::slotFreeRotate() { - if(freeRotate->isChecked()) - originSelector->setCurrentIndex(originSelector->findText(object)); + if(m_FreeRotate->isChecked()) + m_OriginSelector->setCurrentIndex(m_CurrentObjectIndex); else - originSelector->setCurrentIndex(originSelector->findText(i18n("Earth"))); + m_OriginSelector->setCurrentIndex(EARTH); } void XPlanetImageViewer::updateStates() { - if(freeRotate->isChecked()) + if(m_FreeRotate->isChecked()) { - FOVEdit->setDisabled(true); - kstarsFOV->setDisabled(true); - noFOV->setDisabled(true); + m_FOVEdit->setDisabled(true); + m_KStarsFOV->setDisabled(true); + m_NoFOV->setDisabled(true); - latDisplay->setDisabled(false); - lonDisplay->setDisabled(false); - radDisplay->setDisabled(false); + m_PositionDisplay->setDisabled(false); } else { - FOVEdit->setDisabled(false); - kstarsFOV->setDisabled(false); - noFOV->setDisabled(false); + m_FOVEdit->setDisabled(false); + m_KStarsFOV->setDisabled(false); + m_NoFOV->setDisabled(false); - latDisplay->setDisabled(true); - lonDisplay->setDisabled(true); - radDisplay->setDisabled(true); + m_PositionDisplay->setDisabled(true); } } void XPlanetImageViewer::setXPlanetDate(KStarsDateTime time){ //Note Xplanet uses UT time for everything but we want the labels to all be LT KStarsDateTime utTime = KStarsData::Instance()->geo()->LTtoUT(time); - QString year, month, day, hour, minute, second; - - if (year.setNum(utTime.date().year()).size() == 1) - year.push_front('0'); - if (month.setNum(utTime.date().month()).size() == 1) - month.push_front('0'); - if (day.setNum(utTime.date().day()).size() == 1) - day.push_front('0'); - if (hour.setNum(utTime.time().hour()).size() == 1) - hour.push_front('0'); - if (minute.setNum(utTime.time().minute()).size() == 1) - minute.push_front('0'); - if (second.setNum(utTime.time().second()).size() == 1) - second.push_front('0'); - - date = year + month + day + '.' + hour + minute + second; - + m_Date = utTime.toString(Qt::ISODate) + .replace("-",QString("")) + .replace("T",".") + .replace(":",QString("")) + .replace("Z",QString("")); } void XPlanetImageViewer::updateXPlanetTimeUnits(int units) { - timeUnit = units; + m_CurrentTimeUnitIndex = units; updateXPlanetTimeEdit(); } void XPlanetImageViewer::updateXPlanetTimeEdit() { - int timeShift = timeEdit->text().toInt(); - if(timeSlider->value() != timeShift) - timeSlider->setValue(timeShift); + if(m_TimeSlider->isSliderDown()) + return; + int timeShift = m_TimeEdit->value(); + if(m_TimeSlider->value() != timeShift) + { + + if(timeShift > m_TimeSlider->maximum() + 100) + m_TimeSlider->setMaximum(timeShift); + if(timeShift < m_TimeSlider->minimum() - 100) + m_TimeSlider->setMinimum(timeShift); + m_TimeSlider->setValue(timeShift); + } else updateXPlanetTime(timeShift); } +void XPlanetImageViewer::timeSliderDisplay(int timeShift) +{ + m_TimeEdit->setValue(timeShift); +} + void XPlanetImageViewer::incrementXPlanetTime() { - if(!xplanetRunning) + if(!m_XPlanetRunning) { - int timeShift = timeEdit->text().toInt(); - if(timeSlider->maximum() == timeShift) - timeSlider->setMaximum(timeSlider->maximum() + 1); - if(timeEdit->maximum() == timeShift) - timeEdit->setMaximum(timeSlider->maximum() + 1); - timeSlider->setValue(timeShift + 1); + int timeShift = m_TimeEdit->value(); + if(m_TimeSlider->maximum() <= timeShift) + m_TimeSlider->setMaximum(timeShift + 100); + if(m_TimeEdit->maximum() <= timeShift) + m_TimeEdit->setMaximum(timeShift + 100); + m_TimeSlider->setValue(timeShift + 1); } } void XPlanetImageViewer::setXPlanetTime() { - QPointer timedialog = new TimeDialog(xplanetTime, KStarsData::Instance()->geo(), this); + QPointer timedialog = new TimeDialog(m_XPlanetTime, KStarsData::Instance()->geo(), this); if (timedialog->exec() == QDialog::Accepted) { - xplanetTime = timedialog->selectedDateTime(); - XPlanetTimeDisplay->setText(xplanetTime.date().toString() + ", " + xplanetTime.time().toString()); + m_XPlanetTime = timedialog->selectedDateTime(); + m_XPlanetTimeDisplay->setText(i18n("%1, %2", m_XPlanetTime.date().toString(), m_XPlanetTime.time().toString())); int timeShift = 0; - timeSlider->setMaximum(100); - if(timeSlider->value() != timeShift) - timeSlider->setValue(timeShift); + m_TimeSlider->setRange(-100,100); + if(m_TimeSlider->value() != timeShift) + m_TimeSlider->setValue(timeShift); else updateXPlanetTime(timeShift); - startXplanet(); } } void XPlanetImageViewer::setXPlanetTimetoKStarsTime() { - xplanetTime = KStarsData::Instance()->lt(); - XPlanetTimeDisplay->setText(xplanetTime.date().toString() + ", " + xplanetTime.time().toString()); + m_XPlanetTime = KStarsData::Instance()->lt(); + m_XPlanetTimeDisplay->setText(i18n("%1, %2", m_XPlanetTime.date().toString(), m_XPlanetTime.time().toString())); int timeShift = 0; - timeSlider->setMaximum(100); - if(timeSlider->value() != timeShift) - timeSlider->setValue(timeShift); + m_TimeSlider->setRange(-100,100); + if(m_TimeSlider->value() != timeShift) + m_TimeSlider->setValue(timeShift); else updateXPlanetTime(timeShift); - startXplanet(); } void XPlanetImageViewer::resetXPlanetTime() { int timeShift = 0; - timeSlider->setMaximum(100); - timeEdit->setMaximum(100); - if(timeSlider->value() != timeShift) - timeSlider->setValue(timeShift); + m_TimeSlider->setRange(-100, 100); + if(m_TimeSlider->value() != timeShift) + m_TimeSlider->setValue(timeShift); else updateXPlanetTime(timeShift); } void XPlanetImageViewer::toggleXPlanetRun() { - if(XPlanetTimer->isActive()) + if(m_XPlanetTimer->isActive()) { - XPlanetTimer->stop(); + m_XPlanetTimer->stop(); + #ifndef Q_OS_WIN + if(Options::xplanetUseFIFO()) + fifoImageLoadWatcher.cancel(); + #endif } else { - XPlanetTimer->setInterval(Options::xplanetAnimationDelay().toInt()); - XPlanetTimer->start(); + m_XPlanetTimer->setInterval(Options::xplanetAnimationDelay()); + m_XPlanetTimer->start(); } } void XPlanetImageViewer::updateXPlanetFOVEdit() { - FOV = FOVEdit->value(); + m_FOV = m_FOVEdit->value(); startXplanet(); } void XPlanetImageViewer::clearXPlanetFOV() { - FOV = 0; - FOVEdit->setValue(0); + m_FOV = 0; + m_FOVEdit->setValue(0); startXplanet(); } void XPlanetImageViewer::setKStarsXPlanetFOV() { - FOV = KStars::Instance()->map()->fov(); - FOVEdit->setValue(FOV); + m_FOV = KStars::Instance()->map()->fov(); + m_FOVEdit->setValue(m_FOV); startXplanet(); } void XPlanetImageViewer::updateXPlanetRotationEdit() { - rotation = rotateEdit->value(); + m_Rotation = m_RotateEdit->value(); startXplanet(); } void XPlanetImageViewer::resetXPlanetRotation(){ - rotateEdit->setValue(0); + m_RotateEdit->setValue(0); } void XPlanetImageViewer::invertXPlanetRotation(){ - rotateEdit->setValue(180); + m_RotateEdit->setValue(180); } bool XPlanetImageViewer::loadImage() { #ifndef KSTARS_LITE - if (!image.load(file.fileName())) + + if (!m_Image.load(m_File.fileName())) { - QString text = i18n("Loading of the image of object %1 failed.", object); - KMessageBox::error(this, text); + m_ImageLoadSucceeded = false; return false; } + m_ImageLoadSucceeded = true; return true; #else + imageLoadSucceeded = false; return false; #endif } @@ -1024,33 +1072,33 @@ int w = deskRect.width(); // screen width int h = deskRect.height(); // screen height - if (image.width() <= w && image.height() > h) //Window is taller than desktop - image = image.scaled(int(image.width() * h / image.height()), h); - else if (image.height() <= h && image.width() > w) //window is wider than desktop - image = image.scaled(w, int(image.height() * w / image.width())); - else if (image.width() > w && image.height() > h) //window is too tall and too wide + if (m_Image.width() <= w && m_Image.height() > h) //Window is taller than desktop + m_Image = m_Image.scaled(int(m_Image.width() * h / m_Image.height()), h); + else if (m_Image.height() <= h && m_Image.width() > w) //window is wider than desktop + m_Image = m_Image.scaled(w, int(m_Image.height() * w / m_Image.width())); + else if (m_Image.width() > w && m_Image.height() > h) //window is too tall and too wide { //which needs to be shrunk least, width or height? - float fx = float(w) / float(image.width()); - float fy = float(h) / float(image.height()); + float fx = float(w) / float(m_Image.width()); + float fy = float(h) / float(m_Image.height()); if (fx > fy) //width needs to be shrunk less, so shrink to fit in height - image = image.scaled(int(image.width() * fy), h); + m_Image = m_Image.scaled(int(m_Image.width() * fy), h); else //vice versa - image = image.scaled(w, int(image.height() * fx)); + m_Image = m_Image.scaled(w, int(m_Image.height() * fx)); } const bool initialLoad = !isVisible(); show(); // hide is default - m_View->setImage(image); - w = image.width(); + m_View->setImage(m_Image); + w = m_Image.width(); //If the caption is wider than the image, set the window size //to fit the caption if (m_Caption->width() > w) w = m_Caption->width(); if(initialLoad) - resize(w, image.height()); + resize(w, m_Image.height()); else { m_View->refreshImage(); @@ -1068,44 +1116,37 @@ void XPlanetImageViewer::saveFileToDisk() { #ifndef KSTARS_LITE + QFileDialog saveDialog(KStars::Instance(), i18n("Save Image"), m_LastFile); + saveDialog.setDefaultSuffix("png"); + saveDialog.setAcceptMode(QFileDialog::AcceptSave); + saveDialog.exec(); - QUrl newURL = QFileDialog::getSaveFileUrl(KStars::Instance(), i18n("Save Image"), lastURL); // save-dialog with default filename - if (!newURL.isEmpty()) - { - if (newURL.toLocalFile().endsWith(QLatin1String(".png")) == false) - newURL.setPath(newURL.toLocalFile() + ".png"); + if(saveDialog.result() == QFileDialog::Rejected) + return; + if(saveDialog.selectedFiles().isEmpty()) + return; + QString newFileName = saveDialog.selectedFiles().first(); + if(newFileName.isEmpty()) + return; - QFile f(newURL.toLocalFile()); - if (f.exists()) - { - int r = KMessageBox::warningContinueCancel(parentWidget(), - i18n("A file named \"%1\" already exists. " - "Overwrite it?", - newURL.fileName()), - i18n("Overwrite File?"), KStandardGuiItem::overwrite()); - if (r == KMessageBox::Cancel) - return; - - f.remove(); - } + m_LastFile = newFileName; - lastURL = QUrl(newURL.toString(QUrl::RemoveFilename)); + saveFile(newFileName); - saveFile(newURL); - } #endif } -void XPlanetImageViewer::saveFile(QUrl &url) +void XPlanetImageViewer::saveFile(const QString &fileName) { #ifndef KSTARS_LITE - if (file.copy(url.toLocalFile()) == false) + + if (! m_Image.save(fileName, "png")) { - QString text = i18n("Saving of the image %1 failed.", url.toString()); + QString text = i18n("Saving of the image to %1 failed.", fileName); KMessageBox::error(this, text); } else - KStars::Instance()->statusBar()->showMessage(i18n("Saved image to %1", url.toString())); + KStars::Instance()->statusBar()->showMessage(i18n("Saved image to %1", fileName)); #endif } diff --git a/kstars/kstars.kcfg b/kstars/kstars.kcfg --- a/kstars/kstars.kcfg +++ b/kstars/kstars.kcfg @@ -1078,22 +1078,22 @@ Option to use a FIFO file instead of saving to the hard disk true - + How long to wait for XPlanet before giving up in milliseconds 1000 - + How long to pause between frames in the XPlanet Animation 100 - + Width of xplanet window 640 - + Height of xplanet window 480 diff --git a/kstars/xplanet/opsxplanet.cpp b/kstars/xplanet/opsxplanet.cpp --- a/kstars/xplanet/opsxplanet.cpp +++ b/kstars/xplanet/opsxplanet.cpp @@ -95,6 +95,13 @@ if (Options::xplanetProjection() == 0) groupBoxBackground->setEnabled(false); + #ifdef Q_OS_WIN + kcfg_XplanetUseFIFO->setChecked(false); + kcfg_XplanetUseFIFO->setDisabled(true); + kcfg_XplanetUseFIFO->setToolTip(i18n("FIFO files are not supported on Windows")); + #endif + + connect(openXPlanetMaps, SIGNAL(clicked()),this,SLOT(showXPlanetMapsDirectory())); } diff --git a/kstars/xplanet/opsxplanet.ui b/kstars/xplanet/opsxplanet.ui --- a/kstars/xplanet/opsxplanet.ui +++ b/kstars/xplanet/opsxplanet.ui @@ -428,7 +428,7 @@ - XPlanet Requires Maps in order to function properly. It does not ship with a lot of planetary maps. You need to download some in order to get the full benefits of XPlanet. This is a good place to start: <a href =http://xplanet.sourceforge.net/maps.php>http://xplanet.sourceforge.net/maps.php</a> + XPlanet requires maps in order to function properly. It does not ship with a lot of planetary maps. You need to download some in order to get the full benefits of XPlanet. This is a good place to start: <a href="http://xplanet.sourceforge.net/maps.php">http://xplanet.sourceforge.net/maps.php</a> true