File indexing completed on 2024-05-12 04:52:10

0001 /*
0002  * dvbchanneldialog.cpp
0003  *
0004  * Copyright (C) 2007-2011 Christoph Pfister <christophpfister@gmail.com>
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License as published by
0008  * the Free Software Foundation; either version 2 of the License, or
0009  * (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License along
0017  * with this program; if not, write to the Free Software Foundation, Inc.,
0018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0019  */
0020 
0021 #include "../log.h"
0022 
0023 #include <KConfigGroup>
0024 #include <KMessageBox>
0025 #include <QAction>
0026 #include <QBoxLayout>
0027 #include <QCheckBox>
0028 #include <QComboBox>
0029 #include <QCoreApplication>
0030 #include <QGroupBox>
0031 #include <QHeaderView>
0032 #include <QLabel>
0033 #include <QLineEdit>
0034 #include <QMimeData>
0035 #include <QSpinBox>
0036 
0037 #include "dvbchanneldialog.h"
0038 #include "dvbchanneldialog_p.h"
0039 #include "dvbsi.h"
0040 #include "../iso-codes.h"
0041 
0042 bool DvbChannelLessThan::operator()(const DvbSharedChannel &x, const DvbSharedChannel &y) const
0043 {
0044     switch (sortOrder) {
0045     case ChannelNameAscending:
0046         if (x->name != y->name) {
0047             return (x->name.localeAwareCompare(y->name) < 0);
0048         }
0049 
0050         break;
0051     case ChannelNameDescending:
0052         if (x->name != y->name) {
0053             return (x->name.localeAwareCompare(y->name) > 0);
0054         }
0055 
0056         break;
0057     case ChannelNumberAscending:
0058         if (x->number != y->number) {
0059             return (x->number < y->number);
0060         }
0061 
0062         break;
0063     case ChannelNumberDescending:
0064         if (x->number != y->number) {
0065             return (x->number > y->number);
0066         }
0067 
0068         break;
0069     }
0070 
0071     return (x < y);
0072 }
0073 
0074 DvbChannelTableModel::DvbChannelTableModel(QObject *parent) :
0075     TableModel<DvbChannelTableModelHelper>(parent), channelModel(NULL),
0076     dndInsertBeforeNumber(-1), dndEventPosted(false)
0077 {
0078 }
0079 
0080 DvbChannelTableModel::~DvbChannelTableModel()
0081 {
0082 }
0083 
0084 void DvbChannelTableModel::setChannelModel(DvbChannelModel *channelModel_)
0085 {
0086     if (channelModel != NULL) {
0087         qCWarning(logDvb, "Channel model already set");
0088         return;
0089     }
0090 
0091     channelModel = channelModel_;
0092     connect(channelModel, SIGNAL(channelAdded(DvbSharedChannel)),
0093         this, SLOT(channelAdded(DvbSharedChannel)));
0094     connect(channelModel, SIGNAL(channelAboutToBeUpdated(DvbSharedChannel)),
0095         this, SLOT(channelAboutToBeUpdated(DvbSharedChannel)));
0096     connect(channelModel, SIGNAL(channelUpdated(DvbSharedChannel)),
0097         this, SLOT(channelUpdated(DvbSharedChannel)));
0098     connect(channelModel, SIGNAL(channelRemoved(DvbSharedChannel)),
0099         this, SLOT(channelRemoved(DvbSharedChannel)));
0100     reset(channelModel->getChannels());
0101 }
0102 
0103 QVariant DvbChannelTableModel::headerData(int section, Qt::Orientation orientation, int role) const
0104 {
0105     if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) {
0106         switch (section) {
0107         case 0:
0108             return i18nc("@title:column tv show", "Channel");
0109         case 1:
0110             return i18nc("@title:column tv channel", "Number");
0111         }
0112     }
0113 
0114     return QVariant();
0115 }
0116 
0117 QVariant DvbChannelTableModel::data(const QModelIndex &index, int role) const
0118 {
0119     const DvbSharedChannel &channel = value(index);
0120 
0121     if (channel.isValid()) {
0122         switch (role) {
0123         case Qt::DecorationRole:
0124             if (index.column() == 0) {
0125                 if (channel->hasVideo) {
0126                     if (!channel->isScrambled) {
0127                         return QIcon::fromTheme(QLatin1String("video-television"), QIcon(":video-television"));
0128                     } else {
0129                         return QIcon::fromTheme(QLatin1String("video-television-encrypted"), QIcon(":video-television-encrypted"));
0130                     }
0131                 } else {
0132                     if (!channel->isScrambled) {
0133                         return QIcon::fromTheme(QLatin1String("text-speak"), QIcon(":text-speak"));
0134                     } else {
0135                         return QIcon::fromTheme(QLatin1String("audio-radio-encrypted"), QIcon(":audio-radio-encrypted"));
0136                     }
0137                 }
0138             }
0139 
0140             break;
0141         case Qt::DisplayRole:
0142             switch (index.column()) {
0143             case 0:
0144                 return channel->name;
0145             case 1:
0146                 return channel->number;
0147             }
0148 
0149             break;
0150         }
0151     }
0152 
0153     return QVariant();
0154 }
0155 
0156 void DvbChannelTableModel::sort(int column, Qt::SortOrder order)
0157 {
0158     DvbChannelLessThan::SortOrder sortOrder;
0159 
0160     if (order == Qt::AscendingOrder) {
0161         if (column == 0) {
0162             sortOrder = DvbChannelLessThan::ChannelNameAscending;
0163         } else {
0164             sortOrder = DvbChannelLessThan::ChannelNumberAscending;
0165         }
0166     } else {
0167         if (column == 0) {
0168             sortOrder = DvbChannelLessThan::ChannelNameDescending;
0169         } else {
0170             sortOrder = DvbChannelLessThan::ChannelNumberDescending;
0171         }
0172     }
0173 
0174     internalSort(sortOrder);
0175 }
0176 
0177 Qt::ItemFlags DvbChannelTableModel::flags(const QModelIndex &index) const
0178 {
0179     if (index.isValid()) {
0180         return (QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled);
0181     } else {
0182         return (QAbstractTableModel::flags(index) | Qt::ItemIsDropEnabled);
0183     }
0184 }
0185 
0186 QMimeData *DvbChannelTableModel::mimeData(const QModelIndexList &indexes) const
0187 {
0188     QList<DvbSharedChannel> selectedChannels;
0189 
0190     foreach (const QModelIndex &index, indexes) {
0191         if (index.column() == 0) {
0192             selectedChannels.append(value(index));
0193         }
0194     }
0195 
0196     QMimeData *mimeData = new QMimeData();
0197     mimeData->setData(QLatin1String("application/x-org.kde.kaffeine-selectedchannels"), QByteArray());
0198     // this way the list will be properly deleted once drag and drop ends
0199     mimeData->setProperty("SelectedChannels", QVariant::fromValue(selectedChannels));
0200     return mimeData;
0201 }
0202 
0203 QStringList DvbChannelTableModel::mimeTypes() const
0204 {
0205     return QStringList(QLatin1String("application/x-org.kde.kaffeine-selectedchannels"));
0206 }
0207 
0208 Qt::DropActions DvbChannelTableModel::supportedDropActions() const
0209 {
0210     return Qt::MoveAction;
0211 }
0212 
0213 bool DvbChannelTableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row,
0214     int column, const QModelIndex &parent)
0215 {
0216     Q_UNUSED(column)
0217     Q_UNUSED(parent)
0218     dndSelectedChannels.clear();
0219     dndInsertBeforeNumber = -1;
0220 
0221     if (action == Qt::MoveAction) {
0222         dndSelectedChannels =
0223             data->property("SelectedChannels").value<QList<DvbSharedChannel> >();
0224         const DvbSharedChannel &dndInsertBeforeChannel = value(row);
0225 
0226         if (dndInsertBeforeChannel.isValid()) {
0227             dndInsertBeforeNumber = dndInsertBeforeChannel->number;
0228         }
0229 
0230         if (!dndSelectedChannels.isEmpty() && !dndEventPosted) {
0231             dndEventPosted = true;
0232             QCoreApplication::postEvent(this, new QEvent(QEvent::User));
0233         }
0234     }
0235 
0236     return false;
0237 }
0238 
0239 void DvbChannelTableModel::setFilter(const QString &filter)
0240 {
0241     // Qt::CaseSensitive == no filtering
0242     helper.filter.setCaseSensitivity(
0243         filter.isEmpty() ? Qt::CaseSensitive : Qt::CaseInsensitive);
0244     helper.filter.setPattern(filter);
0245     reset(channelModel->getChannels());
0246 }
0247 
0248 void DvbChannelTableModel::channelAdded(const DvbSharedChannel &channel)
0249 {
0250     insert(channel);
0251 }
0252 
0253 void DvbChannelTableModel::channelAboutToBeUpdated(const DvbSharedChannel &channel)
0254 {
0255     aboutToUpdate(channel);
0256 }
0257 
0258 void DvbChannelTableModel::channelUpdated(const DvbSharedChannel &channel)
0259 {
0260     update(channel);
0261 }
0262 
0263 void DvbChannelTableModel::channelRemoved(const DvbSharedChannel &channel)
0264 {
0265     remove(channel);
0266 }
0267 
0268 void DvbChannelTableModel::customEvent(QEvent *event)
0269 {
0270     Q_UNUSED(event)
0271     bool ok = true;
0272     emit checkChannelDragAndDrop(&ok);
0273 
0274     if (ok && !dndSelectedChannels.isEmpty()) {
0275         channelModel->dndMoveChannels(dndSelectedChannels, dndInsertBeforeNumber);
0276     }
0277 
0278     dndSelectedChannels.clear();
0279     dndEventPosted = false;
0280 }
0281 
0282 DvbChannelView::DvbChannelView(QWidget *parent) : QTreeView(parent), tableModel(NULL)
0283 {
0284 }
0285 
0286 DvbChannelView::~DvbChannelView()
0287 {
0288 }
0289 
0290 QAction *DvbChannelView::addEditAction()
0291 {
0292     QAction *action = new QAction(QIcon::fromTheme(QLatin1String("configure"), QIcon(":configure")), i18nc("@action", "Edit"), this);
0293     connect(action, SIGNAL(triggered()), this, SLOT(editChannel()));
0294     addAction(action);
0295     return action;
0296 }
0297 
0298 QAction *DvbChannelView::addRemoveAction()
0299 {
0300     QAction *action = new QAction(QIcon::fromTheme(QLatin1String("edit-delete"), QIcon(":edit-delete")), i18nc("@action", "Remove"), this);
0301     connect(action, SIGNAL(triggered()), this, SLOT(removeChannel()));
0302     addAction(action);
0303     return action;
0304 }
0305 
0306 void DvbChannelView::setModel(DvbChannelTableModel *tableModel_)
0307 {
0308     tableModel = tableModel_;
0309     QTreeView::setModel(tableModel);
0310 }
0311 
0312 void DvbChannelView::checkChannelDragAndDrop(bool *ok)
0313 {
0314     if ((*ok) && ((header()->sortIndicatorSection() != 1) ||
0315         (header()->sortIndicatorOrder() != Qt::AscendingOrder))) {
0316         if (KMessageBox::warningContinueCancel(this, i18nc("@info",
0317             "The channels will be sorted by number to allow drag and drop.\n"
0318             "Do you want to continue?")) == KMessageBox::Continue) {
0319             sortByColumn(1, Qt::AscendingOrder);
0320         } else {
0321             *ok = false;
0322         }
0323     }
0324 }
0325 
0326 void DvbChannelView::channelPidsChanged(const DvbSharedChannel &channel)
0327 {
0328     emit channelPidsUpdated(channel);
0329 }
0330 
0331 void DvbChannelView::editChannel()
0332 {
0333     QModelIndex index = currentIndex();
0334 
0335     if (index.isValid()) {
0336         QDialog *dialog = new DvbChannelEditor(tableModel, tableModel->value(index), this);
0337         dialog->setAttribute(Qt::WA_DeleteOnClose, true);
0338         dialog->setModal(true);
0339         connect(dialog, SIGNAL(channelPidsChanged(DvbSharedChannel)),
0340             this, SLOT(channelPidsChanged(DvbSharedChannel)));
0341         dialog->show();
0342     }
0343 }
0344 
0345 void DvbChannelView::removeChannel()
0346 {
0347     QList<DvbSharedChannel> selectedChannels;
0348 
0349     foreach (const QModelIndex &index, selectionModel()->selectedIndexes()) {
0350         if (index.column() == 0) {
0351             selectedChannels.append(tableModel->value(index));
0352         }
0353     }
0354 
0355     DvbChannelModel *channelModel = tableModel->getChannelModel();
0356 
0357     foreach (const DvbSharedChannel &channel, selectedChannels) {
0358         channelModel->removeChannel(channel);
0359     }
0360 }
0361 
0362 void DvbChannelView::removeAllChannels()
0363 {
0364     DvbChannelModel *channelModel = tableModel->getChannelModel();
0365 
0366     foreach (const DvbSharedChannel &channel, channelModel->getChannels().values()) {
0367         channelModel->removeChannel(channel);
0368     }
0369 }
0370 
0371 static QLatin1String enumToString(DvbTransponderBase::FecRate fecRate)
0372 {
0373     const char *text = "";
0374 
0375     switch (fecRate) {
0376     case DvbTransponderBase::FecNone: text = "NONE"; break;
0377     case DvbTransponderBase::Fec1_2: text = "1/2"; break;
0378     case DvbTransponderBase::Fec1_3: text = "1/3"; break;
0379     case DvbTransponderBase::Fec1_4: text = "1/4"; break;
0380     case DvbTransponderBase::Fec2_3: text = "2/3"; break;
0381     case DvbTransponderBase::Fec2_5: text = "2/5"; break;
0382     case DvbTransponderBase::Fec3_4: text = "3/4"; break;
0383     case DvbTransponderBase::Fec3_5: text = "3/5"; break;
0384     case DvbTransponderBase::Fec4_5: text = "4/5"; break;
0385     case DvbTransponderBase::Fec5_6: text = "5/6"; break;
0386     case DvbTransponderBase::Fec6_7: text = "6/7"; break;
0387     case DvbTransponderBase::Fec7_8: text = "7/8"; break;
0388     case DvbTransponderBase::Fec8_9: text = "8/9"; break;
0389     case DvbTransponderBase::Fec9_10: text = "9/10"; break;
0390     case DvbTransponderBase::FecAuto: text = "AUTO"; break;
0391     }
0392 
0393     return QLatin1String(text);
0394 }
0395 
0396 static QLatin1String enumToString(DvbCTransponder::Modulation modulation)
0397 {
0398     const char *text = "";
0399 
0400     switch (modulation) {
0401     case DvbCTransponder::Qam16: text = "16-QAM"; break;
0402     case DvbCTransponder::Qam32: text = "32-QAM"; break;
0403     case DvbCTransponder::Qam64: text = "64-QAM"; break;
0404     case DvbCTransponder::Qam128: text = "128-QAM"; break;
0405     case DvbCTransponder::Qam256: text = "256-QAM"; break;
0406     case DvbCTransponder::ModulationAuto: text = "AUTO"; break;
0407     }
0408 
0409     return QLatin1String(text);
0410 }
0411 
0412 static QString enumToString(DvbSTransponder::Polarization polarization)
0413 {
0414     switch (polarization) {
0415     case DvbSTransponder::Horizontal: return i18n("Horizontal");
0416     case DvbSTransponder::Vertical: return i18n("Vertical");
0417     case DvbSTransponder::CircularLeft: return i18n("Circular left");
0418     case DvbSTransponder::CircularRight: return i18n("Circular right");
0419     case DvbSTransponder::Off: return i18n("Off");
0420     }
0421 
0422     return QString();
0423 }
0424 
0425 static QLatin1String enumToString(DvbS2Transponder::Modulation modulation)
0426 {
0427     const char *text = "";
0428 
0429     switch (modulation) {
0430     case DvbS2Transponder::Qpsk: text = "QPSK"; break;
0431     case DvbS2Transponder::Psk8: text = "8-PSK"; break;
0432     case DvbS2Transponder::Apsk16: text = "16-APSK"; break;
0433     case DvbS2Transponder::Apsk32: text = "32-APSK"; break;
0434     case DvbS2Transponder::ModulationAuto: text = "AUTO"; break;
0435     }
0436 
0437     return QLatin1String(text);
0438 }
0439 
0440 static QLatin1String enumToString(DvbS2Transponder::RollOff rollOff)
0441 {
0442     const char *text = "";
0443 
0444     switch (rollOff) {
0445     case DvbS2Transponder::RollOff20: text = "0.20"; break;
0446     case DvbS2Transponder::RollOff25: text = "0.25"; break;
0447     case DvbS2Transponder::RollOff35: text = "0.35"; break;
0448     case DvbS2Transponder::RollOffAuto: text = "AUTO"; break;
0449     }
0450 
0451     return QLatin1String(text);
0452 }
0453 
0454 static QLatin1String enumToString(DvbTTransponder::Bandwidth bandwidth)
0455 {
0456     const char *text = "";
0457 
0458     switch (bandwidth) {
0459     case DvbTTransponder::Bandwidth5MHz: text = "5MHz"; break;
0460     case DvbTTransponder::Bandwidth6MHz: text = "6MHz"; break;
0461     case DvbTTransponder::Bandwidth7MHz: text = "7MHz"; break;
0462     case DvbTTransponder::Bandwidth8MHz: text = "8MHz"; break;
0463     case DvbTTransponder::BandwidthAuto: text = "AUTO"; break;
0464     }
0465 
0466     return QLatin1String(text);
0467 }
0468 
0469 static QLatin1String enumToString(DvbT2Transponder::Bandwidth bandwidth)
0470 {
0471     const char *text = "";
0472 
0473     switch (bandwidth) {
0474     case DvbT2Transponder::Bandwidth1_7MHz: text = "1.7MHz"; break;
0475     case DvbT2Transponder::Bandwidth5MHz:   text = "5MHz"; break;
0476     case DvbT2Transponder::Bandwidth6MHz:   text = "6MHz"; break;
0477     case DvbT2Transponder::Bandwidth7MHz:   text = "7MHz"; break;
0478     case DvbT2Transponder::Bandwidth8MHz:   text = "8MHz"; break;
0479     case DvbT2Transponder::Bandwidth10MHz:  text = "10MHz"; break;
0480     case DvbT2Transponder::BandwidthAuto:   text = "AUTO"; break;
0481     }
0482 
0483     return QLatin1String(text);
0484 }
0485 static QLatin1String enumToString(DvbTTransponder::Modulation modulation)
0486 {
0487     const char *text = "";
0488 
0489     switch (modulation) {
0490     case DvbTTransponder::Qpsk: text = "QPSK"; break;
0491     case DvbTTransponder::Qam16: text = "16-QAM"; break;
0492     case DvbTTransponder::Qam64: text = "64-QAM"; break;
0493     case DvbTTransponder::ModulationAuto: text = "AUTO"; break;
0494     }
0495 
0496     return QLatin1String(text);
0497 }
0498 
0499 static QLatin1String enumToString(DvbT2Transponder::Modulation modulation)
0500 {
0501     const char *text = "";
0502 
0503     switch (modulation) {
0504     case DvbT2Transponder::Qpsk: text = "QPSK"; break;
0505     case DvbT2Transponder::Qam16: text = "16-QAM"; break;
0506     case DvbT2Transponder::Qam64: text = "64-QAM"; break;
0507     case DvbT2Transponder::Qam256: text = "256-QAM"; break;
0508     case DvbT2Transponder::ModulationAuto: text = "AUTO"; break;
0509     }
0510 
0511     return QLatin1String(text);
0512 }
0513 
0514 static QLatin1String enumToString(DvbTTransponder::TransmissionMode transmissionMode)
0515 {
0516     const char *text = "";
0517 
0518     switch (transmissionMode) {
0519     case DvbTTransponder::TransmissionMode2k: text = "2k"; break;
0520     case DvbTTransponder::TransmissionMode4k: text = "4k"; break;
0521     case DvbTTransponder::TransmissionMode8k: text = "8k"; break;
0522     case DvbTTransponder::TransmissionModeAuto: text = "AUTO"; break;
0523     }
0524 
0525     return QLatin1String(text);
0526 }
0527 
0528 static QLatin1String enumToString(DvbT2Transponder::TransmissionMode transmissionMode)
0529 {
0530     const char *text = "";
0531 
0532     switch (transmissionMode) {
0533     case DvbT2Transponder::TransmissionMode1k: text = "1k"; break;
0534     case DvbT2Transponder::TransmissionMode2k: text = "2k"; break;
0535     case DvbT2Transponder::TransmissionMode4k: text = "4k"; break;
0536     case DvbT2Transponder::TransmissionMode8k: text = "8k"; break;
0537     case DvbT2Transponder::TransmissionMode16k: text = "16k"; break;
0538     case DvbT2Transponder::TransmissionMode32k: text = "32k"; break;
0539     case DvbT2Transponder::TransmissionModeAuto: text = "AUTO"; break;
0540     }
0541 
0542     return QLatin1String(text);
0543 }
0544 
0545 static QLatin1String enumToString(IsdbTTransponder::TransmissionMode transmissionMode)
0546 {
0547     const char *text = "";
0548 
0549     switch (transmissionMode) {
0550     case IsdbTTransponder::TransmissionMode2k: text = "2k"; break;
0551     case IsdbTTransponder::TransmissionMode4k: text = "4k"; break;
0552     case IsdbTTransponder::TransmissionMode8k: text = "8k"; break;
0553     case IsdbTTransponder::TransmissionModeAuto: text = "AUTO"; break;
0554     }
0555 
0556     return QLatin1String(text);
0557 }
0558 
0559 static QLatin1String enumToString(DvbTTransponder::GuardInterval guardInterval)
0560 {
0561     const char *text = "";
0562 
0563     switch (guardInterval) {
0564     case DvbTTransponder::GuardInterval1_4: text = "1/4"; break;
0565     case DvbTTransponder::GuardInterval1_8: text = "1/8"; break;
0566     case DvbTTransponder::GuardInterval1_16: text = "1/16"; break;
0567     case DvbTTransponder::GuardInterval1_32: text = "1/32"; break;
0568     case DvbTTransponder::GuardIntervalAuto: text = "AUTO"; break;
0569     }
0570 
0571     return QLatin1String(text);
0572 }
0573 
0574 static QLatin1String enumToString(DvbT2Transponder::GuardInterval guardInterval)
0575 {
0576     const char *text = "";
0577 
0578     switch (guardInterval) {
0579     case DvbT2Transponder::GuardInterval1_4:    text = "1/4"; break;
0580     case DvbT2Transponder::GuardInterval19_128: text = "19/128"; break;
0581     case DvbT2Transponder::GuardInterval1_8:    text = "1/8"; break;
0582     case DvbT2Transponder::GuardInterval19_256: text = "19/256"; break;
0583     case DvbT2Transponder::GuardInterval1_16:   text = "1/16"; break;
0584     case DvbT2Transponder::GuardInterval1_32:   text = "1/32"; break;
0585     case DvbT2Transponder::GuardInterval1_128:  text = "1/128"; break;
0586     case DvbT2Transponder::GuardIntervalAuto:   text = "AUTO"; break;
0587     }
0588 
0589     return QLatin1String(text);
0590 }
0591 
0592 static QLatin1String enumToString(DvbTTransponder::Hierarchy hierarchy)
0593 {
0594     const char *text = "";
0595 
0596     switch (hierarchy) {
0597     case DvbTTransponder::HierarchyNone: text = "NONE"; break;
0598     case DvbTTransponder::Hierarchy1: text = "1"; break;
0599     case DvbTTransponder::Hierarchy2: text = "2"; break;
0600     case DvbTTransponder::Hierarchy4: text = "4"; break;
0601     case DvbTTransponder::HierarchyAuto: text = "AUTO"; break;
0602     }
0603 
0604     return QLatin1String(text);
0605 }
0606 
0607 static QLatin1String enumToString(DvbT2Transponder::Hierarchy hierarchy)
0608 {
0609     const char *text = "";
0610 
0611     switch (hierarchy) {
0612     case DvbT2Transponder::HierarchyNone: text = "NONE"; break;
0613     case DvbT2Transponder::Hierarchy1: text = "1"; break;
0614     case DvbT2Transponder::Hierarchy2: text = "2"; break;
0615     case DvbT2Transponder::Hierarchy4: text = "4"; break;
0616     case DvbT2Transponder::HierarchyAuto: text = "AUTO"; break;
0617     }
0618 
0619     return QLatin1String(text);
0620 }
0621 
0622 static QLatin1String enumToString(AtscTransponder::Modulation modulation)
0623 {
0624     const char *text = "";
0625 
0626     switch (modulation) {
0627     case AtscTransponder::Qam64: text = "64-QAM"; break;
0628     case AtscTransponder::Qam256: text = "256-QAM"; break;
0629     case AtscTransponder::Vsb8: text = "8-VSB"; break;
0630     case AtscTransponder::Vsb16: text = "16-VSB"; break;
0631     case AtscTransponder::ModulationAuto: text = "AUTO"; break;
0632     }
0633 
0634     return QLatin1String(text);
0635 }
0636 
0637 static QLatin1String enumToString(IsdbTTransponder::Bandwidth bandwidth)
0638 {
0639     const char *text = "";
0640 
0641     switch (bandwidth) {
0642     case IsdbTTransponder::Bandwidth6MHz: text = "6MHz"; break;
0643     case IsdbTTransponder::Bandwidth7MHz: text = "7MHz"; break;
0644     case IsdbTTransponder::Bandwidth8MHz: text = "8MHz"; break;
0645     }
0646 
0647     return QLatin1String(text);
0648 }
0649 
0650 static QLatin1String enumToString(IsdbTTransponder::Modulation modulation)
0651 {
0652     const char *text = "";
0653 
0654     switch (modulation) {
0655     case IsdbTTransponder::Dqpsk: text = "DQPSK"; break;
0656     case IsdbTTransponder::Qpsk: text = "QPSK"; break;
0657     case IsdbTTransponder::Qam16: text = "16-QAM"; break;
0658     case IsdbTTransponder::Qam64: text = "64-QAM"; break;
0659     case IsdbTTransponder::ModulationAuto: text = "AUTO"; break;
0660     }
0661 
0662     return QLatin1String(text);
0663 }
0664 
0665 static QLatin1String enumToString(IsdbTTransponder::GuardInterval guardInterval)
0666 {
0667     const char *text = "";
0668 
0669     switch (guardInterval) {
0670     case IsdbTTransponder::GuardInterval1_4: text = "1/4"; break;
0671     case IsdbTTransponder::GuardInterval1_8: text = "1/8"; break;
0672     case IsdbTTransponder::GuardInterval1_16: text = "1/16"; break;
0673     case IsdbTTransponder::GuardInterval1_32: text = "1/32"; break;
0674     case IsdbTTransponder::GuardIntervalAuto: text = "AUTO"; break;
0675     }
0676 
0677     return QLatin1String(text);
0678 }
0679 
0680 static QLatin1String enumToString(IsdbTTransponder::PartialReception partialReception)
0681 {
0682     const char *text = "";
0683 
0684     switch (partialReception) {
0685     case IsdbTTransponder::PR_disabled: text = "No"; break;
0686     case IsdbTTransponder::PR_enabled: text = "Yes"; break;
0687     case IsdbTTransponder::PR_AUTO: text = "AUTO"; break;
0688     }
0689 
0690     return QLatin1String(text);
0691 }
0692 
0693 static QLatin1String enumToString(IsdbTTransponder::SoundBroadcasting soundBroadcasting)
0694 {
0695     const char *text = "";
0696 
0697     switch (soundBroadcasting) {
0698     case IsdbTTransponder::SB_disabled: text = "No"; break;
0699     case IsdbTTransponder::SB_enabled: text = "Yes"; break;
0700     case IsdbTTransponder::SB_AUTO: text = "AUTO"; break;
0701     }
0702 
0703     return QLatin1String(text);
0704 }
0705 
0706 DvbChannelEditor::DvbChannelEditor(DvbChannelTableModel *model_, const DvbSharedChannel &channel_,
0707     QWidget *parent) : QDialog(parent), model(model_), channel(channel_)
0708 {
0709     setWindowTitle(i18nc("@title:window", "Edit Channel"));
0710 
0711     QWidget *widget = new QWidget(this);
0712     QBoxLayout *mainLayout = new QVBoxLayout(widget);
0713     QGridLayout *gridLayout = new QGridLayout();
0714 
0715     audioStreamBox = NULL;
0716 
0717     nameEdit = new QLineEdit(widget);
0718     nameEdit->setText(channel->name);
0719     gridLayout->addWidget(nameEdit, 0, 1);
0720 
0721     QLabel *label = new QLabel(i18nc("@label tv channel", "Name:"), widget);
0722     label->setBuddy(nameEdit);
0723     gridLayout->addWidget(label, 0, 0);
0724 
0725     numberBox = new QSpinBox(widget);
0726     numberBox->setRange(1, 99999);
0727     numberBox->setValue(channel->number);
0728     gridLayout->addWidget(numberBox, 0, 3);
0729 
0730     label = new QLabel(i18nc("@label tv channel", "Number:"), widget);
0731     label->setBuddy(numberBox);
0732     gridLayout->addWidget(label, 0, 2);
0733     mainLayout->addLayout(gridLayout);
0734 
0735     QBoxLayout *boxLayout = new QHBoxLayout();
0736 
0737     QGroupBox *groupBox = new QGroupBox(widget);
0738     gridLayout = new QGridLayout(groupBox);
0739     gridLayout->addWidget(new QLabel(i18nc("@label tv channel", "Source:")), 0, 0);
0740     gridLayout->addWidget(new QLabel(channel->source), 0, 1);
0741 
0742     int row = 11;
0743 
0744     switch (channel->transponder.getTransmissionType()) {
0745     case DvbTransponderBase::Invalid:
0746         break;
0747     case DvbTransponderBase::DvbC: {
0748         const DvbCTransponder *tp = channel->transponder.as<DvbCTransponder>();
0749         gridLayout->addWidget(new QLabel(i18n("Frequency (MHz):")), 1, 0);
0750         gridLayout->addWidget(
0751             new QLabel(QString::number(tp->frequency / 1000000.0)), 1, 1);
0752         gridLayout->addWidget(new QLabel(i18n("Symbol rate (kS/s):")), 2, 0);
0753         gridLayout->addWidget(new QLabel(QString::number(tp->symbolRate / 1000.0)), 2, 1);
0754         gridLayout->addWidget(new QLabel(i18n("Modulation:")), 3, 0);
0755         gridLayout->addWidget(new QLabel(enumToString(tp->modulation)), 3, 1);
0756         gridLayout->addWidget(new QLabel(i18n("FEC rate:")), 4, 0);
0757         gridLayout->addWidget(new QLabel(enumToString(tp->fecRate)), 4, 1);
0758         break;
0759         }
0760     case DvbTransponderBase::DvbS:
0761     case DvbTransponderBase::DvbS2: {
0762         const DvbS2Transponder *tp2 = channel->transponder.as<DvbS2Transponder>();
0763         const DvbSTransponder *tp = channel->transponder.as<DvbSTransponder>();
0764 
0765         if (tp == NULL) {
0766             tp = tp2;
0767         }
0768 
0769         gridLayout->addWidget(new QLabel(i18n("Polarization:")), 1, 0);
0770         gridLayout->addWidget(new QLabel(enumToString(tp->polarization)), 1, 1);
0771         gridLayout->addWidget(new QLabel(i18n("Frequency (MHz):")), 2, 0);
0772         gridLayout->addWidget(new QLabel(QString::number(tp->frequency / 1000.0)), 2, 1);
0773         gridLayout->addWidget(new QLabel(i18n("Symbol rate (kS/s):")), 3, 0);
0774         gridLayout->addWidget(new QLabel(QString::number(tp->symbolRate / 1000.0)), 3, 1);
0775         gridLayout->addWidget(new QLabel(i18n("FEC rate:")), 4, 0);
0776         gridLayout->addWidget(new QLabel(enumToString(tp->fecRate)), 4, 1);
0777 
0778         if (tp2 != NULL) {
0779             gridLayout->addWidget(new QLabel(i18n("Modulation:")), 5, 0);
0780             gridLayout->addWidget(new QLabel(enumToString(tp2->modulation)), 5, 1);
0781             gridLayout->addWidget(new QLabel(i18n("Roll-off:")), 6, 0);
0782             gridLayout->addWidget(new QLabel(enumToString(tp2->rollOff)), 6, 1);
0783         }
0784 
0785         break;
0786         }
0787     case DvbTransponderBase::DvbT: {
0788         const DvbTTransponder *tp = channel->transponder.as<DvbTTransponder>();
0789         gridLayout->addWidget(new QLabel(i18n("Frequency (MHz):")), 1, 0);
0790         gridLayout->addWidget(
0791             new QLabel(QString::number(tp->frequency / 1000000.0)), 1, 1);
0792         gridLayout->addWidget(new QLabel(i18n("Bandwidth:")), 2, 0);
0793         gridLayout->addWidget(new QLabel(enumToString(tp->bandwidth)), 2, 1);
0794         gridLayout->addWidget(new QLabel(i18n("Modulation:")), 3, 0);
0795         gridLayout->addWidget(new QLabel(enumToString(tp->modulation)), 3, 1);
0796         gridLayout->addWidget(new QLabel(i18n("FEC rate:")), 4, 0);
0797         gridLayout->addWidget(new QLabel(enumToString(tp->fecRateHigh)), 4, 1);
0798         gridLayout->addWidget(new QLabel(i18n("FEC rate LP:")), 5, 0);
0799         gridLayout->addWidget(new QLabel(enumToString(tp->fecRateLow)), 5, 1);
0800         gridLayout->addWidget(new QLabel(i18n("Transmission mode:")), 6, 0);
0801         gridLayout->addWidget(new QLabel(enumToString(tp->transmissionMode)), 6, 1);
0802         gridLayout->addWidget(new QLabel(i18n("Guard interval:")), 7, 0);
0803         gridLayout->addWidget(new QLabel(enumToString(tp->guardInterval)), 7, 1);
0804         gridLayout->addWidget(new QLabel(i18n("Hierarchy:")), 8, 0);
0805         gridLayout->addWidget(new QLabel(enumToString(tp->hierarchy)), 8, 1);
0806         break;
0807         }
0808     case DvbTransponderBase::DvbT2: {
0809         const DvbT2Transponder *tp = channel->transponder.as<DvbT2Transponder>();
0810         gridLayout->addWidget(new QLabel(i18n("Frequency (MHz):")), 1, 0);
0811         gridLayout->addWidget(
0812             new QLabel(QString::number(tp->frequency / 1000000.0)), 1, 1);
0813         gridLayout->addWidget(new QLabel(i18n("Bandwidth:")), 2, 0);
0814         gridLayout->addWidget(new QLabel(enumToString(tp->bandwidth)), 2, 1);
0815         gridLayout->addWidget(new QLabel(i18n("Modulation:")), 3, 0);
0816         gridLayout->addWidget(new QLabel(enumToString(tp->modulation)), 3, 1);
0817         gridLayout->addWidget(new QLabel(i18n("FEC rate:")), 4, 0);
0818         gridLayout->addWidget(new QLabel(enumToString(tp->fecRateHigh)), 4, 1);
0819         gridLayout->addWidget(new QLabel(i18n("FEC rate LP:")), 5, 0);
0820         gridLayout->addWidget(new QLabel(enumToString(tp->fecRateLow)), 5, 1);
0821         gridLayout->addWidget(new QLabel(i18n("Transmission mode:")), 6, 0);
0822         gridLayout->addWidget(new QLabel(enumToString(tp->transmissionMode)), 6, 1);
0823         gridLayout->addWidget(new QLabel(i18n("Guard interval:")), 7, 0);
0824         gridLayout->addWidget(new QLabel(enumToString(tp->guardInterval)), 7, 1);
0825         gridLayout->addWidget(new QLabel(i18n("Hierarchy:")), 8, 0);
0826         gridLayout->addWidget(new QLabel(enumToString(tp->hierarchy)), 8, 1);
0827         gridLayout->addWidget(new QLabel(i18n("PLP (stream ID):")), 9, 0);
0828         gridLayout->addWidget(
0829             new QLabel(QString::number(tp->streamId)), 9, 1);
0830         break;
0831         }
0832     case DvbTransponderBase::IsdbT: {
0833         const IsdbTTransponder *tp = channel->transponder.as<IsdbTTransponder>();
0834         row= 1;
0835         gridLayout->addWidget(new QLabel(i18n("Frequency (MHz):")), row, 0);
0836         gridLayout->addWidget(
0837             new QLabel(QString::number(tp->frequency / 1000000.0)), row++, 1);
0838         gridLayout->addWidget(new QLabel(i18n("Bandwidth:")), row, 0);
0839         gridLayout->addWidget(new QLabel(enumToString(tp->bandwidth)), row++, 1);
0840         gridLayout->addWidget(new QLabel(i18n("Transmission mode:")), row, 0);
0841         gridLayout->addWidget(new QLabel(enumToString(tp->transmissionMode)), row++, 1);
0842         gridLayout->addWidget(new QLabel(i18n("Guard interval:")), row, 0);
0843         gridLayout->addWidget(new QLabel(enumToString(tp->guardInterval)), row++, 1);
0844 
0845         gridLayout->addWidget(new QLabel(i18n("Partial reception:")), row, 0);
0846         gridLayout->addWidget(new QLabel(enumToString(tp->partialReception)), row++, 1);
0847         gridLayout->addWidget(new QLabel(i18n("Sound broadcasting:")), row, 0);
0848         gridLayout->addWidget(new QLabel(enumToString(tp->soundBroadcasting)), row++, 1);
0849 
0850         if (tp->soundBroadcasting == 1) {
0851             gridLayout->addWidget(new QLabel(i18n("SB channel ID:")), row, 0);
0852             gridLayout->addWidget(new QLabel(QString::number(tp->subChannelId)), row++, 1);
0853             gridLayout->addWidget(new QLabel(i18n("SB index:")), row, 0);
0854             gridLayout->addWidget(new QLabel(QString::number(tp->subChannelId)), row++, 1);
0855             gridLayout->addWidget(new QLabel(i18n("SB count:")), row, 0);
0856             gridLayout->addWidget(new QLabel(QString::number(tp->sbSegmentCount)), row++, 1);
0857         }
0858 
0859         if (tp->layerEnabled[0]) {
0860             gridLayout->addWidget(new QLabel(i18n("Layer A Modulation:")), row, 0);
0861             gridLayout->addWidget(new QLabel(enumToString(tp->modulation[0])), row++, 1);
0862             gridLayout->addWidget(new QLabel(i18n("Layer A FEC rate:")), row, 0);
0863             gridLayout->addWidget(new QLabel(enumToString(tp->fecRate[0])), row++, 1);
0864             gridLayout->addWidget(new QLabel(i18n("Layer A segments:")), row, 0);
0865             gridLayout->addWidget(new QLabel(QString::number(tp->segmentCount[0])), row++, 1);
0866             gridLayout->addWidget(new QLabel(i18n("Layer A interleaving:")), row, 0);
0867             gridLayout->addWidget(new QLabel(QString::number(tp->interleaving[0])), row++, 1);
0868         }
0869         if (tp->layerEnabled[1]) {
0870             gridLayout->addWidget(new QLabel(i18n("Layer B Modulation:")), row, 0);
0871             gridLayout->addWidget(new QLabel(enumToString(tp->modulation[1])), row++, 1);
0872             gridLayout->addWidget(new QLabel(i18n("Layer B FEC rate:")), row, 0);
0873             gridLayout->addWidget(new QLabel(enumToString(tp->fecRate[1])), row++, 1);
0874             gridLayout->addWidget(new QLabel(i18n("Layer B segments:")), row, 0);
0875             gridLayout->addWidget(new QLabel(QString::number(tp->segmentCount[1])), row++, 1);
0876             gridLayout->addWidget(new QLabel(i18n("Layer B interleaving:")), row, 0);
0877             gridLayout->addWidget(new QLabel(QString::number(tp->interleaving[1])), row++, 1);
0878         }
0879         if (tp->layerEnabled[2]) {
0880             gridLayout->addWidget(new QLabel(i18n("Layer C Modulation:")), row, 0);
0881             gridLayout->addWidget(new QLabel(enumToString(tp->modulation[2])), row++, 1);
0882             gridLayout->addWidget(new QLabel(i18n("Layer C FEC rate:")), row, 0);
0883             gridLayout->addWidget(new QLabel(enumToString(tp->fecRate[2])), row++, 1);
0884             gridLayout->addWidget(new QLabel(i18n("Layer C segments:")), row, 0);
0885             gridLayout->addWidget(new QLabel(QString::number(tp->segmentCount[2])), row++, 1);
0886             gridLayout->addWidget(new QLabel(i18n("Layer C interleaving:")), row, 0);
0887             gridLayout->addWidget(new QLabel(QString::number(tp->interleaving[2])), row++, 1);
0888         }
0889 
0890         break;
0891         }
0892     case DvbTransponderBase::Atsc: {
0893         const AtscTransponder *tp = channel->transponder.as<AtscTransponder>();
0894         gridLayout->addWidget(new QLabel(i18n("Frequency (MHz):")), 1, 0);
0895         gridLayout->addWidget(
0896             new QLabel(QString::number(tp->frequency / 1000000.0)), 1, 1);
0897         gridLayout->addWidget(new QLabel(i18n("Modulation:")), 2, 0);
0898         gridLayout->addWidget(new QLabel(enumToString(tp->modulation)), 2, 1);
0899         break;
0900         }
0901     }
0902 
0903     gridLayout->addWidget(new QLabel(), 10, 0, 1, 2);
0904 
0905     gridLayout->addItem(new QSpacerItem(0, 0), row, 0, 1, 2);
0906     gridLayout->setRowStretch(row, 1);
0907     boxLayout->addWidget(groupBox);
0908 
0909     groupBox = new QGroupBox(widget);
0910     gridLayout = new QGridLayout(groupBox);
0911     gridLayout->addWidget(new QLabel(i18n("Network ID:")), 0, 0);
0912 
0913     row = 1;
0914 
0915     networkIdBox = new QSpinBox(groupBox);
0916     networkIdBox->setRange(-1, (1 << 16) - 1);
0917     networkIdBox->setValue(channel->networkId);
0918     gridLayout->addWidget(networkIdBox, 0, 1);
0919 
0920     gridLayout->addWidget(new QLabel(i18n("Transport stream ID:")), row, 0);
0921 
0922     transportStreamIdBox = new QSpinBox(groupBox);
0923     transportStreamIdBox->setRange(0, (1 << 16) - 1);
0924     transportStreamIdBox->setValue(channel->transportStreamId);
0925     gridLayout->addWidget(transportStreamIdBox, row++, 1);
0926 
0927     gridLayout->addWidget(new QLabel(i18n("Service ID:")), row, 0);
0928 
0929     serviceIdBox = new QSpinBox(groupBox);
0930     serviceIdBox->setRange(0, (1 << 16) - 1);
0931     serviceIdBox->setValue(channel->serviceId);
0932     gridLayout->addWidget(serviceIdBox, row++, 1);
0933 
0934     DvbPmtSection pmtSection(channel->pmtSectionData);
0935     DvbPmtParser pmtParser(pmtSection);
0936 
0937     gridLayout->addWidget(new QLabel(i18n("Audio channel:")), row, 0);
0938     if (pmtParser.audioPids.count() > 1) {
0939         audioStreamBox = new QComboBox(groupBox);
0940 
0941         for (int i = 0; i < pmtParser.audioPids.size(); ++i) {
0942             const QPair<int, QString> &it = pmtParser.audioPids.at(i);
0943             QString text = QString::number(it.first);
0944 
0945             if (!it.second.isEmpty()) {
0946                 QString languageString;
0947 
0948                 if (!IsoCodes::getLanguage(it.second, &languageString))
0949                     languageString = it.second;
0950 
0951                 text = text + QLatin1String(" (") + languageString + QLatin1Char(')');
0952             }
0953 
0954             audioStreamBox->addItem(text);
0955             audioPids.append(it.first);
0956         }
0957         audioStreamBox->setCurrentIndex(audioPids.indexOf(channel->audioPid));
0958         gridLayout->addWidget(audioStreamBox, row++, 1);
0959     } else {
0960         const QPair<int, QString> &it = pmtParser.audioPids.at(0);
0961         QString text = QString::number(it.first);
0962 
0963         if (!it.second.isEmpty()) {
0964             QString languageString;
0965 
0966             if (!IsoCodes::getLanguage(it.second, &languageString))
0967                 languageString = it.second;
0968 
0969             text = text + QLatin1String(" (") + languageString + QLatin1Char(')');
0970         }
0971         gridLayout->addWidget(new QLabel(text), row++, 1);
0972     }
0973 
0974     gridLayout->addWidget(new QLabel(i18n("Scrambled:")), row, 0);
0975     scrambledBox = new QCheckBox(groupBox);
0976     scrambledBox->setChecked(channel->isScrambled);
0977     gridLayout->addWidget(scrambledBox, row++, 1);
0978 
0979     row++;
0980 
0981     gridLayout->addWidget(new QLabel(i18n("PMT PID:")), row, 0);
0982     gridLayout->addWidget(new QLabel(QString::number(channel->pmtPid)), row++, 1);
0983 
0984     if (pmtParser.videoPid >= 0) {
0985         gridLayout->addWidget(new QLabel(i18n("Video PID:")), row, 0);
0986         gridLayout->addWidget(new QLabel(QString::number(pmtParser.videoPid)), row++, 1);
0987     }
0988 
0989     if (!pmtParser.subtitlePids.isEmpty()) {
0990         gridLayout->addWidget(new QLabel(i18n("Subtitle PID:")), row, 0);
0991     }
0992 
0993     for (int i = 0; i < pmtParser.subtitlePids.size(); ++i) {
0994         const QPair<int, QString> &it = pmtParser.subtitlePids.at(i);
0995         QString languageString;
0996 
0997         if (!IsoCodes::getLanguage(it.second, &languageString))
0998             languageString = it.second;
0999 
1000 
1001         gridLayout->addWidget(new QLabel(QString(QLatin1String("%1 (%2)")).arg(it.first).arg(languageString)),
1002             row++, 1);
1003     }
1004 
1005     if (pmtParser.teletextPid != -1) {
1006         gridLayout->addWidget(new QLabel(i18n("Teletext PID:")), row, 0);
1007         gridLayout->addWidget(
1008             new QLabel(QString::number(pmtParser.teletextPid)), row++, 1);
1009     }
1010 
1011     gridLayout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 2);
1012     gridLayout->setRowStretch(5, 1);
1013     boxLayout->addWidget(groupBox);
1014     mainLayout->addLayout(boxLayout);
1015 
1016     mainLayout = new QVBoxLayout;
1017     setLayout(mainLayout);
1018     mainLayout->addWidget(widget);
1019 
1020     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
1021     connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
1022     connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
1023     mainLayout->addWidget(buttonBox);
1024 
1025 }
1026 
1027 DvbChannelEditor::~DvbChannelEditor()
1028 {
1029 }
1030 
1031 void DvbChannelEditor::accept()
1032 {
1033     DvbChannel updatedChannel = *channel;
1034     int oldAudioPid = channel->audioPid;
1035 
1036     updatedChannel.name = nameEdit->text();
1037     updatedChannel.number = numberBox->value();
1038     updatedChannel.networkId = networkIdBox->value();
1039     updatedChannel.transportStreamId = transportStreamIdBox->value();
1040     updatedChannel.serviceId = serviceIdBox->value();
1041 
1042     if (audioStreamBox && audioStreamBox->currentIndex() != -1) {
1043         updatedChannel.audioPid = audioPids.at(audioStreamBox->currentIndex());
1044     }
1045 
1046     updatedChannel.isScrambled = scrambledBox->isChecked();
1047     model->getChannelModel()->updateChannel(channel, updatedChannel);
1048 
1049     /*
1050      * If a channel is being played, a change at a PID should
1051      * be reflected at the played channel.
1052      *
1053      * TODO: add support for videos with multiple PIDs
1054      */
1055     if (updatedChannel.audioPid != oldAudioPid)
1056         emit channelPidsChanged(channel);
1057 
1058     QDialog::accept();
1059 }
1060 
1061 #include "moc_dvbchanneldialog_p.cpp"
1062 #include "moc_dvbchanneldialog.cpp"