File indexing completed on 2024-04-28 04:01:26

0001 /*
0002  * Copyright 1999 by Martin R. Jones <mjones@kde.org>
0003  *
0004  * This program is free software; you can redistribute it and/or modify
0005  * it under the terms of the GNU General Public License as published by
0006  * the Free Software Foundation; either version 2 of the License, or
0007  * (at your option) any later version.
0008  *
0009  * This program is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  * GNU General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU General Public License
0015  * along with this program; if not, write to the Free Software
0016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0017  */
0018 #include "amordialog.h"
0019 
0020 #include <QCheckBox>
0021 #include <QLabel>
0022 #include <QListWidget>
0023 #include <QSlider>
0024 #include <QPixmap>
0025 #include <QVBoxLayout>
0026 #include <QTextBrowser>
0027 #include <QStandardPaths>
0028 #include <QGridLayout>
0029 #include <QDir>
0030 #include <QDialogButtonBox>
0031 #include <QPushButton>
0032 
0033 #include <KConfig>
0034 #include <KConfigGroup>
0035 #include <KSharedConfig>
0036 #include <KLocalizedString>
0037 
0038 AmorDialog::AmorDialog(QWidget *parent)
0039   : QDialog( parent )
0040 {
0041     setAttribute(Qt::WA_DeleteOnClose);
0042     setWindowTitle(i18nc("@title:window", "Options"));
0043 
0044 
0045     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel, this);
0046     connect(buttonBox, &QDialogButtonBox::clicked,
0047             this, [this, buttonBox](QAbstractButton *btn) {
0048                 if (btn == buttonBox->button(QDialogButtonBox::Ok)) {
0049                     slotOk();
0050                 } else if (btn == buttonBox->button(QDialogButtonBox::Apply)) {
0051                     slotApply();
0052                 } else if (btn == buttonBox->button(QDialogButtonBox::Cancel)) {
0053                     slotCancel();
0054                 }
0055             });
0056 
0057     mConfig.read();
0058     auto l = new QVBoxLayout(this);
0059     QGridLayout *gridLayout = new QGridLayout();
0060     gridLayout->setContentsMargins( 0, 0, 0, 0 );
0061     l->addLayout(gridLayout);
0062     l->addStretch(2);
0063     l->addWidget(buttonBox);
0064 
0065     QLabel *label = new QLabel( i18n( "Theme:" ), this);
0066     gridLayout->addWidget( label, 0, 0 );
0067 
0068     mThemeListView = new QListWidget(this);
0069     mThemeListView->setIconSize( QSize( 32, 32 ) );
0070     mThemeListView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
0071     mThemeListView->setAlternatingRowColors( true );
0072     connect( mThemeListView, SIGNAL(currentRowChanged(int)), SLOT(slotHighlighted(int)) );
0073     mThemeListView->setMinimumSize( fontMetrics().maxWidth()*20, fontMetrics().lineSpacing()*6 );
0074     gridLayout->addWidget( mThemeListView, 1, 0 );
0075 
0076     mAboutEdit = new QTextBrowser( this );
0077     mAboutEdit->setReadOnly( true );
0078     mAboutEdit->setMinimumHeight( fontMetrics().lineSpacing()*4 );
0079     gridLayout->addWidget( mAboutEdit, 2, 0 );
0080 
0081     // Animation offset
0082     label = new QLabel( i18n("Offset:"), this );
0083     gridLayout->addWidget( label, 0, 1 );
0084 
0085     QSlider *slider = new QSlider( Qt::Vertical, this );
0086     slider->setRange( -40, 40 );
0087     slider->setPageStep( 5 );
0088     slider->setValue( mConfig.mOffset );
0089     connect( slider, SIGNAL(valueChanged(int)), SLOT(slotOffset(int)) );
0090     gridLayout->addWidget( slider, 1, 1, 2, 1 );
0091 
0092     // Always on top
0093     QCheckBox *checkBox = new QCheckBox( i18n( "Always on top" ), this );
0094     connect( checkBox, SIGNAL(toggled(bool)), SLOT(slotOnTop(bool)) );
0095     checkBox->setChecked( mConfig.mOnTop );
0096     gridLayout->addWidget( checkBox, 3, 0, 1, 2 );
0097 
0098     checkBox = new QCheckBox( i18n( "Show random tips" ), this );
0099     connect( checkBox, SIGNAL(toggled(bool)), SLOT(slotRandomTips(bool)) );
0100     checkBox->setChecked( mConfig.mTips ); // always keep this one after the connect, or the QList would not be grayed when it should
0101     gridLayout->addWidget( checkBox, 4, 0, 1, 2 );
0102 
0103     checkBox = new QCheckBox( i18n( "Use a random character" ), this );
0104     connect( checkBox, SIGNAL(toggled(bool)), SLOT(slotRandomTheme(bool)) );
0105     checkBox->setChecked( mConfig.mRandomTheme );
0106     gridLayout->addWidget( checkBox, 5, 0, 1, 2 );
0107 
0108     checkBox = new QCheckBox( i18n( "Allow application tips" ), this );
0109     connect( checkBox, SIGNAL(toggled(bool)), SLOT(slotApplicationTips(bool)) );
0110     checkBox->setChecked( mConfig.mAppTips );
0111     gridLayout->addWidget( checkBox, 6, 0, 1, 2 );
0112 
0113     readThemes();
0114 }
0115 
0116 
0117 void AmorDialog::readThemes()
0118 {
0119     // Non-recursive search for theme files, with the relative paths stored
0120     // in files so that absolute paths are not used.
0121     const auto folders = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("amor"),
0122                                         QStandardPaths::LocateDirectory);
0123 
0124     for (const auto &folder : folders) {
0125         QDir amorDir(folder);
0126         const auto files = amorDir.entryList({ QStringLiteral("*rc") }, QDir::Files, QDir::NoSort);
0127 
0128         for (const auto &file : files) {
0129             addTheme(folder, file);
0130         }
0131     }
0132 }
0133 
0134 
0135 void AmorDialog::addTheme(const QString& folder, const QString& file)
0136 {
0137     KConfig config(QStandardPaths::locate(QStandardPaths::GenericDataLocation,
0138                                           QStringLiteral("amor/%1").arg(file)));
0139     KConfigGroup configGroup( &config, "Config" );
0140 
0141     QString pixmapPath = folder
0142                        + QDir::separator()
0143                        + configGroup.readPathEntry( "PixmapPath", QString() );
0144     if( pixmapPath.isEmpty() ) {
0145         return;
0146     }
0147 
0148     pixmapPath += QDir::separator();
0149     if( pixmapPath[0] != QDir::separator() ) {
0150         // relative to config file. We add a / to indicate the dir
0151         pixmapPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation,
0152                                             QStringLiteral("amor/%1").arg(pixmapPath),
0153                                             QStandardPaths::LocateDirectory);
0154     }
0155 
0156     QString description = configGroup.readEntry( "Description" );
0157     QString about = configGroup.readEntry( "About", " " );
0158     QString pixmapName = configGroup.readEntry( "Icon" );
0159 
0160     pixmapPath += pixmapName;
0161     QPixmap pixmap( pixmapPath );
0162 
0163     QListWidgetItem *item = new QListWidgetItem( QIcon(pixmap), description, mThemeListView );
0164     mThemes.append( file );
0165     mThemeAbout.append( about );
0166 
0167     if( mConfig.mTheme == file ) {
0168         mThemeListView->setCurrentItem( item );
0169     }
0170 }
0171 
0172 
0173 void AmorDialog::slotHighlighted(int index)
0174 {
0175     if( index < 0 ) {
0176         return;
0177     }
0178 
0179     mConfig.mTheme = mThemes.at( index );
0180     mAboutEdit->setPlainText( mThemeAbout.at( index ) );
0181 }
0182 
0183 
0184 void AmorDialog::slotOffset(int off)
0185 {
0186     mConfig.mOffset = off;
0187     Q_EMIT offsetChanged( mConfig.mOffset );
0188 }
0189 
0190 
0191 void AmorDialog::slotOnTop(bool onTop)
0192 {
0193     mConfig.mOnTop = onTop;
0194 }
0195 
0196 
0197 void AmorDialog::slotRandomTips(bool tips)
0198 {
0199     mConfig.mTips = tips;
0200 }
0201 
0202 
0203 void AmorDialog::slotRandomTheme(bool randomTheme)
0204 {
0205     mThemeListView->setEnabled( !randomTheme );
0206     mConfig.mRandomTheme = randomTheme;
0207 }
0208 
0209 
0210 void AmorDialog::slotApplicationTips(bool tips)
0211 {
0212     mConfig.mAppTips = tips;
0213 }
0214 
0215 
0216 void AmorDialog::slotOk()
0217 {
0218     mConfig.write();
0219     Q_EMIT changed();
0220     accept();
0221 }
0222 
0223 
0224 void AmorDialog::slotApply()
0225 {
0226     mConfig.write();
0227     Q_EMIT changed();
0228 }
0229 
0230 
0231 void AmorDialog::slotCancel()
0232 {
0233     // restore offset
0234     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0235     KConfigGroup cs( config, "General" );
0236     Q_EMIT offsetChanged( cs.readEntry( "Offset", 0 ) );
0237     reject();
0238 }
0239 
0240 
0241 // kate: word-wrap off; encoding utf-8; indent-width 4; tab-width 4; line-numbers on; mixed-indent off; remove-trailing-space-save on; replace-tabs-save on; replace-tabs on; space-indent on;
0242 // vim:set spell et sw=4 ts=4 nowrap cino=l1,cs,U1: