File indexing completed on 2024-05-05 04:51:45
0001 /* 0002 SPDX-FileCopyrightText: 2003-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-FileCopyrightText: 2009-2011 Michal Malek <michalm@jabster.pl> 0004 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 0010 #include "k3bfillstatusdisplay.h" 0011 #include "k3bdoc.h" 0012 0013 #include "k3bapplication.h" 0014 #include "k3bmediaselectiondialog.h" 0015 #include "k3bdevice.h" 0016 #include "k3bdevicemanager.h" 0017 #include "k3bmsf.h" 0018 #include "k3bmediacache.h" 0019 #include "k3baction.h" 0020 #include "k3bthememanager.h" 0021 0022 #include <KColorScheme> 0023 #include <KConfigGroup> 0024 #include <KSharedConfig> 0025 #include <KLocalizedString> 0026 #include <KIO/Global> 0027 #include <KMessageBox> 0028 0029 #include <QActionGroup> 0030 #include <QDebug> 0031 #include <QEvent> 0032 #include <QLocale> 0033 #include <QRect> 0034 #include <QTimer> 0035 #include <QBrush> 0036 #include <QColor> 0037 #include <QFont> 0038 #include <QFontMetrics> 0039 #include <QMouseEvent> 0040 #include <QPainter> 0041 #include <QPaintEvent> 0042 #include <QPixmap> 0043 #include <QValidator> 0044 #include <QFrame> 0045 #include <QHBoxLayout> 0046 #include <QInputDialog> 0047 #include <QMenu> 0048 #include <QStyle> 0049 #include <QStyleOptionProgressBar> 0050 #include <QToolButton> 0051 #include <QToolTip> 0052 #include <QWhatsThis> 0053 0054 0055 class K3b::FillStatusDisplayWidget::Private 0056 { 0057 public: 0058 K3b::Msf cdSize; 0059 bool showTime; 0060 K3b::Doc* doc; 0061 }; 0062 0063 0064 K3b::FillStatusDisplayWidget::FillStatusDisplayWidget( K3b::Doc* doc, QWidget* parent ) 0065 : QWidget( parent ) 0066 { 0067 d = new Private(); 0068 d->doc = doc; 0069 setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred ) ); 0070 } 0071 0072 0073 K3b::FillStatusDisplayWidget::~FillStatusDisplayWidget() 0074 { 0075 delete d; 0076 } 0077 0078 0079 const K3b::Msf& K3b::FillStatusDisplayWidget::cdSize() const 0080 { 0081 return d->cdSize; 0082 } 0083 0084 0085 void K3b::FillStatusDisplayWidget::setShowTime( bool b ) 0086 { 0087 d->showTime = b; 0088 update(); 0089 } 0090 0091 0092 void K3b::FillStatusDisplayWidget::setCdSize( const K3b::Msf& size ) 0093 { 0094 d->cdSize = size; 0095 update(); 0096 } 0097 0098 0099 QSize K3b::FillStatusDisplayWidget::sizeHint() const 0100 { 0101 return minimumSizeHint(); 0102 } 0103 0104 0105 QSize K3b::FillStatusDisplayWidget::minimumSizeHint() const 0106 { 0107 const int margin = style()->pixelMetric( QStyle::PM_ButtonMargin ); 0108 const QFontMetrics fm( font() ); 0109 return QSize( -1, fm.height() + 2 * margin ); 0110 } 0111 0112 0113 void K3b::FillStatusDisplayWidget::mousePressEvent( QMouseEvent* e ) 0114 { 0115 if( e->button() == Qt::RightButton ) 0116 emit contextMenu( e->globalPos() ); 0117 } 0118 0119 0120 void K3b::FillStatusDisplayWidget::paintEvent( QPaintEvent* ) 0121 { 0122 QPainter p( this ); 0123 0124 const QPalette::ColorGroup colorGroup = isEnabled() ? QPalette::Normal : QPalette::Disabled; 0125 0126 const Msf docSize = d->doc->length(); 0127 const Msf cdSize = d->cdSize; 0128 const Msf maxValue = (cdSize > docSize ? cdSize : docSize) + ( 10*60*75 ); 0129 const Msf tolerance = 60*75; 0130 0131 QBrush fillBrush; 0132 if( docSize <= cdSize - tolerance ) { 0133 fillBrush = KColorScheme( colorGroup, KColorScheme::Selection ).background( KColorScheme::PositiveBackground ); 0134 } 0135 else if( docSize > cdSize + tolerance ) { 0136 fillBrush = KColorScheme( colorGroup, KColorScheme::Selection ).background( KColorScheme::NegativeBackground ); 0137 } 0138 else { 0139 fillBrush = KColorScheme( colorGroup, KColorScheme::Selection ).background( KColorScheme::NeutralBackground ); 0140 } 0141 0142 QPen normalPen = KColorScheme(colorGroup, KColorScheme::Window).foreground(KColorScheme::NormalText).color(); 0143 if (K3b::Theme* theme = k3bappcore->themeManager()->currentTheme()) { 0144 normalPen.setColor(theme->foregroundColor()); 0145 } 0146 const QPen fillPen = KColorScheme( colorGroup, KColorScheme::Selection ).foreground( KColorScheme::NormalText ).color(); 0147 0148 QStyleOptionProgressBar sopb; 0149 sopb.direction = layoutDirection(); 0150 sopb.fontMetrics = fontMetrics(); 0151 sopb.palette = palette(); 0152 sopb.palette.setBrush( QPalette::Highlight, fillBrush ); 0153 QFont overSizeFont(font()); 0154 int fontPointSize = qMax(8, overSizeFont.pointSize() - 4); 0155 sopb.rect = rect(); 0156 sopb.rect.setY(sopb.rect.y() + fontPointSize); 0157 sopb.state = isEnabled() ? QStyle::State_Enabled : QStyle::State_None; 0158 sopb.minimum = 0; 0159 sopb.maximum = maxValue.totalFrames(); 0160 sopb.progress = docSize.totalFrames(); 0161 style()->drawControl( QStyle::CE_ProgressBar, &sopb, &p ); 0162 0163 QRect barRect = style()->subElementRect(QStyle::SE_ProgressBarContents, &sopb); 0164 barRect.setY(rect().y()); 0165 0166 // so split width() in maxValue pieces 0167 double one = (double)barRect.width() / (double)maxValue.totalFrames(); 0168 0169 QRect crect( barRect ); 0170 crect.setWidth( (int)(one*(double)docSize.totalFrames()) ); 0171 0172 // ==================================================================================== 0173 // Now the colored bar is painted 0174 // Continue with the texts 0175 // ==================================================================================== 0176 0177 // first we determine the text to display 0178 // ==================================================================================== 0179 QString docSizeText; 0180 if( d->showTime ) 0181 docSizeText = i18n("%1 min", d->doc->length().toString(false)); 0182 else 0183 docSizeText = KIO::convertSize( d->doc->size() ); 0184 0185 QString overSizeText; 0186 if( d->cdSize.mode1Bytes() >= d->doc->size() ) 0187 overSizeText = i18n("Available: %1 of %2", 0188 d->showTime 0189 ? i18n("%1 min", (cdSize - d->doc->length()).toString(false) ) 0190 : KIO::convertSize( (cdSize - d->doc->length()).mode1Bytes() ), 0191 d->showTime 0192 ? i18n("%1 min", cdSize.toString(false)) 0193 : KIO::convertSize( cdSize.mode1Bytes() ) ); 0194 else 0195 overSizeText = i18n("Capacity exceeded by %1", 0196 d->showTime 0197 ? i18n("%1 min", (d->doc->length() - cdSize ).toString(false)) 0198 : KIO::convertSize( (long long)d->doc->size() - cdSize.mode1Bytes() ) ); 0199 // ==================================================================================== 0200 0201 // calculate the medium size marker 0202 // ==================================================================================== 0203 int mediumSizeMarkerPos = barRect.left() + (int)(one*cdSize.lba()); 0204 QPoint mediumSizeMarkerFrom( mediumSizeMarkerPos, barRect.bottom() ); 0205 QPoint mediumSizeMarkerTo( mediumSizeMarkerPos, barRect.top() + barRect.height()/2 ); 0206 // ==================================================================================== 0207 0208 // we want to draw the docSizeText centered in the filled area 0209 // if there is not enough space we just align it left 0210 // ==================================================================================== 0211 int docSizeTextPos = 0; 0212 int docSizeTextLength = fontMetrics().boundingRect(docSizeText).width(); 0213 if( docSizeTextLength + 5 > crect.width() ) { 0214 docSizeTextPos = crect.left() + 5; // a little margin 0215 } 0216 else { 0217 docSizeTextPos = ( crect.width() - docSizeTextLength ) / 2; 0218 0219 // make sure the text does not cross the medium size marker 0220 if( docSizeTextPos <= mediumSizeMarkerPos && mediumSizeMarkerPos <= docSizeTextPos + docSizeTextLength ) 0221 docSizeTextPos = qMax( crect.left() + 5, mediumSizeMarkerPos - docSizeTextLength - 5 ); 0222 } 0223 // ==================================================================================== 0224 0225 // calculate the over size text 0226 // ==================================================================================== 0227 overSizeFont.setPointSize(fontPointSize); 0228 overSizeFont.setBold(false); 0229 0230 QRect overSizeTextRect( barRect ); 0231 int overSizeTextLength = QFontMetrics(overSizeFont).boundingRect(overSizeText).width(); 0232 if( overSizeTextLength + 5 > overSizeTextRect.width() - (int)(one*cdSize.totalFrames()) ) { 0233 // we don't have enough space on the right, so we paint to the left of the line 0234 overSizeTextRect.setLeft( (int)(one*cdSize.totalFrames()) - overSizeTextLength - 5 ); 0235 } 0236 else { 0237 overSizeTextRect.setLeft( mediumSizeMarkerPos + 5 ); 0238 } 0239 0240 // make sure the two text do not overlap (this does not cover all cases though) 0241 if( overSizeTextRect.left() < docSizeTextPos + docSizeTextLength ) 0242 docSizeTextPos = qMax( crect.left() + 5, qMin( overSizeTextRect.left() - docSizeTextLength - 5, mediumSizeMarkerPos - docSizeTextLength - 5 ) ); 0243 0244 QRect docTextRect( barRect ); 0245 docTextRect.setLeft( docSizeTextPos ); 0246 0247 // Draw the fill part 0248 p.setPen( fillPen ); 0249 p.setClipRect( QStyle::visualRect( layoutDirection(), barRect, crect ) ); 0250 p.drawLine( QStyle::visualPos( layoutDirection(), barRect, mediumSizeMarkerFrom ), 0251 QStyle::visualPos( layoutDirection(), barRect, mediumSizeMarkerTo ) ); 0252 p.drawText( QStyle::visualRect( layoutDirection(), barRect, docTextRect ), 0253 QStyle::visualAlignment( layoutDirection(), Qt::AlignLeft | Qt::AlignVCenter ), docSizeText ); 0254 p.setFont(overSizeFont); 0255 p.drawText( QStyle::visualRect( layoutDirection(), barRect, overSizeTextRect ), 0256 QStyle::visualAlignment( layoutDirection(), Qt::AlignLeft | Qt::AlignVCenter ), overSizeText ); 0257 0258 // Draw the remain part 0259 p.setPen( normalPen ); 0260 p.setClipRect( QStyle::visualRect( layoutDirection(), barRect, 0261 QRect( crect.right(), barRect.top(), barRect.width()-crect.width(), barRect.height() ) ) ); 0262 p.drawLine( QStyle::visualPos( layoutDirection(), barRect, mediumSizeMarkerFrom ), 0263 QStyle::visualPos( layoutDirection(), barRect, mediumSizeMarkerTo ) ); 0264 p.setFont( font() ); 0265 p.drawText( QStyle::visualRect( layoutDirection(), barRect, docTextRect ), 0266 QStyle::visualAlignment( layoutDirection(), Qt::AlignLeft | Qt::AlignVCenter ), docSizeText ); 0267 p.setFont(overSizeFont); 0268 p.drawText( QStyle::visualRect( layoutDirection(), barRect, overSizeTextRect ), 0269 QStyle::visualAlignment( layoutDirection(), Qt::AlignLeft | Qt::AlignVCenter ), overSizeText ); 0270 // ==================================================================================== 0271 } 0272 0273 0274 0275 // ---------------------------------------------------------------------------------------------------- 0276 0277 0278 0279 class K3b::FillStatusDisplay::Private 0280 { 0281 public: 0282 KActionCollection* actionCollection; 0283 QAction* actionShowMinutes; 0284 QAction* actionShowMegs; 0285 QActionGroup* cdSizeGroup; 0286 QAction* actionAuto; 0287 QAction* action74Min; 0288 QAction* action80Min; 0289 QAction* action100Min; 0290 QAction* actionDvd4_7GB; 0291 QAction* actionDvdDoubleLayer; 0292 QAction* actionBD25; 0293 QAction* actionBD50; 0294 0295 QAction* actionCustomSize; 0296 QAction* actionDetermineSize; 0297 QAction* actionSaveUserDefaults; 0298 QAction* actionLoadUserDefaults; 0299 0300 QMenu* popup; 0301 0302 QToolButton* buttonMenu; 0303 0304 K3b::FillStatusDisplayWidget* displayWidget; 0305 0306 bool showTime; 0307 0308 K3b::Doc* doc; 0309 0310 QTimer updateTimer; 0311 0312 void setCdSize( const K3b::Msf& size ); 0313 }; 0314 0315 0316 void K3b::FillStatusDisplay::Private::setCdSize( const K3b::Msf& size ) 0317 { 0318 // Remove check mark from the currently checked action 0319 if( QAction* checked = cdSizeGroup->checkedAction() ) { 0320 checked->setChecked( false ); 0321 } 0322 0323 switch( size.totalFrames() ) { 0324 case MediaSizeCd74Min: 0325 case 650*512: 0326 displayWidget->setCdSize( MediaSizeCd74Min ); 0327 action74Min->setChecked( true ); 0328 break; 0329 case MediaSizeCd80Min: 0330 case 700*512: 0331 displayWidget->setCdSize( MediaSizeCd80Min ); 0332 action80Min->setChecked( true ); 0333 break; 0334 case MediaSizeCd100Min: 0335 case 880*512: 0336 displayWidget->setCdSize( MediaSizeCd100Min ); 0337 action100Min->setChecked( true ); 0338 break; 0339 case MediaSizeDvd4Gb: 0340 case 2306867: // rounded 4.4*1024*512 0341 displayWidget->setCdSize( MediaSizeDvd4Gb ); 0342 actionDvd4_7GB->setChecked( true ); 0343 break; 0344 case MediaSizeDvd8Gb: 0345 case 8*1024*512: 0346 displayWidget->setCdSize( MediaSizeDvd8Gb ); 0347 actionDvdDoubleLayer->setChecked( true ); 0348 break; 0349 case MediaSizeBluRay25Gb: 0350 //case 25*1024*512: 0351 displayWidget->setCdSize( MediaSizeBluRay25Gb ); 0352 actionBD25->setChecked( true ); 0353 break; 0354 case MediaSizeBluRay50Gb: 0355 //case 50*1024*512: 0356 displayWidget->setCdSize( MediaSizeBluRay50Gb ); 0357 actionBD50->setChecked( true ); 0358 break; 0359 default: 0360 displayWidget->setCdSize( size ); 0361 break; 0362 } 0363 } 0364 0365 0366 K3b::FillStatusDisplay::FillStatusDisplay( K3b::Doc* doc, QWidget *parent ) 0367 : QFrame(parent) 0368 { 0369 d = new Private; 0370 d->doc = doc; 0371 0372 d->displayWidget = new K3b::FillStatusDisplayWidget( doc, this ); 0373 d->buttonMenu = new QToolButton( this ); 0374 d->buttonMenu->setIcon( QIcon::fromTheme( "configure" ) ); 0375 d->buttonMenu->setAutoRaise( true ); 0376 d->buttonMenu->setToolTip( i18n( "Set medium size" ) ); 0377 connect( d->buttonMenu, SIGNAL(clicked()), this, SLOT(slotMenuButtonClicked()) ); 0378 0379 QHBoxLayout* layout = new QHBoxLayout( this ); 0380 layout->setSpacing( frameWidth() ); 0381 layout->setContentsMargins( frameWidth(), frameWidth(), frameWidth(), frameWidth() ); 0382 layout->addWidget( d->displayWidget, 1, Qt::AlignVCenter ); 0383 layout->addWidget( d->buttonMenu ); 0384 0385 setupPopupMenu(); 0386 0387 connect( d->doc, SIGNAL(changed()), this, SLOT(slotDocChanged()) ); 0388 connect( &d->updateTimer, SIGNAL(timeout()), this, SLOT(slotUpdateDisplay()) ); 0389 connect( k3bappcore->mediaCache(), SIGNAL(mediumChanged(K3b::Device::Device*)), 0390 this, SLOT(slotMediumChanged(K3b::Device::Device*)) ); 0391 0392 slotLoadUserDefaults(); 0393 } 0394 0395 K3b::FillStatusDisplay::~FillStatusDisplay() 0396 { 0397 delete d; 0398 } 0399 0400 0401 void K3b::FillStatusDisplay::setupPopupMenu() 0402 { 0403 d->actionCollection = new KActionCollection( this ); 0404 0405 // we use a nother popup for the dvd sizes 0406 d->popup = new QMenu( this ); 0407 0408 d->actionShowMinutes = K3b::createToggleAction( this, i18n("Minutes"), 0, 0, this, SLOT(showTime()), 0409 d->actionCollection, "fillstatus_show_minutes" ); 0410 d->actionShowMegs = K3b::createToggleAction( this, i18n("Megabytes"), 0, 0, this, SLOT(showSize()), 0411 d->actionCollection, "fillstatus_show_megabytes" ); 0412 0413 d->actionAuto = K3b::createToggleAction( this, i18n("Automatic Size"), 0, 0, this, SLOT(slotAutoSize()), 0414 d->actionCollection, "fillstatus_auto" ); 0415 d->action74Min = K3b::createToggleAction( this, i18n("%1 MB",650), 0, 0, this, SLOT(slot74Minutes()), 0416 d->actionCollection, "fillstatus_74minutes" ); 0417 d->action80Min = K3b::createToggleAction( this, i18n("%1 MB",700), 0, 0, this, SLOT(slot80Minutes()), 0418 d->actionCollection, "fillstatus_80minutes" ); 0419 d->action100Min = K3b::createToggleAction( this, i18n("%1 MB",880), 0, 0, this, SLOT(slot100Minutes()), 0420 d->actionCollection, "fillstatus_100minutes" ); 0421 d->actionDvd4_7GB = K3b::createToggleAction( this, KIO::convertSizeFromKiB((int)(4.4*1024.0*1024.0)), 0, 0, this, SLOT(slotDvd4_7GB()), 0422 d->actionCollection, "fillstatus_dvd_4_7gb" ); 0423 d->actionDvdDoubleLayer = K3b::createToggleAction( this, KIO::convertSizeFromKiB((int)(8.0*1024.0*1024.0)), 0424 0, 0, this, SLOT(slotDvdDoubleLayer()), 0425 d->actionCollection, "fillstatus_dvd_double_layer" ); 0426 d->actionBD25 = K3b::createToggleAction( this, KIO::convertSize(K3b::Msf(K3b::MediaSizeBluRay25Gb).mode1Bytes()), 0, 0, this, SLOT(slotBD25()), 0427 d->actionCollection, "fillstatus_bd_25" ); 0428 d->actionBD50 = K3b::createToggleAction( this, KIO::convertSize(K3b::Msf(K3b::MediaSizeBluRay50Gb).mode1Bytes()), 0, 0, this, SLOT(slotBD50()), 0429 d->actionCollection, "fillstatus_bd_50" ); 0430 0431 d->actionCustomSize = K3b::createAction( this, i18n("Custom..."), 0, 0, this, SLOT(slotCustomSize()), 0432 d->actionCollection, "fillstatus_custom_size" ); 0433 d->actionDetermineSize = K3b::createAction( this, i18n("From Medium..."), "media-optical", 0, 0434 this, SLOT(slotDetermineSize()), 0435 d->actionCollection, "fillstatus_size_from_disk" ); 0436 0437 QActionGroup* showSizeInGroup = new QActionGroup( this ); 0438 showSizeInGroup->addAction( d->actionShowMegs ); 0439 showSizeInGroup->addAction( d->actionShowMinutes ); 0440 0441 d->cdSizeGroup = new QActionGroup( this ); 0442 d->cdSizeGroup->addAction( d->actionAuto ); 0443 d->cdSizeGroup->addAction( d->action74Min ); 0444 d->cdSizeGroup->addAction( d->action80Min ); 0445 d->cdSizeGroup->addAction( d->action100Min ); 0446 d->cdSizeGroup->addAction( d->actionDvd4_7GB ); 0447 d->cdSizeGroup->addAction( d->actionDvdDoubleLayer ); 0448 d->cdSizeGroup->addAction( d->actionBD25 ); 0449 d->cdSizeGroup->addAction( d->actionBD50 ); 0450 0451 d->actionLoadUserDefaults = K3b::createAction( this, i18n("User Defaults"), "", 0, 0452 this, SLOT(slotLoadUserDefaults()), 0453 d->actionCollection, "load_user_defaults" ); 0454 d->actionSaveUserDefaults = K3b::createAction( this, i18n("Save User Defaults"), "", 0, 0455 this, SLOT(slotSaveUserDefaults()), 0456 d->actionCollection, "save_user_defaults" ); 0457 0458 QAction* dvdSizeInfoAction = K3b::createAction( this, i18n("Why 4.4 instead of 4.7?"), "", 0, 0459 this, SLOT(slotWhy44()), 0460 d->actionCollection, "why_44_gb" ); 0461 0462 d->popup->addSection( i18n("Show Size In") ); 0463 d->popup->addAction( d->actionShowMinutes ); 0464 d->popup->addAction( d->actionShowMegs ); 0465 d->popup->addSeparator(); 0466 d->popup->addAction( d->actionAuto ); 0467 if ( d->doc->supportedMediaTypes() & K3b::Device::MEDIA_CD_ALL ) { 0468 d->popup->addSection( i18n("CD Size") ); 0469 d->popup->addAction( d->action74Min ); 0470 d->popup->addAction( d->action80Min ); 0471 d->popup->addAction( d->action100Min ); 0472 } 0473 if ( d->doc->supportedMediaTypes() & K3b::Device::MEDIA_DVD_ALL ) { 0474 d->popup->addSection( i18n("DVD Size") ); 0475 d->popup->addAction( dvdSizeInfoAction ); 0476 d->popup->addAction( d->actionDvd4_7GB ); 0477 d->popup->addAction( d->actionDvdDoubleLayer ); 0478 } 0479 if ( d->doc->supportedMediaTypes() & K3b::Device::MEDIA_BD_ALL ) { 0480 d->popup->addSection( i18n("Blu-ray Size") ); 0481 d->popup->addAction( d->actionBD25 ); 0482 d->popup->addAction( d->actionBD50 ); 0483 } 0484 d->popup->addSeparator(); 0485 d->popup->addAction( d->actionCustomSize ); 0486 d->popup->addAction( d->actionDetermineSize ); 0487 d->popup->addSeparator(); 0488 d->popup->addAction( d->actionLoadUserDefaults ); 0489 d->popup->addAction( d->actionSaveUserDefaults ); 0490 0491 connect( d->displayWidget, SIGNAL(contextMenu(QPoint)), this, SLOT(slotPopupMenu(QPoint)) ); 0492 } 0493 0494 0495 void K3b::FillStatusDisplay::showSize() 0496 { 0497 d->actionShowMegs->setChecked( true ); 0498 0499 d->action74Min->setText( i18n("%1 MB",650) ); 0500 d->action80Min->setText( i18n("%1 MB",700) ); 0501 d->action100Min->setText( i18n("%1 MB",880) ); 0502 0503 d->showTime = false; 0504 d->displayWidget->setShowTime(false); 0505 } 0506 0507 void K3b::FillStatusDisplay::showTime() 0508 { 0509 d->actionShowMinutes->setChecked( true ); 0510 0511 d->action74Min->setText( i18np("unused", "%1 minutes", 74) ); 0512 d->action80Min->setText( i18np("unused", "%1 minutes", 80) ); 0513 d->action100Min->setText( i18np("unused", "%1 minutes", 100) ); 0514 0515 d->showTime = true; 0516 d->displayWidget->setShowTime(true); 0517 } 0518 0519 0520 void K3b::FillStatusDisplay::slotAutoSize() 0521 { 0522 slotMediumChanged( 0 ); 0523 } 0524 0525 0526 void K3b::FillStatusDisplay::slot74Minutes() 0527 { 0528 d->displayWidget->setCdSize( K3b::MediaSizeCd74Min ); 0529 } 0530 0531 0532 void K3b::FillStatusDisplay::slot80Minutes() 0533 { 0534 d->displayWidget->setCdSize( K3b::MediaSizeCd80Min ); 0535 } 0536 0537 0538 void K3b::FillStatusDisplay::slot100Minutes() 0539 { 0540 d->displayWidget->setCdSize( K3b::MediaSizeCd100Min ); 0541 } 0542 0543 0544 void K3b::FillStatusDisplay::slotDvd4_7GB() 0545 { 0546 d->displayWidget->setCdSize( K3b::MediaSizeDvd4Gb ); 0547 } 0548 0549 0550 void K3b::FillStatusDisplay::slotDvdDoubleLayer() 0551 { 0552 d->displayWidget->setCdSize( K3b::MediaSizeDvd8Gb ); 0553 } 0554 0555 0556 void K3b::FillStatusDisplay::slotBD25() 0557 { 0558 d->displayWidget->setCdSize( K3b::MediaSizeBluRay25Gb ); 0559 } 0560 0561 0562 void K3b::FillStatusDisplay::slotBD50() 0563 { 0564 d->displayWidget->setCdSize( K3b::MediaSizeBluRay50Gb ); 0565 } 0566 0567 0568 void K3b::FillStatusDisplay::slotWhy44() 0569 { 0570 QWhatsThis::showText( QCursor::pos(), 0571 i18n("<p><b>Why does K3b offer 4.4 GB and 8.0 GB instead of 4.7 and 8.5 like " 0572 "it says on the media?</b>" 0573 "<p>A single layer DVD media has a capacity of approximately " 0574 "4.4 GB which equals 4.4*1024<sup>3</sup> bytes. Media producers just " 0575 "calculate with 1000 instead of 1024 for advertising reasons.<br>" 0576 "This results in 4.4*1024<sup>3</sup>/1000<sup>3</sup> = 4.7 GB."), 0577 this ); 0578 } 0579 0580 0581 void K3b::FillStatusDisplay::slotCustomSize() 0582 { 0583 // allow the units to be translated 0584 QString gbS = i18n("GB"); 0585 QString mbS = i18n("MB"); 0586 QString minS = i18n("min"); 0587 0588 QLocale const locale = QLocale::system(); 0589 0590 // we certainly do not have BD- or HD-DVD-only projects 0591 QString defaultCustom; 0592 if( d->doc->supportedMediaTypes() & K3b::Device::MEDIA_CD_ALL ) { 0593 defaultCustom = d->showTime ? QString("74") + minS : QString("650") + mbS; 0594 } 0595 else { 0596 defaultCustom = locale.toString(4.4,'g',1) + gbS; 0597 } 0598 0599 static const QRegularExpression rx( QString("(\\d+\\") + locale.decimalPoint() + "?\\d*)(" + gbS + '|' + mbS + '|' + minS + ")?" ); 0600 QRegularExpressionValidator validator( rx, this ); 0601 bool ok; 0602 QString size = QInputDialog::getText( this, 0603 i18n("Custom Size"), 0604 i18n("<p>Please specify the size of the medium. Use suffixes <b>GB</b>,<b>MB</b>, " 0605 "and <b>min</b> for <em>gigabytes</em>, <em>megabytes</em>, and <em>minutes</em>" 0606 " respectively."), 0607 QLineEdit::Normal, 0608 defaultCustom, 0609 &ok ); 0610 0611 int validatorPos; 0612 if( ok && validator.validate( size, validatorPos ) ) { 0613 // determine size 0614 auto match = rx.match( size ); 0615 if( match.hasMatch() ) { 0616 QString valStr = match.captured(1); 0617 if( valStr.endsWith( locale.decimalPoint() ) ) 0618 valStr += '0'; 0619 double val = locale.toDouble( valStr, &ok ); 0620 if( ok ) { 0621 QString s = match.captured(2); 0622 if( s == gbS ) 0623 val *= 1024*512; 0624 else if( s == mbS || (s.isEmpty() && !d->showTime) ) 0625 val *= 512; 0626 else 0627 val *= 60*75; 0628 d->setCdSize( static_cast<int>( val ) ); 0629 } 0630 } 0631 } 0632 } 0633 0634 0635 void K3b::FillStatusDisplay::slotMenuButtonClicked() 0636 { 0637 QRect alignedMenu = style()->alignedRect( layoutDirection(), Qt::AlignRight, d->popup->sizeHint(), d->buttonMenu->frameGeometry() ); 0638 alignedMenu.moveBottom( d->buttonMenu->frameGeometry().top() - 1 ); 0639 slotPopupMenu( mapToGlobal( alignedMenu.topLeft() ) ); 0640 } 0641 0642 0643 void K3b::FillStatusDisplay::slotPopupMenu( const QPoint& p ) 0644 { 0645 d->popup->popup(p); 0646 } 0647 0648 0649 void K3b::FillStatusDisplay::slotDetermineSize() 0650 { 0651 bool canceled = false; 0652 K3b::Device::Device* dev = K3b::MediaSelectionDialog::selectMedium( d->doc->supportedMediaTypes(), 0653 K3b::Device::STATE_EMPTY|K3b::Device::STATE_INCOMPLETE, 0654 K3b::Medium::ContentAll, 0655 parentWidget(), 0656 QString(), QString(), &canceled ); 0657 0658 if( dev ) { 0659 K3b::Msf size = k3bappcore->mediaCache()->diskInfo( dev ).capacity(); 0660 if( size > 0 ) 0661 d->setCdSize( size ); 0662 else 0663 KMessageBox::error( parentWidget(), i18n("Medium is not empty.") ); 0664 } 0665 else if( !canceled ) 0666 KMessageBox::error( parentWidget(), i18n("No usable medium found.") ); 0667 } 0668 0669 0670 void K3b::FillStatusDisplay::slotLoadUserDefaults() 0671 { 0672 // load project specific values 0673 KConfigGroup c( KSharedConfig::openConfig(), "default " + d->doc->typeString() + " settings" ); 0674 0675 // defaults to megabytes 0676 d->showTime = c.readEntry( "show minutes", false ); 0677 d->displayWidget->setShowTime(d->showTime); 0678 d->actionShowMegs->setChecked( !d->showTime ); 0679 d->actionShowMinutes->setChecked( d->showTime ); 0680 0681 long size = c.readEntry( "default media size", 0 ); 0682 0683 // Remove check mark from current checked action 0684 if( QAction* checked = d->cdSizeGroup->checkedAction() ) { 0685 checked->setChecked( false ); 0686 } 0687 0688 switch( size ) { 0689 case 0: 0690 // automatic mode 0691 d->actionAuto->setChecked( true ); 0692 break; 0693 case MediaSizeCd74Min: 0694 d->action74Min->setChecked( true ); 0695 break; 0696 case MediaSizeCd80Min: 0697 d->action80Min->setChecked( true ); 0698 break; 0699 case MediaSizeCd100Min: 0700 d->action100Min->setChecked( true ); 0701 break; 0702 case MediaSizeDvd4Gb: 0703 d->actionDvd4_7GB->setChecked( true ); 0704 break; 0705 case MediaSizeDvd8Gb: 0706 d->actionDvdDoubleLayer->setChecked( true ); 0707 break; 0708 case MediaSizeBluRay25Gb: 0709 d->actionBD25->setChecked( true ); 0710 break; 0711 case MediaSizeBluRay50Gb: 0712 d->actionBD50->setChecked( true ); 0713 break; 0714 default: 0715 break; 0716 } 0717 0718 if( size == 0 ) { 0719 slotMediumChanged( 0 ); 0720 } 0721 else { 0722 d->displayWidget->setCdSize( size ); 0723 } 0724 } 0725 0726 0727 void K3b::FillStatusDisplay::slotMediumChanged( K3b::Device::Device* ) 0728 { 0729 if( d->actionAuto->isChecked() ) { 0730 // 0731 // now search for a usable medium 0732 // if we find exactly one usable or multiple with the same size 0733 // we use that size 0734 // 0735 K3b::Medium autoSelectedMedium; 0736 QList<K3b::Device::Device*> devs = k3bcore->deviceManager()->burningDevices(); 0737 0738 Q_FOREACH( K3b::Device::Device* dev, devs ) { 0739 const K3b::Medium medium = k3bappcore->mediaCache()->medium( dev ); 0740 0741 if( ( medium.diskInfo().empty() || 0742 medium.diskInfo().appendable() || 0743 medium.diskInfo().rewritable() ) && 0744 ( medium.diskInfo().mediaType() & d->doc->supportedMediaTypes() ) ) { 0745 0746 // We use a 10% margin to allow the user to fine-tune project sizes 0747 // However, if we have a bigger medium we always use that 0748 if ( ( double )d->doc->size() <= ( double )( medium.diskInfo().capacity().mode1Bytes() ) * 1.1 ) { 0749 0750 // first usable medium 0751 if( !autoSelectedMedium.isValid() ) { 0752 autoSelectedMedium = medium; 0753 } 0754 0755 else { 0756 // prefer the medium which can fit the whole doc 0757 if ( d->doc->length() <= medium.diskInfo().capacity() && 0758 d->doc->length() > autoSelectedMedium.diskInfo().capacity() ) { 0759 autoSelectedMedium = medium; 0760 } 0761 0762 // roughly compare the sizes of the two usable media. If they match, carry on. 0763 else if( medium.diskInfo().capacity().lba()/75/60 0764 != autoSelectedMedium.diskInfo().capacity().lba()/75/60 ) { 0765 // different usable media -> fallback 0766 autoSelectedMedium = K3b::Medium(); 0767 break; 0768 } 0769 } 0770 } 0771 } 0772 } 0773 0774 if( autoSelectedMedium.isValid() ) { 0775 d->displayWidget->setCdSize( autoSelectedMedium.diskInfo().capacity().lba() ); 0776 } 0777 else { 0778 bool haveDVD = !k3bcore->deviceManager()->dvdWriter().isEmpty(); 0779 bool haveBD = !k3bcore->deviceManager()->blueRayWriters().isEmpty(); 0780 0781 0782 // default fallback 0783 // we do not have BD- or HD-DVD only projects 0784 if( ( d->doc->supportedMediaTypes() & K3b::Device::MEDIA_CD_ALL && 0785 d->doc->length().lba() <= MediaSizeCd80Min ) || 0786 !( d->doc->supportedMediaTypes() & ( K3b::Device::MEDIA_DVD_ALL|K3b::Device::MEDIA_BD_ALL ) ) || 0787 ( !haveDVD && !haveBD ) ) { 0788 d->displayWidget->setCdSize( MediaSizeCd80Min ); 0789 } 0790 else if ( haveDVD && ( 0791 ( d->doc->supportedMediaTypes() & K3b::Device::MEDIA_DVD_ALL && 0792 d->doc->length().lba() <= MediaSizeDvd8Gb ) || 0793 !( d->doc->supportedMediaTypes() & K3b::Device::MEDIA_BD_ALL ) || 0794 !haveBD ) ) { 0795 if( d->doc->length().lba() > MediaSizeDvd4Gb ) 0796 d->displayWidget->setCdSize( MediaSizeDvd8Gb ); 0797 else 0798 d->displayWidget->setCdSize( MediaSizeDvd4Gb ); 0799 } 0800 else if ( d->doc->length().lba() <= MediaSizeBluRay25Gb ) { 0801 d->displayWidget->setCdSize( MediaSizeBluRay25Gb ); 0802 } 0803 else { 0804 d->displayWidget->setCdSize( MediaSizeBluRay50Gb ); 0805 } 0806 } 0807 } 0808 } 0809 0810 0811 void K3b::FillStatusDisplay::slotSaveUserDefaults() 0812 { 0813 // save project specific values 0814 KConfigGroup c( KSharedConfig::openConfig(), "default " + d->doc->typeString() + " settings" ); 0815 0816 c.writeEntry( "show minutes", d->showTime ); 0817 c.writeEntry( "default media size", d->actionAuto->isChecked() ? 0 : d->displayWidget->cdSize().lba() ); 0818 } 0819 0820 0821 void K3b::FillStatusDisplay::slotUpdateDisplay() 0822 { 0823 if( d->actionAuto->isChecked() ) { 0824 // 0825 // also update the medium list in case the docs size exceeds the capacity 0826 // 0827 slotMediumChanged( 0 ); 0828 } 0829 else { 0830 d->displayWidget->update(); 0831 } 0832 } 0833 0834 0835 void K3b::FillStatusDisplay::slotDocChanged() 0836 { 0837 // cache updates 0838 if( !d->updateTimer.isActive() ) { 0839 slotUpdateDisplay(); 0840 d->updateTimer.setSingleShot( false ); 0841 d->updateTimer.start( 500 ); 0842 } 0843 } 0844 0845 0846 bool K3b::FillStatusDisplay::event( QEvent* event ) 0847 { 0848 if ( event->type() == QEvent::ToolTip ) { 0849 QHelpEvent* he = ( QHelpEvent* )event; 0850 0851 QToolTip::showText( he->globalPos(), 0852 KIO::convertSize( d->doc->size() ) + 0853 " (" + QLocale::system().toString( d->doc->size() ) + "), " + 0854 i18n("%1 min", d->doc->length().toString(false)) + 0855 " (" + i18n("Right click for media sizes") + ')'); 0856 0857 event->accept(); 0858 0859 return true; 0860 } 0861 0862 return QFrame::event( event ); 0863 } 0864 0865 #include "moc_k3bfillstatusdisplay.cpp"