File indexing completed on 2024-10-06 04:25:59

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <config-k3b.h>
0008 
0009 
0010 #include "k3bdiskinfoview.h"
0011 #include "k3bthememanager.h"
0012 #include "k3bapplication.h"
0013 
0014 #include "k3bdiskinfo.h"
0015 #include "k3bcdtext.h"
0016 #include "k3bdeviceglobals.h"
0017 #include "k3bglobals.h"
0018 #include "k3biso9660.h"
0019 
0020 #include <KCDDB/CDInfo>
0021 
0022 #include <KIconLoader>
0023 #include <KLocalizedString>
0024 #include <KIO/Global>
0025 
0026 #include <QDebug>
0027 #include <QString>
0028 #include <QFont>
0029 #include <QColor>
0030 #include <QPainter>
0031 #include <QPalette>
0032 #include <QPixmap>
0033 #ifdef HAVE_QTWEBENGINEWIDGETS
0034 #include <QWebEngineView>
0035 #endif
0036 #include <QLabel>
0037 #include <QLayout>
0038 #include <QTextBrowser>
0039 
0040 namespace {
0041     QString sectionHeader( const QString& title ) {
0042         return "<h1 class=\"title\">" + title + "</h1>";
0043     }
0044 
0045     QString tableRow( const QString& s1, const QString& s2 ) {
0046         return "<tr><td class=\"infokey\">" + s1 + "</td><td class=\"infovalue\">" + s2 + "</td></tr>";
0047     }
0048 }
0049 
0050 
0051 K3b::DiskInfoView::DiskInfoView( QWidget* parent )
0052     : K3b::MediaContentsView( true,
0053                               Medium::ContentAll,
0054                               Device::MEDIA_ALL|Device::MEDIA_NONE|Device::MEDIA_UNKNOWN,
0055                               Device::STATE_ALL|Device::STATE_NO_MEDIA|Device::STATE_UNKNOWN,
0056                               parent )
0057 {
0058 #ifdef HAVE_QTWEBENGINEWIDGETS
0059     m_infoView = new QWebEngineView( this );
0060 #else
0061     m_infoView = new QTextBrowser( this );
0062 #endif
0063     setMainWidget( m_infoView );
0064 }
0065 
0066 
0067 K3b::DiskInfoView::~DiskInfoView()
0068 {
0069 }
0070 
0071 
0072 void K3b::DiskInfoView::reloadMedium()
0073 {
0074     updateTitle();
0075 
0076     QString s;
0077     K3b::Theme* theme = k3bappcore->themeManager()->currentTheme();
0078     if (medium().diskInfo().diskState() == K3b::Device::STATE_NO_MEDIA) {
0079         s = QString("<font color=\"%1\">%2</font>").arg(theme ?
0080                 theme->palette().color(QPalette::WindowText).name() :
0081                 "green").arg(i18n("No medium present"));
0082     } else {
0083         // FIXME: import a css stylesheet from the theme and, more importantly,
0084         // create a nicer css
0085         // We are not designers :)
0086         s = "<head>"
0087             "<title></title>"
0088             "<style type=\"text/css\">";
0089         if (theme) {
0090             s += QString(".title { padding:4px; font-size:medium; background-color:%1; color:%2 } ")
0091                  .arg(theme->palette().color(QPalette::Window).name())
0092                  .arg(theme->palette().color(QPalette::WindowText).name());
0093         }
0094         s +=  QString(".infovalue { font-weight:bold; padding-left:10px; color:%1; } "
0095               ".infokey { color:%1; } "
0096               ".trackheader { text-align:left; color:%1; } "
0097               ".session { font-style:italic; color:%1; } "
0098               ".cdtext { font-weight:bold; font-style:italic; color:%1; } "
0099               ".tracknumber { color:%1; } "
0100               ".tracktype { color:%1; } "
0101               ".trackattributes { color:%1; } "
0102               ".trackrange { color:%1; } "
0103               ".tracklength { color:%1; } "
0104               "td { vertical-align:top; } ")
0105             .arg(theme->palette().color(QPalette::WindowText).name());
0106         s += "</style>"
0107              "</head>"
0108              "<body>";
0109 
0110         s += sectionHeader(i18n("Medium"));
0111         s += createMediaInfoItems(medium());
0112 
0113         if (medium().content() & K3b::Medium::ContentData) {
0114             s += sectionHeader(i18n("ISO 9660 Filesystem Info"));
0115             s += createIso9660InfoItems(medium().iso9660Descriptor());
0116         }
0117 
0118         if (!medium().toc().isEmpty()) {
0119             s += sectionHeader(i18n("Tracks"));
0120             s += createTrackItems(medium());
0121         }
0122     }
0123 
0124     s += "</body>";
0125 
0126     m_infoView->setHtml(s);
0127 #ifdef K3B_DEBUG
0128     qDebug() << s;
0129 #endif
0130 }
0131 
0132 
0133 void K3b::DiskInfoView::updateTitle()
0134 {
0135     QString title = medium().shortString();
0136     QString subTitle = medium().shortString( Medium::NoStringFlags );
0137     if( title == subTitle )
0138         subTitle.truncate(0);
0139     setTitle( title, subTitle );
0140 
0141     if( medium().diskInfo().diskState() == K3b::Device::STATE_NO_MEDIA ) {
0142         setRightPixmap( K3b::Theme::MEDIA_NONE );
0143     }
0144     else {
0145         if( medium().diskInfo().empty() ) {
0146             setRightPixmap( K3b::Theme::MEDIA_EMPTY );
0147         }
0148         else {
0149             switch( medium().toc().contentType() ) {
0150             case K3b::Device::AUDIO:
0151                 setRightPixmap( K3b::Theme::MEDIA_AUDIO );
0152                 break;
0153             case K3b::Device::DATA: {
0154                 if( medium().content() & K3b::Medium::ContentVideoDVD ) {
0155                     setRightPixmap( K3b::Theme::MEDIA_VIDEO );
0156                 }
0157                 else {
0158                     setRightPixmap( K3b::Theme::MEDIA_DATA );
0159                 }
0160                 break;
0161             }
0162             case K3b::Device::MIXED:
0163                 setRightPixmap( K3b::Theme::MEDIA_MIXED );
0164                 break;
0165             default:
0166                 setRightPixmap( K3b::Theme::MEDIA_NONE );
0167             }
0168         }
0169     }
0170 }
0171 
0172 
0173 namespace {
0174     QString trackItem( const K3b::Medium& medium, int trackIndex ) {
0175         K3b::Device::Track track = medium.toc()[trackIndex];
0176 
0177         QString s = "<tr>";
0178 
0179         // FIXME: Icons
0180 
0181         // track number
0182         s += "<td class=\"tracknumber\">" + QString::number(trackIndex+1).rightJustified( 2, ' ' );
0183         s += "</td>";
0184 
0185         // track type
0186         s += "<td class=\"tracktype\">(";
0187         if( track.type() == K3b::Device::Track::TYPE_AUDIO ) {
0188             //    item->setPixmap( QIcon::fromTheme("audio-x-generic").pixmap(KIconLoader::SizeSmall) );
0189             s += i18n("Audio");
0190         } else {
0191 //            item->setPixmap( QIcon::fromTheme("application-x-tar").pixmap(KIconLoader::SizeSmall) );
0192             if( track.mode() == K3b::Device::Track::MODE1 )
0193                 s += i18n("Data/Mode1");
0194             else if( track.mode() == K3b::Device::Track::MODE2 )
0195                 s += i18n("Data/Mode2");
0196             else if( track.mode() == K3b::Device::Track::XA_FORM1 )
0197                 s += i18n("Data/Mode2 XA Form1");
0198             else if( track.mode() == K3b::Device::Track::XA_FORM2 )
0199                 s += i18n("Data/Mode2 XA Form2");
0200             else
0201                 s += i18n("Data");
0202         }
0203         s += ")</td>";
0204 
0205         // track attributes
0206         s += "<td class=\"trackattributes\">";
0207         s += QString( "%1/%2" )
0208              .arg( track.copyPermitted() ? i18n("copy") : i18n("no copy") )
0209              .arg( track.type() == K3b::Device::Track::TYPE_AUDIO
0210                    ? ( track.preEmphasis() ?  i18n("preemp") : i18n("no preemp") )
0211                    : ( track.recordedIncremental() ?  i18n("incremental") : i18n("uninterrupted") ) );
0212         s += "</td>";
0213 
0214         // track range
0215         s += "<td class=\"trackrange\">";
0216         s += QString("%1 - %2")
0217              .arg(track.firstSector().lba())
0218              .arg(track.lastSector().lba());
0219         s += "</td>";
0220 
0221         // track length
0222         s += "<td class=\"tracklength\">" + QString::number( track.length().lba() ) + " (" + track.length().toString() + ")</td>";
0223 
0224 #ifdef K3B_DEBUG
0225         s += "<td>";
0226         if( track.type() == K3b::Device::Track::TYPE_AUDIO )
0227             s += QString( "%1 (%2)" ).arg(track.index0().toString()).arg(track.index0().lba());
0228         s += "</td>";
0229 #endif
0230 
0231         s += "</tr>";
0232 
0233         if( !medium.cdText().isEmpty() ||
0234             medium.cddbInfo().isValid() ) {
0235             s += "<tr><td></td><td class=\"cdtext\" colspan=\"4\">";
0236             if( !medium.cdText().isEmpty() ) {
0237                 K3b::Device::TrackCdText text = medium.cdText().track( trackIndex );
0238                 s += text.performer() + " - " + text.title() + " (" + i18n("CD-Text") + ')';
0239             }
0240             else {
0241                 KCDDB::TrackInfo info = medium.cddbInfo().track( trackIndex );
0242                 s += info.get( KCDDB::Artist ).toString() + " - " + info.get( KCDDB::Title ).toString();
0243             }
0244             s += "</td></tr>";
0245         }
0246 
0247         return s;
0248     }
0249 
0250     QString sessionItem( int session ) {
0251         return "<tr><td class=\"session\" colspan=\"5\">" + i18n( "Session %1", session ) + "</td></tr>";
0252     }
0253 }
0254 
0255 QString K3b::DiskInfoView::createTrackItems( const K3b::Medium& medium )
0256 {
0257     QString s = "<table>";
0258 
0259     // table header
0260     s += "<tr><th class=\"trackheader\" colspan=\"2\">"
0261          + i18n("Type")
0262          + "</th><th class=\"trackheader\">"
0263          + i18n("Attributes")
0264          + "</th><th class=\"trackheader\">"
0265          + i18n("First-Last Sector")
0266          + "</th><th class=\"trackheader\">"
0267          + i18n("Length");
0268 #ifdef K3B_DEBUG
0269     s += "</td></td>Index0";
0270 #endif
0271     s += "</th></tr>";
0272 
0273     int lastSession = 0;
0274 
0275     // if we have multiple sessions we create a header item for every session
0276     if( medium.diskInfo().numSessions() > 1 && medium.toc()[0].session() > 0 ) {
0277         s += sessionItem( 1 );
0278         lastSession = 1;
0279     }
0280 
0281     // create items for the tracks
0282     for( int index = 0; index < medium.toc().count(); ++index ) {
0283         K3b::Device::Track track = medium.toc()[index];
0284         if( medium.diskInfo().numSessions() > 1 && track.session() != lastSession ) {
0285             lastSession = track.session();
0286             s += sessionItem( lastSession );
0287         }
0288         s += trackItem( medium, index );
0289     }
0290 
0291     s += "</table>";
0292 
0293     return s;
0294 }
0295 
0296 
0297 QString K3b::DiskInfoView::createMediaInfoItems( const K3b::Medium& medium )
0298 {
0299     const K3b::Device::DiskInfo& info = medium.diskInfo();
0300 
0301     QString s = "<table>";
0302 
0303     QString typeStr;
0304     if( info.mediaType() != K3b::Device::MEDIA_UNKNOWN )
0305         typeStr = K3b::Device::mediaTypeString( info.mediaType() );
0306     else
0307         typeStr = i18n("Unknown (probably CD-ROM)");
0308     s += tableRow( i18n( "Type:" ), typeStr );
0309     if( Device::isDvdMedia( info.mediaType() ) )
0310         s += tableRow( i18n("Media ID:"), !info.mediaId().isEmpty() ? QString::fromLatin1( info.mediaId() ) : i18n("unknown") );
0311     s += tableRow( i18n("Capacity:"), i18n("%1 min",info.capacity().toString()) + " (" + KIO::convertSize(info.capacity().mode1Bytes()) + ')' );
0312     if( !info.empty() )
0313         s += tableRow( i18n("Used Capacity:"), i18n("%1 min", medium.actuallyUsedCapacity().toString()) + " (" + KIO::convertSize(medium.actuallyUsedCapacity().mode1Bytes()) + ')' );
0314     if( !info.empty() ||
0315         info.appendable() ||
0316         ( info.mediaType() & ( Device::MEDIA_DVD_PLUS_RW|Device::MEDIA_DVD_RW_OVWR|Device::MEDIA_BD_RE ) ) )
0317         s += tableRow( i18n("Remaining:"), i18n("%1 min", medium.actuallyRemainingSize().toString() ) + " (" + KIO::convertSize(medium.actuallyRemainingSize().mode1Bytes()) + ')' );
0318     s += tableRow( i18n("Rewritable:"), info.rewritable() ? i18nc("Availability", "yes") : i18nc("Availability", "no") );
0319     s += tableRow( i18n("Appendable:"), info.appendable() || ( info.mediaType() & ( Device::MEDIA_DVD_PLUS_RW|Device::MEDIA_DVD_RW_OVWR|Device::MEDIA_BD_RE ) ) ? i18nc("Availability", "yes") : i18nc("Availability", "no") );
0320     s += tableRow( i18n("Empty:"), info.empty() ? i18nc("Availability", "yes") : i18nc("Availability", "no") );
0321     if( !( info.mediaType() & K3b::Device::MEDIA_CD_ALL ) )
0322         s += tableRow( i18nc("Number of layers on an optical medium", "Layers:"), QString::number( info.numLayers() ) );
0323 
0324     if( info.mediaType() == K3b::Device::MEDIA_DVD_PLUS_RW ) {
0325         QString bgf;
0326         switch( info.bgFormatState() ) {
0327         case K3b::Device::BG_FORMAT_NONE:
0328             bgf = i18n("not formatted");
0329             break;
0330         case K3b::Device::BG_FORMAT_INCOMPLETE:
0331             bgf = i18n("incomplete");
0332             break;
0333         case K3b::Device::BG_FORMAT_IN_PROGRESS:
0334             bgf = i18n("in progress");
0335             break;
0336         case K3b::Device::BG_FORMAT_COMPLETE:
0337             bgf = i18n("complete");
0338             break;
0339         default:
0340             bgf = i18n("unknown state");
0341         }
0342 
0343         s += tableRow( i18n("Background Format:"), bgf );
0344     }
0345 
0346     s += tableRow( i18n("Sessions:"), QString::number( info.numSessions() ) );
0347 
0348     if( info.mediaType() & K3b::Device::MEDIA_WRITABLE ) {
0349         QString speedStr;
0350         if( medium.writingSpeeds().isEmpty() ) {
0351             speedStr = '-';
0352         }
0353         else {
0354             foreach( int speed, medium.writingSpeeds() ) {
0355                 if( !speedStr.isEmpty() ) {
0356                     speedStr.append( "<br>" );
0357                 }
0358 
0359                 if( K3b::Device::isCdMedia( info.mediaType() ) )
0360                     speedStr.append( QString( "%1x (%2 KB/s)" ).arg( speed/K3b::Device::SPEED_FACTOR_CD ).arg( speed ) );
0361                 else if( K3b::Device::isDvdMedia( info.mediaType() ) )
0362                     speedStr.append( QString::asprintf( "%.1fx (%d KB/s)", (double)speed / ( double )K3b::Device::SPEED_FACTOR_DVD, speed ) );
0363                 else if ( K3b::Device::isBdMedia( info.mediaType() ) )
0364                     speedStr.append( QString::asprintf( "%.1fx (%d KB/s)", (double)speed / ( double )K3b::Device::SPEED_FACTOR_BD, speed ) );
0365             }
0366         }
0367 
0368         s += tableRow( i18n("Supported writing speeds:"), speedStr );
0369     }
0370 
0371     s += "</table>";
0372 
0373     return s;
0374 }
0375 
0376 
0377 QString K3b::DiskInfoView::createIso9660InfoItems( const K3b::Iso9660SimplePrimaryDescriptor& iso )
0378 {
0379     QString s = "<table>";
0380 
0381     s += tableRow( i18n("System Id:"), iso.systemId.isEmpty() ? QString("-") : iso.systemId );
0382     s += tableRow( i18n("Volume Id:"), iso.volumeId.isEmpty() ? QString("-") : iso.volumeId );
0383     s += tableRow( i18n("Volume Set Id:"), iso.volumeSetId.isEmpty() ? QString("-") : iso.volumeSetId );
0384     s += tableRow( i18n("Publisher Id:"), iso.publisherId.isEmpty() ? QString("-") : iso.publisherId );
0385     s += tableRow( i18n("Preparer Id:"), iso.preparerId.isEmpty() ? QString("-") : iso.preparerId );
0386     s += tableRow( i18n("Application Id:"), iso.applicationId.isEmpty() ? QString("-") : iso.applicationId );
0387     s += tableRow( i18n("Volume Size:"),
0388                    QString( "%1 (%2 * %3 = %4)" )
0389                    .arg(KIO::convertSize(iso.logicalBlockSize*iso.volumeSpaceSize))
0390                    .arg(i18nc( "Size of one block, always 2048", "%1 B", iso.logicalBlockSize) )
0391                    .arg(i18ncp( "Number of blocks (one block has 2048 bytes)", "1 block", "%1 blocks", iso.volumeSpaceSize) )
0392                    .arg(i18np( "1 B", "%1 B", iso.logicalBlockSize*iso.volumeSpaceSize ) ) );
0393 
0394     s += "</table>";
0395 
0396     return s;
0397 }
0398 
0399 #include "moc_k3bdiskinfoview.cpp"