File indexing completed on 2024-10-06 04:26:01
0001 /* 0002 SPDX-FileCopyrightText: 2005-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "k3bmediaselectioncombobox.h" 0009 #include "k3bapplication.h" 0010 #include "k3bmediacache.h" 0011 #include "k3bmediumdelegate.h" 0012 0013 #include "k3bglobalsettings.h" 0014 #include "k3bdevice.h" 0015 #include "k3bdevicemanager.h" 0016 #include "k3bdeviceglobals.h" 0017 #include "k3bdiskinfo.h" 0018 #include "k3bglobals.h" 0019 #include "k3btoc.h" 0020 #include "k3bcdtext.h" 0021 0022 #include <KLocalizedString> 0023 0024 #include <QDebug> 0025 #include <QMap> 0026 #include <QVector> 0027 #include <QList> 0028 #include <QFont> 0029 0030 Q_DECLARE_METATYPE(K3b::Medium) 0031 0032 class K3b::MediaSelectionComboBox::Private 0033 { 0034 public: 0035 Private() 0036 : ignoreDevice( 0 ) { 0037 } 0038 0039 QMap<K3b::Device::Device*, int> deviceIndexMap; 0040 QVector<K3b::Device::Device*> devices; 0041 0042 K3b::Device::Device* ignoreDevice; 0043 0044 // medium strings for every entry 0045 QMap<QString, int> mediaStringMap; 0046 0047 Device::MediaTypes wantedMediumType; 0048 Device::MediaStates wantedMediumState; 0049 Medium::MediumContents wantedMediumContent; 0050 K3b::Msf wantedMediumSize; 0051 0052 QList<Medium> excludedMediums; 0053 0054 QFont origFont; 0055 }; 0056 0057 0058 K3b::MediaSelectionComboBox::MediaSelectionComboBox( QWidget* parent ) 0059 : KComboBox( false, parent ) 0060 { 0061 d = new Private(); 0062 d->origFont = font(); 0063 0064 // set defaults 0065 d->wantedMediumType = K3b::Device::MEDIA_WRITABLE_CD; 0066 d->wantedMediumState = K3b::Device::STATE_EMPTY; 0067 d->wantedMediumContent = K3b::Medium::ContentAll; 0068 0069 setItemDelegate( new MediumDelegate( this ) ); 0070 0071 connect( this, SIGNAL(activated(int)), 0072 this, SLOT(slotActivated(int)) ); 0073 connect( k3bcore->deviceManager(), SIGNAL(changed(K3b::Device::DeviceManager*)), 0074 this, SLOT(slotDeviceManagerChanged(K3b::Device::DeviceManager*)) ); 0075 connect( k3bappcore->mediaCache(), SIGNAL(mediumChanged(K3b::Device::Device*)), 0076 this, SLOT(slotMediumChanged(K3b::Device::Device*)) ); 0077 connect( this, SIGNAL(selectionChanged(K3b::Device::Device*)), 0078 this, SLOT(slotUpdateToolTip(K3b::Device::Device*)) ); 0079 0080 updateMedia(); 0081 } 0082 0083 0084 K3b::MediaSelectionComboBox::~MediaSelectionComboBox() 0085 { 0086 delete d; 0087 } 0088 0089 0090 void K3b::MediaSelectionComboBox::setIgnoreDevice( K3b::Device::Device* dev ) 0091 { 0092 d->ignoreDevice = dev; 0093 updateMedia(); 0094 } 0095 0096 0097 K3b::Device::Device* K3b::MediaSelectionComboBox::selectedDevice() const 0098 { 0099 if( d->devices.count() > currentIndex() && 0100 currentIndex() >= 0 ) 0101 return d->devices[currentIndex()]; 0102 else 0103 return 0; 0104 } 0105 0106 0107 QList<K3b::Device::Device*> K3b::MediaSelectionComboBox::allDevices() const 0108 { 0109 QList<K3b::Device::Device*> l; 0110 for( int i = 0; i < d->devices.count(); ++i ) 0111 l.append( d->devices[i] ); 0112 return l; 0113 } 0114 0115 0116 void K3b::MediaSelectionComboBox::setSelectedDevice( K3b::Device::Device* dev ) 0117 { 0118 if( dev && d->deviceIndexMap.contains( dev ) ) { 0119 setCurrentIndex( d->deviceIndexMap[dev] ); 0120 emit selectionChanged( dev ); 0121 } 0122 } 0123 0124 0125 void K3b::MediaSelectionComboBox::setWantedMediumType( K3b::Device::MediaTypes type ) 0126 { 0127 if( type != 0 && type != d->wantedMediumType) { 0128 d->wantedMediumType = type; 0129 updateMedia(); 0130 } 0131 } 0132 0133 0134 void K3b::MediaSelectionComboBox::setWantedMediumState( K3b::Device::MediaStates state ) 0135 { 0136 if( state != 0 && state != d->wantedMediumState ) { 0137 d->wantedMediumState = state; 0138 updateMedia(); 0139 } 0140 } 0141 0142 0143 void K3b::MediaSelectionComboBox::setWantedMediumContent( K3b::Medium::MediumContents content ) 0144 { 0145 if( content != d->wantedMediumContent ) { 0146 d->wantedMediumContent = content; 0147 updateMedia(); 0148 } 0149 } 0150 0151 0152 void K3b::MediaSelectionComboBox::setWantedMediumSize( const K3b::Msf& minSize ) 0153 { 0154 if ( d->wantedMediumSize != minSize ) { 0155 d->wantedMediumSize = minSize; 0156 updateMedia(); 0157 } 0158 } 0159 0160 0161 K3b::Device::MediaTypes K3b::MediaSelectionComboBox::wantedMediumType() const 0162 { 0163 return d->wantedMediumType; 0164 } 0165 0166 0167 K3b::Device::MediaStates K3b::MediaSelectionComboBox::wantedMediumState() const 0168 { 0169 return d->wantedMediumState; 0170 } 0171 0172 0173 K3b::Medium::MediumContents K3b::MediaSelectionComboBox::wantedMediumContent() const 0174 { 0175 return d->wantedMediumContent; 0176 } 0177 0178 0179 K3b::Msf K3b::MediaSelectionComboBox::wantedMediumSize() const 0180 { 0181 return d->wantedMediumSize; 0182 } 0183 0184 void K3b::MediaSelectionComboBox::slotActivated( int i ) 0185 { 0186 if( d->devices.count() > 0 ) 0187 emit selectionChanged( d->devices[i] ); 0188 } 0189 0190 0191 void K3b::MediaSelectionComboBox::slotMediumChanged( K3b::Device::Device* dev ) 0192 { 0193 updateMedium( dev ); 0194 } 0195 0196 0197 void K3b::MediaSelectionComboBox::clear() 0198 { 0199 d->deviceIndexMap.clear(); 0200 d->mediaStringMap.clear(); 0201 d->devices.clear(); 0202 KComboBox::clear(); 0203 setFont( d->origFont ); 0204 } 0205 0206 0207 void K3b::MediaSelectionComboBox::showNoMediumMessage() 0208 { 0209 // make it italic 0210 QFont f( font() ); 0211 f.setItalic( true ); 0212 setFont( f ); 0213 if ( d->excludedMediums.isEmpty() ) { 0214 addItem( noMediumMessage() ); 0215 } 0216 else { 0217 addItems( noMediumMessages() ); 0218 } 0219 setItemData( 0, f, Qt::FontRole ); 0220 } 0221 0222 0223 void K3b::MediaSelectionComboBox::updateMedia() 0224 { 0225 // remember set of devices 0226 QVector<K3b::Device::Device*> oldDevices = d->devices; 0227 0228 // remember last selected medium 0229 K3b::Device::Device* selected = selectedDevice(); 0230 0231 clear(); 0232 d->excludedMediums.clear(); 0233 0234 // 0235 // We need to only check a selection of the available devices based on the 0236 // wanted media type. 0237 // 0238 0239 // no ROM media -> we most likely want only CD/DVD writers 0240 bool rwOnly = !( wantedMediumType() & (K3b::Device::MEDIA_CD_ROM|K3b::Device::MEDIA_DVD_ROM) ); 0241 bool dvdOnly = !( wantedMediumType() & (K3b::Device::MEDIA_CD_ROM|K3b::Device::MEDIA_WRITABLE_CD) ); 0242 0243 QList<K3b::Device::Device *> devices(k3bcore->deviceManager()->allDevices()); 0244 if( dvdOnly ) { 0245 if( rwOnly ) 0246 devices = k3bcore->deviceManager()->dvdWriter(); 0247 else 0248 devices = k3bcore->deviceManager()->dvdReader(); 0249 } 0250 else if( rwOnly ) 0251 devices = k3bcore->deviceManager()->cdWriter(); 0252 else 0253 devices = k3bcore->deviceManager()->cdReader(); 0254 0255 for( QList<K3b::Device::Device *>::const_iterator it = devices.constBegin(); 0256 it != devices.constEnd(); ++it ) { 0257 if ( d->ignoreDevice == *it ) { 0258 continue; 0259 } 0260 0261 K3b::Medium medium = k3bappcore->mediaCache()->medium( *it ); 0262 0263 if( showMedium( medium ) ) { 0264 addMedium( *it ); 0265 } 0266 else if( !( medium.diskInfo().diskState() & (Device::STATE_NO_MEDIA|Device::STATE_UNKNOWN) ) ) { 0267 d->excludedMediums.append( medium ); 0268 } 0269 } 0270 0271 // 0272 // Now in case no usable medium was found show the user a little message 0273 // 0274 if( d->devices.isEmpty() ) { 0275 showNoMediumMessage(); 0276 if( selected != 0 ) { 0277 // inform that we have no medium at all 0278 emit selectionChanged( 0 ); 0279 } 0280 } 0281 else if( selected && d->deviceIndexMap.contains( selected ) ) { 0282 setCurrentIndex( d->deviceIndexMap[selected] ); 0283 } 0284 else { 0285 emit selectionChanged( selectedDevice() ); 0286 } 0287 0288 // did the selection of devices change 0289 if( !( d->devices == oldDevices ) ) { 0290 emit newMedia(); 0291 for( int i = 0; i < d->devices.count(); ++i ) { 0292 int j = 0; 0293 for( j = 0; j < oldDevices.count(); ++j ) { 0294 if( oldDevices[j] == d->devices[i] ) 0295 break; 0296 } 0297 if( j == oldDevices.count() ) { 0298 // prefer a newly inserted medium over the previously selected 0299 setSelectedDevice( d->devices[i] ); 0300 emit newMedium( d->devices[i] ); 0301 } 0302 } 0303 } 0304 } 0305 0306 0307 void K3b::MediaSelectionComboBox::updateMedium( K3b::Device::Device* ) 0308 { 0309 // for now we simply rebuild the whole list 0310 updateMedia(); 0311 } 0312 0313 0314 void K3b::MediaSelectionComboBox::addMedium( K3b::Device::Device* dev ) 0315 { 0316 // 0317 // In case we only want an empty medium (this might happen in case the 0318 // the medium is rewritable) we do not care about the contents but tell 0319 // the user that the medium is rewritable. 0320 // Otherwise we show the contents type since this might also be used 0321 // for source selection. 0322 // 0323 QString s = mediumString( k3bappcore->mediaCache()->medium( dev ) ); 0324 0325 // 0326 // Now let's see if this string is already contained in the list 0327 // and if so add the device name to both 0328 // 0329 if( d->mediaStringMap.contains( s ) ) { 0330 // 0331 // insert the modified string 0332 // 0333 addItem( s + QString(" (%1 - %2)").arg(dev->vendor()).arg(dev->description()) ); 0334 setItemData( count()-1, QVariant::fromValue(k3bappcore->mediaCache()->medium( dev )), MediumDelegate::MediumRole ); 0335 0336 // 0337 // change the already existing string if we did not already do so 0338 // (which happens if more than 2 entries have the same medium string) 0339 // 0340 int prevIndex = d->mediaStringMap[s]; 0341 if( prevIndex >= 0 ) 0342 setItemText( prevIndex,itemText(prevIndex) + QString(" (%1 - %2)").arg(d->devices[prevIndex]->vendor()).arg(d->devices[prevIndex]->description() )); 0343 0344 // 0345 // mark the string as already changed 0346 // 0347 d->mediaStringMap[s] = -1; 0348 } 0349 else { 0350 // 0351 // insert the plain medium string 0352 // 0353 addItem( s ); 0354 setItemData( count()-1, QVariant::fromValue(k3bappcore->mediaCache()->medium( dev )), MediumDelegate::MediumRole ); 0355 d->mediaStringMap[s] = count()-1; 0356 } 0357 0358 // 0359 // update the helper structures 0360 // 0361 d->deviceIndexMap[dev] = count()-1; 0362 d->devices.append( dev ); 0363 0364 setItemData( count()-1, mediumToolTip( k3bappcore->mediaCache()->medium( dev ) ), Qt::ToolTipRole ); 0365 } 0366 0367 0368 void K3b::MediaSelectionComboBox::slotDeviceManagerChanged( K3b::Device::DeviceManager* ) 0369 { 0370 updateMedia(); 0371 } 0372 0373 0374 bool K3b::MediaSelectionComboBox::showMedium( const K3b::Medium& m ) const 0375 { 0376 // 0377 // also use if wantedMediumState empty and medium rewritable 0378 // because we can always format/erase/overwrite it 0379 // 0380 // DVD+RW and DVD-RW restr. ovwr. are never reported as appendable 0381 // 0382 return( m.diskInfo().mediaType() & d->wantedMediumType 0383 0384 && 0385 0386 ( m.content() & d->wantedMediumContent ) 0387 0388 && 0389 0390 ( m.diskInfo().diskState() & d->wantedMediumState 0391 || 0392 ( d->wantedMediumState & K3b::Device::STATE_EMPTY && 0393 m.diskInfo().rewritable() ) 0394 || 0395 ( d->wantedMediumState & K3b::Device::STATE_INCOMPLETE && 0396 !m.diskInfo().empty() && 0397 m.diskInfo().mediaType() & (K3b::Device::MEDIA_DVD_PLUS_RW|K3b::Device::MEDIA_DVD_RW_OVWR) ) ) 0398 0399 && 0400 0401 ( d->wantedMediumSize == 0 || // no specific size requested 0402 d->wantedMediumSize <= m.diskInfo().capacity() || // size fits 0403 ( !d->wantedMediumState.testFlag( K3b::Device::STATE_COMPLETE ) && // size does not fit but an empty/appendable medium in overburn mode is requested 0404 IsOverburnAllowed( d->wantedMediumSize, m.diskInfo().capacity() ) ) ) 0405 ); 0406 } 0407 0408 0409 QString K3b::MediaSelectionComboBox::mediumString( const K3b::Medium& medium ) const 0410 { 0411 return medium.shortString(); 0412 } 0413 0414 0415 QString K3b::MediaSelectionComboBox::mediumToolTip( const K3b::Medium& m ) const 0416 { 0417 return m.longString( Medium::WithContents|Medium::WithDevice ); 0418 } 0419 0420 0421 QString K3b::MediaSelectionComboBox::noMediumMessage() const 0422 { 0423 if( d->wantedMediumContent && d->wantedMediumContent != Medium::ContentAll ) 0424 return Medium::mediaRequestString( d->wantedMediumContent ); 0425 else 0426 return Medium::mediaRequestString( d->wantedMediumType, d->wantedMediumState, d->wantedMediumSize ); 0427 } 0428 0429 QStringList K3b::MediaSelectionComboBox::noMediumMessages() const 0430 { 0431 if( d->wantedMediumContent && d->wantedMediumContent != Medium::ContentAll ) 0432 return QStringList( Medium::mediaRequestString( d->wantedMediumContent ) ); 0433 else 0434 return Medium::mediaRequestStrings( d->excludedMediums, d->wantedMediumType, d->wantedMediumState, d->wantedMediumSize ); 0435 } 0436 0437 0438 void K3b::MediaSelectionComboBox::slotUpdateToolTip( K3b::Device::Device* dev ) 0439 { 0440 // update the tooltip for the combobox (the tooltip for the dropdown box is created in addMedium) 0441 setToolTip( dev ? mediumToolTip( k3bappcore->mediaCache()->medium( dev ) ) : QString() ); 0442 } 0443 0444 #include "moc_k3bmediaselectioncombobox.cpp"