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

Alles rund um die Programmierung mit Qt
Antworten
-=Freaky=-
Beiträge: 503
Registriert: 29. Dezember 2006 22:54
Wohnort: HL

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

Beitrag 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
-=Freaky=-
Beiträge: 503
Registriert: 29. Dezember 2006 22:54
Wohnort: HL

Beitrag 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
CaptnChaos
Beiträge: 605
Registriert: 28. Juni 2007 15:01
Kontaktdaten:

Beitrag von CaptnChaos »

Code: Alles auswählen

         result.append( plainText.at( i ) );
         result.append( "[b]" ); 
tauscg mal die beiden dinger.
-=Freaky=-
Beiträge: 503
Registriert: 29. Dezember 2006 22:54
Wohnort: HL

Beitrag 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
CaptnChaos
Beiträge: 605
Registriert: 28. Juni 2007 15:01
Kontaktdaten:

Beitrag 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.
-=Freaky=-
Beiträge: 503
Registriert: 29. Dezember 2006 22:54
Wohnort: HL

Beitrag 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
CaptnChaos
Beiträge: 605
Registriert: 28. Juni 2007 15:01
Kontaktdaten:

Beitrag von CaptnChaos »

kannst du mal eine minimale version von deinem programm posten?
das ist immer doof bei so sachen nix zum ausprobieren zu haben.
-=Freaky=-
Beiträge: 503
Registriert: 29. Dezember 2006 22:54
Wohnort: HL

Beitrag 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
Dateianhänge
bbEditorTest.tar.gz
(8.4 KiB) 123-mal heruntergeladen
CaptnChaos
Beiträge: 605
Registriert: 28. Juni 2007 15:01
Kontaktdaten:

Beitrag von CaptnChaos »

Code: Alles auswählen

if( cursor.charFormat() == tcFormat && !cursor.atEnd()/*<- dieses WICHTIG!!!!*/ )
		{
			result.append( plainText.at( i ) );
			cursor.movePosition( QTextCursor::NextCharacter );
			continue;
		}
		
-=Freaky=-
Beiträge: 503
Registriert: 29. Dezember 2006 22:54
Wohnort: HL

Beitrag 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
CaptnChaos
Beiträge: 605
Registriert: 28. Juni 2007 15:01
Kontaktdaten:

Beitrag von CaptnChaos »

passt so wies hier ist. habs ausprobiert.
-=Freaky=-
Beiträge: 503
Registriert: 29. Dezember 2006 22:54
Wohnort: HL

Beitrag von -=Freaky=- »

alles klar vielen dank!
sobald mien system wieder laeuft kompilier ich es so mal bei mir.

mfg,
julian
-=Freaky=-
Beiträge: 503
Registriert: 29. Dezember 2006 22:54
Wohnort: HL

Beitrag 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
Antworten