示例#1
0
bool QuickFindPattern::isLineMatchingBackward(
        const QString& line, int column ) const
{
    int pos = 0;

    if ( ! active_ )
        return false;

    QRegularExpressionMatchIterator matches = regexp_.globalMatch(line);
    QRegularExpressionMatch lastMatch;
    while ( matches.hasNext() ) {
        QRegularExpressionMatch nextMatch = matches.peekNext();
        if ( column >= 0 && nextMatch.capturedEnd() >= column ) {
            break;
        }

        lastMatch = matches.next();
    }

    if ( lastMatch.hasMatch() ) {
        lastMatchStart_ = lastMatch.capturedStart();
        lastMatchEnd_ = lastMatch.capturedEnd() - 1;
        return true;
    }
    else {
        return false;
    }
}
示例#2
0
void HtmlParser::parse()
{
    while(!_downloaded)
    {
        QThread::msleep(10);
    }
    _info->_status = UrlInfo::PARSING;
    emit processing(_info.data());
    _info->_found = _content.contains(_text, Qt::CaseInsensitive);


    int start_offset = -1;
    QRegularExpression regExp("(?:https?|ftp)://(((((((((\\w|\\d)|\\055)|\\056)|\\046)|\\077)|\\043)|\\045)|\\057)|\\075)+");

    while (true)
    {
        QRegularExpressionMatch match = regExp.match(_content, ++start_offset);
        if (!match.hasMatch())
            break;
        start_offset = match.capturedStart();
        int end_offset = match.capturedEnd();
        _links << new HtmlParser(_content.mid(start_offset, end_offset), _text);
    }
    _content.clear();
    if (_downloader)
        delete _downloader;
    _downloader = nullptr;
    _info->_status = UrlInfo::FINISHED;
    emit processing(_info.data());
}
QString TxtFileView::addBoldMarks(QString txtline)
{
    int i=0;
    if(m_isRegEx) {
        QRegularExpressionMatch match;
        while( (match = m_stxtRe.match(txtline, i)).hasMatch() )  {
            txtline.insert(match.capturedEnd(),"</u></b>");
            txtline.insert(match.capturedStart(),"<b><u>");
            i=match.capturedEnd()+6+8;
            m_hits++;
       }
    }
    else {
        while ((i = txtline.indexOf(m_stxt, i, Qt::CaseInsensitive)) != -1) {
            txtline.insert(i+m_stxt.size(),"</u></b>");
            txtline.insert(i,"<b><u>");
            i+=m_stxt.size()+6+8;
            m_hits++;
        }
    }
    return txtline;
}
void AndroidDevice::filterAndAddToTextEdit(const QString& line)
{
    static const QRegularExpression re(
        "(?<date>[\\d-]+) *(?<time>[\\d:\\.]+) *(?<pid>\\d+) *(?<tid>\\d+) *(?<verbosity>[A-Z]) *(?<tag>.+):",
        QRegularExpression::InvertedGreedinessOption | QRegularExpression::DotMatchesEverythingOption
    );

    bool filtersMatch = true;
    const QRegularExpressionMatch match = re.match(line);
    if (match.hasMatch())
    {
        const QStringRef date = match.capturedRef("date");
        const QStringRef time = match.capturedRef("time");
        const QStringRef pid = match.capturedRef("pid");
        const QStringRef tid = match.capturedRef("tid");
        const QStringRef verbosity = match.capturedRef("verbosity");
        const QStringRef tag = match.capturedRef("tag").trimmed();
        const QStringRef text = line.midRef(match.capturedEnd("tag") + 1);

        const auto verbosityLevel = static_cast<VerbosityEnum>(Utils::verbosityCharacterToInt(verbosity.at(0).toLatin1()));

        checkFilters(filtersMatch, m_filtersValid, verbosityLevel, pid, tid, tag, text);

        if (filtersMatch)
        {
            const auto verbosityColorType = static_cast<ColorTheme::ColorType>(verbosityLevel);
            m_deviceWidget->addText(verbosityColorType, verbosity);
            m_deviceWidget->addText(ColorTheme::DateTime, date);
            m_deviceWidget->addText(ColorTheme::DateTime, time);
            m_deviceWidget->addText(ColorTheme::Pid, pid);
            m_deviceWidget->addText(ColorTheme::Tid, tid);
            m_deviceWidget->addText(ColorTheme::Tag, tag);
            m_deviceWidget->addText(verbosityColorType, text);
            m_deviceWidget->flushText();
        }
    }
    else
    {
        qDebug() << "failed to parse" << line;
        checkFilters(filtersMatch, m_filtersValid);
        if (filtersMatch)
        {
            m_deviceWidget->addText(ColorTheme::VerbosityVerbose, QStringRef(&line));
            m_deviceWidget->flushText();
        }
    }

    m_deviceWidget->highlightFilterLineEdit(!m_filtersValid);
}
示例#5
0
bool QuickFindPattern::isLineMatching( const QString& line, int column ) const
{
    if ( ! active_ )
        return false;

    QRegularExpressionMatch match = regexp_.match( line, column );
    if ( match.hasMatch() ) {
        lastMatchStart_ = match.capturedStart();
        lastMatchEnd_ = match.capturedEnd() - 1;
        return true;
    }
    else {
        return false;
    }
}
示例#6
0
bool HRProcessor::test(const Element &, const QString &block)
{
    //! No atomic grouping in python so we simulate it here for performance.
    //! The regex only matches what would be in the atomic group - the HR.
    //! Then check if we are at end of block or if next char is a newline.
    QRegularExpressionMatch m = this->SEARCH_RE.match(block);
    if ( m.hasMatch()
         && ( m.capturedEnd() == block.size()
              || block.at(m.capturedStart()+m.capturedLength()) == '\n' ) ) {
        //! Save match object on class instance so we can use it later.
        this->match = m;
        return true;
    }
    return false;
}
bool SearchWorker::searchTxtLoop(QTextStream *intxt, QString searchtype, QString searchTerm, bool singleMatch, QString fullpath, QString displabel)
{
    int matchcount=0;
    QString matchline = "";
    QString firstmatchline = "";

    //prepare fo RegEx
    bool enableRegEx = m_profile.getBoolOption(Profile::EnableRegEx);
    const QRegularExpression searchExpr(searchTerm, QRegularExpression::UseUnicodePropertiesOption);
    if(!searchExpr.isValid()) enableRegEx=false;

    while (!intxt->atEnd()) {
        if (m_cancelled.loadAcquire() == Cancelled)
            return false;
        QString linetxt = intxt->readLine();
        int findpos=0;
        QRegularExpressionMatch matchR;
        //search for several occurences of search text in one line
        while ( (findpos = (enableRegEx ? (matchR = searchExpr.match(linetxt, findpos)).capturedStart()
                                        : linetxt.indexOf(searchTerm, findpos, Qt::CaseInsensitive))) != -1) {
            //prepate line for output
            if (findpos>10) matchline = "\u2026" + linetxt.mid(findpos-10,120);
            else matchline = linetxt.left(120);
            if(matchcount==0) firstmatchline=matchline;
            enableRegEx ? findpos=matchR.capturedEnd() : findpos+=searchTerm.size();
            matchcount++;

            if(!singleMatch) {
                //found result
                //APPS only on single match
                if(searchtype != "APPS") emit matchFound(fullpath, searchtype, displabel, matchline, 0);
            }
            if (m_cancelled.loadAcquire() == Cancelled)
                return false;
        }
    }
    if( singleMatch && (matchcount >0) ) {
        //found result
        if(searchtype == "APPS") {
            displabel = prepareForApps(intxt);
            matchcount = (-1)*matchcount;
            if(displabel.size()>0)
                emit matchFound(fullpath, searchtype, displabel, firstmatchline, matchcount);
        }
        else emit matchFound(fullpath, searchtype, displabel, firstmatchline, matchcount);
    }
    return true;
}
示例#8
0
 std::tuple<QString, QString> get_class_and_title(const QRegularExpressionMatch &match)
 {
     QString klass = match.captured(1).toLower();
     QString title = match.captured(2);
     if ( match.capturedEnd(2) == -1 ) {
         //! no title was provided, use the capitalized classname as title
         //! e.g.: `!!! note` will render
         //! `<p class="admonition-title">Note</p>`
         title = pypp::capitalize(klass);
     } else if ( title.isEmpty() ) {
         //! an explicit blank title should not be rendered
         //! e.g.: `!!! warning ""` will *not* render `p` with a title
         //title = QString();
     }
     return std::make_tuple(klass, title);
 }
    bool run(const markdown::Element &parent, QStringList &blocks)
    {
        QString block = blocks.first();
        blocks.pop_front();

        QRegularExpressionMatch m = this->RE.match(block);
        if ( m.hasMatch() ) {
            QString before = block.left(m.capturedStart());  // All lines before direction
            QString after = block.mid(m.capturedEnd());  // All lines after direction
            if ( ! before.isEmpty() ) {
                // As the direction was not the first line of the block and the
                // lines before the direction must be parsed first,
                // recursively parse this lines as a block.
                std::shared_ptr<markdown::BlockParser> parser = this->parser.lock();
                QStringList new_blocks = {before};
                parser->parseBlocks(parent, new_blocks);
            }
            // Create direction
            QString body = m.captured(2);
            // background-image
            m = this->BGIMG_RE.match(body);
            if ( m.hasMatch() ) {
                markdown::Element img = markdown::createSubElement(parent, "img");
                img->attrib["class"] = "background";
                img->attrib["src"] = m.captured(1);
                img->attrib["alt"] = m.captured(2);
            }
            // TODO: other direction
            if ( ! m.hasMatch() ) {
                markdown::Element p = markdown::createSubElement(parent, "p");
                p->attrib["class"] = "comment";
                p->text = body;
            }
            if ( ! after.isEmpty() ) {
                // Insert remaining lines as first block for future parsing.
                blocks.insert(0, after);
            }
            return true;
        } else {
            // This should never happen, but just in case...
            qDebug() << "We've got a problem header: " << block;
            return false;
        }
    }
示例#10
0
    bool run(const Element &parent, QStringList &blocks)
    {
        Element sibling = this->lastChild(parent);
        QString block = blocks.front();
        blocks.pop_front();
        QRegularExpressionMatch m = this->RE.match(block);

        if ( m.hasMatch() ) {
            block = block.mid(m.capturedEnd()+1);  //! removes the first line
        }

        QString theRest;
        std::tie(block, theRest) = this->detab(block);

        Element div;
        if ( m.hasMatch() ) {
            QString klass, title;
            std::tie(klass, title) = this->get_class_and_title(m);
            div = createSubElement(parent, "div");
            div->set("class", QString("%1 %2").arg(this->classname()).arg(klass));
            if ( ! title.isEmpty() ) {
                Element p = createSubElement(div, "p");
                p->text = title;
                p->set("class", this->classname_title());
            }
        } else {
            div = sibling;
        }

        std::shared_ptr<BlockParser> parser = this->parser.lock();
        parser->parseChunk(div, block);

        if ( ! theRest.isEmpty() ) {
            //! This block contained unindented line(s) after the first indented
            //! line. Insert these lines as the first block of the master blocks
            //! list for future processing.
            blocks.insert(0, theRest);
        }
        return true;
    }
示例#11
0
QStringList WorkbookParserPrivate::splitoutCellReference(QString expression) {
    QStringList result;
    QRegularExpression re = QRegularExpression(REGEX_CELL_REFERENCE_2);
    QRegularExpressionMatch match;
    int start, end = 0;

    QRegularExpressionMatchIterator it = re.globalMatch(expression);
    while (it.hasNext()) {
        match = it.next();
        start = match.capturedStart(0);
        result.append(expression.mid(end, start - end));
        // TODO replace cell references with actual contents of cell
        result.append(match.captured(0));
        // TODO above
        end = match.capturedEnd(0);
    }

    if (end < expression.length())
        result.append(expression.mid(end));

    return result;
}
示例#12
0
void FlatTextarea::parseLinks() { // some code is duplicated in text.cpp!
	LinkRanges newLinks;

	QString text(toPlainText());
	if (text.isEmpty()) {
		if (!_links.isEmpty()) {
			_links.clear();
			emit linksChanged();
		}
		return;
	}

	initLinkSets();

	int32 len = text.size();
	const QChar *start = text.unicode(), *end = start + text.size();
	for (int32 offset = 0, matchOffset = offset; offset < len;) {
		QRegularExpressionMatch m = reDomain().match(text, matchOffset);
		if (!m.hasMatch()) break;

		int32 domainOffset = m.capturedStart();

		QString protocol = m.captured(1).toLower();
		QString topDomain = m.captured(3).toLower();

		bool isProtocolValid = protocol.isEmpty() || validProtocols().contains(hashCrc32(protocol.constData(), protocol.size() * sizeof(QChar)));
		bool isTopDomainValid = !protocol.isEmpty() || validTopDomains().contains(hashCrc32(topDomain.constData(), topDomain.size() * sizeof(QChar)));

		if (protocol.isEmpty() && domainOffset > offset + 1 && *(start + domainOffset - 1) == QChar('@')) {
			QString forMailName = text.mid(offset, domainOffset - offset - 1);
			QRegularExpressionMatch mMailName = reMailName().match(forMailName);
			if (mMailName.hasMatch()) {
				offset = matchOffset = m.capturedEnd();
				continue;
			}
		}
		if (!isProtocolValid || !isTopDomainValid) {
			offset = matchOffset = m.capturedEnd();
			continue;
		}

		QStack<const QChar*> parenth;
		const QChar *domainEnd = start + m.capturedEnd(), *p = domainEnd;
		for (; p < end; ++p) {
			QChar ch(*p);
			if (chIsLinkEnd(ch)) break; // link finished
			if (chIsAlmostLinkEnd(ch)) {
				const QChar *endTest = p + 1;
				while (endTest < end && chIsAlmostLinkEnd(*endTest)) {
					++endTest;
				}
				if (endTest >= end || chIsLinkEnd(*endTest)) {
					break; // link finished at p
				}
				p = endTest;
				ch = *p;
			}
			if (ch == '(' || ch == '[' || ch == '{' || ch == '<') {
				parenth.push(p);
			} else if (ch == ')' || ch == ']' || ch == '}' || ch == '>') {
				if (parenth.isEmpty()) break;
				const QChar *q = parenth.pop(), open(*q);
				if ((ch == ')' && open != '(') || (ch == ']' && open != '[') || (ch == '}' && open != '{') || (ch == '>' && open != '<')) {
					p = q;
					break;
				}
			}
		}
		if (p > domainEnd) { // check, that domain ended
			if (domainEnd->unicode() != '/' && domainEnd->unicode() != '?') {
				matchOffset = domainEnd - start;
				continue;
			}
		}
		newLinks.push_back(qMakePair(domainOffset - 1, p - start - domainOffset + 2));
		offset = matchOffset = p - start;
	}

	if (newLinks != _links) {
		_links = newLinks;
		emit linksChanged();
	}
}
示例#13
0
bool ZInstrument::loadSfz(const QString& s)
      {
      _program = 0;
      QFile f(s);
      if (!f.open(QIODevice::ReadOnly)) {
            qDebug("ZInstrument: cannot load %s", qPrintable(s));
            return false;
            }
      QFileInfo fi(f);
      QString path = fi.absolutePath();
      qint64 total = fi.size();

      QString sample;

      SfzRegion r;
      SfzRegion g;      // group
      r.init(path);
      g.init(path);

      bool groupMode = false;
      zerberus->setLoadProgress(0);

      while (!f.atEnd()) {
            QByteArray ba = f.readLine();
            zerberus->setLoadProgress(((qreal)f.pos() * 100) / total);
            ba = ba.simplified();

            if (ba.isEmpty() || ba.startsWith("//"))
                  continue;
            if (zerberus->loadWasCanceled())
                  return false;
            if (ba.startsWith("<group>")) {
                  if (!groupMode && !r.isEmpty())
                        addRegion(r);
                  g.init(path);
                  r.init(path);
                  groupMode = true;
                  ba = ba.mid(7);
                  }
            else if (ba.startsWith("<region>")) {
                  if (groupMode) {
                        g = r;
                        groupMode = false;
                        }
                  else {
                        if (!r.isEmpty())
                              addRegion(r);
                        r = g;  // initialize next region with group values
                        }
                  ba = ba.mid(8);
                  }
            QRegularExpression re("\\s?(\\w+)=");
            QRegularExpressionMatchIterator i = re.globalMatch(ba);

            while (i.hasNext()) {
                  QRegularExpressionMatch match = i.next();
                  int si = match.capturedEnd();
                  int ei;
                  if (i.hasNext()) {
                        QRegularExpressionMatch nextMatch = i.peekNext();
                        ei = nextMatch.capturedStart();
                        }
                  else
                        ei = ba.size();
                  QString s = ba.mid(si, ei-si);
                  r.readOp(match.captured(1), s);
                  }
            }
      zerberus->setLoadProgress(100);
      if (!groupMode && !r.isEmpty())
            addRegion(r);
      return true;
      }
示例#14
0
void SourceEntryPrivate::parseData(const QString &data)
{
    if (data.isEmpty())
        return;

    QString tData = data.simplified();

    // Check for nonvalid input
    if (tData.isEmpty() || tData == QChar('#')) {
        isValid = false;
        return;
    }

    // Check source enable state
    if (tData.at(0) == '#') {
        isEnabled = false;
    }
    // Handle multiple comment characters (hey, it happens!)
    while (tData.size() > 0 && tData.at(0) == '#') {
        // Remove starting '#' from tData
        tData = tData.remove(0, 1);
        tData = tData.trimmed();
    }

    // Find any #'s past the start (these are comments)
    int idx = tData.indexOf('#');
    if (idx > 0) {
        // Save the comment, then remove from tData
        comment = tData.right(tData.size() - idx - 1);
        tData.remove(idx, tData.size() - idx + 1);
    }

    const QRegularExpression rx("^([a-z\\-]+) *");
    QRegularExpressionMatch match = rx.match(tData);

    // Parse type
    type = match.captured(1);
    const QSet<QString> types = { QLatin1String("rpm"), QLatin1String("rpm-src"), QLatin1String("deb"), QLatin1String("deb-src") };
    if (!match.isValid() || !types.contains(type)) {
        isValid = false;
        return;
    }
    
    int start = match.capturedEnd(), end = tData.size();
    // Parse architecture, see https://wiki.debian.org/Multiarch/HOWTO, Setting up sources
    if (tData[start] == '[') {
        QString metadata = tData.mid(start+1, tData.indexOf(']')-start-1);
        QStringList options = metadata.split(';');
        for (const QString &option : options) {
            QStringList parts = option.split('=');

            if (parts.size() != 2) {
                isValid = false;
                return;
            }

            QString key = parts.at(0);
            if (key != QLatin1String("arch")) {
                isValid = false;
                return;
            }

            QString value = parts.at(1);
            architectures = value.split(',');
        }
        
        start+=metadata.size()+2;
        for (; tData[start] == ' '; ++start)
        {}
    }
    
    bool inString = false;
    bool done = false;
    for (int i = start; !done && i<end; ++i) {
        switch (tData[i].toLatin1()) {
        case ' ':
            if (!inString) {
                uri = tData.mid(start, i-start);
                start = i+1;
                done = true;
            } break;
        case '[':
            inString = true;
            break;
        case ']':
            inString = false;
            break;
        }
    }
    if (uri.isEmpty() || !done) {
        isValid = false;
        return;
    }

    QStringList pieces = tData.mid(start).split(' ', QString::SkipEmptyParts);
    if (pieces.isEmpty()) {
        // Invalid source entry
        isValid = false;
        return;
    }

    // Parse distro and (optionally) components
    dist = pieces.takeFirst();
    components = pieces;
}
示例#15
0
QList<HTMLSpellCheck::MisspelledWord> HTMLSpellCheck::GetMisspelledWords(const QString &orig_text,
        int start_offset,
        int end_offset,
        const QString &search_regex,
        bool first_only,
        bool include_all_words)
{
    SpellCheck *sc = SpellCheck::instance();
    QString wordChars = sc->getWordChars();
    bool in_tag = false;
    bool in_invalid_word = false;
    bool in_entity = false;
    int word_start = 0;
    QRegularExpression search(search_regex);
    QList<HTMLSpellCheck::MisspelledWord> misspellings;
    // Make sure text has beginning/end boundary markers for easier parsing
    QString text = QChar(' ') + orig_text + QChar(' ');
    // Ignore <style...</style> wherever it appears - change to spaces to keep text positions
    QRegularExpression style_re("<style[^<]*</style>");

    QRegularExpressionMatchIterator i = style_re.globalMatch(text);
    while (i.hasNext()) {
        QRegularExpressionMatch match = i.next();
        for (int pos = match.capturedStart(); pos < match.capturedEnd(); pos++) {
            text[pos] = QChar(' ');
        }
    }

    for (int i = 0; i < text.count(); i++) {
        QChar c = text.at(i);

        if (!in_tag) {
            QChar prev_c = i > 0 ? text.at(i - 1) : QChar(' ');
            QChar next_c = i < text.count() - 1 ? text.at(i + 1) : QChar(' ');

            if (IsBoundary(prev_c, c, next_c, wordChars)) {
                // If we're in an entity and we hit a boundary and it isn't
                // part of an entity then this is an invalid entity.
                if (in_entity && c != QChar(';')) {
                    in_entity = false;
                }

                // Check possibilities that would mean this isn't a word worth considering.
                if (!in_invalid_word && !in_entity && word_start != -1 && (i - word_start) > 0) {
                    QString word = Utility::Substring(word_start, i, text);

                    if (!word.isEmpty() && word_start > start_offset && word_start <= end_offset) {
                        if (include_all_words || !sc->spell(word)) {
                            int cap_start = -1;

                            if (!search_regex.isEmpty()) {
                                QRegularExpressionMatch mo = search.match(word);
                                cap_start = mo.capturedStart();
                            }

                            if (search_regex.isEmpty() || cap_start != -1) {
                                struct MisspelledWord misspelled_word;
                                misspelled_word.text = word;
                                // Make sure we account for the extra boundary added at the beginning
                                misspelled_word.offset = word_start - 1;
                                misspelled_word.length = i - word_start ;
                                misspellings.append(misspelled_word);

                                if (first_only) {
                                    return misspellings;
                                }
                            }
                        }
                    }
                }

                // We want to start the word with the character after the boundary.
                // If the next character is another boundary we'll just move forward one.
                word_start = i + 1;
                in_invalid_word = false;
            } else {
                // Ensure we're not dealing with some crazy run on text that isn't worth
                // considering as an actual word.
                if (!in_invalid_word && (i - word_start) > MAX_WORD_LENGTH) {
                    in_invalid_word = true;
                }
            }

            if (c == QChar('&')) {
                in_entity = true;
            }

            if (c == QChar(';')) {
                in_entity = false;
            }
        }

        if (c == QChar('<')) {
            in_tag = true;
            word_start = -1;
        }

        if (in_tag && c == QChar('>')) {
            word_start = i + 1;
            in_tag = false;
        }
    }

    return misspellings;
}
QString DocumentImporter::importScenario(const ImportParameters& _importParameters) const
{
	//
	// Преобразовать заданный документ в QTextDocument
	//
	QTextDocument documentForImport;
	QFile documentFile(_importParameters.filePath);
	documentFile.open(QIODevice::ReadOnly);
	FormatReader* reader = FormatManager::createReader(&documentFile);
	reader->read(&documentFile, &documentForImport);

	//
	// Найти минимальный отступ слева для всех блоков
	// ЗАЧЕМ: во многих программах (Final Draft, Screeviner) сделано так, что поля
	//		  задаются за счёт оступов. Получается что и заглавие сцены и описание действия
	//		  имеют отступы. Так вот это и будет минимальным отступом, который не будем считать
	//
	int minLeftMargin = 1000;
	{
		QTextCursor cursor(&documentForImport);
		while (!cursor.atEnd()) {
			if (minLeftMargin > cursor.blockFormat().leftMargin()) {
				minLeftMargin = cursor.blockFormat().leftMargin();
			}

			cursor.movePosition(QTextCursor::NextBlock);
			cursor.movePosition(QTextCursor::EndOfBlock);
		}
	}

	//
	// FIXME: много чего дублируется с ScenarioXml
	//

	//
	// Преобразовать его в xml-строку
	//
	QString scenarioXml;
	QTextCursor cursor(&documentForImport);

	QXmlStreamWriter writer(&scenarioXml);
	writer.writeStartDocument();
	writer.writeStartElement(NODE_SCENARIO);
	writer.writeAttribute(ATTRIBUTE_VERSION, "1.0");

	//
	// Для каждого блока текста определяем тип
	//
	// ... последний стиль блока
	ScenarioBlockStyle::Type lastBlockType = ScenarioBlockStyle::Undefined;
	// ... количество пустых строк
	int emptyLines = 0;
	do {
		cursor.movePosition(QTextCursor::EndOfBlock);

		//
		// Если в блоке есть текст
		//
		if (!cursor.block().text().simplified().isEmpty()) {
			//
			// ... определяем тип
			//
			const ScenarioBlockStyle::Type blockType =
				::typeForTextCursor(cursor, lastBlockType, emptyLines, minLeftMargin,
					_importParameters.outline);
			const QString blockTypeName = ScenarioBlockStyle::typeName(blockType);
			QString blockText = cursor.block().text().simplified();

			//
			// ... запишем данные в строку
			//
			writer.writeStartElement(blockTypeName);

			//
			// Если текущий тип "Время и место" и нужно удалить номер сцены, то делаем это
			//
			if (blockType == ScenarioBlockStyle::SceneHeading
				&& _importParameters.removeScenesNumbers){
				blockText = blockText.toUpper();
				QRegularExpressionMatch match = START_FROM_NUMBER_CHECKER.match(blockText);
				if (match.hasMatch()) {
					blockText = blockText.mid(match.capturedEnd());
				}
			}

			//
			// Выполняем корректировки
			//
			blockText = ::clearBlockText(blockType, blockText);

			//
			// Пишем текст
			//
			writer.writeStartElement(NODE_VALUE);
			writer.writeCDATA(blockText);
			writer.writeEndElement();

			//
			// Пишем редакторские комментарии
			//
			if (_importParameters.saveReviewMarks) {
				const QTextBlock currentBlock = cursor.block();
				if (!currentBlock.textFormats().isEmpty()) {
					writer.writeStartElement(NODE_REVIEW_GROUP);
					foreach (const QTextLayout::FormatRange& range, currentBlock.textFormats()) {
						//
						// Всё, кроме стандартного
						//
						if (range.format.boolProperty(Docx::IsForeground)
							|| range.format.boolProperty(Docx::IsBackground)
							|| range.format.boolProperty(Docx::IsHighlight)
							|| range.format.boolProperty(Docx::IsComment)) {
							writer.writeStartElement(NODE_REVIEW);
							writer.writeAttribute(ATTRIBUTE_REVIEW_FROM, QString::number(range.start));
							writer.writeAttribute(ATTRIBUTE_REVIEW_LENGTH, QString::number(range.length));
							if (range.format.hasProperty(QTextFormat::ForegroundBrush)) {
								writer.writeAttribute(ATTRIBUTE_REVIEW_COLOR,
													  range.format.foreground().color().name());
							}
							if (range.format.hasProperty(QTextFormat::BackgroundBrush)) {
								writer.writeAttribute(ATTRIBUTE_REVIEW_BGCOLOR,
													  range.format.background().color().name());
							}
							writer.writeAttribute(ATTRIBUTE_REVIEW_IS_HIGHLIGHT,
												  range.format.boolProperty(Docx::IsHighlight) ? "true" : "false");
							//
							// ... комментарии
							//
							const QStringList comments = range.format.property(Docx::Comments).toStringList();
							const QStringList authors = range.format.property(Docx::CommentsAuthors).toStringList();
							const QStringList dates = range.format.property(Docx::CommentsDates).toStringList();
							for (int commentIndex = 0; commentIndex < comments.size(); ++commentIndex) {
								writer.writeEmptyElement(NODE_REVIEW_COMMENT);
								writer.writeAttribute(ATTRIBUTE_REVIEW_COMMENT, comments.at(commentIndex));
								writer.writeAttribute(ATTRIBUTE_REVIEW_AUTHOR, authors.at(commentIndex));
								writer.writeAttribute(ATTRIBUTE_REVIEW_DATE, dates.at(commentIndex));
							}
							//
							writer.writeEndElement();
						}
					}
					writer.writeEndElement();
				}
			}
			//
			// ... конец абзаца
			//
			writer.writeEndElement();

			//
			// Запомним последний стиль блока и обнулим счётчик пустых строк
			//
			lastBlockType = blockType;
			emptyLines = 0;
		}
		//
		// Если в блоке нет текста, то увеличиваем счётчик пустых строк
		//
		else {
			++emptyLines;
		}

		cursor.movePosition(QTextCursor::NextCharacter);
	} while (!cursor.atEnd());
示例#17
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;
		}
		}
	});
}
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 MarkupHighlighter::highlightBlock(const QString &text)
{

    if (FORMATTING.empty()){
        qWarning() << "Not given any formatting, so not highlighting.";
        return;
    }

    if (text.isEmpty()) return;

    int start=0, end=0, highlightLength = 0;

    QRegularExpression re;
    QTextCharFormat textFormat;
    for (QString exp : TOKENS.keys()){
        setCurrentBlockState(0);
        start = 0, end = 0;

        re = QRegularExpression(exp);

        if (!re.isValid()){
            QString message = "Invalid regular expression \""
                    + re.pattern() + "\" :" + re.errorString();
            qFatal("%s", message.toStdString().data());
            return;
        }

        if (previousBlockState() != 1)
            start = re.match(text).capturedStart();

        while (start >= 0){
            QRegularExpressionMatch match = re.match(text, start);
            end = match.capturedEnd();
            if (end == -1 || (end == start && end != 0)){
                setCurrentBlockState(1);
                highlightLength = text.length();
            } else {
                highlightLength = match.capturedLength();
            }
            QTextCharFormat baseFormat = currentBlock().blockFormat().toCharFormat();
            MarkupHighlighter::MarkupToken tok = TOKENS[exp];
            if (!FORMATTING.contains(tok)){
                qWarning() << "Could not find" << tok;
                break;
            }
            const StyleProxy *styleProxy = FORMATTING[tok];
            textFormat = styleProxy->toFormat(baseFormat);
            setFormat(start, highlightLength, textFormat);
            qDebug() << "highlightBlock";
            qDebug() << "Formatting"
                     << "token" << tok
                     << "with regex=" << exp
                     << ", string="
                     << text.mid(start, highlightLength)
                     << "\n"
                     << "  Bold?" << textFormat.font().bold() << "\n"
                     << "  Italic?" << textFormat.font().italic() << "\n"
                     << "  Size:" << textFormat.font().pointSize() << "\n"
                     << "  Background:" << textFormat.background().color();
            start = re.match(text, end).capturedStart();
            // This should not be 0 again. If it is, that means our search has
            // come up empty.
            if (start == 0)
                start = -1;
        }
    }
}
示例#20
0
bool ZInstrument::loadSfz(const QString& s)
      {
      _program = 0;
      QFileInfo fi(s);
      QString path = fi.absolutePath();

      QStringList fileContents = readFile(s);

      if (fileContents.empty()) {
            return false;
            }

      SfzControl c;
      c.init();
      c.defines.clear();
      for (int i = 0;i < 128; i++)
            c.set_cc[i] = -1;

      int idx = 0;
      bool inBlockComment = false;
      // preprocessor
      while(idx < fileContents.size()) {
            QRegularExpression findWithSpaces("\"(.+)\"");
            QRegularExpression comment("//.*$");
            QRegularExpression trailingSpacesOrTab("^[\\s\\t]*");
            QRegularExpressionMatch foundWithSpaces;
            QString curLine = fileContents[idx];
            QString curLineCopy = curLine;
            bool nextIsImportant = false;
            int idxBlockComment = 0;
            int from = 0;

            for (QChar chr : curLineCopy) {
                  bool terminated = false;

                  if (nextIsImportant) {
                        nextIsImportant = false;
                        if (inBlockComment && chr == '/') { // found block end
                              inBlockComment = false;
                              terminated = true;
                              curLine.remove(from, idxBlockComment - from + 1);
                              idxBlockComment = from - 1;
                              }
                        else if (!inBlockComment && chr == '*') { // found block start
                              inBlockComment = true;
                              terminated = true;
                              from = idxBlockComment - 1;
                              }
                        }

                  if (!terminated && inBlockComment && chr == '*')
                        nextIsImportant = true;
                  else if (!terminated && !inBlockComment && chr == '/')
                        nextIsImportant = true;

                  idxBlockComment++;
                  }

            if (inBlockComment)
                  curLine.remove(from, curLine.size() - from);

            curLine = curLine.remove(comment);
            curLine.remove(trailingSpacesOrTab);
            fileContents[idx] = curLine;

            if (curLine.startsWith("#define")) {
                  QStringList define = curLine.split(" ");
                  foundWithSpaces = findWithSpaces.match(curLine);
                  if (define.size() == 3)
                        c.defines.insert(std::pair<QString, QString>(define[1], define[2]));
                  else if(foundWithSpaces.hasMatch())
                        c.defines.insert(std::pair<QString, QString>(define[1], foundWithSpaces.captured(1)));
                  fileContents.removeAt(idx);
                  }
            else if (curLine.startsWith("#include")) {
                  foundWithSpaces = findWithSpaces.match(curLine);
                  if (foundWithSpaces.hasMatch()) {
                        QString newFilename = foundWithSpaces.captured(1);

                        for(auto define : c.defines) {
                              newFilename.replace(define.first, define.second);
                              }

                        QStringList newFileContents = readFile(path + "/" + newFilename);
                        if (newFileContents.empty())
                              return false;

                        int offset = 1;
                        for (QString newFileLine : newFileContents) {
                              fileContents.insert(idx+offset, newFileLine);
                              offset++;
                              }

                        fileContents.removeAt(idx);
                        }
                  }
            else if (curLine.isEmpty())
                  fileContents.removeAt(idx);
            else
                  idx++;
            }

      int total = fileContents.size();
      SfzRegion r;
      SfzRegion g;      // group
      SfzRegion glob;
      r.init(path);
      g.init(path);
      glob.init(path);

      bool groupMode = false;
      bool globMode = false;
      zerberus->setLoadProgress(0);

      for (int idx = 0; idx < fileContents.size(); idx++) {
            QString curLine = fileContents[idx];
            zerberus->setLoadProgress(((qreal) idx * 100) /  (qreal) total);

            if (zerberus->loadWasCanceled())
                  return false;
            if (curLine.startsWith("<global>")) {
                  if (!globMode && !groupMode && !r.isEmpty())
                        addRegion(r);
                  glob.init(path);
                  g.init(path); // global also resets group
                  r.init(path);
                  globMode = true;
                  }
            if (curLine.startsWith("<group>")) {
                  if (!groupMode && !globMode && !r.isEmpty())
                        addRegion(r);
                  g.init(path);
                  if (globMode) {
                        glob = r;
                        globMode = false;
                        }
                  else {
                        r = glob; // initialize group with global values
                        }
                  groupMode = true;
                  curLine = curLine.mid(7);
                  }
            else if (curLine.startsWith("<region>")) {
                  if (groupMode) {
                        g = r;
                        groupMode = false;
                        }
                  else if (globMode) {
                        glob = r;
                        g = glob;
                        globMode = false;
                        }
                  else {
                        if (!r.isEmpty())
                              addRegion(r);
                        r = g;  // initialize next region with group values
                        }
                  curLine = curLine.mid(8);
                  }
            else if (curLine.startsWith("<control>"))
                  c.init();

            QRegularExpression re("\\s?([\\w\\$]+)="); // defines often use the $-sign
            QRegularExpressionMatchIterator i = re.globalMatch(curLine);

            while (i.hasNext()) {
                  QRegularExpressionMatch match = i.next();
                  int si = match.capturedEnd();
                  int ei;
                  if (i.hasNext()) {
                        QRegularExpressionMatch nextMatch = i.peekNext();
                        ei = nextMatch.capturedStart();
                        }
                  else
                        ei = curLine.size();
                  QString s = curLine.mid(si, ei-si);
                  r.readOp(match.captured(1), s, c);
                  }
            }

      for (int i = 0; i < 128; i++)
            _setcc[i] = c.set_cc[i];

      zerberus->setLoadProgress(100);
      if (!groupMode && !globMode && !r.isEmpty())
            addRegion(r);
      return true;
      }
示例#21
0
void playground(QApplication& a)
{
	std::vector<int> l1 = { 0,1,3,6,9,11 };
	auto fromItem = std::upper_bound(l1.begin(), l1.end(), 2
		, [](const auto &a, const auto &b)
	{
		return a > b;
	});

	return;
	TextColorize::List _coloredTextParts;
	auto match = [&_coloredTextParts](const QString& text, Part::List& parts)
	{
		QRegularExpression::PatternOptions options;
		/*if (tc.caseSensitive == false)
		options |= QRegularExpression::PatternOption::CaseInsensitiveOption;
		*/
		QString rePattern;
		foreach(TextColorize ctp, _coloredTextParts) {
			QString pattern;
			if (ctp.caseSensitive == false)
				pattern += "(?i)";
			pattern += ctp.text;
			pattern.prepend("(").append(")");
			if(ctp.wordOnly)
				pattern.prepend("(?:^|[^\\w])").append("(?:[^\\w]|$)");
			rePattern += "|" + pattern;
		}
		rePattern = rePattern.mid(1);
		QRegularExpression re(rePattern, options);

		QRegularExpressionMatchIterator it = re.globalMatch(text);

		int nonMatchedStart = 0;
		bool hasMatches = it.hasNext();
		while (it.hasNext()) {
			QRegularExpressionMatch match = it.next();

			int matchedGroup = match.lastCapturedIndex();
			while (match.capturedTexts().at(matchedGroup).length() && --matchedGroup);

			qDebug()
				<< match.capturedTexts() << " - "
				<< match.capturedView() << " - "
				<< match.hasPartialMatch() << " - "
				<< matchedGroup;
			int nonMatechedEnd = match.capturedStart(0);
			


			int nonMatchedLength = nonMatechedEnd - nonMatchedStart;
			//auto& ct = _coloredTextParts[match.lastCapturedIndex() - 1];
			auto& ct = _coloredTextParts[0];
			if (nonMatchedLength)
				;// parts.push_back({ text.mid(nonMatchedStart, nonMatchedLength), nullptr });
			parts.push_back({ text.mid(match.capturedStart(0), match.capturedLength(0)), match.lastCapturedIndex() });
			nonMatchedStart = match.capturedEnd(0);
		}
		if (nonMatchedStart < text.length())
			parts.push_back({ text.mid(nonMatchedStart), false });
		return hasMatches;
	};