1 /*
2     SPDX-FileCopyrightText: 2003-2008 Sebastian Trueg <trueg@k3b.org>
3     SPDX-FileCopyrightText: 2010 Michal Malek <michalm@jabster.pl>
4     SPDX-FileCopyrightText: 1998-2010 Sebastian Trueg <trueg@k3b.org>
5 
6     SPDX-License-Identifier: GPL-2.0-or-later
7 */
8 
9 
10 #include "k3bthemeoptiontab.h"
11 #include "k3bapplication.h"
12 #include "k3bthememanager.h"
13 #include "k3bthememodel.h"
14 
15 #include <KTar>
16 #include <KConfig>
17 #include <KLocalizedString>
18 #include <KIO/Global>
19 #include <KIO/StoredTransferJob>
20 #include <KUrlRequester>
21 #include <KUrlRequesterDialog>
22 #include <KMessageBox>
23 #include <KNS3/DownloadDialog>
24 
25 #include <QFile>
26 #include <QFileInfo>
27 #include <QPointer>
28 #include <QStandardPaths>
29 #include <QTemporaryFile>
30 #include <QItemSelectionModel>
31 #include <QLabel>
32 
33 
ThemeOptionTab(QWidget * parent)34 K3b::ThemeOptionTab::ThemeOptionTab( QWidget* parent )
35     : QWidget( parent ),
36       m_themeModel( new ThemeModel( k3bappcore->themeManager(), this ) )
37 {
38     setupUi( this );
39 
40     m_centerPreviewLabel->setAutoFillBackground( true );
41     m_leftPreviewLabel->setAutoFillBackground( true );
42     m_rightPreviewLabel->setAutoFillBackground( true );
43 
44     m_viewTheme->setModel( m_themeModel );
45 
46     connect( m_viewTheme->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
47              this, SLOT(selectionChanged()) );
48     connect( m_buttonInstallTheme, SIGNAL(clicked()),
49              this, SLOT(slotInstallTheme()) );
50     connect( m_buttonRemoveTheme, SIGNAL(clicked()),
51              this, SLOT(slotRemoveTheme()) );
52     connect( m_buttonGetNewThemes, SIGNAL(clicked()),
53              this, SLOT(slotGetNewThemes()) );
54 }
55 
56 
~ThemeOptionTab()57 K3b::ThemeOptionTab::~ThemeOptionTab()
58 {
59 }
60 
61 
readSettings()62 void K3b::ThemeOptionTab::readSettings()
63 {
64     m_themeModel->reload();
65 
66     QModelIndex index = m_themeModel->indexForTheme( k3bappcore->themeManager()->currentTheme() );
67     m_viewTheme->setCurrentIndex( index );
68 }
69 
70 
saveSettings()71 bool K3b::ThemeOptionTab::saveSettings()
72 {
73     QModelIndex index = m_viewTheme->currentIndex();
74     if( Theme* theme = m_themeModel->themeForIndex( index ) ) {
75         k3bappcore->themeManager()->setCurrentTheme( theme );
76     }
77     return true;
78 }
79 
80 
event(QEvent * event)81 bool K3b::ThemeOptionTab::event( QEvent *event )
82 {
83     if( event->type() == QEvent::StyleChange ) {
84         selectionChanged();
85     }
86     return QWidget::event( event );
87 }
88 
89 
selectionChanged()90 void K3b::ThemeOptionTab::selectionChanged()
91 {
92     QModelIndex index = m_viewTheme->currentIndex();
93     if( Theme* theme = m_themeModel->themeForIndex( index ) ) {
94         m_centerPreviewLabel->setText( i18n("K3b - The CD/DVD Kreator") );
95 
96         QPalette pal( palette() );
97         pal.setColor( backgroundRole(), theme->backgroundColor() );
98         pal.setColor( foregroundRole(), theme->backgroundColor() );
99         m_centerPreviewLabel->setPalette( pal );
100         m_leftPreviewLabel->setPalette( pal );
101         m_rightPreviewLabel->setPalette( pal );
102 
103         m_leftPreviewLabel->setPixmap( theme->pixmap( K3b::Theme::PROJECT_LEFT ) );
104         m_rightPreviewLabel->setPixmap( theme->pixmap( K3b::Theme::PROJECT_RIGHT ) );
105 
106         m_buttonRemoveTheme->setEnabled( theme->local() );
107     }
108 }
109 
110 
slotInstallTheme()111 void K3b::ThemeOptionTab::slotInstallTheme()
112 {
113     QUrl themeURL = KUrlRequesterDialog::getUrl( QUrl(), this,
114                                                  i18n("Drag or Type Theme URL") );
115 
116     if( themeURL.url().isEmpty() )
117         return;
118 
119     QTemporaryFile themeTmpFile;
120     KIO::StoredTransferJob* transferJob = KIO::storedGet( themeURL );
121     bool transferJobSucceed = true;
122     connect( transferJob, &KJob::result, [&](KJob*) {
123         if( transferJob->error() != KJob::NoError ) {
124             themeTmpFile.open();
125             themeTmpFile.write( transferJob->data() );
126             themeTmpFile.close();
127         } else {
128             transferJobSucceed = false;
129         }
130     } );
131 
132     if( transferJob->exec() && !transferJobSucceed ) {
133         QString sorryText;
134         QString tmpArg = themeURL.toDisplayString();
135         if (themeURL.isLocalFile())
136             sorryText = i18n("Unable to find the icon theme archive %1.",tmpArg);
137         else
138             sorryText = i18n("Unable to download the icon theme archive.\n"
139                              "Please check that address %1 is correct.",tmpArg);
140         KMessageBox::sorry( this, sorryText );
141         return;
142     }
143 
144     // check if the archive contains a dir with a k3b.theme file
145     QString themeName;
146     KTar archive( &themeTmpFile );
147     archive.open(QIODevice::ReadOnly);
148     const KArchiveDirectory* themeDir = archive.directory();
149     QStringList entries = themeDir->entries();
150     bool validThemeArchive = false;
151     if( entries.count() > 0 ) {
152         if( themeDir->entry(entries.first())->isDirectory() ) {
153             const KArchiveDirectory* subDir = dynamic_cast<const KArchiveDirectory*>( themeDir->entry(entries.first()) );
154             themeName = subDir->name();
155             if( subDir && subDir->entry( "k3b.theme" ) ) {
156                 validThemeArchive = true;
157 
158                 // check for all necessary pixmaps (this is a little evil hacking)
159                 for( int i = 0; i <= K3b::Theme::WELCOME_BG; ++i ) {
160                     if( !subDir->entry( K3b::Theme::filenameForPixmapType( (K3b::Theme::PixmapType)i ) ) ) {
161                         validThemeArchive = false;
162                         break;
163                     }
164                 }
165             }
166         }
167     }
168 
169     if( !validThemeArchive ) {
170         KMessageBox::error( this, i18n("The file is not a valid K3b theme archive.") );
171     }
172     else {
173         QString themeBasePath = QStandardPaths::writableLocation( QStandardPaths::GenericDataLocation ) + "/k3b/pics/";
174         QDir().mkpath( themeBasePath );
175 
176         // check if there already is a theme by that name
177         if( !QFile::exists( themeBasePath + '/' + themeName ) ||
178             KMessageBox::warningYesNo( this,
179                                        i18n("A theme with the name '%1' already exists. Do you want to "
180                                             "overwrite it?", themeName),
181                                        i18n("Theme exists"),
182                                        KStandardGuiItem::overwrite(),
183                                        KStandardGuiItem::cancel() ) == KMessageBox::Yes ) {
184             // install the theme
185             archive.directory()->copyTo( themeBasePath );
186         }
187     }
188 
189     archive.close();
190 
191     readSettings();
192 }
193 
194 
slotRemoveTheme()195 void K3b::ThemeOptionTab::slotRemoveTheme()
196 {
197     QModelIndex index = m_viewTheme->currentIndex();
198     if( Theme* theme = m_themeModel->themeForIndex( index ) ) {
199         QString question=i18n("<qt>Are you sure you want to remove the "
200                               "<strong>%1</strong> theme?<br>"
201                               "<br>"
202                               "This will delete the files installed by this theme.</qt>", theme->name() );
203 
204         if( KMessageBox::warningContinueCancel( this, question, i18n("Delete"), KStandardGuiItem::del() ) != KMessageBox::Continue )
205             return;
206 
207         m_themeModel->removeRow( index.row() );
208 
209         // reread the themes (this will also set the default theme in case we delete the
210         // selected one)
211         readSettings();
212     }
213 }
214 
slotGetNewThemes()215 void K3b::ThemeOptionTab::slotGetNewThemes()
216 {
217     QPointer<KNS3::DownloadDialog> dialog = new KNS3::DownloadDialog( QStringLiteral("k3btheme.knsrc"), this );
218     dialog->exec();
219     if ( dialog && !dialog->changedEntries().isEmpty() )
220         m_themeModel->reload();
221     delete dialog;
222 }
223