File indexing completed on 2024-04-21 05:30:55

0001 /*
0002     SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "exporttemplatehandler.h"
0007 
0008 // local
0009 #include <coretypes.h>
0010 #include "ui_exporttemplatedialog.h"
0011 #include "exporttemplatedialog.h"
0012 #include "appletsmodel.h"
0013 #include "delegates/normalcheckboxdelegate.h"
0014 #include "../settingsdialog/layoutscontroller.h"
0015 #include "../../lattecorona.h"
0016 #include "../../data/appletdata.h"
0017 #include "../../layout/genericlayout.h"
0018 #include "../../layouts/storage.h"
0019 #include "../../templates/templatesmanager.h"
0020 #include "../../view/view.h"
0021 
0022 // Qt
0023 #include <QAction>
0024 #include <QDir>
0025 #include <QFileDialog>
0026 #include <QFileInfo>
0027 #include <QList>
0028 
0029 // KDE
0030 #include <KLocalizedString>
0031 #include <KMessageBox>
0032 #include <KIO/OpenFileManagerWindowJob>
0033 
0034 // Plasma
0035 #include <Plasma/Containment>
0036 
0037 namespace Latte {
0038 namespace Settings {
0039 namespace Handler {
0040 
0041 ExportTemplateHandler::ExportTemplateHandler(Dialog::ExportTemplateDialog *dialog)
0042     : Generic(dialog),
0043       m_dialog(dialog),
0044       m_ui(m_dialog->ui()),
0045       m_appletsModel(new Model::Applets(this))
0046 {
0047     init();
0048 }
0049 
0050 ExportTemplateHandler::ExportTemplateHandler(Dialog::ExportTemplateDialog *dialog, const Data::Layout &layout)
0051     : ExportTemplateHandler(dialog)
0052 {
0053     loadApplets(layout.id);
0054     m_dialog->setWindowTitle(i18n("Export Layout Template"));
0055     o_filepath = dialog->corona()->templatesManager()->proposedTemplateAbsolutePath(layout.name + ".layout.latte");
0056     setFilepath(o_filepath);
0057 }
0058 
0059 ExportTemplateHandler::ExportTemplateHandler(Dialog::ExportTemplateDialog *dialog, const Data::View &view)
0060     : ExportTemplateHandler(dialog)
0061 {
0062     loadApplets(view.id);
0063     m_dialog->setWindowTitle(i18n("Export Dock/Panel Template"));
0064 
0065     QString viewname = view.name.isEmpty() ? view.originLayout() + " " + i18n("Dock") : view.name;
0066     o_filepath = dialog->corona()->templatesManager()->proposedTemplateAbsolutePath(viewname + ".view.latte");
0067     setFilepath(o_filepath);
0068 }
0069 
0070 ExportTemplateHandler::ExportTemplateHandler(Dialog::ExportTemplateDialog *dialog, Latte::View *view)
0071     : ExportTemplateHandler(dialog)
0072 {
0073     QString type = (view->type() == Latte::Types::PanelView ? i18n("Panel") : i18n("Dock"));
0074 
0075     QString temporiginfile = view->layout()->storedView(view->containment()->id());
0076 
0077     loadApplets(temporiginfile);
0078     m_dialog->setWindowTitle(i18n("Export %1 Template", type));
0079 
0080     QString viewname = view->name().isEmpty() ? view->layout()->name() + " " + type : view->name();
0081 
0082     o_filepath = dialog->corona()->templatesManager()->proposedTemplateAbsolutePath(viewname + ".view.latte");
0083     setFilepath(o_filepath);
0084 }
0085 
0086 ExportTemplateHandler::~ExportTemplateHandler()
0087 {
0088 }
0089 
0090 void ExportTemplateHandler::init()
0091 {
0092     m_ui->appletsTable->horizontalHeader()->setStretchLastSection(true);
0093     m_ui->appletsTable->horizontalHeader()->setSectionsClickable(false);
0094 
0095     m_ui->appletsTable->verticalHeader()->setVisible(false);
0096 
0097     m_ui->appletsTable->setItemDelegateForColumn(Model::Applets::NAMECOLUMN, new Settings::Applets::Delegate::NormalCheckBox(this));
0098 
0099     //! Data Changed
0100     connect(this, &ExportTemplateHandler::filepathChanged, this, &ExportTemplateHandler::dataChanged);
0101     connect(m_appletsModel, &Settings::Model::Applets::appletsDataChanged, this, &ExportTemplateHandler::dataChanged);
0102 
0103     //! Applets Model
0104     m_appletsProxyModel = new QSortFilterProxyModel(this);
0105     m_appletsProxyModel->setSourceModel(m_appletsModel);
0106     m_appletsProxyModel->setSortRole(Model::Applets::SORTINGROLE);
0107     m_appletsProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
0108     //  m_appletsProxyModel->sort(Model::Applets::NAMECOLUMN, Qt::AscendingOrder);
0109 
0110     m_ui->appletsTable->setModel(m_appletsProxyModel);
0111 
0112     //! Buttons
0113     connect(m_ui->deselectAllBtn, &QPushButton::clicked, this, &ExportTemplateHandler::onDeselectAll);
0114     connect(m_ui->selectAllBtn, &QPushButton::clicked, this, &ExportTemplateHandler::onSelectAll);
0115     connect(m_ui->buttonBox->button(QDialogButtonBox::Reset), &QPushButton::clicked, this, &ExportTemplateHandler::reset);
0116 
0117     connect(m_ui->chooseBtn, &QPushButton::clicked, this, &ExportTemplateHandler::chooseFileDialog);
0118     connect(m_dialog->exportButton(), &QPushButton::clicked, this, &ExportTemplateHandler::onExport);
0119 
0120     //! Labels
0121     connect(this, &ExportTemplateHandler::filepathChanged, this, &ExportTemplateHandler::onFilepathChanged);
0122 }
0123 
0124 void ExportTemplateHandler::setFilepath(const QString &filepath)
0125 {
0126     if (c_filepath == filepath) {
0127         return;
0128     }
0129 
0130     c_filepath = filepath;
0131     emit filepathChanged();
0132 }
0133 
0134 void ExportTemplateHandler::loadApplets(const QString &file)
0135 {
0136     m_originFilePath = file;
0137     Data::AppletsTable c_data = Latte::Layouts::Storage::self()->plugins(file);
0138     m_appletsModel->setData(c_data);
0139 }
0140 
0141 void ExportTemplateHandler::chooseFileDialog()
0142 {
0143     QFileInfo currentFile(c_filepath);
0144     bool inLayoutState = c_filepath.endsWith("layout.latte");
0145 
0146     QFileDialog *chooseFileDlg = new QFileDialog(m_dialog,
0147                                                  inLayoutState ? i18n("Choose Layout Template file") : i18n("Choose View Template file"),
0148                                                  currentFile.absoluteFilePath(),
0149                                                  inLayoutState ? QStringLiteral(".layout.latte") : QStringLiteral(".view.latte"));
0150 
0151     chooseFileDlg->setLabelText(QFileDialog::Accept, i18nc("choose file","Choose"));
0152     chooseFileDlg->setFileMode(QFileDialog::AnyFile);
0153     chooseFileDlg->setAcceptMode(QFileDialog::AcceptSave);
0154     if (inLayoutState) {
0155         chooseFileDlg->setDefaultSuffix("layout.latte");
0156     } else {
0157         chooseFileDlg->setDefaultSuffix("view.latte");
0158     }
0159 
0160     QStringList filters;
0161 
0162     if (inLayoutState) {
0163         filters << QString(i18nc("layout template", "Latte Dock Layout Template file v0.2") + "(*.layout.latte)");
0164     } else {
0165         filters << QString(i18nc("view template", "Latte Dock View Template file v0.2") + "(*.view.latte)");
0166     }
0167 
0168     chooseFileDlg->setNameFilters(filters);
0169 
0170     connect(chooseFileDlg, &QFileDialog::finished, chooseFileDlg, &QFileDialog::deleteLater);
0171     connect(chooseFileDlg, &QFileDialog::fileSelected, this, [&, inLayoutState](const QString &file) {
0172         if (inLayoutState) {
0173             if (!file.endsWith(".layout.latte")) {
0174                 QString selected = file;
0175                 selected = selected.replace(QDir::homePath(), "~");
0176                 showInlineMessage(i18n("<i>%1</i> does not end with <i>.layout.latte</i> extension. Selected file <b>rejected</b>.", selected),
0177                                   KMessageWidget::Error,
0178                                   true);
0179             } else {
0180                 setFilepath(file);
0181             }
0182         } else {
0183             if (!file.endsWith(".view.latte")) {
0184                 QString selected = file;
0185                 selected = selected.replace(QDir::homePath(), "~");
0186                 showInlineMessage(i18n("<i>%1</i> does not end with <i>.view.latte</i> extension. Selected file <b>rejected</b>.", selected),
0187                                   KMessageWidget::Error,
0188                                   true);
0189             } else {
0190                 setFilepath(file);
0191             }
0192         }
0193     });
0194 
0195     chooseFileDlg->open();
0196     chooseFileDlg->selectFile(currentFile.fileName());
0197 }
0198 
0199 void ExportTemplateHandler::onExport()
0200 {
0201     QString curbasename = QFileInfo(c_filepath).baseName();
0202     QString curfilename = QFileInfo(c_filepath).fileName();
0203 
0204     //! Confirm Overwrite if that is the case
0205     if (QFile(c_filepath).exists()) {
0206         if (!overwriteConfirmation(curfilename)) {
0207             return;
0208         }
0209     }
0210 
0211     //! Proceed with export
0212     auto showExportTemplateError = [this](const QString &templateName) {
0213         showInlineMessage(i18nc("settings:template export fail","Template <b>%1</b> export <b>failed</b>...", templateName),
0214                           KMessageWidget::Error,
0215                           true);
0216     };
0217 
0218     bool result = m_dialog->corona()->templatesManager()->exportTemplate(m_originFilePath,
0219                                                                          c_filepath,
0220                                                                          m_appletsModel->selectedApplets());
0221     if (result) {
0222         QAction *openUrlAction = new QAction(i18n("Open Location..."), this);
0223         openUrlAction->setIcon(QIcon::fromTheme("document-open"));
0224         openUrlAction->setData(c_filepath);
0225         QList<QAction *> actions;
0226         actions << openUrlAction;
0227 
0228         connect(openUrlAction, &QAction::triggered, this, [&, openUrlAction]() {
0229             QString file = openUrlAction->data().toString();
0230 
0231             if (!file.isEmpty()) {
0232                 KIO::highlightInFileManager({file});
0233             }
0234         });
0235 
0236         showInlineMessage(i18nc("settings:template export success","Template <b>%1</b> export succeeded...", curbasename),
0237                           KMessageWidget::Positive,
0238                           false,
0239                           actions);
0240 
0241         emit exportSucceeded();
0242     } else {
0243         showExportTemplateError(QFileInfo(c_filepath).baseName());
0244     }
0245 }
0246 
0247 void ExportTemplateHandler::onFilepathChanged()
0248 {
0249     QString filepath = c_filepath;
0250 
0251     filepath = filepath.replace(QDir::homePath(), "~");
0252     m_ui->fileLbl->setText(filepath);
0253 }
0254 
0255 void ExportTemplateHandler::onSelectAll()
0256 {
0257     m_appletsModel->selectAll();
0258 
0259 }
0260 
0261 void ExportTemplateHandler::onDeselectAll()
0262 {
0263     m_appletsModel->deselectAll();
0264 }
0265 
0266 bool ExportTemplateHandler::hasChangedData() const
0267 {
0268     return (c_filepath != o_filepath) || m_appletsModel->hasChangedData();
0269 }
0270 
0271 bool ExportTemplateHandler::inDefaultValues() const
0272 {
0273     return (c_filepath == o_filepath) && m_appletsModel->inDefaultValues();
0274 }
0275 
0276 void ExportTemplateHandler::reset()
0277 {
0278     setFilepath(o_filepath);
0279 
0280     if (m_appletsModel->hasChangedData()) {
0281         m_appletsModel->reset();
0282     }
0283 }
0284 
0285 void ExportTemplateHandler::resetDefaults()
0286 {
0287     reset();
0288 }
0289 
0290 void ExportTemplateHandler::save()
0291 {
0292     //do nothing
0293 }
0294 
0295 bool ExportTemplateHandler::overwriteConfirmation(const QString &fileName)
0296 {
0297     return (KMessageBox::warningYesNo(m_dialog,
0298                                       i18n("The file \"%1\" already exists. Do you wish to overwrite it?", fileName),
0299                                       i18n("Overwrite File?"),
0300                                       KStandardGuiItem::overwrite(),
0301                                       KStandardGuiItem::cancel()) == KMessageBox::Yes);
0302 }
0303 
0304 }
0305 }
0306 }