File indexing completed on 2024-05-26 04:32:43

0001 /*
0002  *  SPDX-FileCopyrightText: 2020 Saurabh Kumar <saurabhk660@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 #include "DlgExportStoryboard.h"
0007 #include "StoryboardModel.h"
0008 
0009 #include "KoFileDialog.h"
0010 #include <kis_config.h>
0011 #include <kis_file_name_requester.h>
0012 #include <kis_time_span.h>
0013 
0014 #include <QSpinBox>
0015 #include <QMessageBox>
0016 
0017 DlgExportStoryboard::DlgExportStoryboard(ExportFormat format, QSharedPointer<StoryboardModel> model)
0018         : KoDialog()
0019         , m_format(format)
0020         , m_model(model)
0021 {
0022     m_page = new WdgExportStoryboard(this);
0023 
0024     setCaption(format == ExportFormat::PDF
0025                ? i18nc("Export storyboard dialog caption", "Export Storyboard as PDF")
0026                : i18nc("Export storyboard dialog caption", "Export Storyboard as SVG"));
0027 
0028     setButtons(Apply | Cancel);
0029     setButtonText(Apply, i18n("Export"));
0030     setDefaultButton(Apply);
0031 
0032     connect(this, SIGNAL(applyClicked()), this, SLOT(slotExportClicked()));
0033     connect(m_page->boardLayoutComboBox, SIGNAL(activated(int)), this, SLOT(slotLayoutChanged(int)));
0034     connect(m_page->pageSizeComboBox, SIGNAL(activated(int)), this, SLOT(slotPageSettingsChanged(int)));
0035     connect(m_page->pageOrientationComboBox, SIGNAL(activated(int)), this, SLOT(slotPageSettingsChanged(int)));
0036     connect(m_page->rowsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(slotPageSettingsChanged(int)));
0037     connect(m_page->columnsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(slotPageSettingsChanged(int)));
0038 
0039     KisConfig cfg(true);
0040     m_page->boardLayoutComboBox->setCurrentIndex(cfg.readEntry<int>("storyboard/layoutType", ExportLayout::ROWS));
0041     m_page->pageOrientationComboBox->setCurrentIndex(cfg.readEntry<int>("storyboard/pageOrientation", 0));
0042     m_page->rowsSpinBox->setValue(cfg.readEntry<int>("storyboard/rows", 3));
0043     m_page->columnsSpinBox->setValue(cfg.readEntry<int>("storyboard/columns", 3));
0044     m_page->fontSizeSpinBox->setValue(cfg.readEntry<int>("storyboard/fontSize", 15));
0045     m_page->svgTemplatePathFileRequester->setFileName(cfg.readEntry<QString>("storyboard/svgLayoutFileName", ""));
0046     m_page->exportPathFileRequester->setFileName(cfg.readEntry<QString>("storyboard/exportFilePath"));
0047 
0048     if (format == ExportFormat::PDF) {
0049         QStringList mimeTypes;
0050         mimeTypes << "application/pdf";
0051         m_page->exportPathFileRequester->setMimeTypeFilters(mimeTypes);
0052         m_page->exportPathFileRequester->setMode(KoFileDialog::SaveFile);
0053     }
0054     else {
0055         m_page->exportPathFileRequester->setMode(KoFileDialog::OpenDirectory);
0056     }
0057 
0058     QStringList mimeTypes;
0059     mimeTypes << "image/svg+xml";
0060     m_page->svgTemplatePathFileRequester->setMimeTypeFilters(mimeTypes);
0061     m_page->svgTemplatePathFileRequester->setMode(KoFileDialog::OpenFile);
0062 
0063     setMainWidget(m_page);
0064     slotLayoutChanged(m_page->boardLayoutComboBox->currentIndex());
0065     setUsableMaximums(pageSize(), pageOrientation(), exportLayout());
0066 }
0067 
0068 DlgExportStoryboard::~DlgExportStoryboard()
0069 {
0070 }
0071 
0072 
0073 int DlgExportStoryboard::rows() const
0074 {
0075     const int layoutIndex = m_page->boardLayoutComboBox->currentIndex();
0076     if (layoutIndex == ExportLayout::COLUMNS || layoutIndex == ExportLayout::SVG_TEMPLATE) {
0077         return 1;
0078     }
0079     else {
0080         return qMax(m_page->rowsSpinBox->value(), 1);
0081     }
0082 }
0083 
0084 int DlgExportStoryboard::columns() const
0085 {
0086     const int layoutIndex = m_page->boardLayoutComboBox->currentIndex();
0087     if (layoutIndex == ExportLayout::ROWS || layoutIndex == ExportLayout::SVG_TEMPLATE) {
0088         return 1;
0089     }
0090     else {
0091         return qMax(m_page->columnsSpinBox->value(), 1);
0092     }
0093 }
0094 
0095 QPageSize DlgExportStoryboard::pageSize() const
0096 {
0097     int index = m_page->pageSizeComboBox->currentIndex();
0098     switch (index) {
0099         case 0:
0100             return QPageSize(QPageSize::PageSizeId::A0);
0101         case 1:
0102             return QPageSize(QPageSize::PageSizeId::A1);
0103         case 2:
0104             return QPageSize(QPageSize::PageSizeId::A2);
0105         case 3:
0106             return QPageSize(QPageSize::PageSizeId::A3);
0107         case 4:
0108             return QPageSize(QPageSize::PageSizeId::A4);
0109         case 5:
0110             return QPageSize(QPageSize::PageSizeId::A5);
0111         case 6:
0112         default:
0113             return QPageSize(QPageSize::PageSizeId::Letter);
0114     }
0115 }
0116 
0117 QPageLayout::Orientation DlgExportStoryboard::pageOrientation() const
0118 {
0119     return (QPageLayout::Orientation)m_page->pageOrientationComboBox->currentIndex();
0120 }
0121 
0122 bool DlgExportStoryboard::layoutSpecifiedBySvgFile() const
0123 {
0124     const int layoutIndex = m_page->boardLayoutComboBox->currentIndex();
0125     return layoutIndex == ExportLayout::SVG_TEMPLATE;
0126 }
0127 
0128 QString DlgExportStoryboard::layoutSvgFile() const
0129 {
0130     return m_page->svgTemplatePathFileRequester->fileName();
0131 }
0132 
0133 QString DlgExportStoryboard::saveFileName() const
0134 {
0135     return m_page->exportPathFileRequester->fileName();
0136 }
0137 
0138 ExportFormat DlgExportStoryboard::format() const
0139 {
0140     return m_format;
0141 }
0142 
0143 ExportLayout DlgExportStoryboard::exportLayout() const
0144 {
0145     return static_cast<ExportLayout>(m_page->boardLayoutComboBox->currentIndex());
0146 }
0147 
0148 int DlgExportStoryboard::fontSize() const
0149 {
0150     return m_page->fontSizeSpinBox->value();
0151 }
0152 
0153 void DlgExportStoryboard::setUsableMaximums(QPageSize pPageSize, QPageLayout::Orientation pOrientation, ExportLayout pLayout)
0154 {
0155     if (pLayout == ExportLayout::SVG_TEMPLATE) { // Bypass estimates -- We can't really make any educated guess here!
0156         m_page->fontSizeSpinBox->setMaximum(50);
0157     } else {
0158         const QSize pointSize = pPageSize.sizePoints();
0159         const QSize orientedPointSize = pOrientation == QPageLayout::Landscape ? QSize(pointSize.height(), pointSize.width()) : pointSize;
0160         const QSize sizeInPointsPerBoard = QSize(orientedPointSize.width() / columns(), orientedPointSize.height() / rows());
0161 
0162         const int commentCount = m_model ? qMax(m_model->totalCommentCount(), 1) : 1;
0163         const bool stacked = sizeInPointsPerBoard.width() < sizeInPointsPerBoard.height();
0164         const QSize sizeInPointsPerComment = stacked ? QSize(sizeInPointsPerBoard.width(), sizeInPointsPerBoard.height() / commentCount)
0165                                                      : QSize(sizeInPointsPerBoard.width() / commentCount, sizeInPointsPerBoard.height());
0166         const QSize usableMaximumFontSize = sizeInPointsPerComment / 12;
0167         m_page->fontSizeSpinBox->setMaximum(qMin(usableMaximumFontSize.width(), usableMaximumFontSize.height()));
0168     }
0169 }
0170 
0171 void DlgExportStoryboard::slotExportClicked()
0172 {
0173     if (m_page->exportPathFileRequester->fileName().isEmpty()) {
0174         if (m_format == ExportFormat::PDF) {
0175             QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Please enter a file name to export to."));
0176         }
0177         else {
0178             QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Please enter a directory to export to."));
0179         }
0180         return;
0181     }
0182 
0183     if (m_format == ExportFormat::SVG) {
0184 
0185         QDir dir(m_page->exportPathFileRequester->fileName());
0186         if (!dir.exists()) {
0187             QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Please enter an existing directory."));
0188             return;
0189         }
0190 
0191         QFileInfo info("[0-9]*.svg");
0192         QStringList filesList = dir.entryList({ info.fileName() });
0193 
0194         if (!filesList.isEmpty()) {
0195             QMessageBox::StandardButton result =
0196                 QMessageBox::warning(0,
0197                                      i18n("Existing files with similar naming scheme"),
0198                                      i18n("Files with the same naming "
0199                                           "scheme exist in the destination "
0200                                           "directory. They might be "
0201                                           "deleted, continue?\n\n"
0202                                           "Directory: %1\n"
0203                                           "Files: %2",
0204                                           dir.absolutePath(), filesList.at(0) + "..."),
0205                                      QMessageBox::Yes | QMessageBox::No,
0206                                      QMessageBox::No);
0207             if (result == QMessageBox::No) {
0208                 return;
0209             }
0210         }
0211     }
0212 
0213     if (layoutSpecifiedBySvgFile() && m_page->svgTemplatePathFileRequester->fileName().isEmpty()) {
0214         QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Please choose svg file to specify the layout for exporting."));
0215         return;
0216     }
0217     QFileInfo fi(m_page->svgTemplatePathFileRequester->fileName());
0218     if (layoutSpecifiedBySvgFile() && !fi.exists()) {
0219         QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The SVG file to specify layout doesn't exist. Please choose an existing SVG file."));
0220         return;
0221     }
0222 
0223     KisConfig cfg(false);
0224     cfg.writeEntry("storyboard/layoutType", m_page->boardLayoutComboBox->currentIndex());
0225     cfg.writeEntry("storyboard/pageOrientation", m_page->pageOrientationComboBox->currentIndex());
0226     cfg.writeEntry("storyboard/rows", m_page->rowsSpinBox->value());
0227     cfg.writeEntry("storyboard/columns", m_page->columnsSpinBox->value());
0228     cfg.writeEntry("storyboard/svgLayoutFileName", m_page->svgTemplatePathFileRequester->fileName());
0229     cfg.writeEntry("storyboard/exportFilePath", m_page->exportPathFileRequester->fileName());
0230     cfg.writeEntry("storyboard/fontSize", m_page->fontSizeSpinBox->value());
0231 
0232     accept();
0233 }
0234 
0235 void DlgExportStoryboard::slotLayoutChanged(int state)
0236 {
0237     switch (state) {
0238     case ExportLayout::COLUMNS:
0239         m_page->rowsLabel->hide();
0240         m_page->rowsSpinBox->hide();
0241         m_page->svgTemplatePathFileRequester->hide();
0242         m_page->svgTemplatePathLabel->hide();
0243 
0244         m_page->columnsSpinBox->show();
0245         m_page->columnsLabel->show();
0246         break;
0247     case ExportLayout::ROWS:
0248         m_page->columnsLabel->hide();
0249         m_page->columnsSpinBox->hide();
0250         m_page->svgTemplatePathFileRequester->hide();
0251         m_page->svgTemplatePathLabel->hide();
0252 
0253         m_page->rowsSpinBox->show();
0254         m_page->rowsLabel->show();
0255         break;
0256     case ExportLayout::GRID:
0257         m_page->svgTemplatePathFileRequester->hide();
0258         m_page->svgTemplatePathLabel->hide();
0259 
0260         m_page->columnsLabel->show();
0261         m_page->columnsSpinBox->show();
0262         m_page->rowsSpinBox->show();
0263         m_page->rowsLabel->show();
0264         break;
0265     case ExportLayout::SVG_TEMPLATE:
0266         m_page->columnsLabel->hide();
0267         m_page->columnsSpinBox->hide();
0268         m_page->rowsSpinBox->hide();
0269         m_page->rowsLabel->hide();
0270 
0271         m_page->svgTemplatePathFileRequester->show();
0272         m_page->svgTemplatePathLabel->show();
0273         break;
0274     }
0275 }
0276 
0277 void DlgExportStoryboard::slotPageSettingsChanged(int)
0278 {
0279     setUsableMaximums(pageSize(), pageOrientation(), exportLayout());
0280 }