File indexing completed on 2024-05-12 04:06:22
0001 /* 0002 SPDX-FileCopyrightText: 2009, 2010 Stefan Majewsky <majewsky@gmx.net> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "puzzlecreator.h" 0008 #include "slicerconfwidget.h" 0009 #include "file-io/components.h" 0010 #include "file-io/puzzle.h" 0011 #include "file-io/puzzlestructs.h" 0012 0013 #include <Pala/Slicer> 0014 #include <Pala/SlicerJob> 0015 #include <Pala/SlicerMode> 0016 0017 #include <QFormLayout> 0018 #include <QLabel> 0019 #include <QStackedWidget> 0020 #include <QUuid> 0021 #include <QImageReader> 0022 0023 #include <KLineEdit> 0024 #include <KLocalizedString> 0025 #include <KMessageBox> 0026 #include <KUrlRequester> 0027 0028 Palapeli::PuzzleCreatorDialog::PuzzleCreatorDialog() 0029 : m_result(nullptr) 0030 , m_imageSelector(new KUrlRequester) 0031 , m_nameEdit(new KLineEdit) 0032 , m_commentEdit(new KLineEdit) 0033 , m_authorEdit(new KLineEdit) 0034 , m_slicerSelector(new Palapeli::SlicerSelector) 0035 , m_slicerConfigMasterWidget(new QStackedWidget) 0036 { 0037 //setup dialog 0038 setWindowTitle(i18nc("@title:window", "Create New Puzzle")); 0039 buttonBox()->button(QDialogButtonBox::Help)->setVisible(false); 0040 //setup image selector 0041 m_imageSelector->setMode(KFile::File | KFile::LocalOnly | KFile::ExistingOnly); 0042 const auto supportedImageTypes = QImageReader::supportedMimeTypes(); 0043 QStringList mimeTypeFilters; 0044 mimeTypeFilters.reserve(supportedImageTypes.size()); 0045 for (const auto& imageType : supportedImageTypes) { 0046 mimeTypeFilters.append(QString::fromUtf8(imageType)); 0047 } 0048 m_imageSelector->setMimeTypeFilters(mimeTypeFilters); 0049 //build sublayouts 0050 QFormLayout* sourceLayout = new QFormLayout; 0051 sourceLayout->addRow(i18nc("@label:chooser", "Image file:"), m_imageSelector); 0052 sourceLayout->addRow(new QLabel(i18nc("@info", "Please describe below the image which you have chosen."))); 0053 sourceLayout->addRow(i18nc("@label:textbox", "Image name:"), m_nameEdit); 0054 sourceLayout->addRow(i18nc("@label:textbox (like in: This comment is optional.)", "Optional comment:"), m_commentEdit); 0055 sourceLayout->addRow(i18nc("@label:textbox", "Name of image author:"), m_authorEdit); 0056 const auto slicers = m_slicerSelector->slicers(); 0057 for (const Pala::Slicer* slicer : slicers) 0058 { 0059 m_slicerConfigWidgets[slicer] = new Palapeli::SlicerConfigWidget(slicer); 0060 m_slicerConfigMasterWidget->addWidget(m_slicerConfigWidgets[slicer]); 0061 } 0062 //build page widget items 0063 m_sourcePage = addPage(new QWidget, i18nc("@item:inlistbox (page name in an assistant dialog)", "Choose image")); 0064 m_sourcePage->setHeader(i18nc("@title:tab (page header in an assistant dialog)", "Specify the source image to be sliced into pieces")); 0065 m_sourcePage->widget()->setLayout(sourceLayout); 0066 m_slicerPage = addPage(m_slicerSelector, i18nc("@item:inlistbox (page name in an assistant dialog)", "Choose slicer")); 0067 m_slicerPage->setHeader(i18nc("@title:tab (page header in an assistant dialog)", "Choose a slicing method")); 0068 m_slicerConfigPage = addPage(m_slicerConfigMasterWidget, i18nc("@item:inlistbox (page name in an assistant dialog)", "Configure slicer")); 0069 m_slicerConfigPage->setHeader(i18nc("@title:tab (page header in an assistant dialog)", "Tweak the parameters of the chosen slicing method")); 0070 //wire up stuff 0071 connect(this, &PuzzleCreatorDialog::accepted, this, &PuzzleCreatorDialog::createPuzzle); 0072 connect(m_imageSelector, &KUrlRequester::urlSelected, this, &PuzzleCreatorDialog::checkData); 0073 connect(m_nameEdit, &KLineEdit::textChanged, this, &PuzzleCreatorDialog::checkData); 0074 connect(m_authorEdit, &KLineEdit::textChanged, this, &PuzzleCreatorDialog::checkData); 0075 checkData(); //to invalidate first page 0076 setValid(m_slicerPage, false); 0077 connect(m_slicerSelector, &Palapeli::SlicerSelector::currentSelectionChanged, this, &PuzzleCreatorDialog::updateSlicerSelection); 0078 } 0079 0080 Palapeli::Puzzle* Palapeli::PuzzleCreatorDialog::result() const 0081 { 0082 return m_result; 0083 } 0084 0085 void Palapeli::PuzzleCreatorDialog::checkData() 0086 { 0087 bool sourceValid = !m_imageSelector->url().isEmpty(); 0088 sourceValid &= !m_nameEdit->text().isEmpty(); 0089 sourceValid &= !m_authorEdit->text().isEmpty(); 0090 setValid(m_sourcePage, sourceValid); 0091 } 0092 0093 void Palapeli::PuzzleCreatorDialog::updateSlicerSelection(const Palapeli::SlicerSelection& selection) 0094 { 0095 setValid(m_slicerPage, (bool) selection.slicer); 0096 if (!selection.slicer) return; 0097 //update slicer configuration widget 0098 Palapeli::SlicerConfigWidget* scWidget = m_slicerConfigWidgets.value(selection.slicer); 0099 scWidget->setMode(selection.mode); 0100 m_slicerConfigMasterWidget->setCurrentWidget(scWidget); 0101 } 0102 0103 void Palapeli::PuzzleCreatorDialog::createPuzzle() 0104 { 0105 if (m_result) 0106 return; //We won't create the puzzle if there is one already. 0107 //assemble data for creation context 0108 const Palapeli::SlicerSelection selection = m_slicerSelector->currentSelection(); 0109 const Pala::Slicer* slicer = selection.slicer; 0110 if (!slicer) 0111 { 0112 KMessageBox::error(this, i18n("Puzzle cannot be created: The slicer plugin could not be loaded.")); 0113 return; 0114 } 0115 QMap<QByteArray, QVariant> slicerArgs = m_slicerConfigWidgets[selection.slicer]->arguments(); 0116 QImage image; 0117 if (!image.load(m_imageSelector->url().toLocalFile())) 0118 { 0119 KMessageBox::error(this, i18n("Puzzle cannot be created: The file you selected is not an image.")); 0120 return; 0121 } 0122 image = image.convertToFormat(image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32); 0123 Pala::SlicerJob job(image, slicerArgs); 0124 job.setMode(selection.mode); 0125 if (!const_cast<Pala::Slicer*>(slicer)->process(&job)) //BIC: make Pala::Slicer::process() and run() const 0126 { 0127 KMessageBox::error(this, i18n("Puzzle cannot be created: Slicing failed because of undetermined problems.")); 0128 return; 0129 } 0130 //create puzzle creation context 0131 Palapeli::PuzzleCreationContext creationContext; 0132 creationContext.name = m_nameEdit->text(); 0133 creationContext.comment = m_commentEdit->text(); 0134 creationContext.author = m_authorEdit->text(); 0135 creationContext.pieceCount = job.pieces().count(); 0136 creationContext.image = image; 0137 creationContext.thumbnail = image.scaled(Palapeli::PuzzleMetadata::ThumbnailBaseSize, Qt::KeepAspectRatio); 0138 creationContext.modifyProtection = false; //only enabled for default puzzles 0139 creationContext.slicer = selection.slicerPluginName; 0140 creationContext.slicerMode = selection.mode ? selection.mode->key() : QByteArray(); 0141 creationContext.slicerArgs = slicerArgs; 0142 //create puzzle 0143 m_result = new Palapeli::Puzzle(new Palapeli::CreationContextComponent(creationContext), QString(), QUuid::createUuid().toString()); 0144 } 0145 0146 #include "moc_puzzlecreator.cpp"