1 /*
2 SPDX-FileCopyrightText: 2004-2009 Sebastian Trueg <trueg@k3b.org>
3 SPDX-FileCopyrightText: 2009-2011 Michal Malek <michalm@jabster.pl>
4 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org>
5
6 SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "k3baudioconvertingoptionwidget.h"
10
11 #include "k3bpluginmanager.h"
12 #include "k3baudioencoder.h"
13 #include "k3bcore.h"
14
15 #include <KComboBox>
16 #include <KConfig>
17 #include <KColorScheme>
18 #include <KLocalizedString>
19 #include <KDiskFreeSpaceInfo>
20 #include <KUrlRequester>
21 #include <KIconLoader>
22
23 #include <QCheckBox>
24 #include <QLabel>
25 #include <QList>
26 #include <QStandardPaths>
27 #include <QTimer>
28 #include <QToolButton>
29
30
31
32 class K3b::AudioConvertingOptionWidget::Private
33 {
34 public:
35 QList<AudioEncoder*> encoders;
36 QList<QString> extensions;
37
38 QTimer freeSpaceUpdateTimer;
39
40 KIO::filesize_t neededSize;
41
42 AudioEncoder* encoderForIndex( int index ) const;
43 QString pluginNameForIndex( int index ) const;
44 QString extForIndex( int index ) const;
45 int indexForFileType( const QString& pluginName, const QString& ext ) const;
46
47 QString defaultPluginName() const;
48 QString defaultExtension() const;
49 };
50
51
encoderForIndex(int index) const52 K3b::AudioEncoder* K3b::AudioConvertingOptionWidget::Private::encoderForIndex( int index ) const
53 {
54 if( index >= 0 && index < encoders.size() )
55 return encoders.at( index );
56 else
57 return 0;
58 }
59
60
pluginNameForIndex(int index) const61 QString K3b::AudioConvertingOptionWidget::Private::pluginNameForIndex( int index ) const
62 {
63 if( AudioEncoder* encoder = encoderForIndex( index ) )
64 return encoder->pluginInfo().pluginName();
65 else
66 return QString();
67 }
68
69
extForIndex(int index) const70 QString K3b::AudioConvertingOptionWidget::Private::extForIndex( int index ) const
71 {
72 if( index >= 0 && index < extensions.size() )
73 return extensions.at( index );
74 else
75 return "wav";
76 }
77
78
indexForFileType(const QString & pluginName,const QString & ext) const79 int K3b::AudioConvertingOptionWidget::Private::indexForFileType( const QString& pluginName, const QString& ext ) const
80 {
81 if( pluginName.isEmpty() ) {
82 int i = extensions.indexOf( ext );
83 if( i >= 0 )
84 return i;
85 }
86
87 for( int i = 0; i < encoders.size(); ++i ) {
88 AudioEncoder* encoder = encoders.at( i );
89 if( encoder != 0 &&
90 encoder->pluginInfo().pluginName() == pluginName &&
91 extensions.at( i ) == ext ) {
92 return i;
93 }
94 }
95 return 0;
96 }
97
98
defaultPluginName() const99 QString K3b::AudioConvertingOptionWidget::Private::defaultPluginName() const
100 {
101 QString defaultExt = defaultExtension();
102 for( int i = 0; i < extensions.size(); ++i ) {
103 AudioEncoder* encoder = encoders.at( i );
104 if( extensions.at( i ) == defaultExt && encoder != 0 ) {
105 return encoder->pluginInfo().pluginName();
106 }
107 }
108 return QString();
109 }
110
111
defaultExtension() const112 QString K3b::AudioConvertingOptionWidget::Private::defaultExtension() const
113 {
114 // we prefer formats in this order:
115 // 1. ogg
116 // 2. mp3
117 // 3. flac
118 // 4. wave
119 bool ogg = false;
120 bool mp3 = false;
121 bool flac = false;
122 Q_FOREACH( const QString& ext, extensions ) {
123 if( ext == "ogg" )
124 ogg = true;
125 else if( ext == "mp3" )
126 mp3 = true;
127 else if( ext == "flac" )
128 flac = true;
129 }
130
131 if( ogg )
132 return "ogg";
133 else if( mp3 )
134 return "mp3";
135 else if( flac )
136 return "flac";
137 else
138 return "wav";
139 }
140
141
AudioConvertingOptionWidget(QWidget * parent)142 K3b::AudioConvertingOptionWidget::AudioConvertingOptionWidget( QWidget* parent )
143 : QWidget( parent )
144 {
145 setupUi( this );
146
147 d = new Private();
148
149 connect( m_editBaseDir, SIGNAL(textChanged(QString)),
150 this, SLOT(slotUpdateFreeTempSpace()) );
151 connect( m_comboFileType, SIGNAL(activated(int)),
152 this, SLOT(slotEncoderChanged()) );
153 connect( &d->freeSpaceUpdateTimer, SIGNAL(timeout()),
154 this, SLOT(slotUpdateFreeTempSpace()) );
155 connect( m_checkCreatePlaylist, SIGNAL(toggled(bool)), this, SIGNAL(changed()) );
156 connect( m_checkSingleFile, SIGNAL(toggled(bool)), this, SIGNAL(changed()) );
157 connect( m_checkWriteCueFile, SIGNAL(toggled(bool)), this, SIGNAL(changed()) );
158 connect( m_comboFileType, SIGNAL(activated(int)), this, SIGNAL(changed()) );
159 connect( m_editBaseDir, SIGNAL(textChanged(QString)), this, SIGNAL(changed()) );
160 connect( m_buttonConfigurePlugin, SIGNAL(clicked()), this, SLOT(slotConfigurePlugin()) );
161
162 m_editBaseDir->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
163 m_buttonConfigurePlugin->setIcon( QIcon::fromTheme( "configure" ) );
164
165 // FIXME: see if sox and the sox encoder are installed and if so do not put the internal wave
166 // writer in the list of encoders.
167 m_comboFileType->addItem( i18n("Wave") );
168 d->encoders.append( 0 );
169 d->extensions.append( "wav" );
170
171 // check the available encoding plugins
172 QList<K3b::Plugin*> fl = k3bcore->pluginManager()->plugins( "AudioEncoder" );
173 for( QList<K3b::Plugin *>::const_iterator it = fl.constBegin(); it != fl.constEnd(); ++it ) {
174 if( AudioEncoder* encoder = qobject_cast<AudioEncoder*>( *it ) ) {
175 QStringList ext = encoder->extensions();
176
177 for( QStringList::const_iterator exIt = ext.constBegin();
178 exIt != ext.constEnd(); ++exIt ) {
179 m_comboFileType->addItem( encoder->fileTypeComment(*exIt) );
180 d->encoders.append( encoder );
181 d->extensions.append( *exIt );
182 }
183 }
184 }
185
186 // refresh every 2 seconds
187 d->freeSpaceUpdateTimer.start(2000);
188 slotUpdateFreeTempSpace();
189 }
190
191
~AudioConvertingOptionWidget()192 K3b::AudioConvertingOptionWidget::~AudioConvertingOptionWidget()
193 {
194 delete d;
195 }
196
197
baseDir() const198 QString K3b::AudioConvertingOptionWidget::baseDir() const
199 {
200 return m_editBaseDir->url().toLocalFile();
201 }
202
203
setBaseDir(const QString & path)204 void K3b::AudioConvertingOptionWidget::setBaseDir( const QString& path )
205 {
206 m_editBaseDir->setUrl( QUrl::fromLocalFile( path ) );
207 }
208
209
setNeededSize(KIO::filesize_t size)210 void K3b::AudioConvertingOptionWidget::setNeededSize( KIO::filesize_t size )
211 {
212 d->neededSize = size;
213 if( d->neededSize > 0 )
214 m_labelNeededSpace->setText( KIO::convertSize( d->neededSize ) );
215 else
216 m_labelNeededSpace->setText( i18n("unknown") );
217
218 slotUpdateFreeTempSpace();
219 }
220
221
slotConfigurePlugin()222 void K3b::AudioConvertingOptionWidget::slotConfigurePlugin()
223 {
224 // 0 for wave
225 if( AudioEncoder* enc = encoder() )
226 {
227 int ret = k3bcore->pluginManager()->execPluginDialog( enc, this );
228 if( ret == QDialog::Accepted )
229 {
230 emit changed();
231 }
232 }
233 }
234
235
slotUpdateFreeTempSpace()236 void K3b::AudioConvertingOptionWidget::slotUpdateFreeTempSpace()
237 {
238 KColorScheme::ForegroundRole textColor;
239
240 KDiskFreeSpaceInfo diskInfo = KDiskFreeSpaceInfo::freeSpaceInfo( m_editBaseDir->url().toLocalFile() );
241 if( diskInfo.isValid() ) {
242 m_labelFreeSpace->setText( KIO::convertSize(diskInfo.available()) );
243
244 if( d->neededSize > diskInfo.available() )
245 textColor = KColorScheme::NegativeText;
246 else
247 textColor = KColorScheme::NormalText;
248 }
249 else {
250 m_labelFreeSpace->setText( i18n("unknown") );
251 textColor = KColorScheme::NormalText;
252 }
253
254 QPalette pal( m_labelFreeSpace->palette() );
255 pal.setBrush( QPalette::Disabled, QPalette::WindowText, KColorScheme( QPalette::Disabled, KColorScheme::Window ).foreground( textColor ) );
256 pal.setBrush( QPalette::Active, QPalette::WindowText, KColorScheme( QPalette::Active, KColorScheme::Window ).foreground( textColor ) );
257 pal.setBrush( QPalette::Inactive, QPalette::WindowText, KColorScheme( QPalette::Inactive, KColorScheme::Window ).foreground( textColor ) );
258 pal.setBrush( QPalette::Normal, QPalette::WindowText, KColorScheme( QPalette::Normal, KColorScheme::Window ).foreground( textColor ) );
259 m_labelFreeSpace->setPalette( pal );
260 }
261
262
slotEncoderChanged()263 void K3b::AudioConvertingOptionWidget::slotEncoderChanged()
264 {
265 if( Plugin* plugin = encoder() )
266 m_buttonConfigurePlugin->setEnabled( k3bcore->pluginManager()->hasPluginDialog( plugin ) );
267 else
268 m_buttonConfigurePlugin->setEnabled( false );
269 }
270
271
encoder() const272 K3b::AudioEncoder* K3b::AudioConvertingOptionWidget::encoder() const
273 {
274 return d->encoderForIndex( m_comboFileType->currentIndex() ); // 0 for wave
275 }
276
277
extension() const278 QString K3b::AudioConvertingOptionWidget::extension() const
279 {
280 return d->extForIndex( m_comboFileType->currentIndex() );
281 }
282
283
loadConfig(const KConfigGroup & c)284 void K3b::AudioConvertingOptionWidget::loadConfig( const KConfigGroup& c )
285 {
286 m_editBaseDir->setUrl( QUrl::fromLocalFile( c.readEntry( "last ripping directory", QStandardPaths::writableLocation(QStandardPaths::MusicLocation) ) ) );
287
288 m_checkSingleFile->setChecked( c.readEntry( "single_file", false ) );
289 m_checkWriteCueFile->setChecked( c.readEntry( "write_cue_file", false ) );
290
291 m_checkCreatePlaylist->setChecked( c.readEntry( "create_playlist", false ) );
292 m_checkPlaylistRelative->setChecked( c.readEntry( "relative_path_in_playlist", false ) );
293
294 QString encoder;
295 QString filetype;
296 if( c.hasKey( "encoder" ) && c.hasKey( "filetype" ) ) {
297 encoder = c.readEntry( "encoder" );
298 filetype = c.readEntry( "filetype" );
299 }
300 else {
301 encoder = d->defaultPluginName();
302 filetype = d->defaultExtension();
303 }
304 m_comboFileType->setCurrentIndex( d->indexForFileType( encoder, filetype ) );
305
306 slotEncoderChanged();
307 }
308
309
saveConfig(KConfigGroup c)310 void K3b::AudioConvertingOptionWidget::saveConfig( KConfigGroup c )
311 {
312 c.writePathEntry( "last ripping directory", m_editBaseDir->url().url() );
313
314 c.writeEntry( "single_file", m_checkSingleFile->isChecked() );
315 c.writeEntry( "write_cue_file", m_checkWriteCueFile->isChecked() );
316
317 c.writeEntry( "create_playlist", m_checkCreatePlaylist->isChecked() );
318 c.writeEntry( "relative_path_in_playlist", m_checkPlaylistRelative->isChecked() );
319
320 c.writeEntry( "encoder", d->pluginNameForIndex( m_comboFileType->currentIndex() ) );
321 c.writeEntry( "filetype", d->extForIndex( m_comboFileType->currentIndex() ) );
322 }
323
324
325