File indexing completed on 2024-05-12 07:41:29

0001 /*
0002     File                 : ThemeHandler.cpp
0003     Project              : LabPlot
0004     Description          : Widget for handling saving and loading of themes
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2016 Prakriti Bhardwaj <p_bhardwaj14@informatik.uni-kl.de>
0007     SPDX-FileCopyrightText: 2016-2017 Alexander Semke <alexander.semke@web.de>
0008     SPDX-FileCopyrightText: 2018 Stefan Gerlach <stefan.gerlach@uni.kn>
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #include "ThemeHandler.h"
0013 #include "backend/lib/macros.h"
0014 #include "widgets/ThemesWidget.h"
0015 
0016 #include <QDir>
0017 #include <QDirIterator>
0018 #include <QFileInfo>
0019 #include <QHBoxLayout>
0020 #include <QMenu>
0021 #include <QPushButton>
0022 #include <QWidgetAction>
0023 
0024 #include <KConfig>
0025 #include <KConfigGroup>
0026 #include <KLocalizedString>
0027 
0028 // #include <KMessageBox>
0029 // #include <KNS3/UploadDialog>
0030 
0031 /*!
0032   \class ThemeHandler
0033   \brief Provides a widget with buttons for loading of themes.
0034 
0035   Emits \c loadConfig() signal that have to be connected
0036   to the appropriate slots in the backend (plot widgets)
0037 
0038   \ingroup kdefrontend
0039 */
0040 
0041 ThemeHandler::ThemeHandler(QWidget* parent)
0042     : QWidget(parent) {
0043     auto* horizontalLayout = new QHBoxLayout(this);
0044     horizontalLayout->setSpacing(0);
0045     horizontalLayout->setContentsMargins(0, 0, 0, 0);
0046 
0047     m_pbLoadTheme = new QPushButton(this);
0048     horizontalLayout->addWidget(m_pbLoadTheme);
0049     m_pbLoadTheme->setText(i18n("Theme"));
0050     m_pbLoadTheme->setIcon(QIcon::fromTheme(QLatin1String("color-management")));
0051 
0052     //  pbSaveTheme = new QPushButton(this);
0053     //  horizontalLayout->addWidget(pbSaveTheme);
0054     //  pbSaveTheme->setText(i18n("Save Theme"));
0055 
0056     /*
0057         pbPublishTheme = new QPushButton(this);
0058         horizontalLayout->addWidget(pbPublishTheme);
0059         pbPublishTheme->setText("Publish Theme");
0060         pbPublishTheme->setEnabled(false);
0061     */
0062 
0063     connect(m_pbLoadTheme, &QPushButton::clicked, this, &ThemeHandler::showPanel);
0064     //  connect( pbSaveTheme, SIGNAL(clicked()), this, SLOT(saveMenu()));
0065     //  connect( pbPublishTheme, SIGNAL(clicked()), this, SLOT(publishThemes()));
0066 
0067     m_themeList = themeList();
0068 
0069     m_pbLoadTheme->setEnabled(!m_themeList.isEmpty());
0070 }
0071 
0072 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0073 
0074 /*!
0075  * get list of all theme files (full path)
0076  */
0077 QStringList ThemeHandler::themeList() {
0078     DEBUG(Q_FUNC_INFO);
0079     // find all available themes files (system wide and user specific local files)
0080     QStringList dirs = QStandardPaths::locateAll(QStandardPaths::AppDataLocation, QLatin1String("themes"), QStandardPaths::LocateDirectory);
0081 
0082     QStringList themes;
0083     for (const auto& dir : dirs) {
0084         QDirIterator it(dir, QStringList() << QStringLiteral("*"), QDir::Files);
0085         while (it.hasNext())
0086             themes.append(it.next());
0087     }
0088 
0089     if (!themes.isEmpty())
0090         DEBUG(" first theme path: " << STDSTRING(themes.first()));
0091 
0092     return themes;
0093 }
0094 
0095 /*!
0096  * get list of all theme names
0097  */
0098 QStringList ThemeHandler::themes() {
0099     DEBUG("ThemeHandler::themes()");
0100     QStringList themePaths = themeList();
0101 
0102     QStringList themes;
0103     for (int i = 0; i < themePaths.size(); ++i) {
0104         QFileInfo fileinfo(themePaths.at(i));
0105         themes.append(fileinfo.fileName().split(QLatin1Char('.')).at(0));
0106     }
0107 
0108     if (!themes.isEmpty()) {
0109         DEBUG(" first theme: " << STDSTRING(themes.first()));
0110         QDEBUG("    themes = " << themes);
0111     }
0112 
0113     themes.sort();
0114 
0115     return themes;
0116 }
0117 
0118 /*!
0119  * get path for theme of name 'name'
0120  */
0121 const QString ThemeHandler::themeFilePath(const QString& name) {
0122     DEBUG("ThemeHandler::themeFilePath() name = " << STDSTRING(name));
0123     QStringList themePaths = themeList();
0124 
0125     for (int i = 0; i < themePaths.size(); ++i) {
0126         const QString& path = themePaths.at(i);
0127         const QString& fileName = QFileInfo(path).fileName();
0128         if (fileName == name) {
0129             DEBUG(" theme \"" << STDSTRING(name) << "\" path: " << STDSTRING(path));
0130             return path;
0131         }
0132     }
0133 
0134     return {};
0135 }
0136 
0137 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0138 
0139 void ThemeHandler::setCurrentTheme(const QString& name) {
0140     if (!name.isEmpty()) {
0141         m_pbLoadTheme->setText(i18n("Theme '%1'", name));
0142         m_pbLoadTheme->setToolTip(i18n("Theme '%1' is active. Click on the button to change the theme.", name));
0143     } else {
0144         m_pbLoadTheme->setText(i18n("Theme"));
0145         m_pbLoadTheme->setToolTip(i18n("No theme is active. Click on the button to select a theme."));
0146     }
0147 
0148     m_currentTheme = name;
0149 }
0150 
0151 void ThemeHandler::loadSelected(const QString& name) {
0152     Q_EMIT loadThemeRequested(name);
0153     this->setCurrentTheme(name);
0154 
0155     if (!name.isEmpty())
0156         Q_EMIT info(i18n("Theme \"%1\" was loaded.", name));
0157     else
0158         Q_EMIT info(i18n("Theming deactivated."));
0159 
0160     // in case a local theme file was loaded (we have write access), allow to publish it
0161     // TODO: activate this later
0162     //  if (KStandardDirs::checkAccess(themeFilePath, W_OK)) {
0163     //      pbPublishTheme->setEnabled(true);
0164     //      m_currentLocalTheme = themeFilePath.right(themeFilePath.length() - themeFilePath.lastIndexOf(QLatin1String("/")) - 1);
0165     //  } else {
0166     //      pbPublishTheme->setEnabled(false);
0167     //      m_currentLocalTheme.clear();
0168     //  }
0169 }
0170 
0171 void ThemeHandler::showPanel() {
0172 #ifndef SDK
0173     QMenu menu;
0174     ThemesWidget themeWidget(&menu);
0175     themeWidget.setFixedMode();
0176     connect(&themeWidget, &ThemesWidget::themeSelected, this, &ThemeHandler::loadSelected);
0177     connect(&themeWidget, &ThemesWidget::themeSelected, &menu, &QMenu::close);
0178     connect(&themeWidget, &ThemesWidget::canceled, &menu, &QMenu::close);
0179 
0180     auto* widgetAction = new QWidgetAction(this);
0181     widgetAction->setDefaultWidget(&themeWidget);
0182     menu.addAction(widgetAction);
0183 
0184     QPoint pos(-menu.sizeHint().width() + m_pbLoadTheme->width(), -menu.sizeHint().height());
0185     menu.exec(m_pbLoadTheme->mapToGlobal(pos));
0186 #endif
0187 }
0188 
0189 // void ThemeHandler::saveMenu() {
0190 //  QMenu menu;
0191 //  menu.addSection(i18n("Save As"));
0192 //
0193 //  // add editable action
0194 //  QWidgetAction* widgetAction = new QWidgetAction(this);
0195 //  QFrame* frame = new QFrame(this);
0196 //  QHBoxLayout* layout = new QHBoxLayout(frame);
0197 //
0198 //  QLabel* label = new QLabel(i18n("Enter name:"), frame);
0199 //  layout->addWidget(label);
0200 //
0201 //  QLineEdit* leFilename = new QLineEdit(QString(), frame);
0202 //  layout->addWidget(leFilename);
0203 //  connect(leFilename, SIGNAL(returnPressed(QString)), this, SLOT(saveNewSelected(QString)));
0204 //  connect(leFilename, SIGNAL(returnPressed(QString)), &menu, SLOT(close()));
0205 //
0206 //  widgetAction->setDefaultWidget(frame);
0207 //  menu.addAction(widgetAction);
0208 //
0209 //     QPoint pos(-menu.sizeHint().width() + m_pbSaveTheme->width(), -menu.sizeHint().height());
0210 //     menu.exec(m_pbSaveTheme->mapToGlobal(pos));
0211 //  leFilename->setFocus();
0212 // }
0213 
0214 // void ThemeHandler::saveNewSelected(const QString& filename) {
0215 //  KConfig config(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + '/' + "themes" + '/' + filename, KConfig::SimpleConfig);
0216 //  Q_EMIT saveThemeRequested(config);
0217 //  Q_EMIT info( i18n("New theme \"%1\" was saved.", filename) );
0218 //
0219 //  m_currentLocalTheme = filename;
0220 //  m_themeList.append(config.name());
0221 //
0222 //  //enable the publish button so the newly created theme can be published
0223 //  //TODO: enable this later
0224 // //   pbPublishTheme->setEnabled(true);
0225 // }
0226 
0227 /*!
0228     opens the dialog to upload the currently selected local theme.
0229     The publish button is only enabled if a local theme was loaded or one of the themes was modified and saved locally.
0230  */
0231 // void ThemeHandler::publishThemes() {
0232 //  int ret = KMessageBox::questionYesNo(this,
0233 //          i18n("Do you want to upload your theme %1 to public web server?", m_currentLocalTheme),
0234 //          i18n("Publish Theme"));
0235 //  if (ret != KMessageBox::Yes)
0236 //      return;
0237 //
0238 //  // creating upload dialog
0239 //  KNS3::UploadDialog dialog("labplot2_themes.knsrc", this);
0240 //  dialog.setUploadFile(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + '/' + "themes" + '/' + m_currentLocalTheme);
0241 //  dialog.setUploadName(m_currentLocalTheme);
0242 //  //dialog.setDescription(); TODO: allow the user to provide a short description for the theme to be uploaded
0243 //  dialog.exec();
0244 // }