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