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"