From 41715a8d27965f1d0f222da2ff003c388693c58c Mon Sep 17 00:00:00 2001 From: zeljko Date: Wed, 21 Apr 2010 19:24:32 +0000 Subject: [PATCH] Qt: TQtTextEdit rework - added insertLine() setLineText() removeLine() using QTextCursor git-svn-id: trunk@24799 - --- lcl/interfaces/qt/qtprivate.pp | 90 +++++++++++----------- lcl/interfaces/qt/qtwidgets.pas | 130 ++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 42 deletions(-) diff --git a/lcl/interfaces/qt/qtprivate.pp b/lcl/interfaces/qt/qtprivate.pp index 64b1dc24ea..d2c1bf422d 100644 --- a/lcl/interfaces/qt/qtprivate.pp +++ b/lcl/interfaces/qt/qtprivate.pp @@ -97,11 +97,10 @@ type procedure ExternalUpdate(var Astr: WideString; AClear: Boolean = True); procedure IsChanged; // OnChange triggered by program action protected - procedure Put(Index: Integer; const S: string); override; function GetTextStr: string; override; function GetCount: integer; override; function Get(Index : Integer) : string; override; - //procedure SetSorted(Val : boolean); virtual; + procedure Put(Index: Integer; const S: string); override; public constructor Create(TextEdit : QTextEditH; TheOwner: TWinControl); destructor Destroy; override; @@ -110,9 +109,7 @@ type procedure Delete(Index : integer); override; procedure Insert(Index : integer; const S: string); override; procedure SetText(TheText: PChar); override; - //procedure Sort; virtual; public - //property Sorted: boolean read FSorted write SetSorted; property Owner: TWinControl read FOwner; procedure TextChangedHandler; cdecl; end; @@ -130,10 +127,10 @@ implementation ------------------------------------------------------------------------------} procedure TQtMemoStrings.InternalUpdate; var - Astr: WideString; + W: WideString; begin - QTextEdit_toPlainText(FQtTextEdit,@Astr); // get the memo content - FStringList.Text := UTF16ToUTF8(Astr); + QTextEdit_toPlainText(FQtTextEdit,@W); // get the memo content + FStringList.Text := UTF16ToUTF8(W); FTextChanged := False; end; @@ -146,17 +143,17 @@ end; ------------------------------------------------------------------------------} procedure TQtMemoStrings.ExternalUpdate(var Astr: WideString; AClear: Boolean = True); var - Str: WideString; + W: WideString; begin FUpdating := True; - Str := GetUtf8String(AStr); + W := GetUtf8String(AStr); if AClear then begin QTextEdit_clear(FQtTextEdit); - QTextEdit_setPlainText(FQtTextEdit,@Str); + QTextEdit_setPlainText(FQtTextEdit,@W); end else - QTextEdit_append(FQtTextEdit,@Str); + QTextEdit_append(FQtTextEdit,@W); if QTextEdit_alignment(FQtTextEdit) <> AlignmentMap[TCustomMemo(FOwner).Alignment] then QTextEdit_setAlignment(FQtTextEdit, AlignmentMap[TCustomMemo(FOwner).Alignment]); @@ -185,16 +182,6 @@ begin end; end; -procedure TQtMemoStrings.Put(Index: Integer; const S: string); -var - W: WideString; -begin - FStringList[Index] := S; - W := FStringList.Text; - ExternalUpdate(W, True); - FTextChanged := False; -end; - {------------------------------------------------------------------------------ Method: TQtMemoStrings.GetTextStr Params: None @@ -236,6 +223,15 @@ begin else Result := ''; end; +procedure TQtMemoStrings.Put(Index: Integer; const S: string); +var + W: WideString; +begin + if FTextChanged then InternalUpdate; + FStringList[Index] := S; + W := GetUTF8String(S); + TQtTextEdit(FOwner.Handle).setLineText(Index, W); +end; {------------------------------------------------------------------------------ Method: TQtMemoStrings.Create @@ -310,7 +306,7 @@ end; ------------------------------------------------------------------------------} procedure TQtMemoStrings.Assign(Source: TPersistent); var - Astr: WideString; + W: WideString; begin if (Source=Self) or (Source=nil) then @@ -319,12 +315,12 @@ begin begin FStringList.Clear; FStringList.Text := TStrings(Source).Text; - Astr := FStringList.Text; - ExternalUpdate(Astr,True); + W := FStringList.Text; + ExternalUpdate(W,True); FTextChanged := False; exit; end; - Inherited Assign(Source); + inherited Assign(Source); end; {------------------------------------------------------------------------------ @@ -340,8 +336,7 @@ begin FStringList.Clear; if not (csDestroying in FOwner.ComponentState) - and not (csFreeNotification in FOwner.ComponentState) - then + and not (csFreeNotification in FOwner.ComponentState) then QTextEdit_clear(FQtTextEdit); FTextChanged := False; @@ -358,15 +353,18 @@ end; ------------------------------------------------------------------------------} procedure TQtMemoStrings.Delete(Index: integer); var - Astr: WideString; + W: WideString; begin if FTextChanged then InternalUpdate; - if Index < FStringList.Count then + if (Index >= 0) and (Index < FStringList.Count) then begin FStringList.Delete(Index); - Astr := FStringList.Text; - ExternalUpdate(AStr,True); + TQtTextEdit(FOwner.Handle).removeLine(Index); + {TODO: remove old way after testing + W := FStringList.Text; + ExternalUpdate(W, True); FTextChanged := False; + } end; end; @@ -379,16 +377,24 @@ end; ------------------------------------------------------------------------------} procedure TQtMemoStrings.Insert(Index: integer; const S: string); var - Astr: WideString; + W: WideString; begin if FTextChanged then InternalUpdate; if Index < 0 then Index := 0; if Index <= FStringList.Count then begin - FStringList.Insert(Index,S); - Astr := S; - ExternalUpdate(AStr, False); - FTextChanged := False; + FStringList.Insert(Index, S); + // append is much faster in case when we add strings + if TQtTextEdit(FOwner.Handle).getBlockCount - Index <= 1 then + begin + W := S; + ExternalUpdate(W, False); + FTextChanged := False; + end else + begin + W := GetUTF8String(S); + TQtTextEdit(FOwner.Handle).insertLine(Index, W); + end; end; end; @@ -401,13 +407,13 @@ end; ------------------------------------------------------------------------------} procedure TQtMemoStrings.SetText(TheText: PChar); Var - str: String; - Astr: WideString; + S: String; + W: WideString; begin - str := StrPas(TheText); - FStringList.Text := str; - AStr := Str; - ExternalUpdate(Astr,True); + S := StrPas(TheText); + FStringList.Text := S; + W := S; + ExternalUpdate(W,True); FTextChanged := False; end; diff --git a/lcl/interfaces/qt/qtwidgets.pas b/lcl/interfaces/qt/qtwidgets.pas index 143f542ff3..5333280202 100644 --- a/lcl/interfaces/qt/qtwidgets.pas +++ b/lcl/interfaces/qt/qtwidgets.pas @@ -650,19 +650,23 @@ type FList: TStrings; procedure append(AStr: WideString); function getAlignment: QtAlignment; + function getBlockCount: Integer; function getMaxLength: Integer; function getText: WideString; override; function getTextStatic: Boolean; override; function getSelectionStart: Integer; function getSelectionEnd: Integer; function getSelectionLength: Integer; + procedure insertLine(const AIndex: integer; AText: WideString); function isUndoAvailable: Boolean; + procedure removeLine(const AIndex: integer); procedure setAlignment(const AAlignment: QtAlignment); procedure setBorder(const ABorder: Boolean); procedure setDefaultColorRoles; override; procedure setEchoMode(const AMode: QLineEditEchoMode); procedure setLineWrapMode(const AMode: QTextEditLineWrapMode); procedure setMaxLength(const ALength: Integer); + procedure setLineText(const AIndex: integer; AText: WideString); procedure setText(const AText: WideString); override; procedure setReadOnly(const AReadOnly: Boolean); procedure setSelection(const AStart, ALength: Integer); @@ -5861,6 +5865,11 @@ begin Result := QTextEdit_alignment(QTextEditH(Widget)); end; +function TQtTextEdit.getBlockCount: Integer; +begin + Result := QTextDocument_blockCount(QTextEdit_document(QTextEditH(Widget))); +end; + function TQtTextEdit.getMaxLength: Integer; begin {$note implement TQtTextEdit.getMaxLength} @@ -5922,6 +5931,127 @@ begin {$note implement TQtTextEdit.setMaxLength} end; +procedure TQtTextEdit.insertLine(const AIndex: integer; AText: WideString); +var + QtCursor: QTextCursorH; + b: Boolean; + WrapMode: QTextEditLineWrapMode; +begin + WrapMode := QTextEdit_lineWrapMode(QTextEditH(Widget)); + {we must remove wrapping to get correct line !} + setLineWrapMode(QTextEditNoWrap); + QtCursor := QTextCursor_create(); + try + QTextEdit_textCursor(QTextEditH(Widget), QtCursor); + QTextCursor_beginEditBlock(QtCursor); + QTextCursor_movePosition(QtCursor, QTextCursorStart, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorStartOfLine, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorDown, + QTextCursorMoveAnchor, AIndex); + QTextCursor_insertBlock(QtCursor); + QTextCursor_movePosition(QtCursor, QTextCursorUp, + QTextCursorMoveAnchor, 1); + QTextCursor_insertText(QtCursor, @AText); + QTextCursor_endEditBlock(QtCursor); + finally + QTextCursor_destroy(QtCursor); + setLineWrapMode(WrapMode); + end; +end; + +procedure TQtTextEdit.removeLine(const AIndex: integer); +var + QtCursor: QTextCursorH; + B: Boolean; + WrapMode: QTextEditLineWrapMode; + Diff: Integer; +begin + Diff := getBlockCount - AIndex; + {we must remove wrapping to get correct line !} + WrapMode := QTextEdit_lineWrapMode(QTextEditH(Widget)); + setLineWrapMode(QTextEditNoWrap); + QtCursor := QTextCursor_create(); + try + QTextEdit_textCursor(QTextEditH(Widget), QtCursor); + QTextCursor_beginEditBlock(QtCursor); + // small optimization if we delete from end of list + if Diff <= 2 then + begin + QTextCursor_movePosition(QtCursor, QTextCursorEnd, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorStartOfLine, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorUp, + QTextCursorMoveAnchor, Diff - 1); + end else + begin + QTextCursor_movePosition(QtCursor, QTextCursorStart, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorStartOfLine, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorDown, + QTextCursorMoveAnchor, AIndex); + QTextCursor_movePosition(QtCursor, QTextCursorEndOfLine, + QTextCursorMoveAnchor, 1); + end; + + QTextCursor_select(QtCursor, QTextCursorLineUnderCursor); + B := QTextCursor_hasSelection(QtCursor); + if not B then + QTextCursor_deleteChar(QtCursor) + else + QTextCursor_deletePreviousChar(QtCursor); + + if (AIndex = 0) then + begin + QTextCursor_movePosition(QtCursor, QTextCursorStart, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorStartOfLine, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorDown, + QTextCursorMoveAnchor, 1); + end; + if B then + QTextCursor_deletePreviousChar(QtCursor); + QTextCursor_endEditBlock(QtCursor); + finally + QTextCursor_destroy(QtCursor); + setLineWrapMode(WrapMode); + end; +end; + +procedure TQtTextEdit.setLineText(const AIndex: integer; AText: WideString); +var + QtCursor: QTextCursorH; + WrapMode: QTextEditLineWrapMode; +begin + {we must remove wrapping to get correct line !} + WrapMode := QTextEdit_lineWrapMode(QTextEditH(Widget)); + setLineWrapMode(QTextEditNoWrap); + QtCursor := QTextCursor_create(); + try + QTextEdit_textCursor(QTextEditH(Widget), QtCursor); + QTextCursor_beginEditBlock(QtCursor); + QTextCursor_movePosition(QtCursor, QTextCursorStart, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorStartOfLine, + QTextCursorMoveAnchor, 1); + QTextCursor_movePosition(QtCursor, QTextCursorDown, + QTextCursorMoveAnchor, AIndex); + QTextCursor_select(QtCursor, QTextCursorLineUnderCursor); + QTextCursor_removeSelectedText(QtCursor); + QTextCursor_insertText(QtCursor, @AText); + QTextCursor_movePosition(QtCursor, QTextCursorEndOfLine, + QTextCursorMoveAnchor, 1); + QTextCursor_endEditBlock(QtCursor); + finally + QTextCursor_destroy(QtCursor); + setLineWrapMode(WrapMode); + end; +end; + procedure TQtTextEdit.setText(const AText: WideString); begin QTextEdit_setPlainText(QTextEditH(Widget), @AText);