File indexing completed on 2024-04-21 14:46:31

0001 /*
0002     SPDX-FileCopyrightText: 2011 Rafał Kułaga <rl.kulaga@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "printingwizard.h"
0008 
0009 #include <QStackedWidget>
0010 #include <QPrinter>
0011 #include <QStandardPaths>
0012 
0013 #include "finderchart.h"
0014 #include "loggingform.h"
0015 #include "detailstable.h"
0016 #include "pwizobjectselection.h"
0017 #include "pwizchartconfig.h"
0018 #include "pwizfovbrowse.h"
0019 #include "pwizfovconfig.h"
0020 #include "pwizfovtypeselection.h"
0021 #include "pwizfovmanual.h"
0022 #include "pwizfovsh.h"
0023 #include "pwizchartcontents.h"
0024 #include "pwizprint.h"
0025 #include "projections/projector.h"
0026 #include "kstars.h"
0027 #include "kstarsdata.h"
0028 #include "skymap.h"
0029 #include "legend.h"
0030 #include "shfovexporter.h"
0031 #include "Options.h"
0032 #include "kspaths.h"
0033 
0034 PWizWelcomeUI::PWizWelcomeUI(QWidget *parent) : QFrame(parent)
0035 {
0036     setupUi(this);
0037 }
0038 
0039 PrintingWizard::PrintingWizard(QWidget *parent)
0040     : QDialog(parent), m_KStars(KStars::Instance()), m_FinderChart(nullptr), m_SkyObject(nullptr), m_FovType(FT_UNDEFINED),
0041       m_FovImageSize(QSize(500, 500)), m_ShBeginObject(nullptr), m_PointingShBegin(false), m_SwitchColors(false),
0042       m_RecapturingFov(false), m_RecaptureIdx(-1)
0043 {
0044     m_Printer = new QPrinter(QPrinter::ScreenResolution);
0045 
0046     setupWidgets();
0047 }
0048 
0049 PrintingWizard::~PrintingWizard()
0050 {
0051     // Clean up
0052     if (m_Printer)
0053     {
0054         delete m_Printer;
0055     }
0056     if (m_FinderChart)
0057     {
0058         delete m_FinderChart;
0059     }
0060 
0061     qDeleteAll(m_FovSnapshots);
0062 }
0063 
0064 void PrintingWizard::updateStepButtons()
0065 {
0066     switch (m_WizardStack->currentIndex())
0067     {
0068         case PW_OBJECT_SELECTION: // object selection
0069         {
0070             nextB->setEnabled(m_SkyObject != nullptr);
0071             break;
0072         }
0073     }
0074 }
0075 
0076 void PrintingWizard::beginPointing()
0077 {
0078     // If there is sky object already selected, center sky map around it
0079     if (m_SkyObject)
0080     {
0081         m_KStars->map()->setClickedObject(m_SkyObject);
0082         m_KStars->map()->slotCenter();
0083     }
0084 
0085     m_KStars->map()->setObjectPointingMode(true);
0086     hide();
0087 }
0088 
0089 void PrintingWizard::beginShBeginPointing()
0090 {
0091     m_PointingShBegin = true;
0092 
0093     if (m_ShBeginObject)
0094     {
0095         m_KStars->map()->setClickedObject(m_SkyObject);
0096         m_KStars->map()->slotCenter();
0097     }
0098 
0099     m_KStars->map()->setObjectPointingMode(true);
0100     hide();
0101 }
0102 
0103 void PrintingWizard::pointingDone(SkyObject *obj)
0104 {
0105     if (m_PointingShBegin)
0106     {
0107         m_ShBeginObject = obj;
0108         m_WizFovShUI->setBeginObject(obj);
0109         m_PointingShBegin = false;
0110     }
0111     else
0112     {
0113         m_SkyObject = obj;
0114         m_WizObjectSelectionUI->setSkyObject(obj);
0115     }
0116 
0117     show();
0118 }
0119 
0120 void PrintingWizard::beginFovCapture()
0121 {
0122     if (m_SkyObject)
0123     {
0124         slewAndBeginCapture(m_SkyObject);
0125     }
0126 }
0127 
0128 void PrintingWizard::beginFovCapture(SkyPoint *center, FOV *fov)
0129 {
0130     slewAndBeginCapture(center, fov);
0131 }
0132 
0133 void PrintingWizard::captureFov()
0134 {
0135     if (m_KStars->data()->getVisibleFOVs().isEmpty())
0136     {
0137         return;
0138     }
0139 
0140     QPixmap pixmap(m_FovImageSize);
0141     m_SimpleFovExporter.exportFov(m_KStars->data()->getVisibleFOVs().first(), &pixmap);
0142     if (m_WizFovConfigUI->isLegendEnabled())
0143     {
0144         // Set legend position, orientation and type
0145         Legend legend(m_WizFovConfigUI->getLegendOrientation(), m_WizFovConfigUI->getLegendPosition());
0146         legend.setType(m_WizFovConfigUI->getLegendType());
0147 
0148         // Check if alpha blending is enabled
0149         if (m_WizFovConfigUI->isAlphaBlendingEnabled())
0150         {
0151             QColor bgColor = legend.getBgColor();
0152             bgColor.setAlpha(200);
0153             legend.setBgColor(bgColor);
0154         }
0155 
0156         // Paint legend
0157         legend.paintLegend(&pixmap);
0158     }
0159     FovSnapshot *snapshot = new FovSnapshot(pixmap, QString(), m_KStars->data()->getVisibleFOVs().first(),
0160                                             m_KStars->map()->getCenterPoint());
0161 
0162     if (m_RecapturingFov)
0163     {
0164         delete m_FovSnapshots.at(m_RecaptureIdx);
0165         m_FovSnapshots.replace(m_RecaptureIdx, snapshot);
0166         m_KStars->map()->setFovCaptureMode(false);
0167         m_RecapturingFov = false;
0168         m_RecaptureIdx   = -1;
0169         fovCaptureDone();
0170     }
0171     else
0172     {
0173         m_FovSnapshots.append(snapshot);
0174     }
0175 }
0176 
0177 void PrintingWizard::fovCaptureDone()
0178 {
0179     //Restore old color scheme if necessary
0180     //(if printing was aborted, the ColorScheme is still restored)
0181     if (m_SwitchColors)
0182     {
0183         m_KStars->loadColorScheme(m_PrevSchemeName);
0184         m_KStars->map()->forceUpdate();
0185     }
0186 
0187     if (m_RecapturingFov)
0188     {
0189         m_RecapturingFov = false;
0190         m_RecaptureIdx   = -1;
0191     }
0192 
0193     show();
0194 }
0195 
0196 void PrintingWizard::beginShFovCapture()
0197 {
0198     if (!m_ShBeginObject)
0199     {
0200         return;
0201     }
0202 
0203     ShFovExporter exporter(this, KStars::Instance()->map());
0204 
0205     // Get selected FOV symbol
0206     double fovArcmin(0);
0207     foreach (FOV *fov, KStarsData::Instance()->getAvailableFOVs())
0208     {
0209         if (fov->name() == m_WizFovShUI->getFovName())
0210         {
0211             fovArcmin = qMin(fov->sizeX(), fov->sizeY());
0212             break;
0213         }
0214     }
0215 
0216     // Calculate path and check if it's not empty
0217     if (!exporter.calculatePath(*m_SkyObject, *m_ShBeginObject, fovArcmin / 60, m_WizFovShUI->getMaglim()))
0218     {
0219         KMessageBox::information(this,
0220                                  i18n("Star hopper returned empty path. We advise you to change star hopping settings "
0221                                       "or use manual capture mode."),
0222                                  i18n("Star hopper failed to find path"));
0223         return;
0224     }
0225 
0226     // If FOV shape should be overridden, do this now
0227     m_SimpleFovExporter.setFovShapeOverriden(m_WizFovConfigUI->isFovShapeOverriden());
0228     m_SimpleFovExporter.setFovSymbolDrawn(m_WizFovConfigUI->isFovShapeOverriden());
0229 
0230     // If color scheme should be switched, save previous scheme name and switch to "sky chart" color scheme
0231     m_SwitchColors   = m_WizFovConfigUI->isSwitchColorsEnabled();
0232     m_PrevSchemeName = m_KStars->data()->colorScheme()->fileName();
0233     if (m_SwitchColors)
0234     {
0235         m_KStars->loadColorScheme("chart.colors");
0236     }
0237 
0238     // Save previous FOV symbol names and switch to symbol selected by user
0239     QStringList prevFovNames = Options::fOVNames();
0240     Options::setFOVNames(QStringList(m_WizFovShUI->getFovName()));
0241     KStarsData::Instance()->syncFOV();
0242     if (KStarsData::Instance()->getVisibleFOVs().isEmpty())
0243     {
0244         return;
0245     }
0246 
0247     // Hide Printing Wizard
0248     hide();
0249 
0250     // Draw and export path
0251     exporter.exportPath();
0252 
0253     // Restore old color scheme if necessary
0254     if (m_SwitchColors)
0255     {
0256         m_KStars->loadColorScheme(m_PrevSchemeName);
0257         m_KStars->map()->forceUpdate();
0258     }
0259 
0260     // Update skymap
0261     m_KStars->map()->forceUpdate(true);
0262 
0263     // Restore previous FOV symbol names
0264     Options::setFOVNames(prevFovNames);
0265     KStarsData::Instance()->syncFOV();
0266 
0267     //FIXME: this is _dirty_ workaround to get PrintingWizard displayed in its previous position.
0268     QTimer::singleShot(50, this, SLOT(show()));
0269 }
0270 
0271 void PrintingWizard::recaptureFov(int idx)
0272 {
0273     // Set recapturing flag and index of the FOV snapshot to replace
0274     m_RecapturingFov = true;
0275     m_RecaptureIdx   = idx;
0276 
0277     // Begin FOV snapshot capture
0278     SkyPoint p = m_FovSnapshots.at(m_RecaptureIdx)->getCentralPoint();
0279     slewAndBeginCapture(&p, m_FovSnapshots.at(m_RecaptureIdx)->getFov());
0280 }
0281 
0282 void PrintingWizard::slotPrevPage()
0283 {
0284     int currentIdx = m_WizardStack->currentIndex();
0285     switch (currentIdx)
0286     {
0287         case PW_FOV_BROWSE:
0288         {
0289             switch (m_FovType)
0290             {
0291                 case FT_MANUAL:
0292                 {
0293                     m_WizardStack->setCurrentIndex(PW_FOV_MANUAL);
0294                     break;
0295                 }
0296 
0297                 case FT_STARHOPPER:
0298                 {
0299                     m_WizardStack->setCurrentIndex(PW_FOV_SH);
0300                     break;
0301                 }
0302 
0303                 default:
0304                 {
0305                     return;
0306                 }
0307             }
0308 
0309             break;
0310         }
0311 
0312         case PW_FOV_SH:
0313         {
0314             m_WizardStack->setCurrentIndex(PW_FOV_CONFIG);
0315             break;
0316         }
0317 
0318         default:
0319         {
0320             m_WizardStack->setCurrentIndex(currentIdx - 1);
0321             break;
0322         }
0323     }
0324 
0325     updateStepButtons();
0326     updateButtons();
0327 }
0328 
0329 void PrintingWizard::slotNextPage()
0330 {
0331     int currentIdx = m_WizardStack->currentIndex();
0332     switch (currentIdx)
0333     {
0334         case PW_FOV_TYPE:
0335         {
0336             m_FovType = m_WizFovTypeSelectionUI->getFovExportType();
0337             m_WizardStack->setCurrentIndex(PW_FOV_CONFIG);
0338             break;
0339         }
0340 
0341         case PW_FOV_CONFIG:
0342         {
0343             switch (m_FovType)
0344             {
0345                 case FT_MANUAL:
0346                 {
0347                     m_WizardStack->setCurrentIndex(PW_FOV_MANUAL);
0348                     break;
0349                 }
0350 
0351                 case FT_STARHOPPER:
0352                 {
0353                     m_WizardStack->setCurrentIndex(PW_FOV_SH);
0354                     break;
0355                 }
0356 
0357                 default: // Undefined FOV type - do nothing
0358                 {
0359                     return;
0360                 }
0361             }
0362 
0363             break;
0364         }
0365 
0366         case PW_FOV_MANUAL:
0367         {
0368             m_WizardStack->setCurrentIndex(PW_FOV_BROWSE);
0369             break;
0370         }
0371 
0372         case PW_FOV_BROWSE:
0373         {
0374             m_WizChartContentsUI->entered();
0375             m_WizardStack->setCurrentIndex(PW_CHART_CONTENTS);
0376             break;
0377         }
0378 
0379         case PW_CHART_CONTENTS:
0380         {
0381             createFinderChart();
0382             m_WizardStack->setCurrentIndex(PW_CHART_PRINT);
0383             break;
0384         }
0385 
0386         default:
0387         {
0388             m_WizardStack->setCurrentIndex(currentIdx + 1);
0389         }
0390     }
0391 
0392     updateButtons();
0393     updateStepButtons();
0394 }
0395 
0396 void PrintingWizard::setupWidgets()
0397 {
0398 #ifdef Q_OS_OSX
0399     setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
0400 #endif
0401     m_WizardStack = new QStackedWidget(this);
0402 
0403     setWindowTitle(i18nc("@title:window", "Printing Wizard"));
0404 
0405     QVBoxLayout *mainLayout = new QVBoxLayout;
0406     mainLayout->addWidget(m_WizardStack);
0407     setLayout(mainLayout);
0408 
0409     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
0410     mainLayout->addWidget(buttonBox);
0411     connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0412 
0413     nextB = new QPushButton(i18n("&Next >"));
0414     nextB->setToolTip(i18n("Go to next Wizard page"));
0415     nextB->setDefault(true);
0416     backB = new QPushButton(i18n("< &Back"));
0417     backB->setToolTip(i18n("Go to previous Wizard page"));
0418     backB->setEnabled(false);
0419 
0420     buttonBox->addButton(backB, QDialogButtonBox::ActionRole);
0421     buttonBox->addButton(nextB, QDialogButtonBox::ActionRole);
0422 
0423     connect(nextB, SIGNAL(clicked()), this, SLOT(slotNextPage()));
0424     connect(backB, SIGNAL(clicked()), this, SLOT(slotPrevPage()));
0425 
0426     // Create step widgets
0427     m_WizWelcomeUI          = new PWizWelcomeUI(m_WizardStack);
0428     m_WizObjectSelectionUI  = new PWizObjectSelectionUI(this, m_WizardStack);
0429     m_WizChartConfigUI      = new PWizChartConfigUI(this);
0430     m_WizFovTypeSelectionUI = new PWizFovTypeSelectionUI(this, m_WizardStack);
0431     m_WizFovConfigUI        = new PWizFovConfigUI(m_WizardStack);
0432     m_WizFovManualUI        = new PWizFovManualUI(this, m_WizardStack);
0433     m_WizFovShUI            = new PWizFovShUI(this, m_WizardStack);
0434     m_WizFovBrowseUI        = new PWizFovBrowseUI(this, m_WizardStack);
0435     m_WizChartContentsUI    = new PWizChartContentsUI(this, m_WizardStack);
0436     m_WizPrintUI            = new PWizPrintUI(this, m_WizardStack);
0437 
0438     // Add step widgets to m_WizardStack
0439     m_WizardStack->addWidget(m_WizWelcomeUI);
0440     m_WizardStack->addWidget(m_WizObjectSelectionUI);
0441     m_WizardStack->addWidget(m_WizChartConfigUI);
0442     m_WizardStack->addWidget(m_WizFovTypeSelectionUI);
0443     m_WizardStack->addWidget(m_WizFovConfigUI);
0444     m_WizardStack->addWidget(m_WizFovManualUI);
0445     m_WizardStack->addWidget(m_WizFovShUI);
0446     m_WizardStack->addWidget(m_WizFovBrowseUI);
0447     m_WizardStack->addWidget(m_WizChartContentsUI);
0448     m_WizardStack->addWidget(m_WizPrintUI);
0449 
0450     // Set banner images for steps
0451     QPixmap bannerImg;
0452     if (bannerImg.load(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "wzstars.png")))
0453     {
0454         m_WizWelcomeUI->banner->setPixmap(bannerImg);
0455         m_WizObjectSelectionUI->banner->setPixmap(bannerImg);
0456         m_WizChartConfigUI->banner->setPixmap(bannerImg);
0457         m_WizFovTypeSelectionUI->banner->setPixmap(bannerImg);
0458         m_WizFovConfigUI->banner->setPixmap(bannerImg);
0459         m_WizFovManualUI->banner->setPixmap(bannerImg);
0460         m_WizFovShUI->banner->setPixmap(bannerImg);
0461         m_WizFovBrowseUI->banner->setPixmap(bannerImg);
0462         m_WizChartContentsUI->banner->setPixmap(bannerImg);
0463         m_WizPrintUI->banner->setPixmap(bannerImg);
0464     }
0465 
0466     backB->setEnabled(false);
0467 }
0468 
0469 void PrintingWizard::updateButtons()
0470 {
0471     nextB->setEnabled(m_WizardStack->currentIndex() < m_WizardStack->count() - 1);
0472     backB->setEnabled(m_WizardStack->currentIndex() > 0);
0473 }
0474 
0475 void PrintingWizard::slewAndBeginCapture(SkyPoint *center, FOV *fov)
0476 {
0477     if (!center)
0478     {
0479         return;
0480     }
0481 
0482     // If pointer to FOV is passed...
0483     if (fov)
0484     {
0485         // Switch to appropriate FOV symbol
0486         Options::setFOVNames(QStringList(fov->name()));
0487         m_KStars->data()->syncFOV();
0488 
0489         // Adjust map's zoom level
0490         double zoom = m_FovImageSize.width() > m_FovImageSize.height() ?
0491                           SimpleFovExporter::calculateZoomLevel(m_FovImageSize.width(), fov->sizeX()) :
0492                           SimpleFovExporter::calculateZoomLevel(m_FovImageSize.height(), fov->sizeY());
0493         m_KStars->map()->setZoomFactor(zoom);
0494     }
0495 
0496     m_SimpleFovExporter.setFovShapeOverriden(m_WizFovConfigUI->isFovShapeOverriden());
0497     m_SimpleFovExporter.setFovSymbolDrawn(m_WizFovConfigUI->isFovShapeOverriden());
0498 
0499     m_SwitchColors   = m_WizFovConfigUI->isSwitchColorsEnabled();
0500     m_PrevSchemeName = m_KStars->data()->colorScheme()->fileName();
0501     if (m_SwitchColors)
0502     {
0503         m_KStars->loadColorScheme("chart.colors");
0504     }
0505 
0506     m_KStars->hideAllFovExceptFirst();
0507     m_KStars->map()->setClickedPoint(center);
0508     m_KStars->map()->slotCenter();
0509     m_KStars->map()->setFovCaptureMode(true);
0510     hide();
0511 }
0512 
0513 void PrintingWizard::createFinderChart()
0514 {
0515     // Delete old (if needed) and create new FinderChart
0516     if (m_FinderChart)
0517     {
0518         delete m_FinderChart;
0519     }
0520     m_FinderChart = new FinderChart;
0521 
0522     // Insert title and subtitle
0523     m_FinderChart->insertTitleSubtitle(m_WizChartConfigUI->titleEdit->text(), m_WizChartConfigUI->subtitleEdit->text());
0524 
0525     // Insert description
0526     if (!m_WizChartConfigUI->descriptionTextEdit->toPlainText().isEmpty())
0527     {
0528         m_FinderChart->insertDescription(m_WizChartConfigUI->descriptionTextEdit->toPlainText());
0529     }
0530 
0531     // Insert simple finder chart logging form
0532     if (m_WizChartContentsUI->isLoggingFormChecked())
0533     {
0534         LoggingForm chartLogger;
0535         chartLogger.createFinderChartLogger();
0536         m_FinderChart->insertSectionTitle(i18n("Logging Form"));
0537         m_FinderChart->insertLoggingForm(&chartLogger);
0538     }
0539 
0540     m_FinderChart->insertSectionTitle(i18n("Field of View Snapshots"));
0541 
0542     // Insert FOV images and descriptions
0543     for (int i = 0; i < m_FovSnapshots.size(); i++)
0544     {
0545         FOV *fov = m_FovSnapshots.at(i)->getFov();
0546         QString fovDescription =
0547             i18nc("%1 = FOV index, %2 = FOV count, %3 = FOV name, %4 = FOV X size, %5 = FOV Y size",
0548                   "FOV (%1/%2): %3 (%4' x %5')", QString::number(i + 1), QString::number(m_FovSnapshots.size()),
0549                   fov->name(), QString::number(fov->sizeX()), QString::number(fov->sizeY())) +
0550             "\n";
0551         m_FinderChart->insertImage(m_FovSnapshots.at(i)->getPixmap().toImage(),
0552                                    fovDescription + m_FovSnapshots.at(i)->getDescription(), true);
0553     }
0554 
0555     if (m_WizChartContentsUI->isGeneralTableChecked() || m_WizChartContentsUI->isPositionTableChecked() ||
0556         m_WizChartContentsUI->isRSTTableChecked() || m_WizChartContentsUI->isAstComTableChecked())
0557     {
0558         m_FinderChart->insertSectionTitle(i18n("Details About Object"));
0559         m_FinderChart->insertGeoTimeInfo(KStarsData::Instance()->ut(), KStarsData::Instance()->geo());
0560     }
0561 
0562     // Insert details table : general
0563     DetailsTable detTable;
0564     if (m_WizChartContentsUI->isGeneralTableChecked())
0565     {
0566         detTable.createGeneralTable(m_SkyObject);
0567         m_FinderChart->insertDetailsTable(&detTable);
0568     }
0569 
0570     // Insert details table : position
0571     if (m_WizChartContentsUI->isPositionTableChecked())
0572     {
0573         detTable.createCoordinatesTable(m_SkyObject, m_KStars->data()->ut(), m_KStars->data()->geo());
0574         m_FinderChart->insertDetailsTable(&detTable);
0575     }
0576 
0577     // Insert details table : RST
0578     if (m_WizChartContentsUI->isRSTTableChecked())
0579     {
0580         detTable.createRSTTAble(m_SkyObject, m_KStars->data()->ut(), m_KStars->data()->geo());
0581         m_FinderChart->insertDetailsTable(&detTable);
0582     }
0583 
0584     // Insert details table : Asteroid/Comet
0585     if (m_WizChartContentsUI->isAstComTableChecked())
0586     {
0587         detTable.createAsteroidCometTable(m_SkyObject);
0588         m_FinderChart->insertDetailsTable(&detTable);
0589     }
0590 }