File indexing completed on 2024-05-12 05:13:29
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 "themeeditorpage.h" 0008 #include "contactprintthemepreview.h" 0009 #include "desktopfilepage.h" 0010 #include "editorpage.h" 0011 #include "themeeditortabwidget.h" 0012 #include "themeeditorwidget.h" 0013 #include "themesession.h" 0014 0015 #include "contactprintthemeeditor_debug.h" 0016 #include <KLocalizedString> 0017 #include <KMessageBox> 0018 #include <KZip> 0019 #include <QInputDialog> 0020 #include <QTemporaryDir> 0021 #include <QUrl> 0022 0023 #include <QDir> 0024 #include <QFileDialog> 0025 #include <QHBoxLayout> 0026 #include <QPointer> 0027 0028 ThemeEditorPage::ThemeEditorPage(const QString &projectDir, const QString &themeName, QWidget *parent) 0029 : QWidget(parent) 0030 , mThemeSession(new GrantleeThemeEditor::ThemeSession(projectDir, QStringLiteral("headerthemeeditor"))) 0031 { 0032 auto lay = new QHBoxLayout(this); 0033 mTabWidget = new GrantleeThemeEditor::ThemeEditorTabWidget; 0034 connect(mTabWidget, &GrantleeThemeEditor::ThemeEditorTabWidget::currentChanged, this, &ThemeEditorPage::slotCurrentWidgetChanged); 0035 lay->addWidget(mTabWidget); 0036 mEditorPage = new EditorPage(EditorPage::MainPage, projectDir); 0037 mEditorPage->setPageFileName(QStringLiteral("theme.html")); 0038 connect(mEditorPage, &EditorPage::needUpdateViewer, this, &ThemeEditorPage::slotUpdateViewer); 0039 connect(mEditorPage, &EditorPage::changed, this, &ThemeEditorPage::slotChanged); 0040 mTabWidget->addTab(mEditorPage, i18n("Editor (%1)", QStringLiteral("theme.html"))); 0041 0042 GrantleeThemeEditor::DesktopFilePage::DesktopFileOptions opt; 0043 mDesktopPage = new GrantleeThemeEditor::DesktopFilePage(QStringLiteral("theme.html"), opt, this); 0044 mDesktopPage->setDefaultDesktopName(QStringLiteral("theme.desktop")); 0045 mDesktopPage->setThemeName(themeName); 0046 mTabWidget->addTab(mDesktopPage, i18n("Desktop File")); 0047 0048 connect(mDesktopPage, 0049 &GrantleeThemeEditor::DesktopFilePage::mainFileNameChanged, 0050 mEditorPage->preview(), 0051 &GrantleeThemeEditor::PreviewWidget::slotMainFileNameChanged); 0052 connect(mDesktopPage, 0053 &GrantleeThemeEditor::DesktopFilePage::mainFileNameChanged, 0054 mTabWidget, 0055 &GrantleeThemeEditor::ThemeEditorTabWidget::slotMainFileNameChanged); 0056 connect(mDesktopPage, &GrantleeThemeEditor::DesktopFilePage::changed, this, &ThemeEditorPage::slotChanged); 0057 connect(mTabWidget, &GrantleeThemeEditor::ThemeEditorTabWidget::tabCloseRequested, this, &ThemeEditorPage::slotCloseTab); 0058 } 0059 0060 ThemeEditorPage::~ThemeEditorPage() 0061 { 0062 qDeleteAll(mExtraPage); 0063 mExtraPage.clear(); 0064 delete mThemeSession; 0065 } 0066 0067 void ThemeEditorPage::slotCurrentWidgetChanged(int index) 0068 { 0069 if (index < 0) { 0070 return; 0071 } 0072 auto page = dynamic_cast<GrantleeThemeEditor::EditorPage *>(mTabWidget->widget(index)); 0073 Q_EMIT canInsertFile(page); 0074 } 0075 0076 void ThemeEditorPage::updatePreview() 0077 { 0078 mEditorPage->preview()->updateViewer(); 0079 } 0080 0081 void ThemeEditorPage::slotChanged() 0082 { 0083 setChanged(true); 0084 } 0085 0086 void ThemeEditorPage::setChanged(bool b) 0087 { 0088 if (mChanged != b) { 0089 mChanged = b; 0090 Q_EMIT changed(b); 0091 } 0092 } 0093 0094 void ThemeEditorPage::slotUpdateViewer() 0095 { 0096 if (themeWasChanged()) { 0097 saveTheme(false); 0098 } 0099 mEditorPage->preview()->updateViewer(); 0100 } 0101 0102 void ThemeEditorPage::slotCloseTab(int index) 0103 { 0104 mTabWidget->removeTab(index); 0105 setChanged(true); 0106 } 0107 0108 void ThemeEditorPage::insertFile() 0109 { 0110 QWidget *w = mTabWidget->currentWidget(); 0111 if (!w) { 0112 return; 0113 } 0114 auto page = dynamic_cast<GrantleeThemeEditor::EditorPage *>(w); 0115 if (page) { 0116 const QString fileName = QFileDialog::getOpenFileName(this); 0117 if (!fileName.isEmpty()) { 0118 page->insertFile(fileName); 0119 } 0120 } 0121 } 0122 0123 bool ThemeEditorPage::themeWasChanged() const 0124 { 0125 return mChanged; 0126 } 0127 0128 void ThemeEditorPage::installTheme(const QString &themePath) 0129 { 0130 QDir dir(themePath); 0131 QDir themeDir(themePath + QLatin1Char('/') + mDesktopPage->themeName()); 0132 if (themeDir.exists()) { 0133 const int answer = KMessageBox::questionTwoActions(this, 0134 i18n("Theme already exists. Do you want to overwrite it?"), 0135 i18n("Theme already exists"), 0136 KStandardGuiItem::overwrite(), 0137 KStandardGuiItem::cancel()); 0138 if (answer == KMessageBox::ButtonCode::SecondaryAction) { 0139 return; 0140 } 0141 } else { 0142 if (!dir.mkdir(mDesktopPage->themeName())) { 0143 KMessageBox::error(this, i18n("Cannot create theme folder.")); 0144 return; 0145 } 0146 } 0147 const QString newPath = themePath + QLatin1Char('/') + mDesktopPage->themeName(); 0148 mEditorPage->installTheme(newPath); 0149 for (EditorPage *page : std::as_const(mExtraPage)) { 0150 page->installTheme(newPath); 0151 } 0152 mDesktopPage->installTheme(newPath); 0153 KMessageBox::information(this, i18n("Theme installed in \"%1\"", themeDir.absolutePath())); 0154 } 0155 0156 void ThemeEditorPage::uploadTheme() 0157 { 0158 #if 0 0159 // force update for screenshot 0160 mEditorPage->preview()->updateViewer(); 0161 QTemporaryDir tmp; 0162 const QString themename = mDesktopPage->themeName(); 0163 const QString zipFileName = tmp.path() + QLatin1Char('/') + themename + QLatin1StringView(".zip"); 0164 KZip *zip = new KZip(zipFileName); 0165 if (zip->open(QIODevice::WriteOnly)) { 0166 const QString previewFileName = tmp.path() + QLatin1Char('/') + themename + QLatin1StringView("_preview.png"); 0167 // qCDebug(CONTACTPRINTTHEMEEDITOR_LOG)<<" previewFileName"<<previewFileName; 0168 QStringList lst; 0169 lst << previewFileName; 0170 mEditorPage->preview()->createScreenShot(lst); 0171 0172 const bool fileAdded = zip->addLocalFile(previewFileName, themename + QLatin1Char('/') + QLatin1StringView("theme_preview.png")); 0173 if (!fileAdded) { 0174 KMessageBox::error(this, i18n("We cannot add preview file in zip file"), i18n("Failed to add file.")); 0175 delete zip; 0176 return; 0177 } 0178 0179 createZip(themename, zip); 0180 zip->close(); 0181 // qCDebug(CONTACTPRINTTHEMEEDITOR_LOG)<< "zipFilename"<<zipFileName; 0182 0183 QPointer<KNS3::UploadDialog> dialog = new KNS3::UploadDialog(QStringLiteral("messageviewer_header_themes.knsrc"), this); 0184 dialog->setUploadFile(QUrl::fromLocalFile(zipFileName)); 0185 dialog->setUploadName(themename); 0186 dialog->setPreviewImageFile(0, QUrl::fromLocalFile(previewFileName)); 0187 const QString description = mDesktopPage->description(); 0188 dialog->setDescription(description.isEmpty() ? i18n("My favorite KMail header") : description); 0189 dialog->exec(); 0190 delete dialog; 0191 } else { 0192 qCDebug(CONTACTPRINTTHEMEEDITOR_LOG) << " We can't open in zip write mode"; 0193 } 0194 delete zip; 0195 #endif 0196 } 0197 0198 void ThemeEditorPage::createZip(const QString &themeName, KZip *zip) 0199 { 0200 mEditorPage->createZip(themeName, zip); 0201 0202 for (EditorPage *page : std::as_const(mExtraPage)) { 0203 page->createZip(themeName, zip); 0204 } 0205 mDesktopPage->createZip(themeName, zip); 0206 } 0207 0208 void ThemeEditorPage::addExtraPage() 0209 { 0210 bool ok = false; 0211 QString filename = QInputDialog::getText(this, i18n("Filename of extra page"), i18n("Filename:"), {}, {}, &ok); 0212 if (ok) { 0213 if (!filename.trimmed().isEmpty()) { 0214 if (!filename.endsWith(QLatin1StringView(".html")) && !filename.endsWith(QLatin1StringView(".css")) 0215 && !filename.endsWith(QLatin1StringView(".js"))) { 0216 filename += QLatin1StringView(".html"); 0217 } 0218 createExtraPage(filename); 0219 mThemeSession->addExtraPage(filename); 0220 setChanged(true); 0221 } 0222 } 0223 } 0224 0225 EditorPage *ThemeEditorPage::createExtraPage(const QString &filename) 0226 { 0227 auto extraPage = new EditorPage(EditorPage::ExtraPage, QString()); 0228 connect(extraPage, &EditorPage::changed, this, &ThemeEditorPage::slotChanged); 0229 extraPage->setPageFileName(filename); 0230 mTabWidget->addTab(extraPage, filename); 0231 mTabWidget->setCurrentWidget(extraPage); 0232 mExtraPage.append(extraPage); 0233 return extraPage; 0234 } 0235 0236 void ThemeEditorPage::storeTheme(const QString &directory) 0237 { 0238 const QString themeDirectory = directory.isEmpty() ? projectDirectory() : directory; 0239 mEditorPage->saveTheme(themeDirectory); 0240 0241 for (EditorPage *page : std::as_const(mExtraPage)) { 0242 page->saveTheme(themeDirectory); 0243 } 0244 mDesktopPage->saveTheme(themeDirectory); 0245 mThemeSession->setMainPageFileName(mDesktopPage->filename()); 0246 mThemeSession->writeSession(directory); 0247 if (directory.isEmpty()) { 0248 setChanged(false); 0249 } 0250 } 0251 0252 bool ThemeEditorPage::saveTheme(bool withConfirmation) 0253 { 0254 if (themeWasChanged()) { 0255 if (withConfirmation) { 0256 const int result = KMessageBox::questionTwoActionsCancel(this, 0257 i18n("Do you want to save current project?"), 0258 i18n("Save current project"), 0259 KStandardGuiItem::save(), 0260 KStandardGuiItem::discard()); 0261 if (result == KMessageBox::ButtonCode::PrimaryAction) { 0262 storeTheme(); 0263 } else if (result == KMessageBox::Cancel) { 0264 return false; 0265 } 0266 } else { 0267 storeTheme(); 0268 } 0269 } 0270 setChanged(false); 0271 return true; 0272 } 0273 0274 void ThemeEditorPage::loadTheme(const QString &filename) 0275 { 0276 if (mThemeSession->loadSession(filename)) { 0277 mDesktopPage->loadTheme(mThemeSession->projectDirectory()); 0278 mEditorPage->loadTheme(mThemeSession->projectDirectory() + QLatin1Char('/') + mThemeSession->mainPageFileName()); 0279 mEditorPage->preview()->setThemePath(mThemeSession->projectDirectory(), mThemeSession->mainPageFileName()); 0280 0281 const QStringList lstExtraPages = mThemeSession->extraPages(); 0282 for (const QString &page : lstExtraPages) { 0283 EditorPage *extraPage = createExtraPage(page); 0284 extraPage->loadTheme(mThemeSession->projectDirectory() + QLatin1Char('/') + page); 0285 } 0286 mTabWidget->setCurrentIndex(0); 0287 setChanged(false); 0288 } 0289 } 0290 0291 void ThemeEditorPage::reloadConfig() 0292 { 0293 mEditorPage->preview()->loadConfig(); 0294 } 0295 0296 QString ThemeEditorPage::projectDirectory() const 0297 { 0298 return mThemeSession->projectDirectory(); 0299 } 0300 0301 void ThemeEditorPage::saveThemeAs(const QString &directory) 0302 { 0303 storeTheme(directory); 0304 } 0305 0306 #include "moc_themeeditorpage.cpp"