diff --git a/lcl/interfaces/qt/qtprivate.pp b/lcl/interfaces/qt/qtprivate.pp index 1b5114b601..2040344b4e 100644 --- a/lcl/interfaces/qt/qtprivate.pp +++ b/lcl/interfaces/qt/qtprivate.pp @@ -563,21 +563,52 @@ procedure TQtListStrings.Put(Index: Integer; const S: string); begin inherited Put(Index, S); if Assigned(FWinControl) and (FWinControl.HandleAllocated) then + begin FOwner.setItemText(Index, S); + if FOwner is TQtCheckListBox then + begin + FOwner.ItemFlags[Index] := FOwner.ItemFlags[Index] or QtItemIsUserCheckable; + if TQtCheckListBox(FOwner).AllowGrayed then + FOwner.ItemFlags[Index] := FOwner.ItemFlags[Index] or QtItemIsTristate + else + FOwner.ItemFlags[Index] := FOwner.ItemFlags[Index] and not QtItemIsTristate; + end; + end; end; procedure TQtListStrings.InsertItem(Index: Integer; const S: string); begin inherited InsertItem(Index, S); if Assigned(FWinControl) and (FWinControl.HandleAllocated) then + begin FOwner.insertItem(Index, S); + if FOwner is TQtCheckListBox then + begin + FOwner.ItemFlags[Index] := FOwner.ItemFlags[Index] or QtItemIsUserCheckable; + if TQtCheckListBox(FOwner).AllowGrayed then + FOwner.ItemFlags[Index] := FOwner.ItemFlags[Index] or QtItemIsTristate + else + FOwner.ItemFlags[Index] := FOwner.ItemFlags[Index] and not QtItemIsTristate; + end; + end; end; procedure TQtListStrings.InsertItem(Index: Integer; const S: string; O: TObject); begin inherited InsertItem(Index, S, O); if Assigned(FWinControl) and (FWinControl.HandleAllocated) then + begin FOwner.insertItem(Index, S); + + if FOwner is TQtCheckListBox then + begin + FOwner.ItemFlags[Index] := FOwner.ItemFlags[Index] or QtItemIsUserCheckable; + if TQtCheckListBox(FOwner).AllowGrayed then + FOwner.ItemFlags[Index] := FOwner.ItemFlags[Index] or QtItemIsTristate + else + FOwner.ItemFlags[Index] := FOwner.ItemFlags[Index] and not QtItemIsTristate; + end; + end; end; constructor TQtListStrings.Create(AWinControl: TWinControl; @@ -589,11 +620,24 @@ begin end; procedure TQtListStrings.Assign(Source: TPersistent); +var + i: Integer; begin if Assigned(FWinControl) and (FWinControl.HandleAllocated) then begin FOwner.BeginUpdate; inherited Assign(Source); + if FOwner is TQtCheckListBox then + begin + for i := 0 to TQtCheckListBox(FOwner).ItemCount - 1 do + begin + FOwner.ItemFlags[i] := FOwner.ItemFlags[i] or QtItemIsUserCheckable; + if TQtCheckListBox(FOwner).AllowGrayed then + FOwner.ItemFlags[i] := FOwner.ItemFlags[i] or QtItemIsTristate + else + FOwner.ItemFlags[i] := FOwner.ItemFlags[i] and not QtItemIsTristate; + end; + end; FOwner.EndUpdate; end; end; diff --git a/lcl/interfaces/qt/qtwidgets.pas b/lcl/interfaces/qt/qtwidgets.pas index af24374591..b3a7ec66b3 100644 --- a/lcl/interfaces/qt/qtwidgets.pas +++ b/lcl/interfaces/qt/qtwidgets.pas @@ -1040,6 +1040,7 @@ type TQtAbstractItemView = class(TQtAbstractScrollArea) private + FAllowGrayed: boolean; FSavedEvent: QMouseEventH; FSavedEventTimer: QTimerH; FSavedEventTimerHook: QTimer_hookH; @@ -1062,6 +1063,8 @@ type procedure setIconSize(const AValue: TSize); procedure SetOwnerDrawn(const AValue: Boolean); protected + function GetItemFlags(AIndex: Integer): QtItemFlags; virtual; + procedure SetItemFlags(AIndex: Integer; AValue: QtItemFlags); virtual; procedure OwnerDataNeeded(ARect: TRect); virtual; procedure PostponedMouseRelease(AEvent: QEventH); virtual; procedure PostponedMouseReleaseTimerEvent(); cdecl; virtual; @@ -1092,9 +1095,11 @@ type procedure setSelectionMode(AMode: QAbstractItemViewSelectionMode); procedure setSelectionBehavior(ABehavior: QAbstractItemViewSelectionBehavior); procedure setWordWrap(const AValue: Boolean); virtual; + property AllowGrayed: boolean read FAllowGrayed write FAllowGrayed; property Checkable: boolean read FCheckable write FCheckable; property HideSelection: Boolean read FHideSelection write FHideSelection; property IconSize: TSize read getIconSize write setIconSize; + property ItemFlags[AIndex: Integer]: QtItemFlags read GetItemFlags write SetItemFlags; property OwnerDrawn: Boolean read GetOwnerDrawn write SetOwnerDrawn; property OwnerData: Boolean read FOwnerData write FOwnerData; property SyncingItems: Boolean read FSyncingItems write FSyncingItems; @@ -1133,21 +1138,29 @@ type TQtListWidget = class(TQtListView) private + FCheckBoxClicked: Boolean; FSavedSelection: TPtrIntArray; FCurrentItemChangedHook: QListWidget_hookH; FSelectionChangeHook: QListWidget_hookH; FItemClickedHook: QListWidget_hookH; FItemTextChangedHook: QListWidget_hookH; FDontPassSelChange: Boolean; + function GetItemChecked(AIndex: Integer): Boolean; function getItemCount: Integer; function GetItemEnabled(AIndex: Integer): Boolean; function GetSelected(AIndex: Integer): Boolean; + procedure SetItemChecked(AIndex: Integer; AValue: Boolean); procedure setItemCount(const AValue: Integer); procedure SetItemEnabled(AIndex: Integer; AValue: Boolean); procedure SetSelected(AIndex: Integer; AValue: Boolean); protected function CreateWidget(const AParams: TCreateParams):QWidgetH; override; procedure OwnerDataNeeded(ARect: TRect); override; + function GetItemFlags(AIndex: Integer): QtItemFlags; override; + procedure SetItemFlags(AIndex: Integer; AValue: QtItemFlags); override; + function GetItemLastCheckState(AItem: QListWidgetItemH): QtCheckState; + procedure SetItemLastCheckState(AItem: QListWidgetItemH); + procedure SetNextStateMap(AItem: QListWidgetItemH); virtual; public FList: TStrings; public @@ -1192,6 +1205,7 @@ type procedure ExchangeItems(const AIndex1, AIndex2: Integer); procedure MoveItem(const AFromIndex, AToIndex: Integer); property ItemCount: Integer read getItemCount write setItemCount; + property ItemChecked[AIndex: Integer]: Boolean read GetItemChecked write SetItemChecked; property Enabled[AIndex: Integer]: Boolean read GetItemEnabled write SetItemEnabled; property Selected[AIndex: Integer]: Boolean read GetSelected write SetSelected; end; @@ -1205,6 +1219,7 @@ type procedure SetItemCheckState(AIndex: Integer; AValue: QtCheckState); protected function CreateWidget(const AParams: TCreateParams):QWidgetH; override; + procedure SetNextStateMap(AItem: QListWidgetItemH); override; public procedure AttachEvents; override; procedure DetachEvents; override; @@ -1290,11 +1305,13 @@ type FSelectionChangedHook: QTreeWidget_hookH; function getColCount: Integer; function getHeader: TQtHeaderView; + function GetItemChecked(AIndex: Integer): Boolean; function getItemCount: Integer; function getMaxColSize(ACol: Integer): Integer; function getMinColSize(ACol: Integer): Integer; function getSortEnabled: Boolean; procedure setColCount(const AValue: Integer); + procedure SetItemChecked(AIndex: Integer; AValue: Boolean); procedure setItemCount(const AValue: Integer); procedure setMaxColSize(ACol: Integer; const AValue: Integer); procedure setMinColSize(ACol: Integer; const AValue: Integer); @@ -1359,6 +1376,7 @@ type {$ENDIF} property ColCount: Integer read getColCount write setColCount; property Header: TQtHeaderView read getHeader; + property ItemChecked[AIndex: Integer]: Boolean read GetItemChecked write SetItemChecked; property ItemCount: Integer read getItemCount write setItemCount; property MaxColSize[ACol: Integer]: Integer read getMaxColSize write setMaxColSize; property MinColSize[ACol: Integer]: Integer read getMinColSize write setMinColSize; @@ -1720,6 +1738,8 @@ const {taCenter } QtAlignHCenter ); + QtCheckStateRole = Ord(QtUserRole) + 1; + implementation uses @@ -9384,6 +9404,16 @@ begin Result := QListWidget_count(QListWidgetH(Widget)); end; +function TQtListWidget.GetItemChecked(AIndex: Integer): Boolean; +var + AItem: QListWidgetItemH; +begin + Result := False; + AItem := getItem(AIndex); + if Assigned(AItem) then + Result := QListWidgetItem_checkState(AItem) = QtChecked; +end; + function TQtListWidget.GetItemEnabled(AIndex: Integer): Boolean; var AItem: QListWidgetItemH; @@ -9404,6 +9434,21 @@ begin Result := getItemSelected(AItem); end; +procedure TQtListWidget.SetItemChecked(AIndex: Integer; AValue: Boolean); +var + AItem: QListWidgetItemH; +begin + AItem := getItem(AIndex); + if Assigned(AItem) then + begin + if AValue then + QListWidgetItem_setCheckState(AItem, QtChecked) + else + QListWidgetItem_setCheckState(AItem, QtUnChecked); + SetItemLastCheckState(AItem); + end; +end; + procedure TQtListWidget.setItemCount(const AValue: Integer); var i: Integer; @@ -9449,11 +9494,48 @@ begin setItemSelected(getItem(AIndex), AValue); end; +function TQtListWidget.GetItemLastCheckState(AItem: QListWidgetItemH + ): QtCheckState; +var + v: QVariantH; + ok: Boolean; +begin + Result := QtUnChecked; + if AItem = nil then + exit; + v := QVariant_create(); + QListWidgetItem_data(AItem, v, QtCheckStateRole); + ok := False; + if QVariant_isValid(v) then + Result := QtCheckState(QVariant_toInt(v, @Ok)); + QVariant_destroy(v); +end; + +procedure TQtListWidget.SetItemLastCheckState(AItem: QListWidgetItemH); +var + v: QVariantH; + AState: QtCheckState; +begin + if AItem = nil then + exit; + AState := QListWidgetItem_checkState(AItem); + v := QVariant_create(Ord(AState)); + QListWidgetItem_setData(AItem, QtCheckStateRole, v); + QVariant_destroy(v); +end; + +procedure TQtListWidget.SetNextStateMap(AItem: QListWidgetItemH); +begin + // does the job only for TQtCheckListBox +end; + function TQtListWidget.CreateWidget(const AParams: TCreateParams): QWidgetH; var Parent: QWidgetH; begin + FCheckBoxClicked := False; SetLength(FSavedSelection, 0); + AllowGrayed := False; FSavedEvent := nil; FSavedEventTimer := nil; FSavedEventTimerHook := nil; @@ -9549,6 +9631,26 @@ begin end; end; +function TQtListWidget.GetItemFlags(AIndex: Integer): QtItemFlags; +var + AItem: QListWidgetItemH; +begin + Result := inherited GetItemFlags(AIndex); + AItem := getItem(AIndex); + if Assigned(AItem) then + Result := QListWidgetItem_flags(AItem); +end; + +procedure TQtListWidget.SetItemFlags(AIndex: Integer; AValue: QtItemFlags); +var + AItem: QListWidgetItemH; +begin + inherited SetItemFlags(AIndex, AValue); + AItem := getItem(AIndex); + if Assigned(AItem) then + QListWidgetItem_setFlags(AItem, AValue); +end; + procedure TQtListWidget.AttachEvents; begin inherited AttachEvents; @@ -9705,8 +9807,11 @@ begin x := QStyle_pixelMetric(QApplication_style(), QStylePM_IndicatorWidth, nil, Widget); if ((MousePos.X > 2) and (MousePos.X < (X + 2))) then + begin + FCheckBoxClicked := True; + SetItemLastCheckState(Item); {signalItemClicked() fires !} - else + end else SendEventToParent; end else SendEventToParent; @@ -10282,6 +10387,7 @@ function TQtCheckListBox.CreateWidget(const AParams: TCreateParams): QWidgetH; var Parent: QWidgetH; begin + FCheckBoxClicked := False; FSavedEvent := nil; FSavedEventTimer := nil; FSavedEventTimerHook := nil; @@ -10299,6 +10405,22 @@ begin Result := QListWidget_create(Parent); end; +procedure TQtCheckListBox.SetNextStateMap(AItem: QListWidgetItemH); +var + ACurrState: QtCheckState; +begin + inherited SetNextStateMap(AItem); + if (AItem = nil) or not AllowGrayed then + exit; + ACurrState := GetItemLastCheckState(AItem); + + case ACurrState of + QtUnchecked: ItemCheckState[GetRow(AItem)] := QtPartiallyChecked; + QtPartiallyChecked: ItemCheckState[GetRow(AItem)] := QtChecked; + QtChecked: ItemCheckState[GetRow(AItem)] := QtUnChecked; + end; +end; + procedure TQtCheckListBox.AttachEvents; begin inherited AttachEvents; @@ -10362,6 +10484,14 @@ begin QApplication_keyboardModifiers()); SlotMouse(Widget, AMouseEvent); QMouseEvent_destroy(AMouseEvent); + {$note seem that we have qtbug with tristate listwidget items, so + we must handle statemap somehow} + //TODO try to fix nextstatemap + if FCheckBoxClicked then + begin + FCheckBoxClicked := False; + SetNextStateMap(item); + end; AMouseEvent := QMouseEvent_create(QEventMouseButtonRelease, @APos, @AGlobalPos, QtLeftButton, QtLeftButton, @@ -10409,6 +10539,7 @@ begin begin AItem := QListWidget_item(QListWidgetH(Widget), AIndex); QListWidgetItem_setCheckState(AItem, AValue); + SetItemLastCheckState(AItem); end; end; @@ -10670,6 +10801,7 @@ begin {$ifdef VerboseQt} WriteLn('TQtTreeWidget.Create'); {$endif} + AllowGrayed := False; FSelection := TFPList.Create; FSavedEvent := nil; FSavedEventTimer := nil; @@ -10885,6 +11017,16 @@ begin Result := FHeader; end; +function TQtTreeWidget.GetItemChecked(AIndex: Integer): Boolean; +var + AItem: QTreeWidgetItemH; +begin + Result := False; + AItem := topLevelItem(AIndex); + if AItem <> nil then + Result := QTreeWidgetItem_checkState(AItem, 0) = QtChecked; +end; + function TQtTreeWidget.getItemCount: Integer; begin Result := QTreeWidget_topLevelItemCount(QTreeWidgetH(Widget)); @@ -10917,6 +11059,20 @@ begin QTreeWidget_setColumnCount(QTreeWidgetH(Widget), AValue); end; +procedure TQtTreeWidget.SetItemChecked(AIndex: Integer; AValue: Boolean); +var + AItem: QTreeWidgetItemH; +begin + AItem := topLevelItem(AIndex); + if AItem <> nil then + begin + if AValue then + QTreeWidgetItem_setCheckState(AItem, 0, QtChecked) + else + QTreeWidgetItem_setCheckState(AItem, 0, QtUnChecked); + end; +end; + procedure TQtTreeWidget.setItemCount(const AValue: Integer); var i: Integer; @@ -13936,11 +14092,22 @@ begin QAbstractItemView_iconSize(QAbstractItemViewH(Widget), @Result); end; +function TQtAbstractItemView.GetItemFlags(AIndex: Integer): QtItemFlags; +begin + Result := QtNoItemFlags; +end; + procedure TQtAbstractItemView.setIconSize(const AValue: TSize); begin QAbstractItemView_setIconSize(QAbstractItemViewH(Widget), @AValue); end; +procedure TQtAbstractItemView.SetItemFlags(AIndex: Integer; AValue: QtItemFlags + ); +begin + // must be overrided ! +end; + procedure TQtAbstractItemView.SetOwnerDrawn(const AValue: Boolean); begin if AValue and (FNewDelegate = nil) then diff --git a/lcl/interfaces/qt/qtwschecklst.pp b/lcl/interfaces/qt/qtwschecklst.pp index 6e19e7adeb..52baf19543 100644 --- a/lcl/interfaces/qt/qtwschecklst.pp +++ b/lcl/interfaces/qt/qtwschecklst.pp @@ -96,6 +96,7 @@ begin SelMode := QAbstractItemViewSingleSelection; QtListWidget.setSelectionMode(SelMode); + QtListWidget.AllowGrayed := TCustomCheckListBox(AWinControl).AllowGrayed; QtListWidget.AttachEvents; @@ -127,6 +128,7 @@ begin if not WSCheckHandleAllocated(ACheckListBox, 'GetState') then Exit; QtListWidget := TQtCheckListBox(ACheckListBox.Handle); + QtListWidget.AllowGrayed := ACheckListBox.AllowGrayed; Result := QtCheckStateToLCLCheckStateMap[QtListWidget.ItemCheckState[AIndex]]; end; @@ -151,6 +153,7 @@ begin if not WSCheckHandleAllocated(ACheckListBox, 'SetState') then Exit; QtListWidget := TQtCheckListBox(ACheckListBox.Handle); + QtListWidget.AllowGrayed := ACheckListBox.AllowGrayed; QtListWidget.BeginUpdate; QtListWidget.ItemCheckState[AIndex] := LCLCheckStateToQtCheckStateMap[AState]; QtListWidget.EndUpdate; diff --git a/lcl/interfaces/qt/qtwscomctrls.pp b/lcl/interfaces/qt/qtwscomctrls.pp index 89554237e1..654f2b9a30 100644 --- a/lcl/interfaces/qt/qtwscomctrls.pp +++ b/lcl/interfaces/qt/qtwscomctrls.pp @@ -1310,9 +1310,7 @@ class procedure TQtWSCustomListView.ItemSetChecked(const ALV: TCustomListView; const AIndex: Integer; const AItem: TListItem; const AChecked: Boolean); var QtListWidget: TQtListWidget; - LWI: QListWidgetItemH; QtTreeWidget: TQtTreeWidget; - TWI: QTreeWidgetItemH; begin if not WSCheckHandleAllocated(ALV, 'ItemSetChecked') then Exit; @@ -1323,19 +1321,11 @@ begin if IsIconView(ALV) then begin QtListWidget := TQtListWidget(ALV.Handle); - LWI := QtListWidget.getItem(AIndex); - if AChecked then - QListWidgetItem_setCheckState(LWI, QtChecked) - else - QListWidgetItem_setCheckState(LWI, QtUnChecked); + QtListWidget.ItemChecked[AIndex] := AChecked; end else begin QtTreeWidget := TQtTreeWidget(ALV.Handle); - TWI := QtTreeWidget.topLevelItem(AIndex); - if AChecked then - QTreeWidgetItem_setCheckState(TWI, 0, QtChecked) - else - QTreeWidgetItem_setCheckState(TWI, 0, QtUnChecked); + QtTreeWidget.ItemChecked[AIndex] := AChecked; end; end;