00001 #include <qsqldatabase.h>
00002 #include "settings.h"
00003 #include "mythcontext.h"
00004 #include "mythdbcon.h"
00005 #include "mythwidgets.h"
00006 #include "channeleditor.h"
00007
00008 #include <qapplication.h>
00009 #include <qlayout.h>
00010 #include <qdialog.h>
00011 #include <qcursor.h>
00012
00013 #include <mythwidgets.h>
00014 #include <mythdialogs.h>
00015 #include <mythwizard.h>
00016
00017 #include "channelsettings.h"
00018 #include "transporteditor.h"
00019 #include "sourceutil.h"
00020
00021 #include "scanwizard.h"
00022 #include "importicons.h"
00023
00024 ChannelWizard::ChannelWizard(int id, int default_sourceid)
00025 : ConfigurationWizard()
00026 {
00027 setLabel(QObject::tr("Channel Options"));
00028
00029
00030 addChild(cid = new ChannelID());
00031 cid->setValue(id);
00032
00033 ChannelOptionsCommon *common =
00034 new ChannelOptionsCommon(*cid, default_sourceid);
00035 addChild(common);
00036
00037 ChannelOptionsFilters *filters =
00038 new ChannelOptionsFilters(*cid);
00039 addChild(filters);
00040
00041 int cardtypes = countCardtypes();
00042 bool hasDVB = cardTypesInclude("DVB");
00043
00044
00045
00046 QString cardtype = getCardtype();
00047 if (!hasDVB || cardtypes > 1 || id == 0) {
00048 ChannelOptionsV4L* v4l = new ChannelOptionsV4L(*cid);
00049 addChild(v4l);
00050 }
00051 }
00052
00053 QString ChannelWizard::getCardtype() {
00054 MSqlQuery query(MSqlQuery::InitCon());
00055 query.prepare("SELECT cardtype"
00056 " FROM capturecard, cardinput, channel"
00057 " WHERE channel.chanid = :CHID "
00058 " AND channel.sourceid = cardinput.sourceid"
00059 " AND cardinput.cardid = capturecard.cardid");
00060 query.bindValue(":CHID", cid->getValue());
00061
00062 if (query.exec() && query.isActive() && query.size() > 0)
00063 {
00064 query.next();
00065 return query.value(0).toString();
00066 }
00067 else
00068 {
00069 return "";
00070 }
00071 }
00072
00073 bool ChannelWizard::cardTypesInclude(const QString& thecardtype) {
00074 MSqlQuery query(MSqlQuery::InitCon());
00075 query.prepare("SELECT count(cardtype)"
00076 " FROM capturecard, cardinput, channel"
00077 " WHERE channel.chanid= :CHID "
00078 " AND channel.sourceid = cardinput.sourceid"
00079 " AND cardinput.cardid = capturecard.cardid"
00080 " AND capturecard.cardtype= :CARDTYPE ");
00081 query.bindValue(":CHID", cid->getValue());
00082 query.bindValue(":CARDTYPE", thecardtype);
00083
00084 if (query.exec() && query.isActive() && query.size() > 0)
00085 {
00086 query.next();
00087 int count = query.value(0).toInt();
00088
00089 if (count > 0)
00090 return true;
00091 else
00092 return false;
00093 } else
00094 return false;
00095 }
00096
00097 int ChannelWizard::countCardtypes() {
00098 MSqlQuery query(MSqlQuery::InitCon());
00099 query.prepare("SELECT count(DISTINCT cardtype)"
00100 " FROM capturecard, cardinput, channel"
00101 " WHERE channel.chanid = :CHID "
00102 " AND channel.sourceid = cardinput.sourceid"
00103 " AND cardinput.cardid = capturecard.cardid");
00104 query.bindValue(":CHID", cid->getValue());
00105
00106 if (query.exec() && query.isActive() && query.size() > 0)
00107 {
00108 query.next();
00109 return query.value(0).toInt();
00110 } else
00111 return 0;
00112 }
00113
00114 int ChannelListSetting::fillSelections(void)
00115 {
00116 QString currentValue = getValue();
00117 uint currentIndex = max(getValueIndex(currentValue), 0);
00118 clearSelections();
00119 addSelection(QObject::tr("(New Channel)"), "0",
00120 0 == currentValue.toUInt());
00121
00122 bool fAllSources = true;
00123
00124 QString querystr = "SELECT channel.name,channum,chanid ";
00125
00126 if ((currentSourceID.isEmpty()) ||
00127 (currentSourceID == "Unassigned") ||
00128 (currentSourceID == "All"))
00129 {
00130 querystr += ",videosource.name FROM channel "
00131 "LEFT JOIN videosource ON "
00132 "(channel.sourceid = videosource.sourceid) ";
00133 fAllSources = true;
00134 }
00135 else
00136 {
00137 querystr += QString("FROM channel WHERE sourceid='%1' ")
00138 .arg(currentSourceID);
00139 fAllSources = false;
00140 }
00141
00142 if (currentSortMode == QObject::tr("Channel Name"))
00143 {
00144 querystr += " ORDER BY channel.name";
00145 }
00146 else if (currentSortMode == QObject::tr("Channel Number"))
00147 {
00148 querystr += " ORDER BY channum + 0";
00149 }
00150
00151 MSqlQuery query(MSqlQuery::InitCon());
00152 query.prepare(querystr);
00153
00154 uint selidx = 0, idx = 1;
00155 if (query.exec() && query.isActive() && query.size() > 0)
00156 {
00157 for (; query.next() ; idx++)
00158 {
00159 QString name = QString::fromUtf8(query.value(0).toString());
00160 QString channum = query.value(1).toString();
00161 QString chanid = query.value(2).toString();
00162 QString sourceid = "Unassigned";
00163
00164 if (fAllSources && !query.value(3).toString().isNull())
00165 {
00166 sourceid = query.value(3).toString();
00167 if (currentSourceID == "Unassigned")
00168 continue;
00169 }
00170
00171 if (channum == "" && currentHideMode)
00172 continue;
00173
00174 if (name == "")
00175 name = "(Unnamed : " + chanid + ")";
00176
00177 if (currentSortMode == QObject::tr("Channel Name"))
00178 {
00179 if (channum != "")
00180 name += " (" + channum + ")";
00181 }
00182 else if (currentSortMode == QObject::tr("Channel Number"))
00183 {
00184 if (channum != "")
00185 name = channum + ". " + name;
00186 else
00187 name = "???. " + name;
00188 }
00189
00190 if ((currentSourceID == "") && (currentSourceID != "Unassigned"))
00191 name += " (" + sourceid + ")";
00192
00193 bool sel = (chanid == currentValue);
00194 selidx = (sel) ? idx : selidx;
00195 addSelection(name, chanid, sel);
00196 }
00197 }
00198
00199
00200
00201 setCurrentItem((!selidx && currentIndex < idx) ? currentIndex : selidx);
00202 return idx;
00203 }
00204
00205 class SourceSetting : public ComboBoxSetting, public Storage
00206 {
00207 public:
00208 SourceSetting() : ComboBoxSetting(this)
00209 {
00210 setLabel(QObject::tr("Video Source"));
00211 addSelection(QObject::tr("(All)"),"All");
00212 };
00213
00214 void load()
00215 {
00216 MSqlQuery query(MSqlQuery::InitCon());
00217 query.prepare("SELECT name, sourceid FROM videosource");
00218
00219 if (query.exec() && query.isActive() && query.size() > 0)
00220 {
00221 while(query.next())
00222 {
00223 addSelection(query.value(0).toString(),
00224 query.value(1).toString());
00225 }
00226 }
00227 addSelection(QObject::tr("(Unassigned)"),"Unassigned");
00228 }
00229 void save(void) { }
00230 void save(QString ) { }
00231 };
00232
00233 class SortMode : public ComboBoxSetting, public TransientStorage
00234 {
00235 public:
00236 SortMode() : ComboBoxSetting(this)
00237 {
00238 setLabel(QObject::tr("Sort Mode"));
00239 addSelection(QObject::tr("Channel Name"));
00240 addSelection(QObject::tr("Channel Number"));
00241 };
00242 };
00243
00244 class NoChanNumHide : public CheckBoxSetting, public TransientStorage
00245 {
00246 public:
00247 NoChanNumHide() : CheckBoxSetting(this)
00248 { setLabel(QObject::tr("Hide channels without channel number.")); }
00249 };
00250
00251 ChannelEditor::ChannelEditor() : ConfigurationDialog()
00252 {
00253 setLabel(tr("Channels"));
00254
00255 addChild(list = new ChannelListSetting());
00256
00257 SortMode *sort = new SortMode();
00258 source = new SourceSetting();
00259 TransButtonSetting *del = new TransButtonSetting();
00260 NoChanNumHide *hide = new NoChanNumHide();
00261
00262 del->setLabel(tr("Delete Channels"));
00263 del->setHelpText(
00264 tr("Delete all channels on currently selected source[s]."));
00265
00266 HorizontalConfigurationGroup *src =
00267 new HorizontalConfigurationGroup(false, false, true, true);
00268 src->addChild(source);
00269 src->addChild(del);
00270
00271 sort->setValue(sort->getValueIndex(list->getSortMode()));
00272 source->setValue(max(source->getValueIndex(list->getSourceID()), 0));
00273 hide->setValue(list->getHideMode());
00274
00275 addChild(sort);
00276 addChild(src);
00277 addChild(hide);
00278
00279 buttonScan = new TransButtonSetting();
00280 buttonScan->setLabel(QObject::tr("Channel Scanner"));
00281 buttonScan->setHelpText(QObject::tr("Starts the channel scanner."));
00282 buttonScan->setEnabled(SourceUtil::IsAnySourceScanable());
00283
00284 buttonImportIcon = new TransButtonSetting();
00285 buttonImportIcon->setLabel(QObject::tr("Icon Download"));
00286 buttonImportIcon->setHelpText(QObject::tr("Starts the icon downloader"));
00287 buttonImportIcon->setEnabled(SourceUtil::IsAnySourceScanable());
00288
00289 buttonTransportEditor = new TransButtonSetting();
00290 buttonTransportEditor->setLabel(QObject::tr("Transport Editor"));
00291 buttonTransportEditor->setHelpText(
00292 QObject::tr("Allows you to edit the transports directly") + " " +
00293 QObject::tr("This is rarely required unless you are using "
00294 "a satellite dish and must enter an initial "
00295 "frequency to for the channel scanner to try."));
00296
00297 HorizontalConfigurationGroup *h =
00298 new HorizontalConfigurationGroup(false, false);
00299 h->addChild(buttonScan);
00300 h->addChild(buttonImportIcon);
00301 h->addChild(buttonTransportEditor);
00302 addChild(h);
00303
00304 connect(source, SIGNAL(valueChanged(const QString&)),
00305 list, SLOT(setSourceID(const QString&)));
00306 connect(sort, SIGNAL(valueChanged(const QString&)),
00307 list, SLOT(setSortMode(const QString&)));
00308 connect(hide, SIGNAL(valueChanged(bool)),
00309 list, SLOT(setHideMode(bool)));
00310 connect(list, SIGNAL(accepted(int)),
00311 this, SLOT(edit(int)));
00312 connect(list, SIGNAL(menuButtonPressed(int)),
00313 this, SLOT(menu(int)));
00314 connect(buttonScan, SIGNAL(pressed()),
00315 this, SLOT(scan()));
00316 connect(buttonImportIcon, SIGNAL(pressed()),
00317 this, SLOT(channelIconImport()));
00318 connect(buttonTransportEditor, SIGNAL(pressed()),
00319 this, SLOT(transportEditor()));
00320 connect(del, SIGNAL(pressed()),
00321 this, SLOT(deleteChannels()));
00322 }
00323
00324 void ChannelEditor::deleteChannels(void)
00325 {
00326 const QString currentLabel = source->getSelectionLabel();
00327 const QString currentSourceID = source->getValue();
00328
00329 bool del_all = currentSourceID.isEmpty() || currentSourceID == "All";
00330 bool del_nul = currentSourceID == "Unassigned";
00331
00332 QString chan_msg =
00333 (del_all) ? tr("Are you sure you would like to delete ALL channels?") :
00334 ((del_nul) ?
00335 tr("Are you sure you would like to delete all unassigned channels?") :
00336 tr("Are you sure you would like to delete the channels on %1?")
00337 .arg(currentLabel));
00338
00339 DialogCode val = MythPopupBox::Show2ButtonPopup(
00340 gContext->GetMainWindow(), "", chan_msg,
00341 tr("Yes, delete the channels"),
00342 tr("No, don't"), kDialogCodeButton1);
00343
00344 if (kDialogCodeButton0 != val)
00345 return;
00346
00347 MSqlQuery query(MSqlQuery::InitCon());
00348 if (del_all)
00349 {
00350 query.prepare("TRUNCATE TABLE channel");
00351 }
00352 else if (del_nul)
00353 {
00354 query.prepare("SELECT sourceid "
00355 "FROM videosource "
00356 "GROUP BY sourceid");
00357
00358 if (!query.exec() || !query.isActive())
00359 {
00360 MythContext::DBError("ChannelEditor Delete Channels", query);
00361 return;
00362 }
00363
00364 QString tmp = "";
00365 while (query.next())
00366 tmp += "'" + query.value(0).toString() + "',";
00367
00368 if (tmp.isEmpty())
00369 {
00370 query.prepare("TRUNCATE TABLE channel");
00371 }
00372 else
00373 {
00374 tmp = tmp.left(tmp.length() - 1);
00375 query.prepare(QString("DELETE FROM channel "
00376 "WHERE sourceid NOT IN (%1)").arg(tmp));
00377 }
00378 }
00379 else
00380 {
00381 query.prepare("DELETE FROM channel "
00382 "WHERE sourceid = :SOURCEID");
00383 query.bindValue(":SOURCEID", currentSourceID);
00384 }
00385
00386 if (!query.exec())
00387 MythContext::DBError("ChannelEditor Delete Channels", query);
00388
00389 list->fillSelections();
00390 }
00391
00392 MythDialog* ChannelEditor::dialogWidget(MythMainWindow* parent,
00393 const char* widgetName)
00394 {
00395 dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
00396 connect(dialog, SIGNAL(editButtonPressed()), this, SLOT(edit()));
00397 connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(del()));
00398 return dialog;
00399 }
00400
00401 DialogCode ChannelEditor::exec(void)
00402 {
00403 while (ConfigurationDialog::exec() == kDialogCodeAccepted) {}
00404 return kDialogCodeRejected;
00405 }
00406
00407 void ChannelEditor::edit()
00408 {
00409 id = list->getValue().toInt();
00410 ChannelWizard cw(id, source->getValue().toUInt());
00411 cw.exec();
00412
00413 list->fillSelections();
00414 list->setFocus();
00415 }
00416
00417 void ChannelEditor::edit(int )
00418 {
00419 edit();
00420 }
00421
00422 void ChannelEditor::del()
00423 {
00424 id = list->getValue().toInt();
00425
00426 DialogCode val = MythPopupBox::Show2ButtonPopup(
00427 gContext->GetMainWindow(),
00428 "", tr("Are you sure you would like to delete this channel?"),
00429 tr("Yes, delete the channel"),
00430 tr("No, don't"), kDialogCodeButton1);
00431
00432 if (kDialogCodeButton0 == val)
00433 {
00434 MSqlQuery query(MSqlQuery::InitCon());
00435 query.prepare("DELETE FROM channel WHERE chanid = :CHID ;");
00436 query.bindValue(":CHID", id);
00437 if (!query.exec() || !query.isActive())
00438 MythContext::DBError("ChannelEditor Delete Channel", query);
00439
00440 list->fillSelections();
00441 }
00442 }
00443
00444 void ChannelEditor::menu(int )
00445 {
00446 id = list->getValue().toInt();
00447 if (id == 0)
00448 edit();
00449 else
00450 {
00451 DialogCode val = MythPopupBox::Show2ButtonPopup(
00452 gContext->GetMainWindow(),
00453 "", tr("Channel Menu"),
00454 tr("Edit.."), tr("Delete.."), kDialogCodeButton0);
00455
00456 if (kDialogCodeButton0 == val)
00457 emit edit();
00458 else if (kDialogCodeButton1 == val)
00459 emit del();
00460 else
00461 list->setFocus();
00462 }
00463 }
00464
00465 void ChannelEditor::scan(void)
00466 {
00467 #ifdef USING_BACKEND
00468 int val = source->getValue().toInt();
00469 uint sourceid = (val > 0) ? val : 0;
00470 ScanWizard *scanwizard = new ScanWizard(sourceid);
00471 scanwizard->exec(false, true);
00472 scanwizard->deleteLater();
00473
00474 list->fillSelections();
00475 list->setFocus();
00476 #else
00477 VERBOSE(VB_IMPORTANT, "You must compile the backend "
00478 "to be able to scan for channels");
00479 #endif
00480 }
00481
00482 void ChannelEditor::transportEditor(void)
00483 {
00484 uint sourceid = source->getValue().toUInt();
00485
00486 TransportListEditor *editor = new TransportListEditor(sourceid);
00487 editor->exec();
00488 editor->deleteLater();
00489
00490 list->fillSelections();
00491 list->setFocus();
00492 }
00493
00494 void ChannelEditor::channelIconImport(void)
00495 {
00496 if (list->fillSelections() == 0)
00497 {
00498 MythPopupBox::showOkPopup(gContext->GetMainWindow(), "",
00499 tr("Add some for channels first!"));
00500 return;
00501 }
00502
00503
00504 QString querystr = QString("SELECT channel.name FROM channel WHERE chanid='%1' ").arg(list->getValue());
00505 QString channelname = "";
00506 MSqlQuery query(MSqlQuery::InitCon());
00507 query.prepare(querystr);
00508
00509 if (query.exec() && query.isActive() && query.size() > 0)
00510 {
00511 query.next();
00512 channelname = QString::fromUtf8(query.value(0).toString());
00513 }
00514
00515 QStringList buttons;
00516 buttons.append(tr("Cancel"));
00517 buttons.append(tr("Download all icons.."));
00518 buttons.append(tr("Rescan for missing icons.."));
00519 if (!channelname.isEmpty())
00520 buttons.append(tr("Download icon for ") + channelname);
00521
00522 int val = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(),
00523 "", "Channel Icon Import", buttons, kDialogCodeButton2);
00524
00525 ImportIconsWizard *iconwizard;
00526 if (val == kDialogCodeButton0)
00527 return;
00528 else if (val == kDialogCodeButton1)
00529 iconwizard = new ImportIconsWizard(false);
00530 else if (val == kDialogCodeButton2)
00531 iconwizard = new ImportIconsWizard(true);
00532 else if (val == kDialogCodeButton3)
00533 iconwizard = new ImportIconsWizard(true, channelname);
00534 else
00535 return;
00536
00537 iconwizard->exec();
00538 iconwizard->deleteLater();
00539
00540 list->fillSelections();
00541 list->setFocus();
00542 }