File indexing completed on 2024-05-12 05:13:28

0001 /*
0002    SPDX-FileCopyrightText: 2015-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "themeeditormainwindow.h"
0008 #include "contactprintthemeconfiguredialog.h"
0009 #include "managethemes.h"
0010 #include "newthemedialog.h"
0011 #include "themeeditorpage.h"
0012 
0013 #include <KActionCollection>
0014 #include <KConfigGroup>
0015 #include <KLocalizedString>
0016 #include <KMessageBox>
0017 #include <KRecentFilesAction>
0018 #include <KStandardAction>
0019 #include <QAction>
0020 #include <QFileDialog>
0021 
0022 #include <KAuthorized>
0023 #include <KSharedConfig>
0024 #include <QApplication>
0025 #include <QCloseEvent>
0026 #include <QPointer>
0027 #include <QStandardPaths>
0028 
0029 ThemeEditorMainWindow::ThemeEditorMainWindow()
0030     : KXmlGuiWindow()
0031 {
0032     setupActions();
0033     setupGUI();
0034     updateActions();
0035     readConfig();
0036 }
0037 
0038 ThemeEditorMainWindow::~ThemeEditorMainWindow() = default;
0039 
0040 void ThemeEditorMainWindow::writeConfig()
0041 {
0042     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0043 
0044     KConfigGroup group = config->group(QStringLiteral("ThemeEditorMainWindow"));
0045     group.writeEntry("Size", size());
0046     mRecentFileAction->saveEntries(group);
0047 }
0048 
0049 void ThemeEditorMainWindow::readConfig()
0050 {
0051     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0052     KConfigGroup group = KConfigGroup(config, QStringLiteral("ThemeEditorMainWindow"));
0053     const QSize sizeDialog = group.readEntry("Size", QSize(600, 400));
0054     if (sizeDialog.isValid()) {
0055         resize(sizeDialog);
0056     }
0057 }
0058 
0059 void ThemeEditorMainWindow::updateActions()
0060 {
0061     const bool projectDirectoryIsEmpty = (mThemeEditor != nullptr);
0062     mAddExtraPage->setEnabled(projectDirectoryIsEmpty);
0063     mCloseAction->setEnabled(projectDirectoryIsEmpty);
0064     if (mUploadTheme) {
0065         mUploadTheme->setEnabled(projectDirectoryIsEmpty);
0066     }
0067     mSaveAction->setEnabled(projectDirectoryIsEmpty);
0068     mInstallTheme->setEnabled(projectDirectoryIsEmpty);
0069     mInsertFile->setEnabled(projectDirectoryIsEmpty);
0070     mUpdateView->setEnabled(projectDirectoryIsEmpty);
0071     mSaveAsAction->setEnabled(projectDirectoryIsEmpty);
0072 }
0073 
0074 void ThemeEditorMainWindow::setupActions()
0075 {
0076     mRecentFileAction = new KRecentFilesAction(i18n("Load Recent Theme..."), this);
0077     connect(mRecentFileAction, &KRecentFilesAction::urlSelected, this, &ThemeEditorMainWindow::slotThemeSelected);
0078     actionCollection()->addAction(QStringLiteral("load_recent_theme"), mRecentFileAction);
0079     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0080     KConfigGroup groupConfig = config->group(QStringLiteral("ThemeEditorMainWindow"));
0081     mRecentFileAction->loadEntries(groupConfig);
0082 
0083     mAddExtraPage = new QAction(i18n("Add Extra Page..."), this);
0084     connect(mAddExtraPage, &QAction::triggered, this, &ThemeEditorMainWindow::slotAddExtraPage);
0085     actionCollection()->addAction(QStringLiteral("add_extra_page"), mAddExtraPage);
0086     if (KAuthorized::authorize(QStringLiteral("ghns"))) {
0087         mUploadTheme = new QAction(QIcon::fromTheme(QStringLiteral("get-hot-new-stuff")), i18n("Upload theme..."), this);
0088         connect(mUploadTheme, &QAction::triggered, this, &ThemeEditorMainWindow::slotUploadTheme);
0089         actionCollection()->addAction(QStringLiteral("upload_theme"), mUploadTheme);
0090     }
0091 
0092     mNewThemeAction = KStandardAction::openNew(this, &ThemeEditorMainWindow::slotNewTheme, actionCollection());
0093     mNewThemeAction->setText(i18n("New theme..."));
0094 
0095     mOpenAction = KStandardAction::open(this, &ThemeEditorMainWindow::slotOpenTheme, actionCollection());
0096     mOpenAction->setText(i18n("Open theme..."));
0097     mSaveAction = KStandardAction::save(this, &ThemeEditorMainWindow::slotSaveTheme, actionCollection());
0098     mSaveAction->setText(i18n("Save theme"));
0099 
0100     mSaveAsAction = KStandardAction::saveAs(this, &ThemeEditorMainWindow::slotSaveAsTheme, actionCollection());
0101     mSaveAsAction->setText(i18n("Save theme as..."));
0102 
0103     mCloseAction = KStandardAction::close(this, &ThemeEditorMainWindow::slotCloseTheme, actionCollection());
0104     KStandardAction::quit(this, &ThemeEditorMainWindow::slotQuitApp, actionCollection());
0105     KStandardAction::preferences(this, &ThemeEditorMainWindow::slotConfigure, actionCollection());
0106 
0107     mInstallTheme = new QAction(i18n("Install theme"), this);
0108     actionCollection()->addAction(QStringLiteral("install_theme"), mInstallTheme);
0109     connect(mInstallTheme, &QAction::triggered, this, &ThemeEditorMainWindow::slotInstallTheme);
0110 
0111     mInsertFile = new QAction(i18n("Insert File..."), this);
0112     actionCollection()->addAction(QStringLiteral("insert_file"), mInsertFile);
0113     connect(mInsertFile, &QAction::triggered, this, &ThemeEditorMainWindow::slotInsertFile);
0114 
0115     mManageTheme = new QAction(i18n("Manage themes..."), this);
0116     connect(mManageTheme, &QAction::triggered, this, &ThemeEditorMainWindow::slotManageTheme);
0117     actionCollection()->addAction(QStringLiteral("manage_themes"), mManageTheme);
0118 
0119     mUpdateView = new QAction(QIcon::fromTheme(QStringLiteral("view-refresh")), i18n("Update view"), this);
0120     actionCollection()->setDefaultShortcut(mUpdateView, QKeySequence(Qt::Key_F5));
0121     connect(mUpdateView, &QAction::triggered, this, &ThemeEditorMainWindow::slotUpdateView);
0122     actionCollection()->addAction(QStringLiteral("update_view"), mUpdateView);
0123 }
0124 
0125 void ThemeEditorMainWindow::slotManageTheme()
0126 {
0127     QPointer<GrantleeThemeEditor::ManageThemes> dialog = new GrantleeThemeEditor::ManageThemes(QStringLiteral("kaddressbook/printing/themes/"), this);
0128     dialog->exec();
0129     delete dialog;
0130 }
0131 
0132 void ThemeEditorMainWindow::slotInsertFile()
0133 {
0134     mThemeEditor->insertFile();
0135 }
0136 
0137 void ThemeEditorMainWindow::slotConfigure()
0138 {
0139     QPointer<ContactPrintThemeConfigureDialog> dialog = new ContactPrintThemeConfigureDialog(this);
0140     if (dialog->exec()) {
0141         if (mThemeEditor) {
0142             mThemeEditor->reloadConfig();
0143         }
0144     }
0145     delete dialog;
0146 }
0147 
0148 void ThemeEditorMainWindow::slotInstallTheme()
0149 {
0150     // Save before installing :)
0151     if (slotSaveTheme()) {
0152         const QString localThemePath =
0153             QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1StringView("/kaddressbook/printing/themes");
0154         if (QDir().mkpath(localThemePath)) {
0155             mThemeEditor->installTheme(localThemePath);
0156         }
0157     }
0158 }
0159 
0160 void ThemeEditorMainWindow::slotUploadTheme()
0161 {
0162     // Save before upload :)
0163     if (slotSaveTheme()) {
0164         mThemeEditor->uploadTheme();
0165     }
0166 }
0167 
0168 bool ThemeEditorMainWindow::slotSaveTheme()
0169 {
0170     bool result = false;
0171     if (mThemeEditor) {
0172         result = mThemeEditor->saveTheme(false);
0173         mSaveAction->setEnabled(!result);
0174     }
0175     return result;
0176 }
0177 
0178 void ThemeEditorMainWindow::slotCloseTheme()
0179 {
0180     saveCurrentProject(SaveAndCloseTheme);
0181 }
0182 
0183 void ThemeEditorMainWindow::slotOpenTheme()
0184 {
0185     if (!saveCurrentProject(SaveOnly)) {
0186         return;
0187     }
0188 
0189     const QString directory = QFileDialog::getExistingDirectory(this, i18n("Select theme directory"));
0190     if (directory.isEmpty()) {
0191         return;
0192     }
0193     closeThemeEditor();
0194     if (loadTheme(directory)) {
0195         mRecentFileAction->addUrl(QUrl::fromLocalFile(directory));
0196     }
0197     mSaveAction->setEnabled(false);
0198 }
0199 
0200 bool ThemeEditorMainWindow::loadTheme(const QString &directory)
0201 {
0202     if (!directory.isEmpty()) {
0203         const QString filename = directory + QLatin1StringView("/theme.themerc");
0204         if (!QFileInfo::exists(filename)) {
0205             KMessageBox::error(this, i18n("Directory does not contain a theme file. We cannot load theme."));
0206             return false;
0207         }
0208 
0209         mThemeEditor = new ThemeEditorPage(QString(), QString());
0210         connect(mThemeEditor, &ThemeEditorPage::changed, mSaveAction, &QAction::setEnabled);
0211         connect(mThemeEditor, &ThemeEditorPage::canInsertFile, this, &ThemeEditorMainWindow::slotCanInsertFile);
0212         mThemeEditor->loadTheme(filename);
0213         setCentralWidget(mThemeEditor);
0214         updateActions();
0215     }
0216     return true;
0217 }
0218 
0219 void ThemeEditorMainWindow::slotAddExtraPage()
0220 {
0221     if (mThemeEditor) {
0222         mThemeEditor->addExtraPage();
0223     }
0224 }
0225 
0226 void ThemeEditorMainWindow::closeThemeEditor()
0227 {
0228     delete mThemeEditor;
0229     mThemeEditor = nullptr;
0230     setCentralWidget(nullptr);
0231     updateActions();
0232 }
0233 
0234 bool ThemeEditorMainWindow::saveCurrentProject(ActionSaveTheme act)
0235 {
0236     if (mThemeEditor) {
0237         if (!mThemeEditor->saveTheme()) {
0238             return false;
0239         }
0240     }
0241     switch (act) {
0242     case SaveOnly:
0243         break;
0244     case SaveAndCloseTheme:
0245         closeThemeEditor();
0246         break;
0247     case SaveAndCreateNewTheme: {
0248         delete mThemeEditor;
0249         mThemeEditor = nullptr;
0250         QPointer<GrantleeThemeEditor::NewThemeDialog> dialog = new GrantleeThemeEditor::NewThemeDialog(this);
0251         QString newTheme;
0252         QString projectDirectory;
0253         if (dialog->exec()) {
0254             newTheme = dialog->themeName();
0255             projectDirectory = dialog->directory();
0256         }
0257         if (!projectDirectory.isEmpty()) {
0258             mRecentFileAction->addUrl(QUrl::fromLocalFile(projectDirectory));
0259             mThemeEditor = new ThemeEditorPage(projectDirectory, newTheme);
0260             connect(mThemeEditor, &ThemeEditorPage::changed, mSaveAction, &QAction::setEnabled);
0261             connect(mThemeEditor, &ThemeEditorPage::canInsertFile, this, &ThemeEditorMainWindow::slotCanInsertFile);
0262             setCentralWidget(mThemeEditor);
0263         } else {
0264             setCentralWidget(nullptr);
0265         }
0266         delete dialog;
0267         updateActions();
0268         break;
0269     }
0270     }
0271 
0272     return true;
0273 }
0274 
0275 void ThemeEditorMainWindow::slotNewTheme()
0276 {
0277     saveCurrentProject(SaveAndCreateNewTheme);
0278 }
0279 
0280 void ThemeEditorMainWindow::closeEvent(QCloseEvent *e)
0281 {
0282     if (!saveCurrentProject(SaveAndCloseTheme)) {
0283         e->ignore();
0284     } else {
0285         writeConfig();
0286         e->accept();
0287     }
0288 }
0289 
0290 void ThemeEditorMainWindow::slotQuitApp()
0291 {
0292     if (saveCurrentProject(SaveAndCloseTheme)) {
0293         writeConfig();
0294         qApp->quit();
0295     }
0296 }
0297 
0298 void ThemeEditorMainWindow::slotUpdateView()
0299 {
0300     if (mThemeEditor) {
0301         mThemeEditor->saveTheme(false);
0302         mThemeEditor->updatePreview();
0303     }
0304 }
0305 
0306 void ThemeEditorMainWindow::slotCanInsertFile(bool b)
0307 {
0308     mInsertFile->setEnabled(b);
0309 }
0310 
0311 void ThemeEditorMainWindow::slotThemeSelected(const QUrl &url)
0312 {
0313     if (!saveCurrentProject(SaveAndCloseTheme)) {
0314         return;
0315     }
0316     loadTheme(url.path());
0317     mSaveAction->setEnabled(false);
0318 }
0319 
0320 void ThemeEditorMainWindow::slotSaveAsTheme()
0321 {
0322     const QString directory = QFileDialog::getExistingDirectory(this, i18n("Select theme directory"));
0323     if (!directory.isEmpty()) {
0324         if (mThemeEditor) {
0325             mThemeEditor->saveThemeAs(directory);
0326         }
0327     }
0328 }
0329 
0330 #include "moc_themeeditormainwindow.cpp"