File indexing completed on 2024-05-12 15:28:21

0001 /***************************************************************************
0002     File                 : ExportWorksheetDialog.cpp
0003     Project              : LabPlot
0004     Description          : export worksheet dialog
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2011-2019 Alexander Semke (alexander.semke@web.de)
0007     Copyright            : (C) 2021 Stefan Gerlach (stefan.gerlach@uni.kn)
0008 
0009  ***************************************************************************/
0010 
0011 /***************************************************************************
0012  *                                                                         *
0013  *  This program is free software; you can redistribute it and/or modify   *
0014  *  it under the terms of the GNU General Public License as published by   *
0015  *  the Free Software Foundation; either version 2 of the License, or      *
0016  *  (at your option) any later version.                                    *
0017  *                                                                         *
0018  *  This program is distributed in the hope that it will be useful,        *
0019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0021  *  GNU General Public License for more details.                           *
0022  *                                                                         *
0023  *   You should have received a copy of the GNU General Public License     *
0024  *   along with this program; if not, write to the Free Software           *
0025  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0026  *   Boston, MA  02110-1301  USA                                           *
0027  *                                                                         *
0028  ***************************************************************************/
0029 
0030 #include "ExportWorksheetDialog.h"
0031 #include "ui_exportworksheetwidget.h"
0032 #include "kdefrontend/GuiTools.h"
0033 #include "commonfrontend/worksheet/WorksheetView.h"
0034 
0035 #include <QCompleter>
0036 #include <QDesktopWidget>
0037 #include <QDirModel>
0038 #include <QFileDialog>
0039 #include <QWindow>
0040 
0041 #include <QDialogButtonBox>
0042 #include <KLocalizedString>
0043 #include <KMessageBox>
0044 #include <KSharedConfig>
0045 #include <KWindowConfig>
0046 
0047 /*!
0048     \class ExportWorksheetDialog
0049     \brief Dialog for exporting a worksheet to a file.
0050 
0051     \ingroup kdefrontend
0052 */
0053 
0054 ExportWorksheetDialog::ExportWorksheetDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ExportWorksheetWidget()) {
0055     ui->setupUi(this);
0056 
0057     auto* btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
0058     m_showOptionsButton = new QPushButton;
0059 
0060     connect(btnBox, &QDialogButtonBox::clicked, this, &ExportWorksheetDialog::slotButtonClicked);
0061 
0062     btnBox->addButton(m_showOptionsButton, QDialogButtonBox::ActionRole);
0063     ui->verticalLayout->addWidget(btnBox);
0064 
0065     m_okButton = btnBox->button(QDialogButtonBox::Ok);
0066     m_cancelButton = btnBox->button(QDialogButtonBox::Cancel);
0067 
0068     m_cancelButton->setToolTip(i18n("Close this dialog without exporting."));
0069 
0070     ui->leFileName->setCompleter(new QCompleter(new QDirModel, this));
0071 
0072     ui->bOpen->setIcon(QIcon::fromTheme(QLatin1String("document-open")));
0073 
0074     // see WorksheetView::ExportFormat
0075     ui->cbFormat->addItem(QIcon::fromTheme(QLatin1String("application-pdf")), i18n("Portable Data Format (PDF)"));
0076     ui->cbFormat->addItem(QIcon::fromTheme(QLatin1String("image-svg+xml")), i18n("Scalable Vector Graphics (SVG)"));
0077     ui->cbFormat->insertSeparator(3);
0078     ui->cbFormat->addItem(QIcon::fromTheme(QLatin1String("image-png")), i18n("Portable Network Graphics (PNG)"));
0079     ui->cbFormat->addItem(QIcon::fromTheme(QLatin1String("image-jpeg")), i18n("Joint Photographic Experts Group (JPG)"));
0080     ui->cbFormat->addItem(QIcon::fromTheme(QLatin1String("image-bmp")), i18n("Windows Bitmap (BMP)"));
0081     ui->cbFormat->addItem(QIcon::fromTheme(QLatin1String("image-x-generic")), i18n("Portable Pixmap (PPM)"));
0082     ui->cbFormat->addItem(QIcon::fromTheme(QLatin1String("image-x-generic")), i18n("X11 Bitmap (XBM)"));
0083     ui->cbFormat->addItem(QIcon::fromTheme(QLatin1String("image-x-generic")), i18n("X11 Bitmap (XPM)"));
0084 
0085     ui->cbExportTo->addItem(i18n("File"));
0086     ui->cbExportTo->addItem(i18n("Clipboard"));
0087 
0088     ui->cbExportArea->addItem(i18n("Object's bounding box"));
0089     ui->cbExportArea->addItem(i18n("Current selection"));
0090     ui->cbExportArea->addItem(i18n("Complete worksheet"));
0091 
0092     ui->cbResolution->addItem(i18nc("%1 is the value of DPI of the current screen", "%1 (desktop)", QString::number(QApplication::desktop()->physicalDpiX())));
0093     ui->cbResolution->addItem(QLatin1String("100"));
0094     ui->cbResolution->addItem(QLatin1String("150"));
0095     ui->cbResolution->addItem(QLatin1String("200"));
0096     ui->cbResolution->addItem(QLatin1String("300"));
0097     ui->cbResolution->addItem(QLatin1String("600"));
0098     ui->cbResolution->setValidator(new QIntValidator(ui->cbResolution));
0099 
0100     connect(ui->cbFormat, static_cast<void (QComboBox::*)(int)>(&KComboBox::currentIndexChanged),
0101             this, &ExportWorksheetDialog::formatChanged);
0102     connect(ui->cbExportTo, static_cast<void (QComboBox::*)(int)>(&KComboBox::currentIndexChanged),
0103             this, &ExportWorksheetDialog::exportToChanged);
0104     connect(ui->bOpen, &QPushButton::clicked, this, &ExportWorksheetDialog::selectFile);
0105     connect(ui->leFileName, &QLineEdit::textChanged, this, &ExportWorksheetDialog::fileNameChanged);
0106     connect(m_showOptionsButton, &QPushButton::clicked, this, &ExportWorksheetDialog::toggleOptions);
0107     ui->leFileName->setFocus();
0108 
0109     setWindowTitle(i18nc("@title:window", "Export Worksheet"));
0110     setWindowIcon(QIcon::fromTheme(QLatin1String("document-export-database")));
0111 
0112     //restore saved settings if available
0113     KConfigGroup conf(KSharedConfig::openConfig(), "ExportWorksheetDialog");
0114     ui->cbFormat->setCurrentIndex(conf.readEntry("Format", 0));
0115     ui->cbExportTo->setCurrentIndex(conf.readEntry("ExportTo", 0));
0116     ui->cbExportArea->setCurrentIndex(conf.readEntry("Area", 0));
0117     ui->chkExportBackground->setChecked(conf.readEntry("Background", true));
0118     ui->cbResolution->setCurrentIndex(conf.readEntry("Resolution", 0));
0119     m_showOptions = conf.readEntry("ShowOptions", true);
0120     m_showOptions ? m_showOptionsButton->setText(i18n("Hide Options")) :
0121                 m_showOptionsButton->setText(i18n("Show Options"));
0122     ui->gbOptions->setVisible(m_showOptions);
0123 
0124     create(); // ensure there's a window created
0125     if (conf.exists()) {
0126         KWindowConfig::restoreWindowSize(windowHandle(), conf);
0127         resize(windowHandle()->size()); // workaround for QTBUG-40584
0128     } else
0129         resize(QSize(0, 0).expandedTo(minimumSize()));
0130 }
0131 
0132 ExportWorksheetDialog::~ExportWorksheetDialog() {
0133     //save current settings
0134     KConfigGroup conf(KSharedConfig::openConfig(), "ExportWorksheetDialog");
0135     conf.writeEntry("Format", ui->cbFormat->currentIndex());
0136     conf.writeEntry("ExportTo", ui->cbExportTo->currentIndex());
0137     conf.writeEntry("Area", ui->cbExportArea->currentIndex());
0138     conf.writeEntry("Background", ui->chkExportBackground->isChecked());
0139     conf.writeEntry("Resolution", ui->cbResolution->currentIndex());
0140     conf.writeEntry("ShowOptions", m_showOptions);
0141 
0142     KWindowConfig::saveWindowSize(windowHandle(), conf);
0143 }
0144 
0145 void ExportWorksheetDialog::setFileName(const QString& name) {
0146     KConfigGroup conf(KSharedConfig::openConfig(), "ExportWorksheetDialog");
0147     QString dir = conf.readEntry("LastDir", "");
0148     if (dir.isEmpty()) dir = QDir::homePath();
0149     ui->leFileName->setText(dir + QLatin1String("/") +  name);
0150 
0151     formatChanged(ui->cbFormat->currentIndex());
0152     exportToChanged(ui->cbExportTo->currentIndex());
0153 }
0154 
0155 QString ExportWorksheetDialog::path() const {
0156     if (ui->cbExportTo->currentIndex() == 0)
0157         return ui->leFileName->text();
0158     else
0159         return QString();
0160 }
0161 
0162 WorksheetView::ExportFormat ExportWorksheetDialog::exportFormat() const {
0163     int index = ui->cbFormat->currentIndex();
0164 
0165     //we have a separator in the format combobox at the 3th position -> skip it
0166     if (index > 2)
0167         index--;
0168 
0169     return WorksheetView::ExportFormat(index);
0170 }
0171 
0172 WorksheetView::ExportArea ExportWorksheetDialog::exportArea() const {
0173     return WorksheetView::ExportArea(ui->cbExportArea->currentIndex());
0174 }
0175 
0176 bool ExportWorksheetDialog::exportBackground() const {
0177     return ui->chkExportBackground->isChecked();
0178 }
0179 
0180 int ExportWorksheetDialog::exportResolution() const {
0181     if (ui->cbResolution->currentIndex() == 0)
0182         return QApplication::desktop()->physicalDpiX();
0183     else
0184         return ui->cbResolution->currentText().toInt();
0185 }
0186 
0187 void ExportWorksheetDialog::slotButtonClicked(QAbstractButton* button) {
0188     if (button == m_okButton)
0189         okClicked();
0190     else if (button == m_cancelButton)
0191         reject();
0192 }
0193 
0194 //SLOTS
0195 void ExportWorksheetDialog::okClicked() {
0196     if ( QFile::exists(ui->leFileName->text()) ) {
0197         int r = KMessageBox::questionYesNo(this, i18n("The file already exists. Do you really want to overwrite it?"), i18n("Export"));
0198         if (r == KMessageBox::No)
0199             return;
0200     }
0201 
0202     KConfigGroup conf(KSharedConfig::openConfig(), "ExportWorksheetDialog");
0203     QString path = ui->leFileName->text();
0204     if (!path.isEmpty()) {
0205         QString dir = conf.readEntry("LastDir", "");
0206         int pos = path.lastIndexOf(QLatin1String("/"));
0207         if (pos != -1) {
0208             QString newDir = path.left(pos);
0209             if (newDir != dir)
0210                 conf.writeEntry("LastDir", newDir);
0211         }
0212     }
0213 
0214     accept();
0215 }
0216 
0217 /*!
0218     Shows/hides the GroupBox with export options in this dialog.
0219 */
0220 void ExportWorksheetDialog::toggleOptions() {
0221     m_showOptions = !m_showOptions;
0222     ui->gbOptions->setVisible(m_showOptions);
0223     m_showOptions ? m_showOptionsButton->setText(i18n("Hide Options")) :
0224             m_showOptionsButton->setText(i18n("Show Options"));
0225 
0226     //resize the dialog
0227     layout()->activate();
0228     resize( QSize(this->width(), 0).expandedTo(minimumSize()) );
0229 }
0230 
0231 /*!
0232     opens a file dialog and lets the user select the file.
0233 */
0234 void ExportWorksheetDialog::selectFile() {
0235     KConfigGroup conf(KSharedConfig::openConfig(), "ExportWorksheetDialog");
0236     const QString dir = conf.readEntry("LastDir", "");
0237 
0238     DEBUG(Q_FUNC_INFO << ", format" << ui->cbFormat->currentIndex())
0239     QString format;
0240     int index = ui->cbFormat->currentIndex();
0241     if (index > 2)  // consider separator
0242         index--;
0243 
0244     switch ((WorksheetView::ExportFormat)index) {
0245     case WorksheetView::ExportFormat::PDF:
0246         format = i18n("Portable Data Format (*.pdf *.PDF)");
0247         break;
0248     case WorksheetView::ExportFormat::SVG:
0249         format = i18n("Scalable Vector Graphics (*.svg *.SVG)");
0250         break;
0251     case WorksheetView::ExportFormat::PNG:
0252         format = i18n("Portable Network Graphics (*.png *.PNG)");
0253         break;
0254     case WorksheetView::ExportFormat::JPG:
0255         format = i18n("Joint Photographic Experts Group (*.jpg *.jpeg *.JPG *.JPEG)");
0256         break;
0257     case WorksheetView::ExportFormat::BMP:
0258         format = i18n("Windows Bitmap (*.bmp *.BMP)");
0259         break;
0260     case WorksheetView::ExportFormat::PPM:
0261         format = i18n("Portable Pixmap (*.ppm *.PPM)");
0262         break;
0263     case WorksheetView::ExportFormat::XBM:
0264         format = i18n("X11 Bitmap (*.xbm *.XBM)");
0265         break;
0266     case WorksheetView::ExportFormat::XPM:
0267         format = i18n("X11 Bitmap (*.xpm *.XPM)");
0268         break;
0269     }
0270 
0271     const QString path = QFileDialog::getSaveFileName(this, i18n("Export to file"), dir, format);
0272     if (!path.isEmpty()) {
0273         ui->leFileName->setText(path);
0274 
0275         int pos = path.lastIndexOf(QLatin1String("/"));
0276         if (pos != -1) {
0277             const QString newDir = path.left(pos);
0278             if (newDir != dir && QDir(newDir).exists())
0279                 conf.writeEntry("LastDir", newDir);
0280         }
0281     }
0282 }
0283 
0284 /*!
0285     called when the output format was changed. Adjusts the extension for the specified file.
0286  */
0287 void ExportWorksheetDialog::formatChanged(int index) {
0288     //we have a separator in the format combobox at the 3rd position -> skip it
0289     if (index > 2)
0290         index --;
0291 
0292     QStringList extensions;
0293     // see WorksheetView::ExportFormat
0294     extensions << QLatin1String(".pdf") << QLatin1String(".svg") << QLatin1String(".png") << QLatin1String(".jpg") << QLatin1String(".bmp")
0295         << QLatin1String(".ppm") << QLatin1String(".xbm") << QLatin1String(".xpm");
0296     QString path = ui->leFileName->text();
0297     int i = path.indexOf(QLatin1Char('.'));
0298     if (i == -1)
0299         path = path + extensions.at(index);
0300     else
0301         path = path.left(i) + extensions.at(index);
0302 
0303     ui->leFileName->setText(path);
0304 
0305     // show resolution option for png format
0306     bool visible = (index == 2);
0307     ui->lResolution->setVisible(visible);
0308     ui->cbResolution->setVisible(visible);
0309 }
0310 
0311 /*!
0312     called when the target destination (file or clipboard) format was changed.
0313  */
0314 void ExportWorksheetDialog::exportToChanged(int index) {
0315     bool toFile = (index == 0);
0316     ui->lFileName->setVisible(toFile);
0317     ui->leFileName->setVisible(toFile);
0318     ui->bOpen->setVisible(toFile);
0319 
0320     if (toFile)
0321         m_okButton->setToolTip(i18n("Export to file and close the dialog."));
0322     else
0323         m_okButton->setToolTip(i18n("Export to clipboard and close the dialog."));
0324 }
0325 
0326 void ExportWorksheetDialog::fileNameChanged(const QString& name) {
0327     if (name.simplified().isEmpty()) {
0328         m_okButton->setEnabled(false);
0329         return;
0330     }
0331     QString path = ui->leFileName->text();
0332     int pos = path.lastIndexOf(QLatin1String("/"));
0333     if (pos != -1) {
0334         QString dir = path.left(pos);
0335         bool invalid = !QDir(dir).exists();
0336         GuiTools::highlight(ui->leFileName, invalid);
0337         if (invalid) {
0338             m_okButton->setEnabled(false);
0339             return;
0340         }
0341     }
0342 
0343     m_okButton->setEnabled(true);
0344 }