Seite 1 von 1

qtextedit:zeichen einfügen an best. pos. nach zeichenformat

Verfasst: 13. Oktober 2007 11:30
von -=Freaky=-
hi,

ich versuche gerade, in einer von QTextEdit abgeleiteten klasse eine methode toBB zu implementieren, die eben den formatierten text (vorerst nur fett, kursiv, unterstrichen) in bb-code umwandeln soll (fuer foren).

Code: Alles auswählen

QString myEdit::toBB()
{
	QString plainText = toPlainText();
	if( plainText.isEmpty() )
			return QString();
	
	QString result;

	QTextCursor cursor = textCursor();
	cursor.movePosition( QTextCursor::Start );
	cursor.movePosition( QTextCursor::NextCharacter );

	QTextCharFormat tcFormat;
	for( int i = 0; i < plainText.size(); i++ )
	{
		if( cursor.charFormat() == tcFormat )
		{
			result.append( plainText.at( i ) );
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		}
		
		if( cursor.charFormat().fontWeight() == QFont::Bold
				  && tcFormat.fontWeight() != QFont::Bold )
		{
			result.append( plainText.at( i ) );
			result.append( "[b]" );
			tcFormat = cursor.charFormat();
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		}
		else if( ( cursor.charFormat().fontWeight() != QFont::Bold || cursor.atEnd() )
				       && tcFormat.fontWeight() == QFont::Bold )
		{
			result.append( plainText.at( i ) );
			result.append( "[/b]" );
			tcFormat = cursor.charFormat();
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		}
		
		if( cursor.charFormat().fontItalic() && !tcFormat.fontItalic() )
		{
			result.append( plainText.at( i ) );
			result.append( "[i]" );
			tcFormat = cursor.charFormat();
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		}
		else if( ( !cursor.charFormat().fontItalic() || cursor.atEnd() )
					  && tcFormat.fontItalic() )
		{
			result.append( plainText.at( i ) );
			result.append( "[/i]" );
			tcFormat = cursor.charFormat();
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		}
		
		if( cursor.charFormat().fontUnderline() && !tcFormat.fontUnderline() )
		{
			result.append( plainText.at( i ) );
			result.append( "[u]" );
			tcFormat = cursor.charFormat();
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		}
		else if( ( !cursor.charFormat().fontUnderline() || cursor.atEnd() )
					  && tcFormat.fontUnderline() )
		{
			result.append( plainText.at( i ) );
			result.append( "[/u]" );
			tcFormat = cursor.charFormat();
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		}
		
		result.append( plainText.at( i ) );
		cursor.movePosition( QTextCursor::NextCharacter );
	}

	return result;
}
das ist meine methode wie sie jetzt ist.

das problem: die bb-tags ( , , , , , ) stehen immer eine Stelle zuweit im result-string.
ich habe aber keine ahnung, wieso.

hoffe, mir kann geholfen werden, danke im voraus.

mfg,
julian

Verfasst: 15. Oktober 2007 13:05
von -=Freaky=-
ist die frage zu bloed? ich kann mir nicht vorstellen dass hierzu keinen antworten parat sind.

vllt noch als info: ohne das

Code: Alles auswählen

cursor.movePosition( QTextCursor::NextCharacter );
nach

Code: Alles auswählen

cursor.movePosition( QTextCursor::Start );
wird das erste oeffnende tag wieder um eine Stelle ("nach rechts") verschoben, alle (oeffnenden und schliessenden) tags danach allerdings um 2 stellen. Nach dem letzten Buchstaben d. textes (ohne tags) wird ausserdem abgeschnitten.
=> "Bold Italic Underlined"

wobei es so aussehen sollte:
=> "Bold Italic Underlined"

mfg,
julian

Verfasst: 15. Oktober 2007 13:17
von CaptnChaos

Code: Alles auswählen

         result.append( plainText.at( i ) );
         result.append( "[b]" ); 
tauscg mal die beiden dinger.

Verfasst: 15. Oktober 2007 13:49
von -=Freaky=-
lol ok gute idee :D
dankeschoen!

trotzdem kommt jetzt das dabei raus:
"Bold Italic Underlined"
also am ende wirds abgeschnitten.

// edit: cursor.atEnd() funktioniert ja anscheinend nicht. da wird doch string-anfang und -ende als extra zeichen gewertet. also muesste die schleife so aussehen:

Code: Alles auswählen

for( int i = 0; i < plainText.size()+2; i++ )
aber dann wuerde der index am ende zu gross.
sollte ich da immer abfragen ala

Code: Alles auswählen

if( i >= plainText.size() )
    result.append( plainText.at( plainText.size() - 1 ) );
?

mfg,
julian

Verfasst: 15. Oktober 2007 14:01
von CaptnChaos
hm, ich glaube das liegt an deiner for schleife, wenn du das mit while(!textCursor.atEnd())
machen würdest, sähe das anders aus.
Ach ja, vllt red ich auch müll, aber ist der letzte char in einem String nicht \0, kann der
überhaupt formatiert sein?
mach das :&& tcFormat.fontUnderline()
mal weg.

Verfasst: 15. Oktober 2007 21:25
von -=Freaky=-
danke fuer die hilfe.

also,

Code: Alles auswählen

int i = 0;
while( !cursor.atEnd() )
{ ... i++ ... }
fuehrt zum selben ergebnis.

wenn ich per index auf ein zeichen im QString zugreife, entweder

Code: Alles auswählen

string[ string.size() - 1 ]
oder

Code: Alles auswählen

string.at( string.size() - 1 )
dann bekomme ich das letzte zeichen zurueck, was kein nullterminierungszeichen ist:

Code: Alles auswählen

QString string;
string = "abcde12345";
QChar c = string.at( string.size() - 1 ); // c == '5'
KernelPanic hat geschrieben:mach das :&& tcFormat.fontUnderline()
mal weg
wenn ich das wegnehme, dann wird ein "[/u]" nach zeiche eingefuegt, obwohl das vorherige zeichen gar nicht unterstrichen ist. (oder hab ich nen denkfehler?)

mfg,
julian

Verfasst: 16. Oktober 2007 07:31
von CaptnChaos
kannst du mal eine minimale version von deinem programm posten?
das ist immer doof bei so sachen nix zum ausprobieren zu haben.

Verfasst: 17. Oktober 2007 13:31
von -=Freaky=-
klar kein problem. es ist schon nur der editor viel minimaler wird schwer...
ich habs mal gepackt und angehaengt.
falls fehler auftreten (beim kompilieren), einfach bescheid sagen. ich hab ein paar irrelevante dinge rausgenommen (einen dialog (ui-file), einen button, eine methode) und konnte es noch nicht testen, da ich gerade das gentoo system neu aufsetze und qt noch kompilieren muss.

danke fuer die hilfsbereitschaft,
mfg,
julian

Verfasst: 17. Oktober 2007 15:35
von CaptnChaos

Code: Alles auswählen

if( cursor.charFormat() == tcFormat && !cursor.atEnd()/*<- dieses WICHTIG!!!!*/ )
		{
			result.append( plainText.at( i ) );
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		}
		

Verfasst: 17. Oktober 2007 16:04
von -=Freaky=-
vielen dank!
ich kann es leider immer noch nicht testen, aber kann es sein dass da anstatt dem und (&&) ein oder (||) hingehoert? denn zeichen gleicher formatierung sollen ja trotzdem angehaengt werden, auch wenn der cursor nicht am ende ist.

mfg,
julian

Verfasst: 17. Oktober 2007 16:10
von CaptnChaos
passt so wies hier ist. habs ausprobiert.

Verfasst: 17. Oktober 2007 16:29
von -=Freaky=-
alles klar vielen dank!
sobald mien system wieder laeuft kompilier ich es so mal bei mir.

mfg,
julian

Verfasst: 22. Oktober 2007 18:02
von -=Freaky=-
vielen dank fuer deine hilfe, es hat wirklich so funktioniert.

allerdings wollte ich auch verschachtelte tags unterstuetzen, sowas wie

Code: Alles auswählen

[b]Wort1 [i]Wo[u]r[/b]t2[/i] Wort3[/u]
(obwohl die meisten foren das selbst nicht supporten ...), deshalb hab ich das ganze nochmal etwas umstrukturiert und vereinfacht und bei meinen paar kleinen tests eben hats super funktioniert.

sieht jetzt so aus:

Code: Alles auswählen

QString myEdit::toBB()
{
	QString plainText = toPlainText();
	if( plainText.isEmpty() )
			return QString();
	
	QString result;
	QTextCursor cursor = textCursor();
	cursor.movePosition( QTextCursor::Start );
	cursor.movePosition( QTextCursor::NextCharacter );
	QTextCharFormat tcFormat;
	QStringList opened;
	for( int i = 0; i < plainText.size(); i++ )
	{		
		if( cursor.charFormat() == tcFormat )
		{
			result.append( plainText.at( i ) );
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		} 
		
		if( cursor.charFormat().fontWeight() == QFont::Bold
				  && tcFormat.fontWeight() != QFont::Bold )
		{
			opened << "b";
			result.append( "[b]" );
		}
		if( cursor.charFormat().fontWeight() != QFont::Bold
				       && tcFormat.fontWeight() == QFont::Bold )
		{
			opened.removeAt( opened.lastIndexOf( "b" ) );
			result.append( "[/b]" );
		}
		
		if( cursor.charFormat().fontItalic() && !tcFormat.fontItalic() )
		{
			opened << "i";
			result.append( "[i]" );
		}
		if( !cursor.charFormat().fontItalic()
					  && tcFormat.fontItalic() )
		{
			opened.removeAt( opened.lastIndexOf( "i" ) );
			result.append( "[/i]" );
		}
		
		if( cursor.charFormat().fontUnderline() && !tcFormat.fontUnderline() )
		{
			opened << "u";
			result.append( "[u]" );
		}
		if( !cursor.charFormat().fontUnderline()
				&& tcFormat.fontUnderline() )
		{
			opened.removeAt( opened.lastIndexOf( "u" ) );
			result.append( "[/u]" );
		}
		
		result.append( plainText.at( i ) );
		tcFormat = cursor.charFormat();
		cursor.movePosition( QTextCursor::NextCharacter );
	}
	if( opened.size() > 0 )
		for( int i =  opened.size() - 1; i >= 0; i-- )
			result.append( tr( "[/%1]" ).arg( opened.at( i ) ) );
	return result;
}
... nur falls das jemanden interessiert. :)

mfg,
julian