15 #include <QTextStream>
16 #include <QElapsedTimer>
26 #define LOC QString("ChanImport: ")
50 bool _delete,
bool insert,
bool save,
51 bool fta_only,
bool lcn_only,
bool complete_only,
52 bool full_channel_search,
53 bool remove_duplicates,
57 m_isInteractive(interactive),
63 m_completeOnly(complete_only),
64 m_fullChannelSearch(full_channel_search),
65 m_removeDuplicates(remove_duplicates),
67 m_serviceRequirements(service_requirements)
79 if (_transports.empty())
85 LOG(VB_GENERAL, LOG_INFO,
LOC + (channels ?
87 QString(
"Found %1 channels")
89 "No new channels to process") :
90 "No channels to process.."));
94 (
m_success ? tr(
"Found %n channel(s)",
"", channels) :
95 tr(
"Failed to find any new channels!"))
96 : tr(
"Failed to find any channels."));
106 "No new channels to process" :
107 "No channels to process..");
121 QTextStream ssMsg(&msg);
127 ssMsg << Qt::endl << Qt::endl;
128 ssMsg <<
"Scan parameters:" << Qt::endl;
129 ssMsg <<
"Desired Services : " << (require_av ?
"tv" : require_a ?
"tv+radio" :
"all") << Qt::endl;
130 ssMsg <<
"Unencrypted Only : " << (
m_ftaOnly ?
"yes" :
"no") << Qt::endl;
131 ssMsg <<
"Logical Channel Numbers only: " << (
m_lcnOnly ?
"yes" :
"no") << Qt::endl;
132 ssMsg <<
"Complete scan data required : " << (
m_completeOnly ?
"yes" :
"no") << Qt::endl;
133 ssMsg <<
"Full search for old channels: " << (
m_fullChannelSearch ?
"yes" :
"no") << Qt::endl;
138 if (!transports.empty())
141 ssMsg <<
"Transport list before processing (" << transports.size() <<
"):" << Qt::endl;
146 ssMsg <<
"Channel list before processing (";
148 ssMsg <<
FormatChannels(transports, &info).toLatin1().constData();
150 LOG(VB_GENERAL, LOG_INFO,
LOC + msg);
164 if (!duplicates.empty())
168 ssMsg <<
"Discarded duplicate transports (" << duplicates.size() <<
"):" << Qt::endl;
170 ssMsg <<
"Discarded duplicate channels (" <<
SimpleCountChannels(duplicates) <<
"):" << Qt::endl;
171 ssMsg <<
FormatChannels(duplicates).toLatin1().constData() << Qt::endl;
172 LOG(VB_CHANSCAN, LOG_INFO,
LOC + msg);
190 if (!db_trans.empty())
193 ssMsg <<
"Transports with channels in DB but not in scan (";
194 ssMsg << db_trans.size() <<
"):" << Qt::endl;
205 ssMsg <<
"Channel list after compare with database (";
207 ssMsg <<
FormatChannels(transports, &info).toLatin1().constData();
215 std::copy(db_trans.cbegin(), db_trans.cend(), std::back_inserter(trans));
237 LOG(VB_GENERAL, LOG_INFO,
LOC + msg);
274 std::vector<uint> off_air_list;
275 QMap<uint,bool> deleted;
278 for (
size_t i = 0; i < transports.size(); ++i)
281 for (
size_t j = 0; j < transports[i].m_channels.size(); ++j)
290 off_air_list.push_back(i<<16|j);
295 off_air_transports.push_back(transport_copy);
298 if (off_air_list.empty())
302 std::cout << std::endl <<
"Off-air channels (" <<
SimpleCountChannels(off_air_transports) <<
"):" << std::endl;
304 std::cout <<
FormatChannels(off_air_transports, &infoA).toLatin1().constData() << std::endl;
309 QString msg = tr(
"Found %n off-air channel(s).",
"", off_air_list.size());
318 for (
uint item : off_air_list)
321 int j = item & 0xFFFF;
323 transports[i].m_channels[j].m_channelId);
324 deleted[item] =
true;
329 for (
uint item : off_air_list)
332 int j = item & 0xFFFF;
333 int chanid = transports[i].m_channels[j].m_channelId;
352 for (
size_t i = 0; i < transports.size(); ++i)
354 newlist.push_back(transports[i]);
355 newlist.back().m_channels.clear();
356 for (
size_t j = 0; j < transports[i].m_channels.size(); ++j)
358 if (!deleted.contains(i<<16|j))
360 newlist.back().m_channels.push_back(
361 transports[i].m_channels[j]);
366 transports = newlist;
367 return deleted.size();
374 "SELECT mplexid FROM dtv_multiplex "
375 "WHERE sourceid = :SOURCEID1 AND "
379 " WHERE sourceid = :SOURCEID2)");
388 QString msg = tr(
"Found %n unused transport(s).",
"", query.
size());
389 LOG(VB_GENERAL, LOG_INFO,
LOC + msg);
393 if (query.
size() == 0)
403 "DELETE FROM dtv_multiplex "
404 "WHERE sourceid = :SOURCEID1 AND "
408 " WHERE sourceid = :SOURCEID2)");
420 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Manual delete of transport not implemented");
451 QString msg = tr(
"Found %n old %1 channel(s).",
"", old_chan)
460 QString msg = tr(
"Found %n new %1 channel(s).",
"", new_chan)
488 QString msg = tr(
"Found %n conflicting old %1 channel(s).",
497 QString msg = tr(
"Found %n new conflicting %1 channel(s).",
506 QTextStream ssMsg(&msg);
508 if (!updated.empty())
510 ssMsg << Qt::endl << Qt::endl;
511 ssMsg <<
"Updated old transports (" << updated.size() <<
"):" << Qt::endl;
518 if (!skipped_updates.empty())
521 ssMsg <<
"Skipped old channels (" <<
SimpleCountChannels(skipped_updates) <<
"):" << Qt::endl;
524 if (!inserted.empty())
530 if (!skipped_inserts.empty())
533 ssMsg <<
"Skipped new channels (" <<
SimpleCountChannels(skipped_inserts) <<
"):" << Qt::endl;
545 ssMsg <<
GetSummary(ninfo, nstats).toLatin1().constData();
547 LOG(VB_GENERAL, LOG_INFO,
LOC + msg);
571 bool cancel_all =
false;
576 for (
const auto & transport : transports)
582 for (
size_t j = 0; j < transport.m_channels.size(); ++j)
624 bool conflicting =
false;
633 bool ok_done =
false;
673 bool inserted =
false;
715 if (!transport.m_iptvTuning.GetDataURL().isEmpty())
717 transport.m_iptvTuning);
740 next_list.push_back(new_transport);
743 skipped_list.push_back(skipped_transport);
746 inserted_list.push_back(inserted_transport);
775 for (
const auto & transport : transports)
781 for (
size_t j = 0; j < transport.m_channels.size(); ++j)
799 bool conflicting =
false;
818 bool updated =
false;
876 next_list.push_back(new_transport);
879 skipped_list.push_back(skipped_transport);
882 updated_list.push_back(updated_transport);
905 transport_copy = transport;
921 if (!transports.empty())
922 tuner_type = transports[0].m_tunerType;
927 uint freq_mult = (is_dvbs) ? 1 : 1000;
929 std::vector<bool> ignore;
930 ignore.resize(transports.size());
931 for (
size_t i = 0; i < transports.size(); ++i)
936 for (
size_t j = i+1; j < transports.size(); ++j)
938 if (!transports[i].IsEqual(
939 tuner_type, transports[j], 500 * freq_mult))
944 for (
size_t k = 0; k < transports[j].m_channels.size(); ++k)
946 bool found_same =
false;
947 for (
size_t l = 0; l < transports[i].m_channels.size(); ++l)
949 if (transports[j].m_channels[k].IsSameChannel(
950 transports[i].m_channels[l]))
953 transports[i].m_channels[l].ImportExtraInfo(
954 transports[j].m_channels[k]);
958 transports[i].m_channels.push_back(transports[j].m_channels[k]);
960 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
961 QString(
"Transport on same frequency:") +
FormatTransport(transports[j]));
964 no_dups.push_back(transports[i]);
966 transports = no_dups;
981 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
982 QString(
"Number of transports:%1").arg(transports.size()));
985 std::vector<bool> ignore;
986 ignore.resize(transports.size());
987 for (
size_t i = 0; i < transports.size(); ++i)
990 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"Transport " +
995 for (
size_t j = i+1; j < transports.size(); ++j)
998 bool found_same =
true;
999 bool found_diff =
true;
1002 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
"Comparing transport A " +
1004 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
"Comparing transport B " +
1007 for (
size_t k = 0; found_same && k < tb.
m_channels.size(); ++k)
1021 if (found_same && !found_diff)
1023 size_t lowss = transports[i].m_signalStrength < transports[j].m_signalStrength ? i : j;
1024 ignore[lowss] =
true;
1025 duplicates.push_back(transports[lowss]);
1027 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"Duplicate transports found:");
1036 no_dups.push_back(transports[i]);
1040 transports = no_dups;
1048 for (
auto & transport : transports)
1051 for (
auto & channel : transport.m_channels)
1053 if (
m_ftaOnly && channel.m_isEncrypted &&
1057 if (require_a && channel.m_isDataService)
1060 if (require_av && channel.m_isAudioService)
1064 if (
m_lcnOnly && channel.m_chanNum.isEmpty())
1067 LOG(VB_CHANSCAN, LOG_INFO,
LOC + QString(
"No LCN: %1").arg(msg));
1073 !(channel.m_inPat &&
1077 LOG(VB_CHANSCAN, LOG_INFO,
LOC + QString(
"Not in PAT/PMT: %1").arg(msg));
1083 channel.m_atscMajorChannel == 0 &&
1084 channel.m_atscMinorChannel == 0 &&
1085 (!channel.m_inPat ||
1088 (channel.m_patTsId !=
1089 channel.m_sdtTsId)))
1092 LOG(VB_CHANSCAN, LOG_INFO,
LOC + QString(
"Not in PAT/PMT/SDT: %1").arg(msg));
1100 LOG(VB_CHANSCAN, LOG_INFO,
LOC + QString(
"No name: %1").arg(msg));
1105 if (channel.m_inChannelsConf &&
1106 !(channel.m_inPat ||
1113 filtered.push_back(channel);
1115 transport.m_channels = filtered;
1121 QMap<uint64_t, bool> rs;
1124 for (
auto & transport : transports)
1126 for (
auto & channel : transport.m_channels)
1128 if (channel.m_oldOrigNetId > 0)
1130 uint64_t key = ((uint64_t)channel.m_oldOrigNetId << 32) | (channel.m_oldTsId << 16) | channel.m_oldServiceId;
1137 for (
auto & transport : transports)
1140 for (
auto & channel : transport.m_channels)
1142 uint64_t key = ((uint64_t)channel.m_origNetId << 32) | (channel.m_sdtTsId << 16) | channel.m_serviceId;
1143 if (rs.value(key,
false))
1146 LOG(VB_CHANSCAN, LOG_INFO,
LOC + QString(
"Relocated: %1").arg(msg));
1149 filtered.push_back(channel);
1151 transport.m_channels = filtered;
1166 int found_in_same_transport = 0;
1167 int found_in_other_transport = 0;
1168 int found_nowhere = 0;
1171 if (!transports.empty())
1172 tuner_type = transports[0].m_tunerType;
1178 uint freq_mult = (is_dvbs) ? 1 : 1000;
1183 "FROM dtv_multiplex "
1184 "WHERE sourceid = :SOURCEID "
1186 "ORDER BY mplexid");
1195 QMap<uint,bool> found_in_scan;
1196 while (query.
next())
1200 if (db_transport.
FillFromDB(tuner_type, mplexid))
1208 bool found_transport =
false;
1209 QMap<uint,bool> found_in_database;
1212 for (
size_t ist = 0; ist < transports.size(); ++ist)
1215 if (scan_transport.
IsEqual(tuner_type, db_transport, 500 * freq_mult,
true))
1217 found_transport =
true;
1219 for (
size_t jdc = 0; jdc < db_transport.
m_channels.size(); ++jdc)
1221 if (!found_in_database[jdc])
1224 for (
size_t ksc = 0; ksc < scan_transport.
m_channels.size(); ++ksc)
1226 if (!found_in_scan[(ist<<16)+ksc])
1231 found_in_same_transport++;
1232 found_in_database[jdc] =
true;
1233 found_in_scan[(ist<<16)+ksc] =
true;
1250 for (
size_t ist = 0; ist < transports.size(); ++ist)
1253 for (
size_t jdc = 0; jdc < db_transport.
m_channels.size(); ++jdc)
1255 if (!found_in_database[jdc])
1258 for (
size_t ksc = 0; ksc < scan_transport.
m_channels.size(); ++ksc)
1260 if (!found_in_scan[(ist<<16)+ksc])
1265 found_in_other_transport++;
1266 found_in_database[jdc] =
true;
1267 found_in_scan[(ist<<16)+ksc] =
true;
1281 if (found_transport)
1284 tmp.m_channels.clear();
1286 for (
size_t idc = 0; idc < db_transport.
m_channels.size(); ++idc)
1288 if (!found_in_database[idc])
1295 if (!
tmp.m_channels.empty())
1296 not_in_scan.push_back(
tmp);
1299 LOG(VB_GENERAL, LOG_INFO,
LOC +
1300 QString(
"Old channels found in same transport: %1")
1301 .arg(found_in_same_transport));
1302 LOG(VB_GENERAL, LOG_INFO,
LOC +
1303 QString(
"Old channels found in other transport: %1")
1304 .arg(found_in_other_transport));
1305 LOG(VB_GENERAL, LOG_INFO,
LOC +
1306 QString(
"Old channels not found (off-air): %1")
1307 .arg(found_nowhere));
1315 for (
auto & transport : transports)
1317 for (
auto & chan : transport.m_channels)
1319 if (((chan.m_couldBeOpencable && (chan.m_siStandard ==
"mpeg")) ||
1320 chan.m_isOpencable) && !chan.m_inVct)
1322 chan.m_siStandard =
"opencable";
1332 for (
const auto & transport : transports)
1334 for (
const auto & chan : transport.m_channels)
1336 int enc = (chan.m_isEncrypted) ?
1339 if (chan.m_siStandard ==
"dvb") info.
m_dvbChannels[enc] += 1;
1341 if (chan.m_siStandard ==
"opencable") info.
m_scteChannels[enc] += 1;
1343 if (chan.m_siStandard !=
"ntsc")
1348 if (chan.m_siStandard ==
"atsc")
1351 (chan.m_atscMinorChannel)];
1355 if (chan.m_siStandard ==
"ntsc")
1358 (chan.m_atscMinorChannel)];
1372 for (
const auto & transport : transports)
1374 for (
const auto & chan : transport.m_channels)
1381 if (chan.m_siStandard ==
"atsc")
1385 (chan.m_atscMinorChannel)] == 1) ? 1 : 0;
1387 (info.
m_atscMinCnt[(chan.m_atscMinorChannel)] == 1) ? 1 : 0;
1408 QTextStream ssMsg(&msg);
1412 QString si_standard = (chan.
m_siStandard==
"opencable") ?
1415 if (si_standard ==
"atsc" || si_standard ==
"scte")
1417 ssMsg << (QString(
"%1:%2:%3-%4:%5:%6=%7=%8:%9")
1425 .arg(si_standard)).toLatin1().constData();
1427 else if (si_standard ==
"dvb")
1429 ssMsg << (QString(
"%1:%2:%3:%4:%5:%6=%7:%8")
1435 .arg(si_standard)).toLatin1().constData();
1439 ssMsg << (QString(
"%1:%2:%3:%4:%5")
1443 .arg(si_standard)).toLatin1().constData();
1449 msg = msg.leftJustified(72);
1454 << (QString(
"cnt(pnum:%1,channum:%2)")
1457 ).toLatin1().constData();
1462 (QString(
":atsc_cnt(tot:%1,minor:%2)")
1467 ).toLatin1().constData();
1490 QTextStream ssMsg(&msg);
1492 QString si_standard = (chan.
m_siStandard==
"opencable") ?
1495 if (si_standard ==
"atsc" || si_standard ==
"scte")
1497 if (si_standard ==
"atsc")
1505 ssMsg << (QString(
"%1-%2")
1511 ssMsg << (QString(
"%1-%2")
1517 ssMsg << (QString(
" (%1)")
1518 .arg(chan.
m_callSign)).toLatin1().constData();
1520 else if (si_standard ==
"dvb")
1522 ssMsg << (QString(
"%1 (%2 %3)")
1524 .arg(chan.
m_netId)).toLatin1().constData();
1528 ssMsg << (QString(
"%1-%2")
1530 .toLatin1().constData();
1534 ssMsg << (QString(
"%1-%2")
1536 .toLatin1().constData();
1547 struct less_than_key
1555 std::sort(transports.begin(), transports.end(), less_than_key());
1559 for (
auto & transport : transports)
1561 auto fmt_chan = [transport, info](
const QString & m,
const auto & chan)
1562 {
return m +
FormatChannel(transport, chan, info) +
"\n"; };
1563 msg = std::accumulate(transport.m_channels.cbegin(), transport.m_channels.cend(),
1574 QTextStream ssMsg(&msg);
1576 ssMsg << QString(
" onid:%1").arg(transport.
m_networkID);
1586 struct less_than_key
1594 std::sort(transports.begin(), transports.end(), less_than_key());
1596 auto fmt_trans = [](
const QString& msg,
const auto & transport)
1598 return std::accumulate(transports.cbegin(), transports.cend(),
1599 QString(), fmt_trans);
1606 QString msg = tr(
"Channels: FTA Enc Dec\n") +
1607 QString(
"ATSC %1 %2 %3\n")
1611 QString(
"DVB %1 %2 %3\n")
1615 QString(
"SCTE %1 %2 %3\n")
1619 QString(
"MPEG %1 %2 %3\n")
1623 QString(
"NTSC %1\n")
1625 tr(
"Unique: prog %1 atsc %2 atsc minor %3 channum %4\n")
1628 tr(
"Max atsc major count: %1")
1694 new_chan = old_chan = 0;
1695 for (
const auto & transport : transports)
1697 for (
const auto& chan : transport.m_channels)
1701 if (chan.m_channelId)
1713 auto add_count = [](
int count,
const auto & transport)
1714 {
return count + transport.m_channels.size(); };
1715 return std::accumulate(transports.cbegin(), transports.cend(),
1736 static QMutex s_lastFreeLock;
1737 static QMap<uint,uint> s_lastFreeChanNumMap;
1745 for (
char suffix =
'A'; suffix <=
'Z'; ++suffix)
1753 QMutexLocker locker(&s_lastFreeLock);
1755 for (last_free_chan_num++; ; ++last_free_chan_num)
1757 chanNum = QString::number(last_free_chan_num);
1761 s_lastFreeChanNumMap[chan.
m_sourceId] = last_free_chan_num;
1789 auto *deleteDialog =
1792 if (deleteDialog->Create())
1794 deleteDialog->AddButton(tr(
"Delete All"));
1795 deleteDialog->AddButton(tr(
"Set all invisible"));
1797 deleteDialog->AddButton(tr(
"Ignore All"));
1799 [
this](
const QString & ,
int result)
1819 std::cout << msg.toLatin1().constData()
1821 << tr(
"Do you want to:").toLatin1().constData()
1823 << tr(
"1. Delete All").toLatin1().constData()
1825 << tr(
"2. Set all invisible").toLatin1().constData()
1828 << tr(
"4. Ignore All").toLatin1().constData()
1835 uint val = QString(ret.c_str()).toUInt(&ok);
1836 if (ok && (val == 1 || val == 2 || val == 4))
1846 std::cout << tr(
"Please enter either 1, 2 or 4:")
1847 .toLatin1().constData() << std::endl;
1877 auto *insertDialog =
1880 if (insertDialog->Create())
1882 insertDialog->AddButton(tr(
"Insert All"));
1883 insertDialog->AddButton(tr(
"Insert Manually"));
1884 insertDialog->AddButton(tr(
"Ignore All"));
1886 [
this](
const QString & ,
int result)
1906 std::cout << msg.toLatin1().constData()
1908 << tr(
"Do you want to:").toLatin1().constData()
1910 << tr(
"1. Insert All").toLatin1().constData()
1912 << tr(
"2. Insert Manually").toLatin1().constData()
1914 << tr(
"3. Ignore All").toLatin1().constData()
1921 uint val = QString(ret.c_str()).toUInt(&ok);
1922 if (ok && (1 <= val) && (val <= 3))
1930 std::cout << tr(
"Please enter either 1, 2, or 3:")
1931 .toLatin1().constData() << std::endl;
1962 auto *updateDialog =
1965 if (updateDialog->Create())
1967 updateDialog->AddButton(tr(
"Update All"));
1968 updateDialog->AddButton(tr(
"Ignore All"));
1970 [
this](
const QString& ,
int result)
1989 std::cout << msg.toLatin1().constData()
1991 << tr(
"Do you want to:").toLatin1().constData()
1993 << tr(
"1. Update All").toLatin1().constData()
1995 << tr(
"2. Update Manually").toLatin1().constData()
1997 << tr(
"3. Ignore All").toLatin1().constData()
2004 uint val = QString(ret.c_str()).toUInt(&ok);
2005 if (ok && (1 <= val) && (val <= 3))
2013 std::cout << tr(
"Please enter either 1, 2, or 3:")
2014 .toLatin1().constData() << std::endl;
2022 const QString& title,
2023 const QString& message, QString &text)
2043 popupStack = parent->
GetStack(
"popup stack");
2045 "manualchannelpopup");
2047 if (popup->Create())
2049 popup->AddButtonD(QCoreApplication::translate(
"(Common)",
"OK"), 0 == dmc);
2050 popup->AddButtonD(tr(
"Edit"), 1 == dmc);
2051 popup->AddButtonD(QCoreApplication::translate(
"(Common)",
"Cancel"), 2 == dmc);
2052 popup->AddButtonD(QCoreApplication::translate(
"(Common)",
"Cancel All"), 3 == dmc);
2054 [
this](
const QString & ,
int result)
2085 tr(
"Please enter a unique channel number."),
2087 if (textEdit->Create())
2090 [
this,&text](QString result)
2093 text = std::move(result);
2110 case 0: rval =
kOCTOk;
break;
2120 const QString& title,
2121 const QString& message, QString &text)
2142 popupStack = parent->
GetStack(
"popup stack");
2144 "resolvechannelpopup");
2146 if (popup->Create())
2148 popup->AddButtonD(QCoreApplication::translate(
"(Common)",
"OK"), 0 == dmc);
2149 popup->AddButtonD(QCoreApplication::translate(
"(Common)",
"OK All"), 1 == dmc);
2150 popup->AddButtonD(tr(
"Edit"), 2 == dmc);
2151 popup->AddButtonD(QCoreApplication::translate(
"(Common)",
"Cancel"), 3 == dmc);
2152 popup->AddButtonD(QCoreApplication::translate(
"(Common)",
"Cancel All"), 4 == dmc);
2154 [
this](
const QString & ,
int result)
2184 tr(
"Please enter a unique channel number."),
2186 if (textEdit->Create())
2189 [
this,&text](QString result)
2192 text = std::move(result);
2210 case 0: rval =
kOCTOk;
break;
2224 QString msg = tr(
"Channel %1 has channel number %2 but that is already in use.")
2236 msg2 += tr(
"Please enter a unique channel number.");
2240 msg2 += tr(
"Default value is %1.").arg(val);
2242 tr(
"Channel Importer"),
2258 std::cout << msg.toLatin1().constData() << std::endl;
2260 QString cancelStr = QCoreApplication::translate(
"(Common)",
2261 "Cancel").toLower();
2262 QString cancelAllStr = QCoreApplication::translate(
"(Common)",
2263 "Cancel All").toLower();
2264 QString msg2 = tr(
"Please enter a non-conflicting channel number "
2265 "(or type '%1' to skip, '%2' to skip all):")
2266 .arg(cancelStr, cancelAllStr);
2270 std::cout << msg2.toLatin1().constData() << std::endl;
2273 QString val = QString(sret.c_str());
2274 if (val.toLower() == cancelStr)
2279 if (val.toLower() == cancelAllStr)
2302 QString msg = tr(
"You chose to manually insert channel %1.")
2313 msg2 += tr(
"Please enter a unique channel number.");
2317 msg2 += tr(
"Default value is %1").arg(val);
2319 tr(
"Channel Importer"),
2336 std::cout << msg.toLatin1().constData() << std::endl;
2338 QString cancelStr = QCoreApplication::translate(
"(Common)",
"Cancel").toLower();
2339 QString cancelAllStr = QCoreApplication::translate(
"(Common)",
"Cancel All").toLower();
2342 QString msg2 = tr(
"Please enter a non-conflicting channel number "
2343 "(or type '%1' to skip, '%2' to skip all): ")
2344 .arg(cancelStr, cancelAllStr);
2348 std::cout << msg2.toLatin1().constData() << std::endl;
2351 QString val = QString(sret.c_str());
2352 if (val.toLower() == cancelStr)
2357 if (val.toLower() == cancelAllStr)
2386 bool ok = (num.length() >= 1);
2387 ok = ok && ((num[0] >=
'0') && (num[0] <=
'9'));