andre@50: /* Copyright (C) 2016 by ETH Zürich andre@50: * Software engineering by Intevation GmbH andre@50: * andre@50: * This file is Free Software under the GNU GPL (v>=2) andre@50: * and comes with ABSOLUTELY NO WARRANTY! andre@50: * See LICENSE.txt for details. andre@50: */ andre@50: andre@50: /** @file See mainwindow.h */ andre@50: #include "mainwindow.h" andre@50: andre@50: #include "constants.h" andre@50: #include "converter.h" andre@50: #include "filenamerequester.h" andre@50: andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: #include andre@50: andre@50: MainWindow::MainWindow() { andre@50: setupGUI(); andre@50: readSettings(); andre@50: #ifndef Q_OS_WIN andre@50: QIcon windowIcon = QIcon(ICON_NAME); andre@50: setWindowIcon(windowIcon); andre@50: setWindowTitle(QStringLiteral(APPNAME)); andre@50: #endif andre@50: } andre@50: andre@50: void MainWindow::setupGUI() { andre@50: auto vLay = new QVBoxLayout; andre@50: auto inoutLay = new QGridLayout; andre@50: auto inputLabel = new QLabel(tr("Input File:")); andre@50: inoutLay->addWidget(inputLabel, 0, 0); andre@50: mInputRequester = new FileNameRequester(QDir::Files); andre@50: mInputRequester->setExistingOnly(true); andre@50: inputLabel->setBuddy(mInputRequester); andre@50: andre@50: inoutLay->addWidget(mInputRequester, 0, 1); andre@50: andre@50: auto outLabel = new QLabel(tr("Export Folder:")); andre@50: inoutLay->addWidget(outLabel, 1, 0); andre@50: mOutRequester = new FileNameRequester(QDir::Dirs); andre@50: mOutRequester->setExistingOnly(false); andre@50: inoutLay->addWidget(mOutRequester, 1, 1); andre@50: outLabel->setBuddy(mOutRequester); andre@50: andre@50: vLay->addLayout(inoutLay); andre@50: andre@50: auto optionsGrp = new QGroupBox("Export Options:"); andre@50: auto optionsLay = new QVBoxLayout; andre@50: mPdfChk = new QCheckBox(tr("PDF")); andre@50: mPdfChk->setToolTip(tr("Convert into PDF Format.")); andre@50: mHtmlChk = new QCheckBox(tr("HTML")); andre@50: mHtmlChk->setToolTip(tr("Convert into HTML Format.")); andre@50: mXlsxChk = new QCheckBox(tr("XLSX")); andre@50: mXlsxChk->setToolTip(tr("Convert into XLSX Format.")); andre@50: andre@50: optionsLay->addWidget(mPdfChk); andre@50: optionsLay->addWidget(mHtmlChk); andre@50: optionsLay->addWidget(mXlsxChk); andre@50: optionsGrp->setLayout(optionsLay); andre@50: vLay->addWidget(optionsGrp); andre@50: andre@50: mTitleEdit = new QLineEdit; andre@50: auto titleLay = new QHBoxLayout; andre@50: auto titleLabel = new QLabel(QStringLiteral("") + tr("mandatory") + andre@50: QStringLiteral("")); andre@50: mTitleEdit->setPlaceholderText(tr("Title (e.g. Feedback Questions SS2016)")); andre@50: titleLay->addWidget(mTitleEdit); andre@50: titleLay->addWidget(titleLabel); andre@50: vLay->addLayout(titleLay); andre@50: vLay->addStretch(1); andre@50: auto btns = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Close); andre@50: mConvertBtn = btns->button(QDialogButtonBox::Ok); andre@50: mConvertBtn->setText(tr("Convert")); andre@50: vLay->addWidget(btns); andre@50: andre@50: auto widget = new QWidget; andre@50: widget->setLayout(vLay); andre@50: setCentralWidget(widget); andre@50: checkCompleted(); andre@50: andre@50: connect(mConvertBtn, &QPushButton::clicked, this, &MainWindow::doConvert); andre@50: connect(mPdfChk, &QCheckBox::stateChanged, this, &MainWindow::checkCompleted); andre@50: connect(mHtmlChk, &QCheckBox::stateChanged, this, &MainWindow::checkCompleted); andre@50: connect(mXlsxChk, &QCheckBox::stateChanged, this, &MainWindow::checkCompleted); andre@50: connect(mTitleEdit, &QLineEdit::textChanged, this, &MainWindow::checkCompleted); andre@50: connect(mInputRequester, &FileNameRequester::fileNameChanged, this, &MainWindow::checkCompleted); andre@50: connect(mOutRequester, &FileNameRequester::fileNameChanged, this, &MainWindow::checkCompleted); andre@50: } andre@50: andre@50: void MainWindow::showErrorMessage(const QString& errMsg) { andre@50: QMessageBox::warning(this, tr("Error!"), errMsg); andre@50: } andre@50: andre@50: void MainWindow::closeEvent(QCloseEvent *event) { andre@50: mSettings.setValue("geometry", saveGeometry()); andre@50: mSettings.setValue("windowState", saveState()); andre@50: QMainWindow::closeEvent(event); andre@50: } andre@50: andre@50: void MainWindow::readSettings() { andre@50: if (mSettings.contains("geometry")) { andre@50: restoreGeometry(mSettings.value("geometry").toByteArray()); andre@50: restoreState(mSettings.value("windowState").toByteArray()); andre@50: } andre@50: andre@50: setInputFile(mSettings.value("lastInput", andre@50: QStandardPaths::writableLocation(DEFAULT_DIR)).toString()); andre@50: mOutRequester->setFileName(mSettings.value("lastOutput", andre@50: QStandardPaths::writableLocation(DEFAULT_DIR)).toString()); andre@50: andre@50: mPdfChk->setChecked(mSettings.value("pdfChk", true).toBool()); andre@50: mHtmlChk->setChecked(mSettings.value("htmlChk", false).toBool()); andre@50: mXlsxChk->setChecked(mSettings.value("xlsxChk", false).toBool()); andre@50: } andre@50: andre@50: void MainWindow::setInputFile(const QString& file) andre@50: { andre@50: mInputRequester->setFileName(file); andre@50: } andre@50: andre@50: void MainWindow::setTitle(const QString& title) { andre@50: mTitleEdit->setText(title); andre@50: } andre@50: andre@50: void MainWindow::checkCompleted() { andre@50: if (!mTitleEdit->text().isEmpty() && andre@50: (mPdfChk->isChecked() || mXlsxChk->isChecked() || mHtmlChk->isChecked())) { andre@50: mConvertBtn->setEnabled(true); andre@50: } else { andre@50: mConvertBtn->setEnabled(false); andre@50: } andre@50: } andre@50: andre@50: void MainWindow::doConvert() { andre@50: /* Construct output names */ andre@50: QStringList outNames; andre@50: andre@50: QDir outDir(mOutRequester->fileName()); andre@50: if (!outDir.exists() && !outDir.mkpath(mOutRequester->fileName())) { andre@50: showErrorMessage(tr("Failed to create output directory.")); andre@50: return; andre@50: } andre@50: andre@50: const QFileInfo fi(mInputRequester->fileName()); andre@50: if (!fi.exists() || !fi.isReadable()) { andre@50: showErrorMessage(tr("Failed to open \"%1\" for reading.").arg(mInputRequester->fileName())); andre@50: return; andre@50: } andre@50: if (mPdfChk->isChecked()) { andre@50: outNames << outDir.absoluteFilePath(fi.baseName() + QStringLiteral(".pdf")); andre@50: } andre@50: if (mHtmlChk->isChecked()) { andre@50: outNames << outDir.absoluteFilePath(fi.baseName() + QStringLiteral(".html")); andre@50: } andre@50: if (mXlsxChk->isChecked()) { andre@50: outNames << outDir.absoluteFilePath(fi.baseName() + QStringLiteral(".xslx")); andre@50: } andre@50: andre@50: QStringList cleanedNames; andre@50: foreach (const QString &name, outNames) { andre@50: const QFileInfo fi2(name); andre@50: if (!fi2.exists()) { andre@50: cleanedNames << name; andre@50: continue; andre@50: } andre@50: /* File exists. Lets try a number. */ andre@50: bool replacementFound = false; andre@50: for (int i = 1; i < MAX_FILENAME_COUNT; i++) { andre@50: const QString newName = outDir.absoluteFilePath(QStringLiteral("%1_%2.%3").arg( andre@50: fi2.baseName()).arg(i).arg(fi2.suffix())); andre@50: const QFileInfo fi3(newName); andre@50: if (!fi3.exists()) { andre@50: qDebug() << "Using " << newName << " as replacement because other files exist."; andre@50: cleanedNames << newName; andre@50: replacementFound = true; andre@50: break; andre@50: } andre@50: } andre@50: if (!replacementFound) { andre@50: showErrorMessage(tr("Failed to find an available free name for \"%1\" please choose another folder.").arg(name)); andre@50: return; andre@50: } andre@50: } andre@50: andre@50: mSettings.setValue("lastInput", mInputRequester->fileName()); andre@50: mSettings.setValue("lastOutput", mOutRequester->fileName()); andre@50: mSettings.setValue("pdfChk", mPdfChk->isChecked()); andre@50: mSettings.setValue("xlsxChk", mXlsxChk->isChecked()); andre@50: mSettings.setValue("htmlChk", mHtmlChk->isChecked()); andre@50: andre@50: /* Convert away */ andre@50: Converter conv(mInputRequester->fileName(), cleanedNames, mTitleEdit->text()); andre@50: andre@50: conv.start(); andre@50: hide(); andre@50: qDebug() << "Waiting for conversion."; andre@50: conv.wait(); andre@50: qDebug() << "Conversion done."; andre@50: const QStringList errors = conv.errors(); andre@50: if (!errors.isEmpty()) { andre@50: Q_FOREACH (const QString err, errors) { andre@50: showErrorMessage(err); andre@50: } andre@50: } andre@50: andre@50: if (cleanedNames.size() == 1) { andre@50: qDebug() << "Opening: " << QUrl(QStringLiteral("file:///%1").arg(cleanedNames[0]), QUrl::TolerantMode); andre@50: QDesktopServices::openUrl(QUrl(QStringLiteral("file:///%1").arg(cleanedNames[0]), QUrl::TolerantMode)); andre@50: } else { andre@50: qDebug() << "Opening: " << QUrl(QStringLiteral("file:///%1").arg(outDir.path()), QUrl::TolerantMode); andre@50: QDesktopServices::openUrl(QUrl(QStringLiteral("file:///%1").arg(outDir.path()), QUrl::TolerantMode)); andre@50: } andre@50: andre@50: close(); andre@50: }