mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-23 13:04:43 +02:00
Qt: menus rework, added actiongroups. fixes #15885
git-svn-id: trunk@23861 -
This commit is contained in:
parent
f8b2fa9e8f
commit
a266017f26
@ -37,6 +37,7 @@ uses
|
||||
|
||||
type
|
||||
// forward declarations
|
||||
TQActions = Array of QActionH;
|
||||
TQtImage = class;
|
||||
TQtFontMetrics = class;
|
||||
TRop2OrCompositionSupport = (rocNotSupported, rocSupported, rocUndefined);
|
||||
@ -76,6 +77,36 @@ type
|
||||
FSelected: Boolean;
|
||||
end;
|
||||
|
||||
{ TQtActionGroup }
|
||||
|
||||
TQtActionGroup = class(TObject)
|
||||
private
|
||||
FActions: TQActions;
|
||||
FGroupIndex: integer;
|
||||
FHandle: QActionGroupH;
|
||||
function getEnabled: boolean;
|
||||
function getExclusive: boolean;
|
||||
function getVisible: boolean;
|
||||
procedure setEnabled(const AValue: boolean);
|
||||
procedure setExclusive(const AValue: boolean);
|
||||
procedure setVisible(const AValue: boolean);
|
||||
public
|
||||
constructor Create(const AParent: QObjectH = nil);
|
||||
destructor Destroy; override;
|
||||
function addAction(action: QActionH): QActionH; overload;
|
||||
function addAction(text: WideString): QActionH; overload;
|
||||
function addAction(icon: QIconH; text: WideString): QActionH; overload;
|
||||
procedure removeAction(action: QActionH);
|
||||
function actions: TQActions;
|
||||
function checkedAction: QActionH;
|
||||
procedure setDisabled(ADisabled: Boolean);
|
||||
property Enabled: boolean read getEnabled write setEnabled;
|
||||
property Exclusive: boolean read getExclusive write setExclusive;
|
||||
property GroupIndex: integer read FGroupIndex write FGroupIndex;
|
||||
property Handle: QActionGroupH read FHandle;
|
||||
property Visible: boolean read getVisible write setVisible;
|
||||
end;
|
||||
|
||||
{ TQtAction }
|
||||
|
||||
TQtAction = class(TObject)
|
||||
@ -3954,6 +3985,102 @@ begin
|
||||
FCurrentTextColor := AColor^;
|
||||
end;
|
||||
|
||||
{ TQtActionGroup }
|
||||
|
||||
constructor TQtActionGroup.Create(const AParent: QObjectH);
|
||||
begin
|
||||
FGroupIndex := 0;
|
||||
Initialize(FActions);
|
||||
FHandle := QActionGroup_create(AParent);
|
||||
end;
|
||||
|
||||
destructor TQtActionGroup.Destroy;
|
||||
begin
|
||||
if FHandle <> nil then
|
||||
QActionGroup_destroy(FHandle);
|
||||
Finalize(FActions);
|
||||
FActions := nil;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TQtActionGroup.getEnabled: boolean;
|
||||
begin
|
||||
Result := QActionGroup_isEnabled(FHandle);
|
||||
end;
|
||||
|
||||
function TQtActionGroup.getExclusive: boolean;
|
||||
begin
|
||||
Result := QActionGroup_isExclusive(FHandle);
|
||||
end;
|
||||
|
||||
function TQtActionGroup.getVisible: boolean;
|
||||
begin
|
||||
Result := QActionGroup_isVisible(FHandle);
|
||||
end;
|
||||
|
||||
procedure TQtActionGroup.setEnabled(const AValue: boolean);
|
||||
begin
|
||||
QActionGroup_setEnabled(FHandle, AValue);
|
||||
end;
|
||||
|
||||
procedure TQtActionGroup.setExclusive(const AValue: boolean);
|
||||
begin
|
||||
QActionGroup_setExclusive(FHandle, AValue);
|
||||
end;
|
||||
|
||||
procedure TQtActionGroup.setVisible(const AValue: boolean);
|
||||
begin
|
||||
QActionGroup_setVisible(FHandle, AValue);
|
||||
end;
|
||||
|
||||
function TQtActionGroup.addAction(action: QActionH): QActionH;
|
||||
begin
|
||||
Result := QActionGroup_addAction(FHandle, action);
|
||||
end;
|
||||
|
||||
function TQtActionGroup.addAction(text: WideString): QActionH;
|
||||
var
|
||||
WStr: WideString;
|
||||
begin
|
||||
WStr := GetUTF8String(text);
|
||||
Result := QActionGroup_addAction(FHandle, @WStr);
|
||||
end;
|
||||
|
||||
function TQtActionGroup.addAction(icon: QIconH; text: WideString): QActionH;
|
||||
var
|
||||
WStr: WideString;
|
||||
begin
|
||||
WStr := GetUTF8String(text);
|
||||
Result := QActionGroup_addAction(FHandle, icon, @WStr);
|
||||
end;
|
||||
|
||||
procedure TQtActionGroup.removeAction(action: QActionH);
|
||||
begin
|
||||
QActionGroup_removeAction(FHandle, action);
|
||||
end;
|
||||
|
||||
function TQtActionGroup.actions: TQActions;
|
||||
var
|
||||
i: Integer;
|
||||
Arr: TPtrIntArray;
|
||||
begin
|
||||
QActionGroup_actions(FHandle, @Arr);
|
||||
SetLength(FActions, length(Arr));
|
||||
for i := 0 to High(Arr) do
|
||||
FActions[i] := QActionH(Arr[i]);
|
||||
Result := FActions;
|
||||
end;
|
||||
|
||||
function TQtActionGroup.checkedAction: QActionH;
|
||||
begin
|
||||
Result := QActionGroup_checkedAction(FHandle);
|
||||
end;
|
||||
|
||||
procedure TQtActionGroup.setDisabled(ADisabled: Boolean);
|
||||
begin
|
||||
QActionGroup_setDisabled(FHandle, ADisabled);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
@ -1105,6 +1105,7 @@ type
|
||||
|
||||
TQtMenu = class(TQtWidget)
|
||||
private
|
||||
FActions: TFPList;
|
||||
FIcon: QIconH;
|
||||
FTriggeredHook: QAction_hookH;
|
||||
FHoveredHook: QAction_hookH;
|
||||
@ -1112,6 +1113,7 @@ type
|
||||
FActionHandle: QActionH;
|
||||
FMenuItem: TMenuItem;
|
||||
FTrackButton: QtMouseButtons;
|
||||
procedure setActionGroups(AItem: TMenuItem);
|
||||
protected
|
||||
function CreateWidget(const APrams: TCreateParams): QWidgetH; override;
|
||||
procedure DoPopupClose;
|
||||
@ -1129,12 +1131,14 @@ type
|
||||
procedure SlotTriggered(checked: Boolean = False); cdecl;
|
||||
function EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl; override;
|
||||
public
|
||||
procedure PopUp(pos: PQtPoint; at: QActionH = nil);
|
||||
function actionHandle: QActionH;
|
||||
function addMenu(AMenu: QMenuH): QActionH;
|
||||
function insertMenu(AIndex: Integer; AMenu: QMenuH): QActionH;
|
||||
function getVisible: Boolean; override;
|
||||
function insertMenu(AIndex: Integer; AMenu: QMenuH; AItem: TMenuItem): QActionH;
|
||||
function getHasSubMenu: boolean;
|
||||
function getText: WideString; override;
|
||||
function getVisible: Boolean; override;
|
||||
procedure PopUp(pos: PQtPoint; at: QActionH = nil);
|
||||
procedure removeActionGroup;
|
||||
procedure setChecked(p1: Boolean);
|
||||
procedure setCheckable(p1: Boolean);
|
||||
procedure setHasSubmenu(AValue: Boolean);
|
||||
@ -8442,16 +8446,25 @@ begin
|
||||
QWidget_grabMouse(Widget);
|
||||
end;
|
||||
|
||||
|
||||
{ TQtMenu }
|
||||
|
||||
function TQtMenu.CreateWidget(const APrams: TCreateParams): QWidgetH;
|
||||
var
|
||||
AGroup: TQtActionGroup;
|
||||
begin
|
||||
FTrackButton := QtNoButton;
|
||||
FIcon := nil;
|
||||
Result := QMenu_create();
|
||||
FDeleteLater := True;
|
||||
FActionHandle := nil;;
|
||||
FActionHandle := nil;
|
||||
FActions := TFPList.Create;
|
||||
AGroup := TQtActionGroup.Create(Result);
|
||||
if FMenuItem <> nil then
|
||||
AGroup.GroupIndex := FMenuItem.GroupIndex
|
||||
else
|
||||
AGroup.GroupIndex := -1;
|
||||
AGroup.Exclusive := False;
|
||||
FActions.Add(AGroup);
|
||||
end;
|
||||
|
||||
procedure TQtMenu.InitializeWidget;
|
||||
@ -8472,9 +8485,20 @@ begin
|
||||
end;
|
||||
|
||||
destructor TQtMenu.Destroy;
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
if FIcon <> nil then
|
||||
QIcon_destroy(FIcon);
|
||||
|
||||
if Assigned(FActions) then
|
||||
begin
|
||||
for i := 0 to FActions.Count - 1 do
|
||||
TQtActionGroup(FActions.Items[i]).Free;
|
||||
|
||||
FActions.Free;
|
||||
end;
|
||||
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
@ -8550,6 +8574,10 @@ begin
|
||||
end;
|
||||
|
||||
function TQtMenu.actionHandle: QActionH;
|
||||
var
|
||||
i: Integer;
|
||||
Arr: TQActions;
|
||||
GotItem: boolean = False;
|
||||
begin
|
||||
if FActionHandle = nil then
|
||||
FActionHandle := QMenu_menuAction(QMenuH(Widget));
|
||||
@ -8562,18 +8590,73 @@ begin
|
||||
Result := QMenu_addMenu(QMenuH(Widget), AMenu);
|
||||
end;
|
||||
|
||||
function TQtMenu.insertMenu(AIndex: Integer; AMenu: QMenuH): QActionH;
|
||||
procedure TQtMenu.removeActionGroup;
|
||||
var
|
||||
Action: QActionGroupH;
|
||||
begin
|
||||
Action := QAction_actionGroup(ActionHandle);
|
||||
if Action <> nil then
|
||||
QActionGroup_removeAction(Action, ActionHandle);
|
||||
end;
|
||||
|
||||
procedure TQtMenu.setActionGroups(AItem: TMenuItem);
|
||||
var
|
||||
i: integer;
|
||||
b: Boolean = True;
|
||||
Group: TQtActionGroup;
|
||||
begin
|
||||
for i := 0 to FActions.Count - 1 do
|
||||
begin
|
||||
Group := TQtActionGroup(FActions.Items[i]);
|
||||
if Group.GroupIndex = AItem.GroupIndex then
|
||||
begin
|
||||
QAction_setEnabled(TQtMenu(AItem.Handle).actionHandle, True);
|
||||
QAction_setVisible(TQtMenu(AItem.Handle).actionHandle, True);
|
||||
Group.addAction(TQtMenu(AItem.Handle).actionHandle);
|
||||
Group.Exclusive := AItem.RadioItem;
|
||||
Group.Visible := True;
|
||||
Group.Enabled := True;
|
||||
b := False;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if b then
|
||||
begin
|
||||
Group := TQtActionGroup.Create(Widget);
|
||||
Group.Exclusive := AItem.RadioItem;
|
||||
Group.GroupIndex := AItem.GroupIndex;
|
||||
QAction_setEnabled(TQtMenu(AItem.Handle).actionHandle, True);
|
||||
QAction_setVisible(TQtMenu(AItem.Handle).actionHandle, True);
|
||||
Group.addAction(TQtMenu(AItem.Handle).actionHandle);
|
||||
Group.Visible := True;
|
||||
Group.Enabled := True;
|
||||
FActions.Add(Group);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TQtMenu.insertMenu(AIndex: Integer; AMenu: QMenuH; AItem: TMenuItem): QActionH;
|
||||
var
|
||||
actionBefore: QActionH;
|
||||
begin
|
||||
|
||||
setHasSubmenu(True);
|
||||
|
||||
if (AItem <> nil) and not AItem.IsLine then
|
||||
setActionGroups(AItem);
|
||||
|
||||
actionBefore := getActionByIndex(AIndex);
|
||||
|
||||
if actionBefore <> nil then
|
||||
Result := QMenu_insertMenu(QMenuH(Widget), actionBefore, AMenu)
|
||||
else
|
||||
Result := QMenu_addMenu(QMenuH(Widget), AMenu);
|
||||
end;
|
||||
|
||||
function TQtMenu.getHasSubMenu: boolean;
|
||||
begin
|
||||
Result := QAction_menu(ActionHandle) <> nil;
|
||||
end;
|
||||
|
||||
function TQtMenu.getVisible: Boolean;
|
||||
begin
|
||||
Result := QAction_isVisible(ActionHandle);
|
||||
@ -8597,13 +8680,15 @@ end;
|
||||
procedure TQtMenu.setChecked(p1: Boolean);
|
||||
begin
|
||||
setCheckable(p1);
|
||||
|
||||
QAction_setChecked(ActionHandle, p1);
|
||||
end;
|
||||
|
||||
procedure TQtMenu.setCheckable(p1: Boolean);
|
||||
begin
|
||||
QAction_setCheckable(ActionHandle, p1);
|
||||
if FMenuItem.RadioItem or FMenuItem.ShowAlwaysCheckable then
|
||||
QAction_setCheckable(ActionHandle, True)
|
||||
else
|
||||
QAction_setCheckable(ActionHandle, p1);
|
||||
end;
|
||||
|
||||
procedure TQtMenu.setHasSubmenu(AValue: Boolean);
|
||||
@ -8616,7 +8701,7 @@ end;
|
||||
|
||||
procedure TQtMenu.setIcon(AIcon: QIconH);
|
||||
begin
|
||||
QMenu_setIcon(QMenuH(Widget), AIcon)
|
||||
QMenu_setIcon(QMenuH(Widget), AIcon);
|
||||
end;
|
||||
|
||||
procedure TQtMenu.setImage(AImage: TQtImage);
|
||||
@ -8679,7 +8764,7 @@ var
|
||||
begin
|
||||
Result := False;
|
||||
QEvent_accept(Event);
|
||||
BeginEventProcessing;
|
||||
|
||||
case QEvent_type(Event) of
|
||||
LCLQt_PopupMenuTriggered:
|
||||
begin
|
||||
@ -8703,7 +8788,6 @@ begin
|
||||
end;
|
||||
|
||||
end;
|
||||
EndEventProcessing;
|
||||
end;
|
||||
|
||||
{ TQtMenuBar }
|
||||
@ -8746,10 +8830,10 @@ end;
|
||||
function TQtMenuBar.getGeometry: TRect;
|
||||
begin
|
||||
Result := inherited getGeometry;
|
||||
|
||||
// workaround since after attaching menu it takes 0 height
|
||||
if Result.Bottom = 0 then
|
||||
begin
|
||||
Result.Bottom := FHeight; // workaround since after attaching menu it takes 0 height
|
||||
end;
|
||||
Result.Bottom := FHeight;
|
||||
end;
|
||||
|
||||
{ TQtProgressBar }
|
||||
@ -9078,7 +9162,7 @@ begin
|
||||
end;
|
||||
ssVertical:
|
||||
begin
|
||||
QAbstractScrollArea_setVerticalScrollBarPolicy(QAbstractScrollAreaH(Widget), QtScrollBarAlwaysOn);
|
||||
QAbstractScrollArea_setVerticalScrollBarPolicy(QAbstractScrollAreaH(Widget), QtScrollBarAlwaysOn);
|
||||
end;
|
||||
ssBoth:
|
||||
begin
|
||||
@ -9401,9 +9485,12 @@ begin
|
||||
FViewPortWidget.setBackgroundRole(QPaletteNoRole);
|
||||
FViewPortWidget.setAutoFillBackground(False);
|
||||
FViewPortWidget.FOwner := Self;
|
||||
FViewPortWidget.AttachEvents; // some event will be redirected to scroll area
|
||||
|
||||
QLCLAbstractScrollArea_override_viewportEvent(QLCLAbstractScrollAreaH(Widget), @ViewPortEventFilter);
|
||||
// some events will be redirected to scroll area
|
||||
FViewPortWidget.AttachEvents;
|
||||
|
||||
QLCLAbstractScrollArea_override_viewportEvent(QLCLAbstractScrollAreaH(Widget),
|
||||
@ViewPortEventFilter);
|
||||
|
||||
setViewport(FViewPortWidget.Widget);
|
||||
end;
|
||||
@ -9910,6 +9997,7 @@ begin
|
||||
QEvent_accept(Event);
|
||||
if (LCLObject <> nil) then
|
||||
begin
|
||||
BeginEventProcessing;
|
||||
case QEvent_type(Event) of
|
||||
QEventMouseButtonPress,
|
||||
QEventMouseButtonRelease,
|
||||
@ -9922,6 +10010,7 @@ begin
|
||||
QEvent_ignore(Event);
|
||||
end;
|
||||
end;
|
||||
EndEventProcessing;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -10111,7 +10200,8 @@ begin
|
||||
QFileDialog_setNameFilter(QFileDialogH(Widget), @AFilter);
|
||||
end;
|
||||
|
||||
procedure TQtFileDialog.setLabelText(const ALabel: QFileDialogDialogLabel; const AText: WideString);
|
||||
procedure TQtFileDialog.setLabelText(const ALabel: QFileDialogDialogLabel;
|
||||
const AText: WideString);
|
||||
begin
|
||||
QFileDialog_setLabelText(QFileDialogH(Widget), ALabel, @AText);
|
||||
end;
|
||||
|
@ -103,7 +103,7 @@ begin
|
||||
else
|
||||
if Widget is TQtMenu then
|
||||
TQtMenu(Widget).insertMenu(AMenuItem.Parent.VisibleIndexOf(AMenuItem),
|
||||
QMenuH(TQtMenu(AMenuItem.Handle).Widget));
|
||||
QMenuH(TQtMenu(AMenuItem.Handle).Widget), AMenuItem);
|
||||
end;
|
||||
|
||||
class function TQtWSMenuItem.CreateMenuFromMenuItem(const AMenuItem: TMenuItem): TQtMenu;
|
||||
@ -116,6 +116,7 @@ begin
|
||||
begin
|
||||
Result.setText(GetUtf8String(AMenuItem.Caption));
|
||||
Result.setEnabled(AMenuItem.Enabled);
|
||||
Result.setCheckable(AMenuItem.RadioItem or AMenuItem.ShowAlwaysCheckable);
|
||||
Result.setChecked(AMenuItem.Checked);
|
||||
Result.setShortcut(AMenuItem.ShortCut);
|
||||
if AMenuItem.HasIcon then
|
||||
@ -311,7 +312,15 @@ begin
|
||||
if not WSCheckMenuItem(AMenuItem, 'SetRadioItem') then
|
||||
Exit;
|
||||
|
||||
TQtMenu(AMenuItem.Handle).setCheckable(RadioItem);
|
||||
{$ifdef VerboseQt}
|
||||
WriteLn('[TQtWSMenuItem.SetRadioItem] AMenuItem: ' + AMenuItem.Name +
|
||||
' Radio ? ',RadioItem);
|
||||
{$endif}
|
||||
|
||||
if not RadioItem then
|
||||
TQtMenu(AMenuItem.Handle).removeActionGroup;
|
||||
|
||||
TQtMenu(AMenuItem.Handle).setCheckable(RadioItem or AMenuItem.ShowAlwaysCheckable);
|
||||
SetCheck(AMenuItem, AMenuItem.Checked);
|
||||
|
||||
Result := True;
|
||||
@ -369,7 +378,6 @@ begin
|
||||
else if (AMenu is TPopUpMenu) then
|
||||
begin
|
||||
Menu := TQtMenu.Create(AMenu.Items);
|
||||
//Menu.setParent(Parent);
|
||||
Menu.AttachEvents;
|
||||
|
||||
Result := HMENU(Menu);
|
||||
|
Loading…
Reference in New Issue
Block a user