QTextFrame Abstände [gelöst]

Alles rund um die Programmierung mit Qt
Antworten
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

QTextFrame Abstände [gelöst]

Beitrag von QtBerserker »

Hallo,

ich versuche in Abhängigkeit einer Enum Text einen QTextDocument/QTextEdit einzufügen:

Code: Alles auswählen

class QED : public QTextEdit
{
...
    enum RegionType {

        Plain,
        Edit,
        Input,
        Output,
        Error,
        Warning
    };

QED::QED()
{
    QTextFrame *topFrame = document()->rootFrame();

    QTextFrameFormat topFrameFormat = topFrame->frameFormat();
    topFrameFormat.setBorder(1);
    topFrameFormat.setMargin(1);
    topFrameFormat.setPadding(1);
    topFrame->setFrameFormat(topFrameFormat);
}

void QED::write( const QString& txt, RegionType region )
{
    QTextFrame *topFrame = document()->rootFrame();

    QTextCursor cursor(this->textCursor());

    cursor.setPosition(topFrame->lastPosition());

    QTextCharFormat textFormat;
    QTextCharFormat boldFormat;
    boldFormat.setFontWeight(QFont::Bold);

    QTextFrameFormat frameFormat;
    frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
    frameFormat.setBorder(1);
    frameFormat.setMargin(1);
    frameFormat.setPadding(1);

    switch( region ) {
    case Edit:
        cursor.insertFrame(frameFormat);
        cursor.insertText(txt, textFormat);
        break;
    case Input:
        cursor.insertFrame(frameFormat);
        cursor.insertText(txt, textFormat);
        break;
    case Output:
        cursor.insertFrame(frameFormat);
        cursor.insertText(txt, boldFormat);
        break;
    case Error:
        cursor.insertFrame(frameFormat);
        cursor.insertText(txt, boldFormat);
       break;
    case Warning:
        cursor.insertFrame(frameFormat);
        cursor.insertText(txt, boldFormat);
        break;
    default:
        cursor.insertFrame(frameFormat);
        cursor.insertText(txt, textFormat);
    }
}
und in main() testweise:

Code: Alles auswählen

    qed.write( "Hello",  QED::Edit );
    qed.write( "World",  QED::Edit );
    qed.write( "Anybody", QED::Input );
    qed.write( "Out", QED::Output );
    qed.write( "There", QED::Error );
    qed.write( "?", QED::Plain );
Klappt soweit recht gut, allerdings ist ein RIESEN Platz schwischen den Frames. Ich habe noch nicht die Stelle gefunden, diesen weg zu bekommen. Über den root frame geht's wohl nicht. Wie geht das? So sieht es aus:

http://img159.imageshack.us/done.php?l= ... nntrd5.png

Grüße
Olaf
Dateianhänge
Unbenannt.png
Unbenannt.png (8.67 KiB) 7952 mal betrachtet
Zuletzt geändert von QtBerserker am 26. September 2008 19:06, insgesamt 1-mal geändert.
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag von patrik08 »

jedesmal wenn du cursor.insertFrame(frameFormat); einfuegst... komt auch ein neuen block ...
Dies bedeutet TextFrame ist in einem block eingeschlossen..
und default bei qt ist der block margin 12pt open und unten...

vor insertFrame formatiere den currenblock cursor.blockformat
auf margin 0pt..

Code: Alles auswählen


cursor.insertBlock();   /*  ausser block 0 */
cursor.beginEditBlock();
cursor.setBlockFormat(xx);
/* frame insert here */
cursor.endEditBlock()


/* set all margin to zero qt4 send 12 top 12 bottom by default */
static inline  QTextBlockFormat DefaultMargin( QTextBlockFormat rootformats = QTextBlockFormat() )
{
    rootformats.setBottomMargin(1);
    rootformats.setTopMargin(1);
    rootformats.setRightMargin(0);
    rootformats.setLeftMargin(0);
    rootformats.setAlignment( Qt::AlignLeft );
    return rootformats;
}


aus meinem beta code... von

http://code.google.com/p/fop-miniscribus/
http://www.qt-apps.org/content/show.php ... tent=80650
.........................
speack português italiano deutsch english castellà qt
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

Beitrag von QtBerserker »

vielen Dank für die Antwort. Das ich bei insertFrame "außen drum'rum" noch einen Block rein lege war mir nicht ganz klar (http://doc.trolltech.com/4.4/richtext-structure.html).

Der Ansatz scheint der richtige zu sein, nur scheine ich nun zusätzlich Raum einzufügen!

Code: Alles auswählen

    QTextCursor cursor(this->document()->rootFrame()->lastCursorPosition());

    QTextBlockFormat blkFormat(cursor.blockFormat());
    blkFormat.setTopMargin(0);
    blkFormat.setBottomMargin(0);
    blkFormat.setRightMargin(0);
    blkFormat.setLeftMargin(0);

    switch( region ) {
    case Edit:
        cursor.insertBlock();
        cursor.beginEditBlock(); 
        cursor.insertFrame(frameFormat);
        cursor.setBlockFormat(blkFormat);
        cursor.insertText(txt, textFormat);
        cursor.endEditBlock();
        break;
Dateianhänge
Snap1.png
Snap1.png (3.21 KiB) 7937 mal betrachtet
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag von patrik08 »

QTextCursor cur0(document());
cur0.movePosition(QTextCursor::End); /* ende document */
QTextFrame gibt dir die cursorposition! oder sogar ein neuen cursor

darum hast du ein block mehr als noetig im html source sichtbar...

was auch geht die frame immer float right setzen ( format) und dann immer im gleichen block ende position -1 ein neuen frame hinzufuegen...

http://www.potu.com/man/doc.trolltech.c ... stPosition

http://www.potu.com/man/doc.trolltech.c ... stPosition

QTextDocument & QTextCursor sind nicht einfach zum lernen
ab besten Oefnest du
alle ordner mit textdocument-**
in /doc/src/snippets/
besonders
$QDIR/doc/src/snippets/textdocument-frames

oder http://fop-miniscribus.googlecode.com/s ... ged/oasis/
den reader von odt file

Code: Alles auswählen

bool OOReader::convertFrame( QTextCursor &cur , const QDomElement e , QTextCharFormat parent ,  bool HandleSpace )
{
	if (e.isNull()) {
		return false;
	}
    const QString name = e.attribute ("draw:style-name");
	const qreal width = Unit(e.attribute("svg:width"));
	const qreal height = Unit(e.attribute("svg:height"));
	const qreal poX = Unit(e.attribute("svg:x"));
	const qreal poY = Unit(e.attribute("svg:y"));
	const int zindex = e.attribute("draw:z-index").toInt();
    
    QTextFrameFormat fox;
    if (css2[name].valid) {
		fox = css2[name].of.toFrameFormat();
    }
    fox.setWidth ( width );
	fox.setHeight( height );
    Q_ASSERT(fox.isValid());
    
	const int lastposition = cur.position();
	QTextCursor cur2(Qdoc);
	cur2.setPosition(lastposition);

	QDomElement img = e.firstChildElement("draw:image");
	QDomElement txtframe = e.firstChildElement("draw:text-box");
	if (!img.isNull()) {
		return convertImage(cur,e,parent ,HandleSpace);
	}
	if (!txtframe.isNull()) {
		QTextFrame  *floatframe = cur2.insertFrame(fox);
		QTextCursor  cur3 = floatframe->firstCursorPosition();
		cur.movePosition(QTextCursor::End);
                /* der erste block 0 ist nur editblock  ab 1>  insert block 
                sonst hat man ein leeren block */
		return iterateElements(txtframe,cur3,0);
	}

	return false;
}

.........................
speack português italiano deutsch english castellà qt
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

Beitrag von QtBerserker »

vielen Dank, ja der TextCursor ist mächtig, aber nicht einfach.

Ich habe mir mit QTextFrameFormat::setPosition(QTextFrameFormat::FloatLeft) beholfen, aber so recht ist mir nicht klar, wieso es funktioniert. Offenbar habe ich den d'runter liegenden Layout Mechanismus verstanden...

Ich habe den src etwas vereinfacht:

Code: Alles auswählen

void QED::write(RegionType region, const QString& txt)
{
    QTextCharFormat textFormat;

    QTextCursor cursor(this->document()->rootFrame()->lastCursorPosition());

    const int previous_region = cursor.block().previous().userState();

    if(previous_region == Prompt) {
        cursor.movePosition(QTextCursor::PreviousBlock);
        cursor.movePosition(QTextCursor::EndOfBlock);
        cursor.setPosition(cursor.position() + 1);
    }

    QTextFrameFormat frameFormat;

    switch( region ) {
    case Plain:
    case Edit:
    case Input:
    case Output:
        frameFormat = DefaultFrameFormat();
        break;
    case Error:
    case Warning:
        frameFormat = DefaultErrorFrameFormat();
        break;
    case Prompt:
        frameFormat = DefaultFrameFormat();
        {
            qreal txt_width = fontMetrics().width(txt);
            txt_width += frameFormat.margin() *2;
            txt_width += frameFormat.border() *2;
            txt_width += frameFormat.padding() *2;
            frameFormat.setWidth(txt_width);
        }
        break;
    default:
        frameFormat = DefaultFrameFormat();
    }

    cursor.insertFrame(frameFormat);
    cursor.insertText(txt, textFormat);

    cursor.block().setUserState(region);
}
nun möchte ich den neuen Frame gleich neben den Prompt Frame setzten, aber es klappt nicht. Wie positioniere ich den Cursor richtig?

Wenn ich mehrere Prompt Frames einfüge, kommt auch nur Müll raus.

Viele Grüße
Olaf

PS: dem HTMl ansehen ist auch eine schöne Debug Möglichkeit, Danke für den Tip![/code]
Dateianhänge
Snap2.png
Snap2.png (2.93 KiB) 7926 mal betrachtet
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

Beitrag von QtBerserker »

kleine Änderung:

Code: Alles auswählen

    if(previous_region == Prompt && region != Prompt) {
        cursor.movePosition(QTextCursor::PreviousBlock);
        cursor.movePosition(QTextCursor::EndOfBlock);
        cursor.setPosition(cursor.position() + 1);
    }
und sieht es so aus wie im Anhang, aber nicht so wie es sein soll.
Dateianhänge
Snap3.png
Snap3.png (2.15 KiB) 7924 mal betrachtet
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag von patrik08 »

Ich begreife immer noch nicht was du im textedit zeigen moechtest...

wen du eigene iconen einsetzen moechtest probiere mal
http://fop-miniscribus.googlecode.com/s ... t/main.cpp

als idee...

eine main.cpp zu builden dann kannst du in verschieden style einfugen...
wie:

Code: Alles auswählen

textCursor().insertText(QString(QChar::ObjectReplacementCharacter),FlaStruct);
kommt dan ein bild als html flash referenz...

Bild
.........................
speack português italiano deutsch english castellà qt
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

Beitrag von QtBerserker »

interessant mit den Icons.

Also, das Ganze soll eine Console/Terminal für scripting werden, zB python, tcl, lua. D.h. ich habe edit regionen (Command Eingabe), Ausgaben für StdOut und StdErr, Eingaben für StdIn und ein variables Promptzeichen.

Der Syntaxhighlighter macht nur Sinn für die Command Eingabe, also muss ich das in der QSyntaxHighlighter::highlightBlock () Funktionen feststellen können (daher der UseState, der ggf. später für Klammerung etc. um den QTextBlockUserData erweitert wird).

Da manche Operationen nur in der Command Eingabe Sinn machen, muss ich wissen, wo ich gerade bin, z.B. darf ich Ausgaben oder den Prompt nicht editieren (also etwas wie cursurIsInEditRegion() ).

Bei der Eingabe kann es auch einen Prefix Prompt geben, zB. "Enter Input Text: " von wo ich die Eingabe zurück an den Interpreter geben muss.

Tja, so ist das nun gedacht. Es gibt einige Versuche im inet, die alle aber irgendwelche Macken haben und das Eingabe Problem mit einem eigenen Dialog gelöst haben ...

Den Tester hänge ich 'mal an ;-)

Viele Grüße
Olaf
Dateianhänge
qed.zip
(4.73 KiB) 187-mal heruntergeladen
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag von patrik08 »

QtBerserker hat geschrieben:interessant mit den Icons.

Also, das Ganze soll eine Console/Terminal für scripting werden, zB python, tcl, lua. D.h. ich habe edit regionen (Command Eingabe), Ausgaben für StdOut und StdErr, Eingaben für StdIn und ein variables Promptzeichen.

Olaf
Ich wuerde alles auf reine textbasis machen also nur block
Vielleicht noch verschiedene icon um zu sehen ob promt oder nur lesen oder schreiben u.n.s.w.

also nur qtextblock
http://doc.trolltech.com/4.4/qtextblock.html#setVisible

und wenn niemand schreiben muss setVisible +- und format propriety QVariant daten speichen ...
oder alles textedit readonly un bei prompt eine QLineEdit auf dem Block rect drauf posizionieren...
oder QAbstractScrollArea mit qtextlinen (sind sehr schnell gegenueber QTextDocument auch Theards moeglich ) http://doc.trolltech.com/qq/qq24-textlayouts.html beim painten einfach alte Cachen und scrollbar zum ende fuehren... oder auch umgekehrt neu oben... die texte kann man immer kopieren und einfuegen.

IMO nur eine idee....
.........................
speack português italiano deutsch english castellà qt
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

Beitrag von QtBerserker »

vielen Dank für die Antwort. Ich habe mir die Qt Doku zu dem RichText nochmals genauer angesehen - Frames scheinen wirklich unnötig für den Fall ...
also nur qtextblock
http://doc.trolltech.com/4.4/qtextblock.html#setVisible

und wenn niemand schreiben muss setVisible +- und format propriety QVariant daten speichen ...
das visible - macht es echt was ich denke, sprich den Text verstecken? Wäre schlecht, da manche Stellen ja read-only sein sollen und nicht hidden (habe noch Qt4.3.x ...) Mit dem "format property QVariant daten" habe ich allerdings nicht verstanden.

Viele Grüße
Olaf
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag von patrik08 »

QtBerserker hat geschrieben:v Mit dem "format property QVariant daten" habe ich allerdings nicht verstanden.
Olaf
in jedem QTextFormat kann man eigene name , QVariant daten speichern.

QVariant QTextFormat::property ( int propertyId ) const
Returns the property specified by the given propertyId.
See also setProperty().

Hast du http://doc.trolltech.com/qq/qq24-textlayouts.html angeschaut als idee ?
.........................
speack português italiano deutsch english castellà qt
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

Beitrag von QtBerserker »

Yep, starker Stoff. Zumindest habe ich erst'mal etwas zum probieren, auch wenn es evtl. über's Ziel heinaus schiesst.

Aber erstmal vielen Dank! Ich setzte den Thread auf gelöst :-)
Olaf
Antworten