void FlatTextarea::onDocumentContentsChange(int position, int charsRemoved, int charsAdded) {
	if (!_links.isEmpty()) {
		bool changed = false;
		for (LinkRanges::iterator i = _links.begin(); i != _links.end();) {
			if (i->first + i->second <= position) {
				++i;
			} else if (i->first >= position + charsRemoved) {
				i->first += charsAdded - charsRemoved;
				++i;
			} else {
				i = _links.erase(i);
				changed = true;
			}
		}
		if (changed) emit linksChanged();
	}

	if (_replacingEmojis || document()->availableRedoSteps() > 0) return;

	const int takeBack = 3;

	position -= takeBack;
	charsAdded += takeBack;
	if (position < 0) {
		charsAdded += position;
		position = 0;
	}
	if (charsAdded <= 0) return;

	_insertions.push_back(Insertion(position, charsAdded));
}
Exemple #2
0
void ShotgunField::setLink(Node *l)
{
    if (m_links.length() != 1 || m_links[0] != l) {
        m_links.clear();
        m_links << l;
        emit linksChanged();
    }
}
bool OutputLink::unlink(InputLink *input)
{
    input->unlink();
    auto it = std::find(begin(m_inputLinks), end(m_inputLinks), input);
    if(it==m_inputLinks.end())return false;
    m_inputLinks.erase(it);
    linksChanged(*this);
    return true;
}
bool OutputLink::addLink(InputLink &input)
{
    if(!input.getModuleInput().getSignalType().isConvertibleTo(c_moduleOutput.getSignalType())) {
        return false;
    }
    input.link(*this);
    //TODO make sure there isn't already an input for this moduleinput
    m_inputLinks.push_back(&input);
    linksChanged(*this);
    return true;
}
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();
	}
}
Exemple #6
0
void FlatTextarea::onDocumentContentsChange(int position, int charsRemoved, int charsAdded) {
	if (_correcting) return;

	QTextCursor(document()->docHandle(), 0).joinPreviousEditBlock();

	_correcting = true;
	if (_maxLength >= 0) {
		QTextCursor c(document()->docHandle(), 0);
		c.movePosition(QTextCursor::End);
		int32 fullSize = c.position(), toRemove = fullSize - _maxLength;
		if (toRemove > 0) {
			if (toRemove > charsAdded) {
				if (charsAdded) {
					c.setPosition(position);
					c.setPosition((position + charsAdded), QTextCursor::KeepAnchor);
					c.removeSelectedText();
				}
				c.setPosition(fullSize - (toRemove - charsAdded));
				c.setPosition(fullSize, QTextCursor::KeepAnchor);
				c.removeSelectedText();
			} else {
				c.setPosition(position + (charsAdded - toRemove));
				c.setPosition(position + charsAdded, QTextCursor::KeepAnchor);
				c.removeSelectedText();
			}
		}
	}
	_correcting = false;

	if (!_links.isEmpty()) {
		bool changed = false;
		for (LinkRanges::iterator i = _links.begin(); i != _links.end();) {
			if (i->first + i->second <= position) {
				++i;
			} else if (i->first >= position + charsRemoved) {
				i->first += charsAdded - charsRemoved;
				++i;
			} else {
				i = _links.erase(i);
				changed = true;
			}
		}
		if (changed) emit linksChanged();
	}

	if (document()->availableRedoSteps() > 0) {
		QTextCursor(document()->docHandle(), 0).endEditBlock();
		return;
	}

	const int takeBack = 3;

	position -= takeBack;
	charsAdded += takeBack;
	if (position < 0) {
		charsAdded += position;
		position = 0;
	}
	if (charsAdded <= 0) {
		QTextCursor(document()->docHandle(), 0).endEditBlock();
		return;
	}

	_correcting = true;
	QSizeF s = document()->pageSize();
	processDocumentContentsChange(position, charsAdded);
	if (document()->pageSize() != s) {
		document()->setPageSize(s);
	}
	_correcting = false;

	QTextCursor(document()->docHandle(), 0).endEditBlock();
}