File indexing completed on 2024-04-21 04:48:10

0001 /* AUDEX CDDA EXTRACTOR
0002  * SPDX-FileCopyrightText: Copyright (C) 2007 Marco Nelles
0003  * <https://userbase.kde.org/Audex>
0004  *
0005  * SPDX-License-Identifier: GPL-3.0-or-later
0006  */
0007 
0008 #include "extractingprogressdialog.h"
0009 
0010 ExtractingProgressDialog::ExtractingProgressDialog(ProfileModel *profile_model, CDDAModel *cdda_model, QWidget *parent)
0011     : QDialog(parent)
0012 {
0013     setWindowTitle(i18n("Rip And Encode"));
0014 
0015     mainLayout = new QVBoxLayout;
0016     setLayout(mainLayout);
0017 
0018     buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel);
0019     cancelButton = buttonBox->button(QDialogButtonBox::Cancel);
0020     connect(buttonBox, &QDialogButtonBox::rejected, this, &ExtractingProgressDialog::slotCancel);
0021 
0022     QWidget *widget = new QWidget(this);
0023     mainLayout->addWidget(widget);
0024     mainLayout->addWidget(buttonBox);
0025     ui.setupUi(widget);
0026 
0027     this->profile_model = profile_model;
0028     this->cdda_model = cdda_model;
0029 
0030     QString title = QString("%1 - %2").arg(cdda_model->artist(), cdda_model->title());
0031     ui.label_header->setText(title);
0032 
0033     p_single_file = profile_model->data(profile_model->index(profile_model->currentProfileRow(), PROFILE_MODEL_COLUMN_SF_INDEX)).toBool();
0034 
0035     if (p_single_file) {
0036         ui.label_extracting->setText(i18n("Ripping whole CD as single track"));
0037         ui.label_encoding->setText(i18n("Encoding"));
0038 
0039     } else {
0040         ui.label_extracting->setText(i18n("Ripping Track 0 of %1", cdda_model->numOfAudioTracks()));
0041         ui.label_encoding->setText(i18n("Encoding Track 0 of %1", cdda_model->numOfAudioTracks()));
0042     }
0043 
0044     audex = new Audex(this, profile_model, cdda_model);
0045 
0046     connect(audex, SIGNAL(error(const QString &, const QString &)), this, SLOT(show_error(const QString &, const QString &)));
0047     connect(audex, SIGNAL(warning(const QString &)), this, SLOT(show_warning(const QString &)));
0048     connect(audex, SIGNAL(info(const QString &)), this, SLOT(show_info(const QString &)));
0049     connect(audex, SIGNAL(finished(bool)), this, SLOT(conclusion(bool)));
0050     connect(audex, SIGNAL(speedEncode(double)), this, SLOT(show_speed_encode(double)));
0051     connect(audex, SIGNAL(speedExtract(double)), this, SLOT(show_speed_extract(double)));
0052     connect(audex, SIGNAL(progressExtractTrack(int)), this, SLOT(show_progress_extract_track(int)));
0053     connect(audex, SIGNAL(progressExtractOverall(int)), this, SLOT(show_progress_extract_overall(int)));
0054     connect(audex, SIGNAL(progressEncodeTrack(int)), this, SLOT(show_progress_encode_track(int)));
0055     connect(audex, SIGNAL(progressEncodeOverall(int)), this, SLOT(show_progress_encode_overall(int)));
0056     connect(audex,
0057             SIGNAL(changedExtractTrack(int, int, const QString &, const QString &)),
0058             this,
0059             SLOT(show_changed_extract_track(int, int, const QString &, const QString &)));
0060     connect(audex, SIGNAL(changedEncodeTrack(int, int, const QString &)), this, SLOT(show_changed_encode_track(int, int, const QString &)));
0061     connect(audex, SIGNAL(timeout()), this, SLOT(ask_timeout()));
0062     connect(ui.details_button, SIGNAL(pressed()), this, SLOT(toggle_details()));
0063 
0064     finished = false;
0065 
0066     progressbar_np_flag = false;
0067 
0068     unity_message = QDBusMessage::createSignal("/Audex", "com.canonical.Unity.LauncherEntry", "Update");
0069 }
0070 
0071 ExtractingProgressDialog::~ExtractingProgressDialog()
0072 {
0073     delete audex;
0074 }
0075 
0076 int ExtractingProgressDialog::exec()
0077 {
0078     KConfigGroup grp(KSharedConfig::openConfig(), "ExtractingProgressDialog");
0079 
0080     resize(600, 400);
0081     current_extract_overall = 0;
0082     current_encode_overall = 0;
0083     ui.details_button->setArrowType(grp.readEntry("Simple", true) ? Qt::UpArrow : Qt::DownArrow);
0084     toggle_details();
0085     show();
0086     setModal(true);
0087     if (audex->prepare()) {
0088         audex->start();
0089     }
0090     int rv = QDialog::exec();
0091 
0092     grp.writeEntry("Simple", (Qt::DownArrow == ui.details_button->arrowType()));
0093 
0094     return rv;
0095 }
0096 
0097 void ExtractingProgressDialog::calc_overall_progress()
0098 {
0099     ui.progressBar_overall->setValue((int)(((float)(current_extract_overall + current_encode_overall) / 2.0f) + .5f));
0100     update_unity();
0101 }
0102 
0103 void ExtractingProgressDialog::toggle_details()
0104 {
0105     if (Qt::UpArrow == ui.details_button->arrowType()) {
0106         ui.details_button->setArrowType(Qt::DownArrow);
0107         ui.details->setVisible(false);
0108         ui.label_overall->setVisible(false);
0109         ui.label_overall_track->setVisible(true);
0110         ui.progressBar_overall->setVisible(true);
0111         resize(width(), 32);
0112 
0113     } else {
0114         ui.details_button->setArrowType(Qt::UpArrow);
0115         ui.details->setVisible(true);
0116         ui.label_overall_track->setVisible(false);
0117 
0118         if (cdda_model->numOfAudioTracksInSelection() < 2) {
0119             ui.label_overall->setVisible(false);
0120             ui.progressBar_overall->setVisible(false);
0121         } else {
0122             ui.label_overall->setVisible(true);
0123         }
0124         resize(width(), 400);
0125     }
0126 }
0127 
0128 void ExtractingProgressDialog::slotCancel()
0129 {
0130     cancel();
0131 }
0132 
0133 void ExtractingProgressDialog::slotClose()
0134 {
0135     close();
0136 }
0137 
0138 void ExtractingProgressDialog::slotEncoderLog()
0139 {
0140     open_encoder_log_view_dialog();
0141 }
0142 
0143 void ExtractingProgressDialog::slotExtractLog()
0144 {
0145     open_extract_log_view_dialog();
0146 }
0147 
0148 void ExtractingProgressDialog::cancel()
0149 {
0150     if (finished) {
0151         close();
0152 
0153     } else {
0154         if (KMessageBox::warningTwoActions(this,
0155                                            i18n("Do you really want to cancel extraction?"),
0156                                            i18n("Cancel"),
0157                                            KStandardGuiItem::cancel(),
0158                                            KStandardGuiItem::cont())
0159             == KMessageBox::PrimaryAction) {
0160             cancelButton->setEnabled(false);
0161             audex->cancel();
0162         }
0163     }
0164 }
0165 
0166 void ExtractingProgressDialog::show_changed_extract_track(int no, int total, const QString &artist, const QString &title)
0167 {
0168     Q_UNUSED(artist);
0169     Q_UNUSED(title);
0170 
0171     if (!p_single_file) {
0172         ui.label_extracting->setText((1 == total) ? i18n("Ripping Track") : i18n("Ripping Track %1 of %2", no, total));
0173         ui.label_overall_track->setText((1 == total) ? i18n("Overall Progress") : i18n("Overall Progress (Ripping Track %1 of %2)", no, total));
0174         current_track = no;
0175         update_unity();
0176 
0177     } else {
0178         ui.label_extracting->setText(i18n("Ripping whole CD as single track"));
0179         ui.label_overall_track->setText(i18n("Overall Progress"));
0180     }
0181 }
0182 
0183 void ExtractingProgressDialog::show_changed_encode_track(int no, int total, const QString &filename)
0184 {
0185     Q_UNUSED(filename);
0186 
0187     if (no == 0) {
0188         ui.label_encoding->setText("<i>" + i18n("Waiting for an encoding job...") + "</i>");
0189         ui.label_speed_encoding->clear();
0190     } else {
0191         if (!p_single_file)
0192             ui.label_encoding->setText((1 == total) ? i18n("Encoding Track") : i18n("Encoding Track %1 of %2", no, total));
0193     }
0194 }
0195 
0196 void ExtractingProgressDialog::show_progress_extract_track(int percent)
0197 {
0198     ui.progressBar_extracting->setValue(percent);
0199 }
0200 
0201 void ExtractingProgressDialog::show_progress_extract_overall(int percent)
0202 {
0203     current_extract_overall = percent;
0204     calc_overall_progress();
0205 }
0206 
0207 void ExtractingProgressDialog::show_progress_encode_track(int percent)
0208 {
0209     if (percent >= 0) {
0210         ui.progressBar_encoding->setValue(percent);
0211         if (progressbar_np_flag) {
0212             ui.progressBar_encoding->setRange(0, 100);
0213             ui.progressBar_encoding->setTextVisible(true);
0214             progressbar_np_flag = false;
0215         }
0216     } else {
0217         if (!progressbar_np_flag) {
0218             progressbar_np_flag = true;
0219             ui.progressBar_encoding->setRange(0, 0);
0220             ui.progressBar_encoding->setTextVisible(false);
0221         }
0222     }
0223 }
0224 
0225 void ExtractingProgressDialog::show_progress_encode_overall(int percent)
0226 {
0227     current_encode_overall = percent;
0228     calc_overall_progress();
0229 }
0230 
0231 void ExtractingProgressDialog::show_speed_encode(double speed)
0232 {
0233     QString s = QString("%1").arg((double)speed, 0, 'f', 2);
0234     ui.label_speed_encoding->setText("<i>" + i18n("Speed: %1x", s) + "</i>");
0235 }
0236 
0237 void ExtractingProgressDialog::show_speed_extract(double speed)
0238 {
0239     QString s = QString("%1").arg((double)speed, 0, 'f', 2);
0240     ui.label_speed_extracting->setText("<i>" + i18n("Speed: %1x", s) + "</i>");
0241 }
0242 
0243 void ExtractingProgressDialog::conclusion(bool successful)
0244 {
0245     // Remove the cancel button
0246     buttonBox->clear();
0247     // Add the new close button
0248     buttonBox->addButton(QDialogButtonBox::Close);
0249     connect(buttonBox, &QDialogButtonBox::rejected, this, &ExtractingProgressDialog::slotClose);
0250 
0251     finished = true;
0252 
0253     update_unity();
0254 
0255     QPalette pal(ui.label_extracting->palette());
0256     KColorScheme kcs(QPalette::Active);
0257     if (successful) {
0258         QListWidgetItem *item = new QListWidgetItem(QIcon::fromTheme("dialog-ok-apply"), i18n("All jobs successfully done."));
0259         ui.klistwidget->addItem(item);
0260         ui.klistwidget->scrollToItem(item);
0261         pal.setBrush(QPalette::Text, kcs.foreground(KColorScheme::PositiveText));
0262         ui.label_extracting->setText("<font style=\"font-weight:bold;\">" + i18n("Finished!") + "</font>");
0263         ui.label_encoding->setText("<font style=\"font-weight:bold;\">" + i18n("Finished!") + "</font>");
0264         ui.label_overall_track->setText("<font style=\"font-weight:bold;\">" + i18n("Finished!") + "</font>");
0265         ui.progressBar_extracting->setValue(100);
0266         ui.progressBar_encoding->setValue(100);
0267         ui.progressBar_overall->setValue(100);
0268     } else {
0269         QListWidgetItem *item = new QListWidgetItem(QIcon::fromTheme("dialog-cancel"), i18n("At least one job failed."));
0270         pal.setBrush(QPalette::Text, kcs.foreground(KColorScheme::NegativeText));
0271         ui.klistwidget->addItem(item);
0272         ui.klistwidget->scrollToItem(item);
0273         ui.label_extracting->setText("<font style=\"color:red;font-weight:bold;\">" + i18n("Failed!") + "</font>");
0274         ui.label_encoding->setText("<font style=\"color:red;font-weight:bold;\">" + i18n("Failed!") + "</font>");
0275         ui.label_overall_track->setText("<font style=\"color:red;font-weight:bold;\">" + i18n("Failed!") + "</font>");
0276         if (audex->encoderLog().count() > 0) {
0277             auto *encoderLogButton = new QPushButton();
0278             encoderLogButton->setText(i18n("Show encoding log..."));
0279             encoderLogButton->setIcon(QIcon::fromTheme(QStringLiteral("media-optical-audio")));
0280             buttonBox->addButton(encoderLogButton, QDialogButtonBox::HelpRole);
0281             connect(encoderLogButton, &QPushButton::clicked, this, &ExtractingProgressDialog::slotEncoderLog);
0282         }
0283         if (audex->extractLog().count() > 0) {
0284             auto *extractLogButton = new QPushButton();
0285             extractLogButton->setText(i18n("Show rip log..."));
0286             extractLogButton->setIcon(QIcon::fromTheme(QStringLiteral("media-optical")));
0287             buttonBox->addButton(extractLogButton, QDialogButtonBox::HelpRole);
0288             connect(extractLogButton, &QPushButton::clicked, this, &ExtractingProgressDialog::slotExtractLog);
0289         }
0290     }
0291 
0292     ui.progressBar_extracting->setEnabled(false);
0293     ui.progressBar_encoding->setEnabled(false);
0294     ui.progressBar_overall->setEnabled(false);
0295     ui.label_speed_extracting->setEnabled(false);
0296     ui.label_speed_encoding->setEnabled(false);
0297     ui.label_overall->setEnabled(false);
0298 
0299     ui.label_extracting->setPalette(pal);
0300     ui.label_encoding->setPalette(pal);
0301 }
0302 
0303 void ExtractingProgressDialog::show_info(const QString &message)
0304 {
0305     QListWidgetItem *item = new QListWidgetItem(QIcon::fromTheme("dialog-information"), message);
0306     ui.klistwidget->addItem(item);
0307     ui.klistwidget->scrollToItem(item);
0308 }
0309 
0310 void ExtractingProgressDialog::show_warning(const QString &message)
0311 {
0312     QListWidgetItem *item = new QListWidgetItem(QIcon::fromTheme("dialog-warning"), message);
0313     ui.klistwidget->addItem(item);
0314     ui.klistwidget->scrollToItem(item);
0315 }
0316 
0317 void ExtractingProgressDialog::show_error(const QString &message, const QString &details)
0318 {
0319     QListWidgetItem *item;
0320     if (details.isEmpty()) {
0321         item = new QListWidgetItem(QIcon::fromTheme("dialog-error"), QString("%1").arg(message));
0322     } else {
0323         item = new QListWidgetItem(QIcon::fromTheme("dialog-error"), QString("%1 (%2)").arg(message, details));
0324     }
0325     ui.klistwidget->addItem(item);
0326     ui.klistwidget->scrollToItem(item);
0327 }
0328 
0329 void ExtractingProgressDialog::ask_timeout()
0330 {
0331     if (KMessageBox::questionTwoActions(this,
0332                                         i18n("Ripping speed was extremely slow for the last 5 minutes.\n"
0333                                              "Do you want to continue extraction?"),
0334                                         i18n("Cancel extraction"),
0335                                         KStandardGuiItem::cont(),
0336                                         KStandardGuiItem::cancel())
0337         == KMessageBox::SecondaryAction) {
0338         audex->cancel();
0339     }
0340 }
0341 
0342 void ExtractingProgressDialog::open_encoder_log_view_dialog()
0343 {
0344     LogViewDialog logViewDialog(audex->encoderLog(), i18n("Encoding log"), this);
0345     logViewDialog.exec();
0346 }
0347 
0348 void ExtractingProgressDialog::open_extract_log_view_dialog()
0349 {
0350     LogViewDialog logViewDialog(audex->extractLog(), i18n("Ripping log"), this);
0351     logViewDialog.exec();
0352 }
0353 
0354 void ExtractingProgressDialog::update_unity()
0355 {
0356     QList<QVariant> args;
0357     int progress = ui.progressBar_overall->value();
0358     bool show_progress = progress > -1 && progress < 100 && !finished;
0359     QMap<QString, QVariant> props;
0360     props["count-visible"] = current_track > 0 && !finished;
0361     props["count"] = current_track;
0362     props["progress-visible"] = show_progress;
0363     props["progress"] = show_progress ? (double)(progress / 100.0) : 0.0;
0364     args.append("application://org.kde.audex.desktop");
0365     args.append(props);
0366     unity_message.setArguments(args);
0367     QDBusConnection::sessionBus().send(unity_message);
0368 }