File indexing completed on 2024-05-12 12:20:43
0001 // SPDX-FileCopyrightText: 2003-2020 The KPhotoAlbum Development Team 0002 // SPDX-FileCopyrightText: 2022-2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 0003 // 0004 // SPDX-License-Identifier: GPL-2.0-or-later 0005 0006 #include "HTMLDialog.h" 0007 0008 #include "Generator.h" 0009 #include "ImageSizeCheckBox.h" 0010 #include "Logging.h" 0011 0012 #include <DB/CategoryCollection.h> 0013 #include <DB/ImageDB.h> 0014 #include <MainWindow/Window.h> 0015 #include <kpabase/SettingsData.h> 0016 0017 #include <KColorScheme> 0018 #include <KConfig> 0019 #include <KConfigGroup> 0020 #include <KFileItem> 0021 #include <KIO/DeleteJob> 0022 #include <KIO/StatJob> 0023 #include <KJob> 0024 #include <KJobWidgets> 0025 #include <KLocalizedString> 0026 #include <KMessageBox> 0027 #include <KTextEdit> 0028 #include <QCheckBox> 0029 #include <QComboBox> 0030 #include <QDialogButtonBox> 0031 #include <QFileDialog> 0032 #include <QGroupBox> 0033 #include <QHBoxLayout> 0034 #include <QLabel> 0035 #include <QLayout> 0036 #include <QLineEdit> 0037 #include <QPushButton> 0038 #include <QScopedPointer> 0039 #include <QSpinBox> 0040 #include <QStandardPaths> 0041 #include <QStringMatcher> 0042 #include <QVBoxLayout> 0043 #include <kio_version.h> 0044 #include <kwidgetsaddons_version.h> 0045 0046 using namespace HTMLGenerator; 0047 0048 HTMLDialog::HTMLDialog(QWidget *parent) 0049 : KPageDialog(parent) 0050 , m_list() 0051 { 0052 setWindowTitle(i18nc("@title:window", "HTML Export")); 0053 QWidget *mainWidget = new QWidget(this); 0054 this->layout()->addWidget(mainWidget); 0055 0056 createContentPage(); 0057 createLayoutPage(); 0058 createDestinationPage(); 0059 // destUrl is only relevant for .kim file creation: 0060 connect(m_generateKimFile, &QCheckBox::toggled, m_destURL, &QLineEdit::setEnabled); 0061 // automatically fill in output directory: 0062 connect(m_title, &QLineEdit::editingFinished, this, &HTMLDialog::slotSuggestOutputDir); 0063 0064 QDialogButtonBox *buttonBox = this->buttonBox(); 0065 connect(buttonBox, &QDialogButtonBox::accepted, this, &HTMLDialog::accept); 0066 connect(buttonBox, &QDialogButtonBox::rejected, this, &HTMLDialog::reject); 0067 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0068 okButton->setDefault(true); 0069 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0070 okButton->setEnabled(m_themes.size() > 0); 0071 connect(okButton, &QPushButton::clicked, this, &HTMLDialog::slotOk); 0072 this->layout()->addWidget(buttonBox); 0073 } 0074 0075 void HTMLDialog::createContentPage() 0076 { 0077 QWidget *contentPage = new QWidget; 0078 KPageWidgetItem *page = new KPageWidgetItem(contentPage, i18n("Content")); 0079 page->setHeader(i18n("Content")); 0080 page->setIcon(QIcon::fromTheme(QString::fromLatin1("document-properties"))); 0081 addPage(page); 0082 0083 QVBoxLayout *lay1 = new QVBoxLayout(contentPage); 0084 QGridLayout *lay2 = new QGridLayout; 0085 lay1->addLayout(lay2); 0086 0087 QLabel *label = new QLabel(i18n("Page title:"), contentPage); 0088 lay2->addWidget(label, 0, 0); 0089 m_title = new QLineEdit(contentPage); 0090 label->setBuddy(m_title); 0091 lay2->addWidget(m_title, 0, 1); 0092 0093 // Copyright 0094 label = new QLabel(i18n("Copyright:"), contentPage); 0095 label->setAlignment(Qt::AlignTop); 0096 lay2->addWidget(label, 1, 0); 0097 m_copyright = new QLineEdit(contentPage); 0098 m_copyright->setText(Settings::SettingsData::instance()->HTMLCopyright()); 0099 label->setBuddy(m_copyright); 0100 lay2->addWidget(m_copyright, 1, 1); 0101 0102 // Description 0103 label = new QLabel(i18n("Description:"), contentPage); 0104 label->setAlignment(Qt::AlignTop); 0105 lay2->addWidget(label, 2, 0); 0106 m_description = new KTextEdit(contentPage); 0107 label->setBuddy(m_description); 0108 lay2->addWidget(m_description, 2, 1); 0109 0110 m_generateKimFile = new QCheckBox(i18n("Create .kim export file"), contentPage); 0111 m_generateKimFile->setChecked(Settings::SettingsData::instance()->HTMLKimFile()); 0112 lay1->addWidget(m_generateKimFile); 0113 0114 m_inlineMovies = new QCheckBox(i18nc("Inline as a verb, i.e. 'please show movies right on the page, not as links'", 0115 "Inline Movies in pages"), 0116 contentPage); 0117 m_inlineMovies->setChecked(Settings::SettingsData::instance()->HTMLInlineMovies()); 0118 lay1->addWidget(m_inlineMovies); 0119 0120 m_html5Video = new QCheckBox(i18nc("Tag as in HTML-tag, not as in image tag", "Use HTML5 video tag"), contentPage); 0121 m_html5Video->setChecked(Settings::SettingsData::instance()->HTML5Video()); 0122 lay1->addWidget(m_html5Video); 0123 0124 QString avconv = QStandardPaths::findExecutable(QString::fromUtf8("avconv")); 0125 if (avconv.isNull()) 0126 avconv = QStandardPaths::findExecutable(QString::fromUtf8("ffmpeg")); 0127 const QString ffmpeg2theora = QStandardPaths::findExecutable(QString::fromUtf8("ffmpeg2theora")); 0128 0129 QString txt = i18n("<p>This selection will generate video files suitable for displaying on web. " 0130 "avconv and ffmpeg2theora are required for video file generation.</p>"); 0131 m_html5VideoGenerate = new QCheckBox(i18n("Generate HTML5 video files (mp4 and ogg)"), contentPage); 0132 m_html5VideoGenerate->setChecked(Settings::SettingsData::instance()->HTML5VideoGenerate()); 0133 lay1->addWidget(m_html5VideoGenerate); 0134 m_html5VideoGenerate->setWhatsThis(txt); 0135 if (avconv.isNull() || ffmpeg2theora.isNull()) 0136 m_html5VideoGenerate->setEnabled(false); 0137 0138 // What to include 0139 QGroupBox *whatToInclude = new QGroupBox(i18n("What to Include"), contentPage); 0140 lay1->addWidget(whatToInclude); 0141 QGridLayout *lay3 = new QGridLayout(whatToInclude); 0142 0143 QCheckBox *cb = new QCheckBox(i18n("Description"), whatToInclude); 0144 m_whatToIncludeMap.insert(QString::fromLatin1("**DESCRIPTION**"), cb); 0145 lay3->addWidget(cb, 0, 0); 0146 0147 m_date = new QCheckBox(i18n("Date"), whatToInclude); 0148 m_date->setChecked(Settings::SettingsData::instance()->HTMLDate()); 0149 m_whatToIncludeMap.insert(QString::fromLatin1("**DATE**"), m_date); 0150 lay3->addWidget(m_date, 0, 1); 0151 0152 int row = 1; 0153 int col = 0; 0154 QString selectionsTmp = Settings::SettingsData::instance()->HTMLIncludeSelections(); 0155 QStringMatcher *pattern = new QStringMatcher(); 0156 pattern->setPattern(QString::fromLatin1("**DESCRIPTION**")); 0157 cb->setChecked(pattern->indexIn(selectionsTmp) >= 0 ? 1 : 0); 0158 0159 QList<DB::CategoryPtr> categories = DB::ImageDB::instance()->categoryCollection()->categories(); 0160 for (QList<DB::CategoryPtr>::Iterator it = categories.begin(); it != categories.end(); ++it) { 0161 if (!(*it)->isSpecialCategory()) { 0162 QCheckBox *cb = new QCheckBox((*it)->name(), whatToInclude); 0163 lay3->addWidget(cb, row, col % 2); 0164 m_whatToIncludeMap.insert((*it)->name(), cb); 0165 pattern->setPattern((*it)->name()); 0166 cb->setChecked(pattern->indexIn(selectionsTmp) >= 0 ? 1 : 0); 0167 if (++col % 2 == 0) 0168 ++row; 0169 } 0170 } 0171 } 0172 0173 void HTMLDialog::createLayoutPage() 0174 { 0175 QWidget *layoutPage = new QWidget; 0176 KPageWidgetItem *page = new KPageWidgetItem(layoutPage, i18n("Layout")); 0177 page->setHeader(i18n("Layout")); 0178 page->setIcon(QIcon::fromTheme(QString::fromLatin1("configure"))); 0179 addPage(page); 0180 0181 QVBoxLayout *lay1 = new QVBoxLayout(layoutPage); 0182 QGridLayout *lay2 = new QGridLayout; 0183 lay1->addLayout(lay2); 0184 0185 // Thumbnail size 0186 QLabel *label = new QLabel(i18n("Thumbnail size:"), layoutPage); 0187 lay2->addWidget(label, 0, 0); 0188 0189 QHBoxLayout *lay3 = new QHBoxLayout; 0190 lay2->addLayout(lay3, 0, 1); 0191 0192 m_thumbSize = new QSpinBox; 0193 m_thumbSize->setRange(16, 256); 0194 0195 m_thumbSize->setValue(Settings::SettingsData::instance()->HTMLThumbSize()); 0196 lay3->addWidget(m_thumbSize); 0197 lay3->addStretch(1); 0198 label->setBuddy(m_thumbSize); 0199 0200 // Number of columns 0201 label = new QLabel(i18n("Number of columns:"), layoutPage); 0202 lay2->addWidget(label, 1, 0); 0203 0204 QHBoxLayout *lay4 = new QHBoxLayout; 0205 lay2->addLayout(lay4, 1, 1); 0206 m_numOfCols = new QSpinBox; 0207 m_numOfCols->setRange(1, 10); 0208 0209 label->setBuddy(m_numOfCols); 0210 0211 m_numOfCols->setValue(Settings::SettingsData::instance()->HTMLNumOfCols()); 0212 lay4->addWidget(m_numOfCols); 0213 lay4->addStretch(1); 0214 0215 // Theme box 0216 label = new QLabel(i18n("Theme:"), layoutPage); 0217 lay2->addWidget(label, 2, 0); 0218 lay4 = new QHBoxLayout; 0219 lay2->addLayout(lay4, 2, 1); 0220 m_themeBox = new KComboBox(layoutPage); 0221 label->setBuddy(m_themeBox); 0222 lay4->addWidget(m_themeBox); 0223 lay4->addStretch(1); 0224 m_themeInfo = new QLabel(i18n("Theme Description"), layoutPage); 0225 m_themeInfo->setWordWrap(true); 0226 lay2->addWidget(m_themeInfo, 3, 1); 0227 connect(m_themeBox, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this, &HTMLDialog::displayThemeDescription); 0228 populateThemesCombo(); 0229 0230 // Image sizes 0231 QGroupBox *sizes = new QGroupBox(i18n("Image Sizes"), layoutPage); 0232 lay1->addWidget(sizes); 0233 QGridLayout *lay5 = new QGridLayout(sizes); 0234 ImageSizeCheckBox *size320 = new ImageSizeCheckBox(320, 200, sizes); 0235 ImageSizeCheckBox *size640 = new ImageSizeCheckBox(640, 480, sizes); 0236 ImageSizeCheckBox *size800 = new ImageSizeCheckBox(800, 600, sizes); 0237 ImageSizeCheckBox *size1024 = new ImageSizeCheckBox(1024, 768, sizes); 0238 ImageSizeCheckBox *size1280 = new ImageSizeCheckBox(1280, 1024, sizes); 0239 ImageSizeCheckBox *size1600 = new ImageSizeCheckBox(1600, 1200, sizes); 0240 ImageSizeCheckBox *sizeOrig = new ImageSizeCheckBox(i18n("Full size"), sizes); 0241 0242 { 0243 int row = 0; 0244 int col = -1; 0245 lay5->addWidget(size320, row, ++col); 0246 lay5->addWidget(size640, row, ++col); 0247 lay5->addWidget(size800, row, ++col); 0248 lay5->addWidget(size1024, row, ++col); 0249 col = -1; 0250 lay5->addWidget(size1280, ++row, ++col); 0251 lay5->addWidget(size1600, row, ++col); 0252 lay5->addWidget(sizeOrig, row, ++col); 0253 } 0254 0255 QString tmp; 0256 if ((tmp = Settings::SettingsData::instance()->HTMLSizes()) != QString::fromLatin1("")) { 0257 QStringMatcher *pattern = new QStringMatcher(QString::fromLatin1("320")); 0258 size320->setChecked(pattern->indexIn(tmp) >= 0 ? 1 : 0); 0259 pattern->setPattern(QString::fromLatin1("640")); 0260 size640->setChecked(pattern->indexIn(tmp) >= 0 ? 1 : 0); 0261 pattern->setPattern(QString::fromLatin1("800")); 0262 size800->setChecked(pattern->indexIn(tmp) >= 0 ? 1 : 0); 0263 pattern->setPattern(QString::fromLatin1("1024")); 0264 size1024->setChecked(pattern->indexIn(tmp) >= 0 ? 1 : 0); 0265 pattern->setPattern(QString::fromLatin1("1280")); 0266 size1280->setChecked(pattern->indexIn(tmp) >= 0 ? 1 : 0); 0267 pattern->setPattern(QString::fromLatin1("1600")); 0268 size1600->setChecked(pattern->indexIn(tmp) >= 0 ? 1 : 0); 0269 pattern->setPattern(QString::fromLatin1("-1")); 0270 sizeOrig->setChecked(pattern->indexIn(tmp) >= 0 ? 1 : 0); 0271 } else 0272 size800->setChecked(1); 0273 0274 m_sizeCheckBoxes << size800 << size1024 << size1280 << size640 << size1600 << size320 << sizeOrig; 0275 0276 lay1->addStretch(1); 0277 QGridLayout *lay6 = new QGridLayout; 0278 lay1->addLayout(lay6); 0279 } 0280 0281 void HTMLDialog::createDestinationPage() 0282 { 0283 QWidget *destinationPage = new QWidget; 0284 0285 KPageWidgetItem *page = new KPageWidgetItem(destinationPage, i18n("Destination")); 0286 page->setHeader(i18n("Destination")); 0287 page->setIcon(QIcon::fromTheme(QString::fromLatin1("drive-harddisk"))); 0288 addPage(page); 0289 0290 QVBoxLayout *lay1 = new QVBoxLayout(destinationPage); 0291 QGridLayout *lay2 = new QGridLayout; 0292 lay1->addLayout(lay2); 0293 int row = -1; 0294 0295 // Base Directory 0296 QLabel *label = new QLabel(i18n("Base folder:"), destinationPage); 0297 lay2->addWidget(label, ++row, 0); 0298 QHBoxLayout *lay3 = new QHBoxLayout; 0299 lay2->addLayout(lay3, row, 1); 0300 0301 m_baseDir = new QLineEdit(destinationPage); 0302 lay3->addWidget(m_baseDir); 0303 label->setBuddy(m_baseDir); 0304 0305 QPushButton *but = new QPushButton(QString::fromLatin1(".."), destinationPage); 0306 lay3->addWidget(but); 0307 but->setFixedWidth(25); 0308 0309 connect(but, &QPushButton::clicked, this, &HTMLDialog::selectDir); 0310 m_baseDir->setText(Settings::SettingsData::instance()->HTMLBaseDir()); 0311 0312 // Output Directory 0313 label = new QLabel(i18n("Gallery folder:"), destinationPage); 0314 lay2->addWidget(label, ++row, 0); 0315 m_outputDir = new QLineEdit(destinationPage); 0316 lay2->addWidget(m_outputDir, row, 1); 0317 label->setBuddy(m_outputDir); 0318 0319 // fully "Assembled" output Directory 0320 label = new QLabel(i18n("Output folder:"), destinationPage); 0321 lay2->addWidget(label, ++row, 0); 0322 m_outputLabel = new QLabel(destinationPage); 0323 lay2->addWidget(m_outputLabel, row, 1); 0324 label->setBuddy(m_outputLabel); 0325 connect(m_baseDir, &QLineEdit::textChanged, this, &HTMLDialog::slotUpdateOutputLabel); 0326 connect(m_outputDir, &QLineEdit::textChanged, this, &HTMLDialog::slotUpdateOutputLabel); 0327 // initial text 0328 slotUpdateOutputLabel(); 0329 0330 // Destination URL 0331 label = new QLabel(i18n("URL for final destination of .kim file:"), destinationPage); 0332 label->setToolTip(i18n( 0333 "<p>If you move the gallery to a remote location, set this to the destination URL.</p>" 0334 "<p>This only affects the generated <filename>.kim</filename> file.</p>")); 0335 lay2->addWidget(label, ++row, 0); 0336 m_destURL = new QLineEdit(destinationPage); 0337 m_destURL->setText(Settings::SettingsData::instance()->HTMLDestURL()); 0338 lay2->addWidget(m_destURL, row, 1); 0339 label->setBuddy(m_destURL); 0340 0341 // Base URL 0342 label = new QLabel(i18n("Open gallery in browser:"), destinationPage); 0343 lay2->addWidget(label, ++row, 0); 0344 m_openInBrowser = new QCheckBox(destinationPage); 0345 m_openInBrowser->setChecked(true); 0346 lay2->addWidget(m_openInBrowser, row, 1); 0347 label->setBuddy(m_openInBrowser); 0348 0349 lay1->addStretch(1); 0350 } 0351 0352 void HTMLDialog::slotOk() 0353 { 0354 if (!checkVars()) 0355 return; 0356 0357 if (activeResolutions().count() < 1) { 0358 KMessageBox::error(nullptr, i18n("You must select at least one resolution.")); 0359 return; 0360 } 0361 0362 accept(); 0363 0364 Settings::SettingsData::instance()->setHTMLBaseDir(m_baseDir->text()); 0365 Settings::SettingsData::instance()->setHTMLDestURL(m_destURL->text()); 0366 Settings::SettingsData::instance()->setHTMLCopyright(m_copyright->text()); 0367 Settings::SettingsData::instance()->setHTMLDate(m_date->isChecked()); 0368 Settings::SettingsData::instance()->setHTMLTheme(m_themeBox->currentIndex()); 0369 Settings::SettingsData::instance()->setHTMLKimFile(m_generateKimFile->isChecked()); 0370 Settings::SettingsData::instance()->setHTMLInlineMovies(m_inlineMovies->isChecked()); 0371 Settings::SettingsData::instance()->setHTML5Video(m_html5Video->isChecked()); 0372 Settings::SettingsData::instance()->setHTML5VideoGenerate(m_html5VideoGenerate->isChecked()); 0373 Settings::SettingsData::instance()->setHTMLThumbSize(m_thumbSize->value()); 0374 Settings::SettingsData::instance()->setHTMLNumOfCols(m_numOfCols->value()); 0375 Settings::SettingsData::instance()->setHTMLSizes(activeSizes()); 0376 Settings::SettingsData::instance()->setHTMLIncludeSelections(includeSelections()); 0377 0378 Generator generator(setup(), this); 0379 generator.generate(); 0380 } 0381 0382 void HTMLDialog::selectDir() 0383 { 0384 QString dir = QFileDialog::getExistingDirectory(this, 0385 i18n("Select base folder..."), 0386 m_baseDir->text()); 0387 if (!dir.isEmpty()) 0388 m_baseDir->setText(dir); 0389 } 0390 0391 bool HTMLDialog::checkVars() 0392 { 0393 QString outputDir = m_baseDir->text() + QString::fromLatin1("/") + m_outputDir->text(); 0394 0395 // Ensure base dir is specified 0396 QString baseDir = m_baseDir->text(); 0397 if (baseDir.isEmpty()) { 0398 KMessageBox::error(this, i18n("<p>You did not specify a base folder. " 0399 "This is the topmost folder for your images. " 0400 "Each generated collection will be contained in this folder " 0401 "in separate subfolders.</p>"), 0402 i18n("No Base Folder Specified")); 0403 return false; 0404 } 0405 0406 // ensure output directory is specified 0407 if (m_outputDir->text().isEmpty()) { 0408 KMessageBox::error(this, i18n("<p>You did not specify an output folder. " 0409 "This is a folder containing the actual images. " 0410 "The folder will be a subfolder of the base folder specified above.</p>"), 0411 i18n("No Output Folder Specified")); 0412 return false; 0413 } 0414 0415 // ensure base dir exists 0416 #if KIO_VERSION < QT_VERSION_CHECK(5, 69, 0) 0417 QScopedPointer<KIO::StatJob> statJob(KIO::stat(QUrl::fromUserInput(baseDir), KIO::StatJob::DestinationSide, 1 /*only basic info*/)); 0418 #else 0419 QScopedPointer<KIO::StatJob> statJob(KIO::statDetails(QUrl::fromUserInput(baseDir), KIO::StatJob::DestinationSide, KIO::StatDetail::StatNoDetails)); 0420 #endif 0421 KJobWidgets::setWindow(statJob.data(), MainWindow::Window::theMainWindow()); 0422 if (!statJob->exec()) { 0423 KMessageBox::error(this, i18n("<p>Error while reading information about %1. " 0424 "This is most likely because the folder does not exist.</p>" 0425 "<p>The error message was: %2</p>", 0426 baseDir, statJob->errorString())); 0427 return false; 0428 } 0429 0430 KFileItem fileInfo(statJob->statResult(), QUrl::fromUserInput(baseDir)); 0431 if (!fileInfo.isDir()) { 0432 KMessageBox::error(this, i18n("<p>%1 does not exist, is not a folder or " 0433 "cannot be written to.</p>", 0434 baseDir)); 0435 return false; 0436 } 0437 0438 // test if destination directory exists. 0439 #if KIO_VERSION < QT_VERSION_CHECK(5, 69, 0) 0440 QScopedPointer<KIO::StatJob> existsJob(KIO::stat(QUrl::fromUserInput(outputDir), KIO::StatJob::DestinationSide, 0 /*only minimal info*/)); 0441 #else 0442 QScopedPointer<KIO::StatJob> existsJob(KIO::statDetails(QUrl::fromUserInput(outputDir), KIO::StatJob::DestinationSide, KIO::StatDetail::StatNoDetails)); 0443 #endif 0444 KJobWidgets::setWindow(existsJob.data(), MainWindow::Window::theMainWindow()); 0445 if (existsJob->exec()) { 0446 const QString question = i18n("<p>Output folder %1 already exists. " 0447 "Usually, this means you should specify a new folder.</p>" 0448 "<p>Should %2 be deleted first?</p>", 0449 outputDir, outputDir); 0450 const QString title = i18nc("@title", "Folder Exists"); 0451 const QString dontAskAgainName = QString::fromLatin1("html_export_delete_original_directory"); 0452 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0453 const auto answer = KMessageBox::questionTwoActions(this, 0454 question, 0455 title, 0456 KStandardGuiItem::del(), 0457 KStandardGuiItem::cancel(), dontAskAgainName); 0458 if (answer == KMessageBox::ButtonCode::PrimaryAction) { 0459 #else 0460 int answer = KMessageBox::warningYesNo(this, 0461 question, 0462 title, KStandardGuiItem::yes(), KStandardGuiItem::no(), 0463 dontAskAgainName); 0464 if (answer == KMessageBox::Yes) { 0465 #endif 0466 QScopedPointer<KJob> delJob(KIO::del(QUrl::fromUserInput(outputDir))); 0467 KJobWidgets::setWindow(delJob.data(), MainWindow::Window::theMainWindow()); 0468 delJob->exec(); 0469 } else 0470 return false; 0471 } 0472 return true; 0473 } 0474 0475 QList<ImageSizeCheckBox *> HTMLDialog::activeResolutions() const 0476 { 0477 QList<ImageSizeCheckBox *> res; 0478 for (QList<ImageSizeCheckBox *>::ConstIterator sizeIt = m_sizeCheckBoxes.begin(); sizeIt != m_sizeCheckBoxes.end(); ++sizeIt) { 0479 if ((*sizeIt)->isChecked()) 0480 res << *sizeIt; 0481 } 0482 return res; 0483 } 0484 0485 QString HTMLDialog::activeSizes() const 0486 { 0487 QString res; 0488 for (QList<ImageSizeCheckBox *>::ConstIterator sizeIt = m_sizeCheckBoxes.begin(); sizeIt != m_sizeCheckBoxes.end(); ++sizeIt) { 0489 if ((*sizeIt)->isChecked()) { 0490 if (res.length() > 0) 0491 res.append(QString::fromLatin1(",")); 0492 res.append(QString::number((*sizeIt)->width())); 0493 } 0494 } 0495 return res; 0496 } 0497 0498 QString HTMLDialog::includeSelections() const 0499 { 0500 QString sel; 0501 Setup setupChoices = setup(); 0502 0503 for (QMap<QString, QCheckBox *>::ConstIterator it = m_whatToIncludeMap.begin(); it != m_whatToIncludeMap.end(); ++it) { 0504 QString name = it.key(); 0505 if (setupChoices.includeCategory(name)) { 0506 if (sel.length() > 0) 0507 sel.append(QString::fromLatin1(",")); 0508 sel.append(name); 0509 } 0510 } 0511 return sel; 0512 } 0513 0514 void HTMLDialog::populateThemesCombo() 0515 { 0516 QStringList dirs = QStandardPaths::locateAll( 0517 QStandardPaths::DataLocation, 0518 QString::fromLocal8Bit("themes/"), 0519 QStandardPaths::LocateDirectory); 0520 int i = 0; 0521 int theme = 0; 0522 int defaultthemes = 0; 0523 qCDebug(HTMLGeneratorLog) << "Theme directories:" << dirs; 0524 for (QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it) { 0525 QDir dir(*it); 0526 qCDebug(HTMLGeneratorLog) << "Searching themes in:" << dir; 0527 QStringList themes = dir.entryList(QDir::Dirs | QDir::Readable); 0528 for (QStringList::Iterator it = themes.begin(); it != themes.end(); ++it) { 0529 qCDebug(HTMLGeneratorLog) << " *" << *it; 0530 if (*it == QString::fromLatin1(".") || *it == QString::fromLatin1("..")) 0531 continue; 0532 QString themePath = QString::fromLatin1("%1/%2/").arg(dir.path(), *it); 0533 0534 KConfig themeconfig(QString::fromLatin1("%1/kphotoalbum.theme").arg(themePath), KConfig::SimpleConfig); 0535 KConfigGroup config = themeconfig.group("theme"); 0536 QString themeName = config.readEntry("Name"); 0537 // without the name, we can't show anything useful for the user to choose 0538 if (themeName.trimmed().isEmpty()) 0539 continue; 0540 QString themeAuthor = config.readEntry("Author"); 0541 m_themeAuthors << themeAuthor; // save author to display later 0542 QString themeDefault = config.readEntry("Default"); 0543 QString themeDescription = config.readEntry("Description"); 0544 m_themeDescriptions << themeDescription; // save description to display later 0545 0546 // m_themeBox->insertItem( i, i18n( "%1 (by %2)",themeName, themeAuthor ) ); // combined alternative 0547 m_themeBox->insertItem(i, i18n("%1", themeName)); 0548 m_themes.insert(i, themePath); 0549 0550 if (themeDefault == QString::fromLatin1("true")) { 0551 theme = i; 0552 defaultthemes++; 0553 } 0554 i++; 0555 } 0556 } 0557 if (m_themeBox->count() < 1) { 0558 KMessageBox::error(this, i18n("Could not find any themes - this is very likely an installation error")); 0559 } 0560 if ((Settings::SettingsData::instance()->HTMLTheme() >= 0) && (Settings::SettingsData::instance()->HTMLTheme() < m_themeBox->count())) 0561 m_themeBox->setCurrentIndex(Settings::SettingsData::instance()->HTMLTheme()); 0562 else { 0563 m_themeBox->setCurrentIndex(theme); 0564 if (defaultthemes > 1) 0565 KMessageBox::information(this, i18n("More than one theme is set as default, using theme %1", m_themeBox->currentText())); 0566 } 0567 } 0568 0569 void HTMLDialog::displayThemeDescription(int themenr) 0570 { 0571 // SLOT: update m_themeInfo label whenever the m_theme QComboBox changes. 0572 QString outtxt = i18nc("This is to show the author of the theme. E.g. copyright character (©) by itself will work fine on this context if no proper word is available in your language.", "by "); 0573 outtxt.append(m_themeAuthors[themenr]); 0574 outtxt.append(i18n("\n ")); 0575 outtxt.append(m_themeDescriptions[themenr]); 0576 m_themeInfo->setText(outtxt); 0577 // Instead of two separate lists for authors and descriptions one could have a combined one by appending the text prior to storing within populateThemesCombo(), 0578 // however, storing author and descriptions separately might be cleaner. 0579 } 0580 0581 void HTMLDialog::slotUpdateOutputLabel() 0582 { 0583 QString outputDir = QDir(m_baseDir->text()).filePath(m_outputDir->text()); 0584 auto labelPalette = m_outputLabel->palette(); 0585 // feedback on validity: 0586 if (outputDir == m_baseDir->text()) { 0587 KColorScheme::adjustForeground(labelPalette, KColorScheme::ForegroundRole::NegativeText, QPalette::WindowText); 0588 KColorScheme::adjustBackground(labelPalette, KColorScheme::BackgroundRole::NegativeBackground, QPalette::Window); 0589 outputDir.append(i18n("<p>Gallery folder cannot be empty.</p>")); 0590 } else if (QDir(outputDir).exists()) { 0591 KColorScheme::adjustForeground(labelPalette, KColorScheme::ForegroundRole::NegativeText, QPalette::WindowText); 0592 KColorScheme::adjustBackground(labelPalette, KColorScheme::BackgroundRole::NegativeBackground, QPalette::Window); 0593 outputDir.append(i18n("<p>The output folder already exists.</p>")); 0594 } else { 0595 labelPalette = palette(); 0596 } 0597 m_outputLabel->setPalette(labelPalette); 0598 m_outputLabel->setText(outputDir); 0599 } 0600 0601 void HTMLDialog::slotSuggestOutputDir() 0602 { 0603 if (m_outputDir->text().isEmpty()) { 0604 // the title is often an adequate directory name: 0605 m_outputDir->setText(m_title->text()); 0606 } 0607 } 0608 0609 bool HTMLDialog::event(QEvent *event) 0610 { 0611 if (event->type() == QEvent::PaletteChange) 0612 slotUpdateOutputLabel(); 0613 return KPageDialog::event(event); 0614 } 0615 0616 int HTMLDialog::exec(const DB::FileNameList &list) 0617 { 0618 if (list.empty()) { 0619 qCWarning(HTMLGeneratorLog) << "HTMLDialog called without images for export"; 0620 return false; 0621 } 0622 m_list = list; 0623 return QDialog::exec(); 0624 } 0625 0626 Setup HTMLGenerator::HTMLDialog::setup() const 0627 { 0628 Setup setup; 0629 setup.setTitle(m_title->text()); 0630 setup.setBaseDir(m_baseDir->text()); 0631 if (m_openInBrowser->isEnabled()) { 0632 setup.setBaseURL(m_baseDir->text()); 0633 } 0634 setup.setDestURL(m_destURL->text()); 0635 setup.setOutputDir(m_outputDir->text()); 0636 setup.setThumbSize(m_thumbSize->value()); 0637 setup.setCopyright(m_copyright->text()); 0638 setup.setDate(m_date->isChecked()); 0639 setup.setDescription(m_description->toPlainText()); 0640 setup.setNumOfCols(m_numOfCols->value()); 0641 setup.setGenerateKimFile(m_generateKimFile->isChecked()); 0642 setup.setThemePath(m_themes[m_themeBox->currentIndex()]); 0643 for (QMap<QString, QCheckBox *>::ConstIterator includeIt = m_whatToIncludeMap.begin(); 0644 includeIt != m_whatToIncludeMap.end(); ++includeIt) { 0645 setup.setIncludeCategory(includeIt.key(), includeIt.value()->isChecked()); 0646 } 0647 setup.setImageList(m_list); 0648 0649 setup.setResolutions(activeResolutions()); 0650 setup.setInlineMovies(m_inlineMovies->isChecked()); 0651 setup.setHtml5Video(m_html5Video->isChecked()); 0652 setup.setHtml5VideoGenerate(m_html5VideoGenerate->isChecked()); 0653 return setup; 0654 } 0655 0656 // vi:expandtab:tabstop=4 shiftwidth=4: 0657 0658 #include "moc_HTMLDialog.cpp"