// display a news void RSSWidget::handleCurrentArticleChanged(const QModelIndex ¤tIndex, const QModelIndex &previousIndex) { m_ui->textBrowser->clear(); if (previousIndex.isValid()) { RSS::Article *article = getArticlePtr(previousIndex); Q_ASSERT(article); article->markAsRead(); } if (!currentIndex.isValid()) return; RSS::Article *article = getArticlePtr(currentIndex); Q_ASSERT(article); QString html; html += "<div style='border: 2px solid red; margin-left: 5px; margin-right: 5px; margin-bottom: 5px;'>"; html += "<div style='background-color: #678db2; font-weight: bold; color: #fff;'>" + article->title() + "</div>"; if (article->date().isValid()) html += "<div style='background-color: #efefef;'><b>" + tr("Date: ") + "</b>" + article->date().toLocalTime().toString(Qt::SystemLocaleLongDate) + "</div>"; if (!article->author().isEmpty()) html += "<div style='background-color: #efefef;'><b>" + tr("Author: ") + "</b>" + article->author() + "</div>"; html += "</div>"; html += "<div style='margin-left: 5px; margin-right: 5px;'>"; if (Qt::mightBeRichText(article->description())) { html += article->description(); } else { QString description = article->description(); QRegularExpression rx; // If description is plain text, replace BBCode tags with HTML and wrap everything in <pre></pre> so it looks nice rx.setPatternOptions(QRegularExpression::InvertedGreedinessOption | QRegularExpression::CaseInsensitiveOption); rx.setPattern("\\[img\\](.+)\\[/img\\]"); description = description.replace(rx, "<img src=\"\\1\">"); rx.setPattern("\\[url=(\")?(.+)\\1\\]"); description = description.replace(rx, "<a href=\"\\2\">"); description = description.replace("[/url]", "</a>", Qt::CaseInsensitive); rx.setPattern("\\[(/)?([bius])\\]"); description = description.replace(rx, "<\\1\\2>"); rx.setPattern("\\[color=(\")?(.+)\\1\\]"); description = description.replace(rx, "<span style=\"color:\\2\">"); description = description.replace("[/color]", "</span>", Qt::CaseInsensitive); rx.setPattern("\\[size=(\")?(.+)\\d\\1\\]"); description = description.replace(rx, "<span style=\"font-size:\\2px\">"); description = description.replace("[/size]", "</span>", Qt::CaseInsensitive); html += "<pre>" + description + "</pre>"; } html += "</div>"; m_ui->textBrowser->setHtml(html); }
int Walltime::toInt( QString const& string ) { int h,m; int s = -1; QRegularExpression re; QRegularExpressionMatch rem; // "h+:mm:ss" re.setPattern("^(\\d+):(\\d+):(\\d+)"); rem = re.match(string); if( rem.hasMatch() ) { try { h = rem.captured(1).toInt(); m = rem.captured(2).toInt(); s = rem.captured(3).toInt(); s+= h*3600 + m*60; } catch(...) { s = -1; } return s; } // "<integer>unit" where unit is d|h|m|s (case insensitive) re.setPattern("^\\s*(\\d+)\\s*([dhmsDHMS]?)\\s*$"); rem = re.match( string ); if( rem.hasMatch() ) { QString number = rem.captured(1); QString unit = rem.captured(2); try { s = number.toInt(); if( s<0 ) s = -1; else if( unit=="d" ) s*=24*3600; else if( unit=="h" ) s*=3600; else if( unit=="m" ) s*=60; else if( unit=="s" ) s*=1; else s = -1; } catch(...) { s = -1; } return s; } // "h+:mm" re.setPattern("^\\s*(\\d+):(\\d+)\\s*$"); rem = re.match( string ); if( rem.hasMatch() ) { try { h = rem.captured(1).toInt(); m = rem.captured(2).toInt(); s = h*3600 + m*60; } catch(...) { s = -1; } return s; } return -1; //keep the compiler happy }
bool Ratings::setRating(const QString& val, RatingAgency ag) { qint32 agencyIndex; for (agencyIndex = 0;; ++agencyIndex) { Q_ASSERT(agencyIndex <= CountRatingAcencies); if (static_cast<qint32>(ag) == (1 << agencyIndex)) break; } /////////////////Fix for bloomberg return values in excel////////////////// if (val.trimmed().toUpper().left(4) == "#N/A") { setRating(RatingValue::NR, ag); setWatch(Stable, ag); return true; } ////////////////////////////////////////////////////////////////////////// const auto agencySyntax = RatingsPrivate::m_ratingSyntax[agencyIndex]; QRegularExpression syntaxCheck; syntaxCheck.setPatternOptions(QRegularExpression::CaseInsensitiveOption | QRegularExpression::DontCaptureOption); for (int i = static_cast<qint16>(RatingValue::AAA); i <= static_cast<qint16>(RatingValue::Dm); ++i){ if (!agencySyntax[i].isEmpty()) { syntaxCheck.setPattern( "(^|[^" + QRegularExpression::escape(RatingsPrivate::m_reservedChars[agencyIndex]) + "])" + QRegularExpression::escape(agencySyntax[i]) + "($|[^" + QRegularExpression::escape(RatingsPrivate::m_reservedChars[agencyIndex]) + "])" ); Q_ASSERT(syntaxCheck.isValid()); if (syntaxCheck.match(val).hasMatch()){ setRating(static_cast<RatingValue>(i), ag); break; } } if (i == static_cast<qint16>(RatingValue::Dm)) { setRating(RatingValue::NR, ag, Stable); return false; } } if (val.indexOf("*-", 0, Qt::CaseInsensitive) >= 0) setWatch(Negative, ag); else if (val.indexOf("*+", 0, Qt::CaseInsensitive) >= 0) setWatch(Positive, ag); else setWatch(Stable, ag); return true; }
int main() { { //! [0] QRegularExpression re("a pattern"); //! [0] } { //! [1] QRegularExpression re; re.setPattern("another pattern"); //! [1] } { //! [2] // matches two digits followed by a space and a word QRegularExpression re("\\d\\d \\w+"); // matches a backslash QRegularExpression re2("\\\\"); //! [2] } { //! [3] QRegularExpression re("a third pattern"); QString pattern = re.pattern(); // pattern == "a third pattern" //! [3] } { //! [4] // matches "Qt rocks", but also "QT rocks", "QT ROCKS", "qT rOcKs", etc. QRegularExpression re("Qt rocks", QRegularExpression::CaseInsensitiveOption); //! [4] } { //! [5] QRegularExpression re("^\\d+$"); re.setPatternOptions(QRegularExpression::MultilineOption); // re matches any line in the subject string that contains only digits (but at least one) //! [5] } { //! [6] QRegularExpression re = QRegularExpression("^two.*words$", QRegularExpression::MultilineOption | QRegularExpression::DotMatchesEverythingOption); QRegularExpression::PatternOptions options = re.patternOptions(); // options == QRegularExpression::MultilineOption | QRegularExpression::DotMatchesEverythingOption //! [6] } { //! [7] // match two digits followed by a space and a word QRegularExpression re("\\d\\d \\w+"); QRegularExpressionMatch match = re.match("abc123 def"); bool hasMatch = match.hasMatch(); // true //! [7] } { //! [8] QRegularExpression re("\\d\\d \\w+"); QRegularExpressionMatch match = re.match("abc123 def"); if (match.hasMatch()) { QString matched = match.captured(0); // matched == "23 def" // ... } //! [8] } { //! [9] QRegularExpression re("\\d\\d \\w+"); QRegularExpressionMatch match = re.match("12 abc 45 def", 1); if (match.hasMatch()) { QString matched = match.captured(0); // matched == "45 def" // ... } //! [9] } { //! [10] QRegularExpression re("^(\\d\\d)/(\\d\\d)/(\\d\\d\\d\\d)$"); QRegularExpressionMatch match = re.match("08/12/1985"); if (match.hasMatch()) { QString day = match.captured(1); // day == "08" QString month = match.captured(2); // month == "12" QString year = match.captured(3); // year == "1985" // ... } //! [10] } { //! [11] QRegularExpression re("abc(\\d+)def"); QRegularExpressionMatch match = re.match("XYZabc123defXYZ"); if (match.hasMatch()) { int startOffset = match.capturedStart(1); // startOffset == 6 int endOffset = match.capturedEnd(1); // endOffset == 9 // ... } //! [11] } { //! [12] QRegularExpression re("^(?<date>\\d\\d)/(?<month>\\d\\d)/(?<year>\\d\\d\\d\\d)$"); QRegularExpressionMatch match = re.match("08/12/1985"); if (match.hasMatch()) { QString date = match.captured("date"); // date == "08" QString month = match.captured("month"); // month == "12" QString year = match.captured("year"); // year == 1985 } //! [12] } { //! [13] QRegularExpression re("(\\w+)"); QRegularExpressionMatchIterator i = re.globalMatch("the quick fox"); //! [13] //! [14] QStringList words; while (i.hasNext()) { QRegularExpressionMatch match = i.next(); QString word = match.captured(1); words << word; } // words contains "the", "quick", "fox" //! [14] } { //! [15] QString pattern("^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \\d\\d?, \\d\\d\\d\\d$"); QRegularExpression re(pattern); QString input("Jan 21,"); QRegularExpressionMatch match = re.match(input, 0, QRegularExpression::PartialPreferCompleteMatch); bool hasMatch = match.hasMatch(); // false bool hasPartialMatch = match.hasPartialMatch(); // true //! [15] } { QString pattern("^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \\d\\d?, \\d\\d\\d\\d$"); QRegularExpression re(pattern); //! [16] QString input("Dec 8, 1985"); QRegularExpressionMatch match = re.match(input, 0, QRegularExpression::PartialPreferCompleteMatch); bool hasMatch = match.hasMatch(); // true bool hasPartialMatch = match.hasPartialMatch(); // false //! [16] } { //! [17] QRegularExpression re("abc\\w+X|def"); QRegularExpressionMatch match = re.match("abcdef", 0, QRegularExpression::PartialPreferCompleteMatch); bool hasMatch = match.hasMatch(); // true bool hasPartialMatch = match.hasPartialMatch(); // false QString captured = match.captured(0); // captured == "def" //! [17] } { //! [18] QRegularExpression re("abc\\w+X|defY"); QRegularExpressionMatch match = re.match("abcdef", 0, QRegularExpression::PartialPreferCompleteMatch); bool hasMatch = match.hasMatch(); // false bool hasPartialMatch = match.hasPartialMatch(); // true QString captured = match.captured(0); // captured == "abcdef" //! [18] } { //! [19] QRegularExpression re("abc|ab"); QRegularExpressionMatch match = re.match("ab", 0, QRegularExpression::PartialPreferFirstMatch); bool hasMatch = match.hasMatch(); // false bool hasPartialMatch = match.hasPartialMatch(); // true //! [19] } { //! [20] QRegularExpression re("abc(def)?"); QRegularExpressionMatch match = re.match("abc", 0, QRegularExpression::PartialPreferFirstMatch); bool hasMatch = match.hasMatch(); // false bool hasPartialMatch = match.hasPartialMatch(); // true //! [20] } { //! [21] QRegularExpression re("(abc)*"); QRegularExpressionMatch match = re.match("abc", 0, QRegularExpression::PartialPreferFirstMatch); bool hasMatch = match.hasMatch(); // false bool hasPartialMatch = match.hasPartialMatch(); // true //! [21] } { //! [22] QRegularExpression invalidRe("(unmatched|parenthesis"); bool isValid = invalidRe.isValid(); // false //! [22] } { //! [23] QRegularExpression invalidRe("(unmatched|parenthesis"); if (!invalidRe.isValid()) { QString errorString = invalidRe.errorString(); // errorString == "missing )" int errorOffset = invalidRe.patternErrorOffset(); // errorOffset == 22 // ... } //! [23] } { //! [24] QRegularExpression re("^this pattern must match exactly$"); //! [24] } { //! [25] QString p("a .*|pattern"); QRegularExpression re("\\A(?:" + p + ")\\z"); // re matches exactly the pattern string p //! [25] } { //! [26] QString escaped = QRegularExpression::escape("a(x) = f(x) + g(x)"); // escaped == "a\\(x\\)\\ \\=\\ f\\(x\\)\\ \\+\\ g\\(x\\)" //! [26] } { QString name; QString nickname; //! [27] QString pattern = "(" + QRegularExpression::escape(name) + "|" + QRegularExpression::escape(nickname) + ")"; QRegularExpression re(pattern); //! [27] } { QString string; QRegularExpression re; //! [28] QRegularExpressionMatch match = re.match(string); for (int i = 0; i <= match.lastCapturedIndex(); ++i) { QString captured = match.captured(i); // ... } //! [28] } { //! [29] QRegularExpression re("(\\d\\d) (?<name>\\w+)"); QRegularExpressionMatch match = re.match("23 Jordan"); if (match.hasMatch()) { QString number = match.captured(1); // first == "23" QString name = match.captured("name"); // name == "Jordan" } //! [29] } { //! [30] // extracts the words QRegularExpression re("(\\w+)"); QString subject("the quick fox"); QRegularExpressionMatchIterator i = re.globalMatch(subject); while (i.hasNext()) { QRegularExpressionMatch match = i.next(); // ... } //! [30] } }
void Reader_RFM008B::readData() { if(m_serial->canReadLine()){ if(!allLines){ // Logger::instance()->writeRecord(Logger::severity_level::debug, m_module, Q_FUNC_INFO, QString("Reading Data...")); QByteArray buffer = m_serial->readAll(); QRegExp regex; regex.setPattern("(L(\\d{2})?W)\\s([0-9a-fA-F]{4})\\s([0-9a-fA-F]{16})"); QString data(buffer); data.remove(QRegExp("[\\n\\t\\r]")); // if(m_outReceived.device()){ // m_outReceived << data; // m_outReceived.flush(); // } int pos = regex.indexIn(data); if(pos != -1){ // The first string in the list is the entire matched string. // Each subsequent list element contains a string that matched a // (capturing) subexpression of the regexp. QStringList matches = regex.capturedTexts(); // crear RFIDData QRegularExpression regexCode; regexCode.setPattern("([0-9a-fA-F]{4})(\\s)([0-9a-fA-F]{16})"); QRegularExpressionMatch match = regexCode.match(matches.at(0)); if(m_outCaptured.device()){ m_outCaptured << matches.at(0); m_outCaptured.flush(); } if(match.hasMatch()) { Rfiddata *data = new Rfiddata(this); // Id collector from configuration file data->setIdpontocoleta(idCollector); // This module can read from only one antena, so the idAntena is static. int idAntena = 1; data->setIdantena(idAntena); qlonglong applicationcode = match.captured(1).toLongLong(); qlonglong identificationcode = match.captured(3).toLongLong(); /* * Filter by time. If more than one transponder was read in a time interval only one of them will be persisted. * A QMap is used to verify if each new data that had arrived was already read in this interval. */ if(!m_map.contains(identificationcode)){ QTimer *timer = new QTimer; timer->setSingleShot(true); timer->setInterval(1000); connect(timer, &QTimer::timeout, [=, this]() { this->m_map.remove(identificationcode); timer->deleteLater(); }); m_map.insert(identificationcode, timer); timer->start(); data->setApplicationcode(applicationcode); data->setIdentificationcode(identificationcode); data->setDatetime(QDateTime::currentDateTime()); data->setSync(Rfiddata::KNotSynced); QList<Rfiddata*> list; list.append(data); try { PersistenceInterface *persister = qobject_cast<PersistenceInterface *>(RFIDMonitor::instance()->defaultService(ServiceType::KPersister)); Q_ASSERT(persister); SynchronizationInterface *synchronizer = qobject_cast<SynchronizationInterface*>(RFIDMonitor::instance()->defaultService(ServiceType::KSynchronizer)); Q_ASSERT(synchronizer); #ifdef CPP_11_ASYNC /*C++11 std::async Version*/ std::function<void(const QList<Rfiddata *>&)> persistence = std::bind(&PersistenceInterface::insertObjectList, persister, std::placeholders::_1); std::async(std::launch::async, persistence, list); std::function<void()> synchronize = std::bind(&SynchronizationInterface::readyRead, synchronizer); std::async(std::launch::async, synchronize); #else /*Qt Concurrent Version*/ QtConcurrent::run(persister, &PersistenceInterface::insertObjectList, list); QtConcurrent::run(synchronizer, &SynchronizationInterface::readyRead); #endif } catch (std::exception &e) { Logger::instance()->writeRecord(Logger::severity_level::fatal, m_module, Q_FUNC_INFO, e.what()); } } } } }else{ // Logger::instance()->writeRecord(Logger::severity_level::debug, m_module, Q_FUNC_INFO, QString("FULL READ...")); QByteArray buffer = m_serial->readLine(); QString data(buffer); data.remove(QRegExp("[\\n\\t\\r]")); // Remove lines only with LI. Not used anywhere. if(data == "LI") return; json::NodeJSMessage answer; answer.setType("READER-RESPONSE"); QJsonObject dataObj; dataObj.insert("sender", QString("app")); dataObj.insert("response", data); dataObj.insert("reader", QString("1")); answer.setDateTime(QDateTime::currentDateTime()); answer.setJsonData(dataObj); QJsonObject jsonAnswer; answer.write(jsonAnswer); static CommunicationInterface *communitacion = 0; communitacion = qobject_cast<CommunicationInterface *>(RFIDMonitor::instance()->defaultService(ServiceType::KCommunicator)); #ifdef CPP_11_ASYNC /*C++11 std::async Version*/ std::function<void (QByteArray)> sendMessage = std::bind(&CommunicationInterface::sendMessage, communitacion, std::placeholders::_1); std::async(std::launch::async, sendMessage, QJsonDocument(jsonAnswer).toJson()); #else /*Qt Concurrent Version*/ QtConcurrent::run(communitacion, &CommunicationInterface::sendMessage, QJsonDocument(jsonAnswer).toJson()); #endif } } }
DATA::Agent LiliHelper::parseAgent(const QString aPath, const QStringList aAliases, const QString aSheet) { QXlsx::Document aDocument (aPath); DATA::Agent aAgent; QStringList aStringList; if (aSheet.length() != 0) { aStringList.append(aSheet); } else { aStringList = aDocument.sheetNames(); } for (auto aSheet : aStringList) { aDocument.selectSheet(aSheet); QXlsx::CellRange aSheetRange (aDocument.dimension()); QHash<QString, QDate> aRefDateMap; QDate aCurrentDate; QString aNote; for (int nRow = aSheetRange.firstRow(); nRow <= aSheetRange.lastRow(); ++nRow) { QVariant aCell = aDocument.read(nRow, 2); const bool bFirst = aCell.type() == QVariant::String && s_aWeekDays.contains(aCell.toString()); if (bFirst) { if (aDocument.read(nRow, 19).type() == QVariant::String) { aNote = aDocument.read(nRow, 19).toString(); } QString aCellRef = QXlsx::CellReference (nRow, 9).toString(); QVariant aDateVariant = aDocument.read(aCellRef); // Looking for date without reference if (!aCurrentDate.isValid() && aDateVariant.type() == QVariant::Date) { aCurrentDate = aDateVariant.toDate(); aRefDateMap.insert(aCellRef, aCurrentDate); } // Looking for date with reference else if (aCurrentDate.isValid() && aDateVariant.type() == QVariant::String) { QRegularExpression aRx; QRegularExpressionMatchIterator aRxIterator; aRx.setPattern("=(\\w+\\d+)\\+(\\d+)"); aRxIterator = aRx.globalMatch(aDateVariant.toString()); if (aRxIterator.hasNext()) { QRegularExpressionMatch aMatch = aRxIterator.next(); QString aReferencedCell = aMatch.captured(1); if (aRefDateMap.contains(aReferencedCell)) { aCurrentDate = aRefDateMap[aReferencedCell].addDays(aMatch.captured(2).toInt()); aRefDateMap.insert(aCellRef, aCurrentDate); } } } } else if (aCurrentDate.isValid()) { QVariant aNameVariant = aDocument.read(nRow, 1); if (aNameVariant.type() == QVariant::String && aAliases.contains(aNameVariant.toString())) { int nHourHead = 2; while (nHourHead <= 54) { QVariant aVariant = aDocument.read(nRow, nHourHead); int nTempHead = nHourHead + 1; if (aVariant.type() == QVariant::Double && aVariant.toInt() == 1) { QTime aStartTime (7, 0); if (nHourHead > 2) { aStartTime = aStartTime.addSecs(1800 + (nHourHead - 3) * 900); } QTime aEndTime = aStartTime.addSecs(15 * 60); aVariant = aDocument.read(nRow, nTempHead); while (nTempHead <= 54 && aVariant.type() == QVariant::Double && aVariant.toInt() == 1) { aEndTime = aEndTime.addSecs(15 * 60); ++nTempHead; aVariant = aDocument.read(nRow, nTempHead); } aAgent.getEvents().append(DATA::CalEvent (QDateTime (aCurrentDate, aStartTime), QDateTime (aCurrentDate, aEndTime), aNote)); } nHourHead = nTempHead; } } } } } return aAgent; }
/** * @brief Parses and transforms the ics data to a hash with the data * @param icsData * @return */ void CalendarItem::generateICSDataHash() { QRegularExpression regex; QRegularExpressionMatch match; QString lastKey; icsDataKeyList.clear(); icsDataHash.clear(); QStringList iscDataLines = icsData.split("\n"); QListIterator<QString> i(iscDataLines); while (i.hasNext()) { QString line = i.next(); line.replace("\r", ""); if (line == "") { continue; } // multi-line text stats with a space if (!line.startsWith(" ")) { // remove the trailing \n if (line.endsWith("\n")) { line.chop(1); } // parse key and value regex.setPattern("^([A-Z\\-_=;]+):(.*)$"); match = regex.match(line); // set last key for multi line texts lastKey = match.captured(1); if (lastKey == "") { continue; } // find a free key lastKey = findFreeHashKey(&icsDataHash, lastKey); // add new key / value pair to the hash icsDataHash[lastKey] = decodeICSDataLine(match.captured(2)); // hash.insert( lastKey, decodeICSDataLine( match.captured(2) ) ); // add the key to the key order list icsDataKeyList.append(lastKey); } else { // remove the trailing \n if (line.endsWith("\n")) { line.chop(1); } // remove leading space regex.setPattern("^ (.+)$"); match = regex.match(line); // add text to last line icsDataHash[lastKey] += decodeICSDataLine(match.captured(1)); } } }
Load::Load(QObject *parent) : QObject(parent), d_ptr(new LoadPrivate(this)) { Q_D(Load); ins = this; setObjectName("Load"); auto avProcess = [this](QNetworkReply *reply){ Q_D(Load); Task &task = d->queue.head(); int sharp = task.code.indexOf(QRegularExpression("[#_]")); switch (task.state){ case None: { QString i = task.code.mid(2, sharp - 2); QString p = sharp == -1 ? QString() : task.code.mid(sharp + 1); QString url("http://www.%1/video/av%2/"); url = url.arg(Utils::customUrl(Utils::Bilibili)).arg(i); if (!p.isEmpty()){ url += QString("index_%1.html").arg(p); } forward(QNetworkRequest(url), Page); break; } case Page: { d->model->clear(); QString api, id, video(reply->readAll()); int part = video.indexOf("<select"); if (part != -1 && sharp == -1){ QRegularExpression r("(?<=>).*?(?=</option>)"); QStringRef list(&video, part, video.indexOf("</select>", part) - part); QRegularExpressionMatchIterator i = r.globalMatch(list); api = "http://www.%1/video/%2/index_%3.html"; api = api.arg(Utils::customUrl(Utils::Bilibili)); while (i.hasNext()){ int index = d->model->rowCount() + 1; QStandardItem *item = new QStandardItem; item->setData(QUrl(api.arg(task.code).arg(index)), UrlRole); item->setData((task.code + "#%1").arg(index), StrRole); item->setData(Page, NxtRole); item->setData(Utils::decodeXml(i.next().captured()), Qt::EditRole); d->model->appendRow(item); } } if (d->model->rowCount() > 0){ emit stateChanged(task.state = Part); } else{ QRegularExpression r = QRegularExpression("cid[=\":]*\\d+", QRegularExpression::CaseInsensitiveOption); QRegularExpressionMatchIterator i = r.globalMatch(video); while (i.hasNext()){ QString m = i.next().captured(); m = QRegularExpression("\\d+").match(m).captured(); if (id.isEmpty()){ id = m; } else if (id != m){ id.clear(); break; } } if (!id.isEmpty()){ api = "http://comment.%1/%2.xml"; api = api.arg(Utils::customUrl(Utils::Bilibili)); forward(QNetworkRequest(api.arg(id)), File); } else{ emit stateChanged(203); qDebug() << "Fail to load danmaku, try biliApi"; dequeue(); } } break; } case File: { dumpDanmaku(reply->readAll(), Utils::Bilibili, false); emit stateChanged(task.state = None); dequeue(); break; } } }; auto avRegular = [](QString &code){ code.remove(QRegularExpression("/index(?=_\\d+\\.html)")); QRegularExpression r("a(v(\\d+([#_])?(\\d+)?)?)?"); r.setPatternOptions(QRegularExpression::CaseInsensitiveOption); return getRegular(r)(code); }; d->pool.append({ avRegular, 0, avProcess }); auto bbProcess = [this, avProcess](QNetworkReply *reply) { Q_D(Load); Task &task = d->queue.head(); switch (task.state) { case None: { QString i = task.code.mid(2); QString u = "http://www.%1/bangumi/i/%2/"; u = u.arg(Utils::customUrl(Utils::Bilibili)).arg(i); forward(QNetworkRequest(u), Page); break; } case Page: { d->model->clear(); QString page(reply->readAll()); QStringList list = page.split("<li data-index"); if (list.size() < 2) { emit stateChanged(task.state = None); dequeue(); break; } list.removeFirst(); QListIterator<QString> iter(list); iter.toBack(); while (iter.hasPrevious()) { QRegularExpression r; const QString &i = iter.previous(); r.setPattern("(?<=href=\")[^\"]+"); QString c = r.match(i).captured(); fixCode(c); r.setPattern("(?<=<span>).+(?=</span>)"); QString t = Utils::decodeXml(r.match(i).captured()); QStandardItem *item = new QStandardItem; item->setData(c, StrRole); item->setData(None, NxtRole); item->setData(t, Qt::EditRole); d->model->appendRow(item); } emit stateChanged(task.state = Part); } } }; auto bbRegular = [](QString &code) { code.replace(QRegularExpression("bangumi/i/(?=\\d+)"), "bb"); QRegularExpression r("b(b(\\d+)?)?"); r.setPatternOptions(QRegularExpression::CaseInsensitiveOption); return getRegular(r)(code); }; d->pool.append({ bbRegular, 0, bbProcess }); auto acProcess = [this](QNetworkReply *reply){ Q_D(Load); Task &task = d->queue.head(); int sharp = task.code.indexOf(QRegularExpression("[#_]")); switch (task.state){ case None: { QString i = task.code.mid(2, sharp - 2); QString p = sharp == -1 ? QString() : task.code.mid(sharp + 1); QString url("http://www.%1/v/ac%2"); url = url.arg(Utils::customUrl(Utils::AcFun)).arg(i); if (!p.isEmpty()){ url += QString("_%1").arg(p); } forward(QNetworkRequest(url), Page); break;; } case Page: { d->model->clear(); QRegularExpressionMatchIterator match = QRegularExpression("data-vid.*?</a>").globalMatch(reply->readAll()); while (match.hasNext()){ QStandardItem *item = new QStandardItem; QString part = match.next().captured(); QRegularExpression r; r.setPattern("(?<=>)[^>]+?(?=</a>)"); item->setData(Utils::decodeXml(r.match(part).captured()), Qt::EditRole); r.setPattern("(?<=data-vid=\").+?(?=\")"); QString next("http://static.comment.%1/V2/%2?pageSize=1000&pageNo=1"); next = next.arg(Utils::customUrl(Utils::AcFun)).arg(r.match(part).captured()); item->setData(next, UrlRole); item->setData((task.code + "#%1").arg(d->model->rowCount() + 1), StrRole); item->setData(File, NxtRole); d->model->appendRow(item); } if (sharp == -1 && d->model->rowCount() >= 2){ emit stateChanged(task.state = Part); } else{ int i = sharp == -1 ? 0 : task.code.mid(sharp + 1).toInt() - 1; if (i >= 0 && i < d->model->rowCount()){ forward(QNetworkRequest(d->model->item(i)->data(UrlRole).toUrl()), File); } else{ emit stateChanged(203); dequeue(); } } break; } case File: { QByteArray data = reply->readAll(); if (data != "[[],[],[]]"){ QNetworkRequest &request = task.request; QUrl url = request.url(); int page = QUrlQuery(url).queryItemValue("pageNo").toInt(); url.setQuery(QString()); request.setUrl(url); dumpDanmaku(data, Utils::AcFun, false); QUrlQuery query; query.addQueryItem("pageSize", "1000"); query.addQueryItem("pageNo", QString::number(page + 1)); url.setQuery(query); request.setUrl(url); forward(request, File); } else{ emit stateChanged(task.state = None); dequeue(); } break; } } }; auto acRegular = getRegular(QRegularExpression("a(c(\\d+([#_])?(\\d+)?)?)?", QRegularExpression::CaseInsensitiveOption)); d->pool.append({ acRegular, 0, acProcess }); auto abProcess = [this, acProcess](QNetworkReply *reply){ Q_D(Load); Task &task = d->queue.head(); int sharp = task.code.indexOf(QRegularExpression("[#_]")); switch (task.state){ case None: { QString url("http://www.%1/bangumi/video/page?bangumiId=%2&pageSize=30&pageNo=%3&order=2"); url = url.arg(Utils::customUrl(Utils::AcFun)).arg(task.code.mid(2, sharp - 2)); url = url.arg(sharp == -1 ? 1 : (task.code.mid(sharp + 1).toInt() - 1) / 30 + 1); forward(QNetworkRequest(url), Page); break; } case Page: { if (sharp != -1){ QJsonObject data = QJsonDocument::fromJson(reply->readAll()).object()["data"].toObject(); int i = task.code.mid(sharp + 1).toInt(); if (i > 0){ i = (i - 1) % 30; } else{ i = data["totalCount"].toInt(); if (i > 30){ task.code = task.code.left(sharp) + QString("#%1").arg(i); task.state = None; task.processer->process(nullptr); break; } } QJsonArray list = data["list"].toArray(); if (i < 0 || i >= list.size()){ emit stateChanged(203); dequeue(); break; } QString head("http://static.comment.%1/V2/%2?pageSize=1000&pageNo=1"); head = head.arg(Utils::customUrl(Utils::AcFun)); head = head.arg(list[i].toObject()["danmakuId"].toString()); forward(QNetworkRequest(head), File); break; } else{ d->model->clear(); } } case Part: { QJsonObject info = QJsonDocument::fromJson(reply->readAll()).object(); if (!info["success"].toBool() && d->model->rowCount() == 0){ emit stateChanged(info["status"].toInt()); dequeue(); } QJsonObject data = info["data"].toObject(); for (const QJsonValue &value : data["list"].toArray()){ QStandardItem *item = new QStandardItem; QJsonObject data = value.toObject(); item->setData(data["title"].toString(), Qt::EditRole); QString head("http://static.comment.%1/V2/%2?pageSize=1000&pageNo=1"); head = head.arg(Utils::customUrl(Utils::AcFun)).arg(data["danmakuId"].toString()); item->setData(head, UrlRole); item->setData((task.code + "#%1").arg(d->model->rowCount() + 1), StrRole); item->setData(File, NxtRole); d->model->appendRow(item); } if (task.state != Part){ emit stateChanged(task.state = Part); } if (data["pageNo"].toInt() < data["totalPage"].toInt()){ QUrl url = reply->request().url(); auto arg = QUrlQuery(url).queryItems(); for (auto &p : arg){ if (p.first == "pageNo"){ p.second = QString::number(p.second.toInt() + 1); break; } } QUrlQuery query; query.setQueryItems(arg); url.setQuery(query); d->remain.insert(d->manager.get(QNetworkRequest(url))); } break; } case File: { acProcess(reply); break; } } }; auto abRegular = getRegular(QRegularExpression("a(b(\\d+([#_])?(\\d+)?)?)?", QRegularExpression::CaseInsensitiveOption)); d->pool.append({ abRegular, 0, abProcess }); auto ccProcess = [this](QNetworkReply *reply){ Q_D(Load); Task &task = d->queue.head(); int sharp = task.code.indexOf(QRegularExpression("[#_]")); switch (task.state){ case None: { QString i = task.code.mid(2, sharp - 2); QString p = sharp == -1 ? QString() : task.code.mid(sharp + 1); QString url("http://www.%1/play/h%2/"); url = url.arg(Utils::customUrl(Utils::TuCao)).arg(i); if (!p.isEmpty()){ url += QString("#%1").arg(p); } forward(QNetworkRequest(url), Page); break; } case Page: { QString page = reply->readAll(); d->model->clear(); QRegularExpressionMatch m; QRegularExpression r("(?<=<li>)[^<]*(?=</li>)"); m = r.match(page, page.indexOf("<ul id=\"player_code\"")); QStringList list = m.captured().split("**"); m = r.match(page, m.capturedEnd()); QString code = m.captured(); for (const QString &iter : list){ QStandardItem *item = new QStandardItem; item->setData(iter.mid(iter.indexOf('|') + 1), Qt::EditRole); QString api("http://www.%1/index.php?m=mukio&c=index&a=init&playerID=%2"); api = api.arg(Utils::customUrl(Utils::TuCao)).arg((code + "-%1").arg(d->model->rowCount())); item->setData(api, UrlRole); item->setData((task.code + "#%1").arg(d->model->rowCount() + 1), StrRole); item->setData(File, NxtRole); d->model->appendRow(item); } if (sharp == -1 && d->model->rowCount() >= 2){ emit stateChanged(task.state = Part); } else{ int i = sharp == -1 ? 0 : task.code.mid(sharp + 1).toInt() - 1; if (i >= 0 && i < d->model->rowCount()){ forward(QNetworkRequest(d->model->item(i)->data(UrlRole).toUrl()), File); } else{ emit stateChanged(203); dequeue(); } } break; } case File: { dumpDanmaku(reply->readAll(), Utils::TuCao, false); emit stateChanged(task.state = None); dequeue(); break; } } }; auto ccRegular = [](QString &code){ code.replace(QRegularExpression("[Hh](?=\\d)"), "cc"); QRegularExpression r("c(c(\\d+([#_])?(\\d+)?)?)?"); r.setPatternOptions(QRegularExpression::CaseInsensitiveOption); return getRegular(r)(code); }; d->pool.append({ ccRegular, 0, ccProcess }); d->pool.append(Proc()); Proc *directProc = &d->pool.last(); directProc->process = [this](QNetworkReply *reply){ Q_D(Load); Task &task = d->queue.head(); switch (task.state){ case None: { QUrl url = QUrl::fromUserInput(task.code); task.request.setUrl(url); task.state = File; forward(); break; } case File: { Record load; QUrl url = reply->url(); QByteArray data(reply->readAll()); load.source = url.url(); load.access = url.isLocalFile() ? url.toLocalFile() : load.source; load.string = QFileInfo(task.code).fileName(); load.delay = task.delay; QString head = Utils::decodeTxt(data.left(512)); if (head.startsWith("[Script Info]")){ load.danmaku = Parse::parseComment(data, Utils::ASS); } else if (!head.startsWith("<?xml")){ load.danmaku = Parse::parseComment(data, Utils::AcFun); } else if (head.indexOf("<packet>") != -1){ load.danmaku = Parse::parseComment(data, Utils::Niconico); } else if (head.indexOf("<i>") != -1){ load.danmaku = Parse::parseComment(data, Utils::Bilibili); QString i = QRegularExpression("(?<=<chatid>)\\d+(?=</chatid>)").match(head).captured(); if (!i.isEmpty()){ load.source = "http://comment.%1/%2.xml"; load.source = load.source.arg(Utils::customUrl(Utils::Bilibili)).arg(i); } } else if (head.indexOf("<c>") != -1){ load.danmaku = Parse::parseComment(data, Utils::AcfunLocalizer); } if (load.delay != 0){ for (Comment &c : load.danmaku){ c.time += load.delay; } } Danmaku::instance()->appendToPool(&load); emit stateChanged(task.state = None); dequeue(); break; } } }; directProc->priority = -100; directProc->regular = [this, directProc](QString &code){ if (code.startsWith("full?") || code.startsWith("hist?")){ code.clear(); return false; } QUrl u = QUrl::fromUserInput(code); if (!u.host().isEmpty() && !u.path().isEmpty()){ return true; } if (QFileInfo(code).exists()){ return true; } code.clear(); return false; }; auto fullBiProcess = [this](QNetworkReply *reply){ Q_D(Load); Task &task = d->queue.head(); switch (task.state) { case None: { emit progressChanged(0); QString api("http://comment.%1/rolldate,%2"); api = api.arg(Utils::customUrl(Utils::Bilibili)); task.code = QUrlQuery(task.code.mid(5)).queryItemValue("source"); forward(QNetworkRequest(api.arg(QFileInfo(task.code).baseName())), Page); break; } case Page: { QByteArray data = reply->readAll(); QJsonArray date = QJsonDocument::fromJson(data).array(); if (date.isEmpty()) { emit stateChanged(203); dequeue(); break; } QJsonObject head = date.first().toObject(); QString url("http://comment.%1/dmroll,%2,%3"); url = url.arg(Utils::customUrl(Utils::Bilibili)); url = url.arg(head["timestamp"].toVariant().toInt()); url = url.arg(QFileInfo(task.code).baseName()); QNetworkRequest request(url); request.setAttribute(QNetworkRequest::User, data); forward(request, Code); break; } case Code: { QByteArray data = task.request.attribute(QNetworkRequest::User).toByteArray(); QJsonArray date = QJsonDocument::fromJson(data).array(); QMap<int, int> count; for (auto iter : date) { QJsonObject item = iter.toObject(); count[item["timestamp"].toVariant().toInt()] += item["new"].toVariant().toInt(); } data = reply->readAll(); if (count.size() >= 2) { int max = QRegularExpression("(?<=\\<max_count\\>).+(?=\\</max_count\\>)").match(data).captured().toInt(); int now = 0; auto getHistory = [d, &count, &task](int date) { QString url("http://comment.%1/dmroll,%2,%3"); url = url.arg(Utils::customUrl(Utils::Bilibili)); url = url.arg(date); url = url.arg(QFileInfo(task.code).baseName()); return d->manager.get(QNetworkRequest(url)); }; for (auto iter = count.begin() + 1;; ++iter) { now += iter.value(); if (iter + 1 == count.end()) { d->remain += getHistory(iter.key()); break; } else if (now + (iter + 1).value() > max) { d->remain += getHistory(iter.key()); now = 0; } } auto pool = QSharedPointer<QVector<Parse::ResultDelegate>>::create(); pool->append(Parse::parseComment(data, Utils::Bilibili)); double total = d->remain.size() + 2; for (QNetworkReply *iter : d->remain) { connect(iter, &QNetworkReply::finished, [=, &task]() { QByteArray data = iter->readAll(); pool->append(Parse::parseComment(data, Utils::Bilibili)); switch (iter->error()) { case QNetworkReply::NoError: emit progressChanged((total - d->remain.size()) / total); case QNetworkReply::OperationCanceledError: if (d->remain.isEmpty() && !pool->empty()) { Record load; load.full = true; for (auto &iter : *pool) { load.danmaku.append(iter); } load.source = task.code; Danmaku::instance()->appendToPool(&load); emit stateChanged(task.state = None); dequeue(); } default: break; } }); } emit progressChanged(2 / total); emit stateChanged(task.state = File); break; } else { emit progressChanged(1); dumpDanmaku(data, Utils::Bilibili, true); emit stateChanged(task.state = None); dequeue(); break; } } } }; auto fullBiRegular = QRegularExpression("^full\\?source=http://comment\\.bilibili\\.com/\\d+\\.xml$"); fullBiRegular.setPatternOptions(QRegularExpression::CaseInsensitiveOption); d->pool.append({ getRegular(fullBiRegular), 100, fullBiProcess }); auto histBiProcess = [this](QNetworkReply *reply){ Q_D(Load); Task &task = d->queue.head(); switch (task.state){ case None: { QUrlQuery query(task.code.mid(5)); task.code = query.queryItemValue("source"); QString cid = QFileInfo(task.code).baseName(); QString dat = query.queryItemValue("date"); QString url; QNetworkRequest request; if (dat != "0" && dat.toUInt() != QDateTime(QDate::currentDate()).toTime_t()){ url = QString("http://comment.%1/dmroll,%2,%3"); url = url.arg(Utils::customUrl(Utils::Bilibili)); url = url.arg(dat).arg(cid); int limit = QDateTime(QDateTime::fromTime_t(dat.toInt()).date().addDays(1)).toTime_t(); request.setAttribute(QNetworkRequest::User, limit); } else{ url = QString("http://comment.%1/%2.xml").arg(Utils::customUrl(Utils::Bilibili)); url = url.arg(cid); } request.setUrl(url); forward(request, File); break; } case File: { Record load; load.danmaku = Parse::parseComment(reply->readAll(), Utils::Bilibili); load.source = task.code; for (Record &iter : Danmaku::instance()->getPool()){ if (iter.source == load.source){ iter.full = false; iter.danmaku.clear(); iter.limit = 1; break; } } load.limit = task.request.attribute(QNetworkRequest::User).toInt(); Danmaku::instance()->appendToPool(&load); emit stateChanged(task.state = None); dequeue(); break; } } }; auto histBiRegular = QRegularExpression("^hist\\?source=http://comment\\.bilibili\\.com/\\d+\\.xml&date=\\d+$"); histBiRegular.setPatternOptions(QRegularExpression::CaseInsensitiveOption); d->pool.append({ getRegular(histBiRegular), 100, histBiProcess }); connect(this, &Load::stateChanged, [this](int code){ switch (code){ case None: case Page: case Part: case Code: case File: break; default: { Q_D(Load); if (!d->tryNext()){ emit errorOccured(code); } break; } } }); }