File indexing completed on 2024-10-06 04:26:03

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "k3bthememanager.h"
0008 
0009 #include "k3bversion.h"
0010 
0011 #include <KConfigGroup>
0012 #include <KColorScheme>
0013 
0014 #include <QDebug>
0015 #include <QDir>
0016 #include <QFile>
0017 #include <QFileInfo>
0018 #include <QStandardPaths>
0019 #include <QStringList>
0020 #include <QPixmap>
0021 
0022 
0023 K3b::Theme::Theme()
0024     : m_bgMode(BG_TILE)
0025 {
0026 }
0027 
0028 
0029 K3b::Theme::Theme( QString name)
0030     : m_bgMode(BG_TILE)
0031 {
0032     QString path = QStandardPaths::locate( QStandardPaths::GenericDataLocation, "k3b/pics/" + name + "/k3b.theme" );
0033     if( !path.isEmpty() )
0034         m_path = path.left( path.length() - 9 );
0035 }
0036 
0037 
0038 QColor K3b::Theme::backgroundColor() const
0039 {
0040     if( m_bgColor.isValid() )
0041         return m_bgColor;
0042     else
0043         return KColorScheme(QPalette::Active, KColorScheme::Window).background(KColorScheme::ActiveBackground).color();
0044 }
0045 
0046 
0047 QColor K3b::Theme::foregroundColor() const
0048 {
0049     if( m_fgColor.isValid() )
0050         return m_fgColor;
0051     else
0052         return KColorScheme(QPalette::Active, KColorScheme::Window).foreground(KColorScheme::ActiveText).color();
0053 }
0054 
0055 
0056 QPixmap K3b::Theme::pixmap( const QString& name ) const
0057 {
0058     QMap<QString, QPixmap>::const_iterator it = m_pixmapMap.constFind( name );
0059     if( it != m_pixmapMap.constEnd() )
0060         return *it;
0061 
0062     // try loading the image
0063     if( QFile::exists( m_path + name ) ) {
0064         QPixmap pix( m_path + name );
0065         if ( !pix.isNull() )
0066             return *m_pixmapMap.insert( name, pix );
0067     }
0068 
0069     qDebug() << "(K3b::Theme)" << m_name << ": could not load image" << name << "in" << m_path;
0070 
0071     return m_emptyPixmap;
0072 }
0073 
0074 
0075 QPixmap K3b::Theme::pixmap( K3b::Theme::PixmapType t ) const
0076 {
0077     return pixmap( filenameForPixmapType( t ) );
0078 }
0079 
0080 
0081 QPalette K3b::Theme::palette() const
0082 {
0083     QPalette pal;
0084     pal.setColor( QPalette::Window, backgroundColor() );
0085     pal.setColor( QPalette::WindowText, foregroundColor() );
0086     return pal;
0087 }
0088 
0089 
0090 QString K3b::Theme::filenameForPixmapType( PixmapType t )
0091 {
0092     QString name;
0093 
0094     switch( t ) {
0095     case MEDIA_AUDIO:
0096         name = "media_audio";
0097         break;
0098     case MEDIA_DATA:
0099         name = "media_data";
0100         break;
0101     case MEDIA_VIDEO:
0102         name = "media_video";
0103         break;
0104     case MEDIA_EMPTY:
0105         name = "media_empty";
0106         break;
0107     case MEDIA_MIXED:
0108         name = "media_mixed";
0109         break;
0110     case MEDIA_NONE:
0111         name = "media_none";
0112         break;
0113     case MEDIA_LEFT:
0114         name = "media_left";
0115         break;
0116     case PROGRESS_WORKING:
0117         name = "progress_working";
0118         break;
0119     case PROGRESS_SUCCESS:
0120         name = "progress_success";
0121         break;
0122     case PROGRESS_FAIL:
0123         name = "progress_fail";
0124         break;
0125     case PROGRESS_RIGHT:
0126         name = "progress_right";
0127         break;
0128     case DIALOG_LEFT:
0129         name = "dialog_left";
0130         break;
0131     case DIALOG_RIGHT:
0132         name = "dialog_right";
0133         break;
0134     case SPLASH:
0135         name = "splash";
0136         break;
0137     case PROJECT_LEFT:
0138         name = "project_left";
0139         break;
0140     case PROJECT_RIGHT:
0141         name = "project_right";
0142         break;
0143     case WELCOME_BG:
0144         name = "welcome_bg";
0145         break;
0146     default:
0147         break;
0148     }
0149 
0150     name.append( ".png" );
0151 
0152     return name;
0153 }
0154 
0155 
0156 K3b::Theme::BackgroundMode K3b::Theme::backgroundMode() const
0157 {
0158     return m_bgMode;
0159 }
0160 
0161 
0162 
0163 class K3b::ThemeManager::Private
0164 {
0165 public:
0166     Private()
0167         : currentTheme(&emptyTheme) {
0168     }
0169 
0170     QList<K3b::Theme*> themes;
0171     QList<K3b::Theme*> gcThemes;
0172     K3b::Theme* currentTheme;
0173     QString currentThemeName;
0174 
0175     K3b::Theme emptyTheme;
0176 };
0177 
0178 
0179 
0180 K3b::ThemeManager::ThemeManager( QObject* parent )
0181     : QObject( parent )
0182 {
0183     d = new Private();
0184     d->emptyTheme.m_name = "Empty Theme";
0185 }
0186 
0187 
0188 K3b::ThemeManager::~ThemeManager()
0189 {
0190     for (QList<K3b::Theme*>::ConstIterator it = d->themes.constBegin(); it != d->themes.constEnd(); ++it)
0191         delete *it;
0192     qDeleteAll(d->gcThemes);
0193     d->themes.clear();
0194     delete d;
0195 }
0196 
0197 
0198 QList<K3b::Theme*>& K3b::ThemeManager::themes() const
0199 {
0200     return d->themes;
0201 }
0202 
0203 
0204 K3b::Theme* K3b::ThemeManager::currentTheme() const
0205 {
0206     return d->currentTheme;
0207 }
0208 
0209 
0210 void K3b::ThemeManager::readConfig( const KConfigGroup& c )
0211 {
0212     // allow one to override the default theme by packaging a default config file
0213     QString defaultTheme = c.readEntry( "default theme", "quant" );
0214 
0215     K3b::Version configVersion( c.readEntry( "config version", "0.1" ) );
0216     if( configVersion >= K3b::Version("0.98") )
0217         setCurrentTheme( c.readEntry( "current theme", defaultTheme ) );
0218     else
0219         setCurrentTheme( defaultTheme );
0220 }
0221 
0222 
0223 void K3b::ThemeManager::saveConfig( KConfigGroup c )
0224 {
0225     qDebug() << d->currentThemeName;
0226     if( !d->currentThemeName.isEmpty() ) {
0227         c.writeEntry( "current theme", d->currentThemeName );
0228     }
0229 }
0230 
0231 
0232 void K3b::ThemeManager::setCurrentTheme( const QString& name )
0233 {
0234     if( name != d->currentThemeName ) {
0235         if( K3b::Theme* theme = findTheme( name ) )
0236             setCurrentTheme( theme );
0237     }
0238 }
0239 
0240 
0241 void K3b::ThemeManager::setCurrentTheme( K3b::Theme* theme )
0242 {
0243     if( !theme && !d->themes.isEmpty() )
0244         theme = d->themes.first();
0245 
0246     if( theme ) {
0247         if( theme != d->currentTheme ) {
0248             d->currentTheme = theme;
0249             d->currentThemeName = theme->name();
0250 
0251             emit themeChanged();
0252             emit themeChanged( theme );
0253         }
0254     }
0255 }
0256 
0257 
0258 K3b::Theme* K3b::ThemeManager::findTheme( const QString& name ) const
0259 {
0260     for( QList<K3b::Theme*>::ConstIterator it = d->themes.constBegin(); it != d->themes.constEnd(); ++it )
0261         if( (*it)->name() == name )
0262             return *it;
0263     return 0;
0264 }
0265 
0266 
0267 void K3b::ThemeManager::loadThemes()
0268 {
0269     // first we cleanup the loaded themes
0270     for (QList<K3b::Theme*>::ConstIterator it = d->themes.constBegin(); it != d->themes.constEnd(); ++it)
0271         d->gcThemes << *it;
0272     d->themes.clear();
0273 
0274     QStringList dirs = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "k3b/pics", QStandardPaths::LocateDirectory );
0275     // now search for themes. As there may be multiple themes with the same name
0276     // we only use the names from this list and then use findResourceDir to make sure
0277     // the local is preferred over the global stuff (like testing a theme by copying it
0278     // to the .kde dir)
0279     QStringList themeNames;
0280     for( QStringList::const_iterator dirIt = dirs.constBegin(); dirIt != dirs.constEnd(); ++dirIt ) {
0281         QDir dir( *dirIt );
0282         QStringList entries = dir.entryList( QDir::Dirs|QDir::NoDotAndDotDot );
0283         // every theme dir needs to contain a k3b.theme file
0284         for( QStringList::const_iterator entryIt = entries.constBegin(); entryIt != entries.constEnd(); ++entryIt ) {
0285             QString themeDir = *dirIt + '/' + *entryIt + '/';
0286             if( !themeNames.contains( *entryIt ) && QFile::exists( themeDir + "k3b.theme" ) ) {
0287                 bool themeValid = true;
0288 
0289                 // check for all necessary pixmaps (this is a little evil hacking)
0290                 for( int i = 0; i <= K3b::Theme::WELCOME_BG; ++i ) {
0291                     if( !QFile::exists( themeDir + K3b::Theme::filenameForPixmapType( (K3b::Theme::PixmapType)i ) ) ) {
0292                         qDebug() << "(K3b::ThemeManager) theme misses pixmap: " << K3b::Theme::filenameForPixmapType( (K3b::Theme::PixmapType)i );
0293                         themeValid = false;
0294                         break;
0295                     }
0296                 }
0297 
0298                 if( themeValid )
0299                     themeNames.append( *entryIt );
0300             }
0301         }
0302     }
0303 
0304     // now load the themes
0305     for( QStringList::const_iterator themeIt = themeNames.constBegin(); themeIt != themeNames.constEnd(); ++themeIt )
0306         loadTheme( *themeIt );
0307 
0308     // load the current theme
0309     setCurrentTheme( findTheme(d->currentThemeName) );
0310 }
0311 
0312 
0313 void K3b::ThemeManager::loadTheme( const QString& name )
0314 {
0315     K3b::Theme* t = new K3b::Theme( name );
0316     if( !t->m_path.isEmpty() ) {
0317         t->m_name = name;
0318         t->m_local = QFileInfo( t->m_path ).isWritable();
0319 
0320         // load the stuff
0321         KConfig cfg( t->m_path + "/k3b.theme" );
0322         KConfigGroup group(&cfg, QString());
0323         t->m_author = group.readEntry( "Author" );
0324         t->m_comment = group.readEntry( "Comment" );
0325         t->m_version = group.readEntry( "Version" );
0326         t->m_bgColor = group.readEntry( "Backgroundcolor", QColor() );
0327         t->m_fgColor = group.readEntry( "Foregroundcolor", QColor() );
0328         t->m_bgMode = ( group.readEntry( "BackgroundMode" ) == "Scaled" ? K3b::Theme::BG_SCALE : K3b::Theme::BG_TILE );
0329 
0330         d->themes.append( t );
0331     } else
0332     delete t;
0333 }
0334 
0335 #include "moc_k3bthememanager.cpp"