예제 #1
0
// display a news
void RSSWidget::handleCurrentArticleChanged(const QModelIndex &currentIndex, 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);
}
예제 #2
0
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
}
예제 #3
0
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]
}

}
예제 #5
0
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
        }
    }
}
예제 #6
0
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;
}
예제 #7
0
/**
 * @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));
        }
    }
}
예제 #8
0
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;
		}
		}
	});
}