Fix plain/rich format convertion algo while typing.

This commit is contained in:
Julien Wadel 2023-04-12 11:58:24 +02:00
parent 3d7a9acc25
commit c36729df6a
3 changed files with 39 additions and 19 deletions

View file

@ -60,7 +60,7 @@ QVector<QPair<bool, QString> > UriTools::parse(const QString& text, const QRegul
else{
currentIndex += results.back().second.length();
if( currentIndex < text.size())
results.push_back({false, text.mid(currentIndex)});
results.append(parse(text.mid(currentIndex), regex));
}
return results;
}
@ -278,10 +278,9 @@ void UriTools::initRegularExpressions() {
// Level 8. --------------------------------------------------------------------
// Regex to match URI. It respects the RFC 3986.
QString URI = "(?:"
+ URI_SCHEME + ":" + "|" + "www\\." + ")"
+ URI_HIER_PART + "(?:" + "\\?" + URI_QUERY + ")?" +
"(?:" + "#" + URI_FRAGMENT + ")?";
QString URI = "(?:" + URI_SCHEME + ":" + "|" + "www\\." + ")"
+ URI_HIER_PART + "(?:" + "\\?" + URI_QUERY + ")?"
+ "(?:" + "#" + URI_FRAGMENT + ")?";
// Regex to match URI. It respects the RFC 3987.
QString IRI = "(?:" + URI_SCHEME + ":" + "|" + "www\\." + ")"

View file

@ -743,6 +743,7 @@ QString Utils::encodeTextToQmlRichFormat(const QString& text, const QVariantMap&
QString images;
QStringList formattedText;
QStringList imageFormat;
bool lastWasUrl = false;
for(auto format : QImageReader::supportedImageFormats())
imageFormat.append(QString::fromLatin1(format).toUpper());
if(options.contains("noLink") && options["noLink"].toBool()){
@ -750,15 +751,21 @@ QString Utils::encodeTextToQmlRichFormat(const QString& text, const QVariantMap&
}else{
auto primaryColor = App::getInstance()->getColorListModel()->getColor("i")->getColor();
auto iriParsed = UriTools::parseIri(text);
for(int i = 0 ; i < iriParsed.size() ; ++i){
QString iri = iriParsed[i].second.replace('&', "&amp;")
.replace('<', "\u2063&lt;")
.replace('>', "\u2063&gt;")
.replace('"', "&quot;")
.replace('\'', "&#039;");
if(!iriParsed[i].first)
if(!iriParsed[i].first){
if(lastWasUrl){
lastWasUrl = false;
if(iri.front() != ' ')
iri.push_front(' ');
}
formattedText.append(iri);
else{
}else{
QString uri = iriParsed[i].second.left(3) == "www" ? "http://"+iriParsed[i].second : iriParsed[i].second ;
int extIndex = iriParsed[i].second.lastIndexOf('.');
QString ext;
@ -774,11 +781,16 @@ QString Utils::encodeTextToQmlRichFormat(const QString& text, const QVariantMap&
? QString(" height='auto'")
: ""
) + " src=\"" + iriParsed[i].second + "\" /></a>";
}else
}else{
formattedText.append( "<a style=\"color:"+ primaryColor.name() +";\" href=\"" + uri + "\">" + iri + "</a>");
lastWasUrl = true;
}
}
}
}
if(lastWasUrl && formattedText.last().back() != ' '){
formattedText.push_back(" ");
}
if(images != "")
images = "<div>" + images +"</div>";

View file

@ -185,23 +185,30 @@ Item {
Timer{// This timer is used to rewrite rich texts from new text only on idle.
id: refreshFormatTimer
//This fix having the wrong format while typing next to emojies.
property bool blockTextChanged : false
property var backupCursorPosition
function updateBlockText(){
blockTextChanged = false
textArea.cursorPosition = backupCursorPosition
}
interval: 300
property bool blockTextChanged : false // Block text changed signal when the format is converted.
property bool textChanged: false // The text has been changed while timer is running (it's true when only key has been pressed like control keys)
property bool restartFromInput : false // Keep in mind that the current time loop has been reset by user inputs.
interval: restartFromInput ? 1000 : 300 // Longer wait if user is currently entering text
repeat: false
onTriggered: {
blockTextChanged = true
backupCursorPosition = textArea.cursorPosition
textArea.text = UtilsCpp.encodeTextToQmlRichFormat(textArea.getText(0,textArea.text.length))
Qt.callLater(updateBlockText)
if(textChanged){
blockTextChanged = true // Block onTextChanged
var backupCursorPosition = textArea.cursorPosition
var lastLength = textArea.length
textArea.text = UtilsCpp.encodeTextToQmlRichFormat(textArea.getText(0,textArea.text.length))// It will send onTextChanged
backupCursorPosition += (textArea.length - lastLength)
textArea.cursorPosition = backupCursorPosition
// Reset states
blockTextChanged = false
textChanged = false
restartFromInput = false
}
}
}
onTextChanged: {
if(!refreshFormatTimer.blockTextChanged){
refreshFormatTimer.textChanged = true
refreshFormatTimer.restart()
}
}
@ -210,6 +217,7 @@ Item {
property var isAutoRepeating : false // shutdown repeating key feature to let optional menu appears and do normal stuff (like accents menu)
Keys.onReleased: {
if(!refreshFormatTimer.blockTextChanged){
refreshFormatTimer.restartFromInput = true
refreshFormatTimer.restart()
}
if( event.isAutoRepeat){// We begin or are currently repeating a key
@ -222,6 +230,7 @@ Item {
}
Keys.onPressed: {
if(!refreshFormatTimer.blockTextChanged){
refreshFormatTimer.restartFromInput = true
refreshFormatTimer.restart()
}
if(event.isAutoRepeat){