File indexing completed on 2024-04-21 03:51:08

0001 /*
0002     SPDX-FileCopyrightText: 2007 Mauricio Piacentini <mauricio@tabuleiro.com>
0003     SPDX-FileCopyrightText: 2007 Matt Williams <matt@milliams.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kgamethemeselector.h"
0008 
0009 #include <KConfigSkeleton>
0010 #include <KLocalizedString>
0011 #include <QDirIterator>
0012 
0013 #include "kgametheme.h"
0014 #include "ui_kgamethemeselector.h"
0015 
0016 class KGameThemeSelectorPrivate
0017 {
0018     KGameThemeSelector *q_ptr;
0019     Q_DECLARE_PUBLIC(KGameThemeSelector)
0020 
0021 public:
0022     KGameThemeSelectorPrivate(KGameThemeSelector *parent)
0023         : q_ptr(parent)
0024     {
0025     }
0026     ~KGameThemeSelectorPrivate()
0027     {
0028         qDeleteAll(themeMap);
0029     }
0030 
0031     QMap<QString, KGameTheme *> themeMap;
0032     Ui::KGameThemeSelectorBase ui;
0033     QString lookupDirectory;
0034     QString groupName;
0035 
0036     void setupData(KConfigSkeleton *config, KGameThemeSelector::NewStuffState knsflags);
0037     void findThemes(const QString &initialSelection);
0038 
0039     // private slots
0040     void _k_updatePreview();
0041     void _k_updateThemeList(const QString &strTheme);
0042 };
0043 
0044 KGameThemeSelector::KGameThemeSelector(QWidget *parent,
0045                                        KConfigSkeleton *aconfig,
0046                                        KGameThemeSelector::NewStuffState knsflags,
0047                                        const QString &groupName,
0048                                        const QString &directory)
0049     : QWidget(parent)
0050     , d_ptr(new KGameThemeSelectorPrivate(this))
0051 {
0052     d_func()->lookupDirectory = directory;
0053     d_func()->groupName = groupName;
0054     d_func()->setupData(aconfig, knsflags);
0055 }
0056 
0057 KGameThemeSelector::~KGameThemeSelector()
0058 {
0059     delete d_ptr;
0060 }
0061 
0062 void KGameThemeSelectorPrivate::setupData(KConfigSkeleton *aconfig, KGameThemeSelector::NewStuffState knsflags)
0063 {
0064     ui.setupUi(q_ptr);
0065     ui.getNewButton->setConfigFile(QStringLiteral("parley-themes.knsrc"));
0066 
0067     // The lineEdit widget holds our theme path for automatic connection via KConfigXT.
0068     // But the user should not manipulate it directly, so we hide it.
0069     ui.kcfg_Theme->hide();
0070     q_func()->connect(ui.kcfg_Theme, SIGNAL(textChanged(QString)), q_ptr, SLOT(_k_updateThemeList(QString)));
0071 
0072     // Disable KNS button?
0073     if (knsflags == KGameThemeSelector::NewStuffDisableDownload) {
0074         ui.getNewButton->hide();
0075     }
0076 
0077     // Get the last used theme path from the KConfigSkeleton
0078     KConfigSkeletonItem *configItem = aconfig->findItem(QStringLiteral("Theme"));
0079     QString lastUsedTheme = configItem->property().toString();
0080 
0081     // Now get our themes into the list widget
0082     findThemes(lastUsedTheme);
0083 
0084     q_func()->connect(ui.getNewButton, &KNSWidgets::Button::dialogFinished, q_ptr, [&](const QList<KNSCore::Entry> &changedEntries) {
0085         if (!changedEntries.isEmpty()) {
0086             findThemes(ui.kcfg_Theme->text());
0087         }
0088     });
0089 }
0090 
0091 void KGameThemeSelectorPrivate::findThemes(const QString &initialSelection)
0092 {
0093     qDeleteAll(themeMap);
0094     themeMap.clear();
0095 
0096     // Disconnect the themeList as we are going to clear it and do not want previews generated
0097     ui.themeList->disconnect();
0098     ui.themeList->clear();
0099     ui.themeList->setSortingEnabled(true);
0100 
0101     QStringList themesAvailable;
0102     QStringList themePaths = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
0103                                                        QCoreApplication::applicationName() + '/' + lookupDirectory + '/',
0104                                                        QStandardPaths::LocateDirectory);
0105     for (const QString &dir : qAsConst(themePaths)) {
0106         QDirIterator it(dir, QStringList() << QStringLiteral("*.desktop"), QDir::NoFilter, QDirIterator::Subdirectories);
0107         while (it.hasNext()) {
0108             it.next();
0109             themesAvailable.append(it.fileName());
0110         }
0111     }
0112 
0113     bool initialFound = false;
0114     for (const QString &file : qAsConst(themesAvailable)) {
0115         QString themePath = lookupDirectory + '/' + file;
0116         KGameTheme *atheme = new KGameTheme(groupName);
0117 
0118         if (atheme->load(themePath)) {
0119             QString themeName = atheme->themeProperty(QStringLiteral("Name"));
0120             // Add underscores to avoid duplicate names.
0121             while (themeMap.contains(themeName))
0122                 themeName += '_';
0123             themeMap.insert(themeName, atheme);
0124             QListWidgetItem *item = new QListWidgetItem(themeName, ui.themeList);
0125 
0126             // Find if this is our currently configured theme
0127             if (themePath == initialSelection) {
0128                 initialFound = true;
0129                 ui.themeList->setCurrentItem(item);
0130                 _k_updatePreview();
0131             }
0132         } else {
0133             delete atheme;
0134         }
0135     }
0136 
0137     if (!initialFound) {
0138         // TODO change this if we ever change KGameTheme::loadDefault
0139         QString defaultPath = QStringLiteral("themes/default.desktop");
0140         for (KGameTheme *theme : qAsConst(themeMap)) {
0141             if (theme->path().endsWith(defaultPath)) {
0142                 const QList<QListWidgetItem *> itemList = ui.themeList->findItems(theme->themeProperty(QStringLiteral("Name")), Qt::MatchExactly);
0143                 // never can be != 1 but better safe than sorry
0144                 if (itemList.count() == 1) {
0145                     ui.themeList->setCurrentItem(itemList.first());
0146                     _k_updatePreview();
0147                 }
0148             }
0149         }
0150     }
0151 
0152     // Reconnect the themeList
0153     q_func()->connect(ui.themeList, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), q_ptr, SLOT(_k_updatePreview()));
0154 }
0155 
0156 void KGameThemeSelectorPrivate::_k_updatePreview()
0157 {
0158     KGameTheme *seltheme = themeMap.value(ui.themeList->currentItem()->text());
0159     // Sanity checkings. Should not happen.
0160     if (!seltheme)
0161         return;
0162     if (seltheme->path() == ui.kcfg_Theme->text()) {
0163         return;
0164     }
0165     ui.kcfg_Theme->setText(seltheme->fileName());
0166 
0167     QString authstr(QStringLiteral("Author"));
0168     QString contactstr(QStringLiteral("AuthorEmail"));
0169     QString descstr(QStringLiteral("Description"));
0170     QString emailstr;
0171     if (!seltheme->themeProperty(contactstr).isEmpty()) {
0172         emailstr = QStringLiteral("<a href=\"mailto:%1\">%1</a>").arg(seltheme->themeProperty(contactstr));
0173     }
0174 
0175     ui.themeAuthor->setText(seltheme->themeProperty(authstr));
0176     ui.themeContact->setText(emailstr);
0177     ui.themeDescription->setText(seltheme->themeProperty(descstr));
0178 
0179     // Draw the preview
0180     QPixmap pix(seltheme->preview());
0181     ui.themePreview->setPixmap(pix.scaled(ui.themePreview->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
0182 }
0183 
0184 void KGameThemeSelectorPrivate::_k_updateThemeList(const QString &strTheme)
0185 {
0186     // find theme and set selection to the current theme; happens when pressing "Default"
0187     QListWidgetItem *currentItem = ui.themeList->currentItem();
0188 
0189     QString currentGameThemeFileName;
0190     if (currentItem) {
0191         KGameTheme *currentGameTheme = themeMap.value(currentItem->text());
0192         if (currentGameTheme) {
0193             currentGameThemeFileName = currentGameTheme->fileName();
0194         }
0195     }
0196 
0197     if (!currentItem || (currentGameThemeFileName != strTheme)) {
0198         for (int i = 0; i < ui.themeList->count(); i++) {
0199             KGameTheme *listItemGameTheme = themeMap.value(ui.themeList->item(i)->text());
0200             if (listItemGameTheme && (listItemGameTheme->fileName() == strTheme)) {
0201                 ui.themeList->setCurrentItem(ui.themeList->item(i));
0202                 break;
0203             }
0204         }
0205     }
0206 }
0207 
0208 #include "moc_kgamethemeselector.cpp"