Qt: menu rework (also fixed issue with destroying menu items - they had not destroyed their handles)

git-svn-id: trunk@12153 -
This commit is contained in:
paul 2007-09-24 06:03:19 +00:00
parent 3bffb8c4b4
commit 763779959f
6 changed files with 140 additions and 141 deletions

View File

@ -86,6 +86,7 @@ type
procedure AppRestore; override; procedure AppRestore; override;
procedure AppBringToFront; override; procedure AppBringToFront; override;
procedure AppSetTitle(const ATitle: string); override; procedure AppSetTitle(const ATitle: string); override;
procedure AttachMenuToWindow(AMenuObject: TComponent); override;
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;

View File

@ -193,11 +193,31 @@ begin
// TODO // TODO
end; end;
procedure TQtWidgetSet.AttachMenuToWindow(AMenuObject: TComponent);
var
AWidget, AMenuWidget: TQtWidget;
QtMainWindow: TQtMainWindow absolute AWidget;
QtMenuBar: TQtMenuBar absolute AMenuWidget;
R, R1: TRect;
begin
AMenuWidget := TQtWidget((AMenuObject as TMenu).Handle);
if AMenuWidget is TQtMenuBar then
begin
AWidget := TQtWidget(TWinControl(AMenuObject.Owner).Handle);
if AWidget is TQtMainWindow then
begin
R := AWidget.LCLObject.ClientRect;
R1 := QtMainWindow.MenuBar.getGeometry;
R1.Right := R.Right;
QtMenuBar.setGeometry(R1);
QtMainWindow.setMenuBar(QMenuBarH(QtMenuBar.Widget));
end;
end;
end;
function TQtWidgetSet.CreateThemeServices: TThemeServices; function TQtWidgetSet.CreateThemeServices: TThemeServices;
begin begin
// TODO: uncomment if you want to test TQtThemeServices
Result := TQtThemeServices.Create; Result := TQtThemeServices.Create;
//Result := inherited CreateThemeServices;
end; end;
function TQtWidgetSet.EventFilter(Sender: QObjectH; Event: QEventH): Boolean; function TQtWidgetSet.EventFilter(Sender: QObjectH; Event: QEventH): Boolean;

View File

@ -806,11 +806,11 @@ type
private private
FIcon: QIconH; FIcon: QIconH;
FActionHook: QAction_hookH; FActionHook: QAction_hookH;
FMenuItem: TMenuItem;
protected
function CreateWidget(const APrams: TCreateParams): QWidgetH; override;
public public
MenuItem: TMenuItem; constructor Create(const AMenuItem: TMenuItem); overload;
public
constructor Create(const AParent: QWidgetH); overload;
constructor Create(const AHandle: QMenuH); overload;
destructor Destroy; override; destructor Destroy; override;
public public
procedure AttachEvents; override; procedure AttachEvents; override;
@ -822,8 +822,7 @@ type
public public
procedure PopUp(pos: PQtPoint; at: QActionH = nil); procedure PopUp(pos: PQtPoint; at: QActionH = nil);
function actionHandle: QActionH; function actionHandle: QActionH;
function addMenu(title: PWideString): TQtMenu; function addMenu(AMenu: QMenuH): QActionH;
function addSeparator: TQtMenu;
function getVisible: Boolean; override; function getVisible: Boolean; override;
function getText: WideString; override; function getText: WideString; override;
procedure setChecked(p1: Boolean); procedure setChecked(p1: Boolean);
@ -846,8 +845,7 @@ type
public public
constructor Create(const AParent: QWidgetH); overload; constructor Create(const AParent: QWidgetH); overload;
public public
function addMenu(title: PWideString): TQtMenu; function addMenu(AMenu: QMenuH): QActionH;
function addSeparator: TQtMenu;
function getGeometry: TRect; override; function getGeometry: TRect; override;
end; end;
@ -1079,10 +1077,13 @@ begin
SetGeometry; SetGeometry;
// set focus policy // set focus policy
if LCLObject.TabStop then if LCLObject <> nil then
setFocusPolicy(QtClickFocus) begin
else if LCLObject.TabStop then
setFocusPolicy(QtNoFocus); setFocusPolicy(QtClickFocus)
else
setFocusPolicy(QtNoFocus);
end;
// Set mouse move messages policy // Set mouse move messages policy
QWidget_setMouseTracking(Widget, True); QWidget_setMouseTracking(Widget, True);
@ -2792,7 +2793,8 @@ end;
procedure TQtWidget.SetGeometry; procedure TQtWidget.SetGeometry;
begin begin
setGeometry(LCLObject.BoundsRect); if LCLObject <> nil then
setGeometry(LCLObject.BoundsRect);
end; end;
{ TQtAbstractButton } { TQtAbstractButton }
@ -5848,18 +5850,18 @@ end;
{ TQtMenu } { TQtMenu }
constructor TQtMenu.Create(const AParent: QWidgetH); function TQtMenu.CreateWidget(const APrams: TCreateParams): QWidgetH;
begin begin
Create;
Widget := QMenu_Create(AParent);
FIcon := nil; FIcon := nil;
Result := QMenu_create();
end; end;
constructor TQtMenu.Create(const AHandle: QMenuH); constructor TQtMenu.Create(const AMenuItem: TMenuItem);
var
AParams: TCreateParams;
begin begin
Create; FMenuItem := AMenuItem;
Widget := AHandle; inherited Create(nil, AParams);
FIcon := nil;
end; end;
destructor TQtMenu.Destroy; destructor TQtMenu.Destroy;
@ -5908,15 +5910,10 @@ begin
Result := QMenu_menuAction(QMenuH(Widget)); Result := QMenu_menuAction(QMenuH(Widget));
end; end;
function TQtMenu.addMenu(title: PWideString): TQtMenu; function TQtMenu.addMenu(AMenu: QMenuH): QActionH;
begin begin
Result := TQtMenu.Create(QMenu_addMenu(QMenuH(Widget), title)); setHasSubmenu(True);
end; Result := QMenu_addMenu(QMenuH(Widget), AMenu);
function TQtMenu.addSeparator: TQtMenu;
begin
Result := TQtMenu.Create(QMenu_addMenu(QMenuH(Widget), PWideString(nil)));
Result.setSeparator(True);
end; end;
function TQtMenu.getVisible: Boolean; function TQtMenu.getVisible: Boolean;
@ -6013,8 +6010,8 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
procedure TQtMenu.SlotTriggered(checked: Boolean); cdecl; procedure TQtMenu.SlotTriggered(checked: Boolean); cdecl;
begin begin
if Assigned(MenuItem) and Assigned(MenuItem.OnClick) then if Assigned(FMenuItem) and Assigned(FMenuItem.OnClick) then
MenuItem.OnClick(Self.MenuItem); FMenuItem.OnClick(FMenuItem);
end; end;
function TQtMenu.EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl; function TQtMenu.EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl;
@ -6039,26 +6036,14 @@ begin
setVisible(FVisible); setVisible(FVisible);
end; end;
function TQtMenuBar.addMenu(title: PWideString): TQtMenu; function TQtMenuBar.addMenu(AMenu: QMenuH): QActionH;
begin begin
if not FVisible then if not FVisible then
begin begin
FVisible := True; FVisible := True;
setVisible(FVisible); setVisible(FVisible);
end; end;
Result := QMenuBar_addMenu(QMenuBarH(Widget), AMenu);
Result := TQtMenu.Create(QMenuBar_addMenu(QMenuBarH(Widget), title));
end;
function TQtMenuBar.addSeparator: TQtMenu;
begin
if not FVisible then
begin
FVisible := True;
setVisible(FVisible);
end;
Result := TQtMenu.Create(QMenuBar_addMenu(QMenuBarH(Widget), PWideString(nil)));
Result.setSeparator(True);
end; end;
function TQtMenuBar.getGeometry: TRect; function TQtMenuBar.getGeometry: TRect;

View File

@ -191,12 +191,6 @@ begin
QMdiArea_addSubWindow(TQtMainWindow(Application.MainForm.Handle).MDIAreaHandle, QtMainWindow.Widget, QtWindow); QMdiArea_addSubWindow(TQtMainWindow(Application.MainForm.Handle).MDIAreaHandle, QtMainWindow.Widget, QtWindow);
{$endif} {$endif}
R := AWinControl.ClientRect;
R1 := QtMainWindow.MenuBar.getGeometry;
R1.Right := R.Right;
QtMainWindow.MenuBar.setGeometry(R1);
QtMainWindow.setMenuBar(QMenuBarH(QtMainWindow.MenuBar.Widget));
// Return the handle // Return the handle
Result := THandle(QtMainWindow); Result := THandle(QtMainWindow);
end; end;

View File

@ -46,9 +46,10 @@ type
TQtWSMenuItem = class(TWSMenuItem) TQtWSMenuItem = class(TWSMenuItem)
private private
protected protected
class function CreateMenuFromMenuItem(const AMenuItem: TMenuItem): TQtMenu;
public public
class procedure AttachMenu(const AMenuItem: TMenuItem); override; class procedure AttachMenu(const AMenuItem: TMenuItem); override;
class function CreateHandle(const AMenuItem: TMenuItem): HMENU; override; class function CreateHandle(const AMenuItem: TMenuItem): HMENU; override;
class procedure DestroyHandle(const AMenuItem: TMenuItem); override; class procedure DestroyHandle(const AMenuItem: TMenuItem); override;
class procedure SetCaption(const AMenuItem: TMenuItem; const ACaption: string); override; class procedure SetCaption(const AMenuItem: TMenuItem; const ACaption: string); override;
class procedure SetShortCut(const AMenuItem: TMenuItem; const OldShortCut, NewShortCut: TShortCut); override; class procedure SetShortCut(const AMenuItem: TMenuItem; const OldShortCut, NewShortCut: TShortCut); override;
@ -97,10 +98,35 @@ implementation
Returns: Nothing Returns: Nothing
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
class procedure TQtWSMenuItem.AttachMenu(const AMenuItem: TMenuItem); class procedure TQtWSMenuItem.AttachMenu(const AMenuItem: TMenuItem);
var
Widget: TQtWidget;
begin begin
// set proper position if not WSCheckMenuItem(AMenuItem, 'AttachMenu') or (AMenuItem.Parent = nil) then
Exit;
Widget := TQtWidget(AMenuItem.Parent.Handle);
if Widget is TQtMenuBar then
TQtMenuBar(Widget).addMenu(QMenuH(TQtMenu(AMenuItem.Handle).Widget))
else
if Widget is TQtMenu then
TQtMenu(Widget).addMenu(QMenuH(TQtMenu(AMenuItem.Handle).Widget));
end; end;
class function TQtWSMenuItem.CreateMenuFromMenuItem(const AMenuItem: TMenuItem): TQtMenu;
begin
Result := TQtMenu.Create(AMenuItem);
Result.setSeparator(AMenuItem.IsLine);
Result.setHasSubmenu(AMenuItem.Count > 0);
if not AMenuItem.IsLine then
begin
Result.setText(GetUtf8String(AMenuItem.Caption));
Result.setEnabled(AMenuItem.Enabled);
Result.setChecked(AMenuItem.Checked);
Result.setShortcut(AMenuItem.ShortCut);
if AMenuItem.HasIcon then
Result.setImage(TQtImage(AMenuItem.Bitmap.Handle));
end;
end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
Function: TQtWSMenuItem.CreateHandle Function: TQtWSMenuItem.CreateHandle
Params: None Params: None
@ -110,9 +136,7 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
class function TQtWSMenuItem.CreateHandle(const AMenuItem: TMenuItem): HMENU; class function TQtWSMenuItem.CreateHandle(const AMenuItem: TMenuItem): HMENU;
var var
ParentMenu, Menu: TQtMenu; Menu: TQtMenu;
MenuBar: TQtMenuBar;
Text: WideString;
begin begin
{$ifdef VerboseQt} {$ifdef VerboseQt}
WriteLn('trace:> [TQtWSMenuItem.CreateHandle] Caption: ', AMenuItem.Caption, WriteLn('trace:> [TQtWSMenuItem.CreateHandle] Caption: ', AMenuItem.Caption,
@ -142,86 +166,19 @@ begin
because TMainMenu uses the special Handle QMenuBar while TPopUpMenu can be because TMainMenu uses the special Handle QMenuBar while TPopUpMenu can be
treat like if this menu item was a subitem of another item treat like if this menu item was a subitem of another item
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
else if ((not AMenuItem.Parent.HasParent) and (AMenuItem.GetParentMenu is TMainMenu)) then else
if ((not AMenuItem.Parent.HasParent) and (AMenuItem.GetParentMenu is TMainMenu)) then
begin begin
MenuBar := TQtMenuBar(AMenuItem.GetParentMenu.Handle); Menu := CreateMenuFromMenuItem(AMenuItem);
Result := HMENU(Menu);
{$ifdef VerboseQt}
Write(' Parent: ', dbghex(PtrInt(MenuBar)), ' The Parent is a TMainMenu');
{$endif}
{ IsLine indicates that the menu item is a separator }
if AMenuItem.IsLine then
begin
Menu := MenuBar.addSeparator;
Menu.setHasSubmenu(False);
Result := HMENU(Menu);
end
else
begin
Text := GetUtf8String(AMenuItem.Caption);
Menu := MenuBar.addMenu(@Text);
Menu.MenuItem := AMenuItem;
Menu.setShortcut(AMenuItem.ShortCut);
if AMenuItem.HasIcon then
Menu.setImage(TQtImage(AMenuItem.Bitmap.Handle));
Menu.setHasSubmenu(AMenuItem.Count > 0);
Result := HMENU(Menu);
end;
end end
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
If the parent has a parent, then that item´s Handle is necessarely a TQtMenu If the parent has a parent, then that item´s Handle is necessarely a TQtMenu
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
else else
begin begin
ParentMenu := TQtMenu(AMenuItem.Parent.Handle); Menu := CreateMenuFromMenuItem(AMenuItem);
Result := HMENU(Menu);
ParentMenu.setHasSubmenu(True);
{$ifdef VerboseQt}
Write(' Parent: ', dbghex(PtrInt(ParentMenu)),
' The Parent is a TPopUpMenu or a TMenuItem');
{$endif}
{ IsLine indicates that the menu item is a separator }
if AMenuItem.IsLine then
begin
Menu := ParentMenu.addSeparator;
Menu.setHasSubmenu(False);
Result := HMENU(Menu);
end
{ Count indicates the number of subitems this item has }
else
begin
Text := GetUtf8String(AMenuItem.Caption);
Menu := ParentMenu.addMenu(@Text);
Menu.MenuItem := AMenuItem;
Menu.setEnabled(AMenuItem.Enabled);
Menu.setChecked(AMenuItem.Checked);
Menu.setShortcut(AMenuItem.ShortCut);
if AMenuItem.HasIcon then
Menu.setImage(TQtImage(AMenuItem.Bitmap.Handle));
Menu.setHasSubmenu(AMenuItem.Count > 0);
Result := HMENU(Menu);
end;
end; end;
if Menu <> nil then if Menu <> nil then
@ -261,6 +218,13 @@ class procedure TQtWSMenuItem.SetCaption(const AMenuItem: TMenuItem; const ACapt
var var
Widget: TQtWidget; Widget: TQtWidget;
begin begin
{$ifdef VerboseQt}
WriteLn('[TQtWSMenuItem.SetCaption] Caption: ' + AMenuItem.Caption + ' NewCaption: ', ACaption);
{$endif}
if not WSCheckMenuItem(AMenuItem, 'SetEnable') then
Exit;
Widget := TQtWidget(AMenuItem.Handle); Widget := TQtWidget(AMenuItem.Handle);
if Widget is TQtMenu then if Widget is TQtMenu then
TQtMenu(Widget).setText(GetUtf8String(ACaption)); TQtMenu(Widget).setText(GetUtf8String(ACaption));
@ -275,6 +239,13 @@ class procedure TQtWSMenuItem.SetShortCut(const AMenuItem: TMenuItem; const OldS
var var
Widget: TQtWidget; Widget: TQtWidget;
begin begin
{$ifdef VerboseQt}
WriteLn('[TQtWSMenuItem.SetCaption] SetShortCut: ' + AMenuItem.Caption);
{$endif}
if not WSCheckMenuItem(AMenuItem, 'SetEnable') then
Exit;
Widget := TQtWidget(AMenuItem.Handle); Widget := TQtWidget(AMenuItem.Handle);
if Widget is TQtMenu then if Widget is TQtMenu then
TQtMenu(Widget).setShortcut(NewShortCut); TQtMenu(Widget).setShortcut(NewShortCut);
@ -287,7 +258,12 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
class procedure TQtWSMenuItem.SetVisible(const AMenuItem: TMenuItem; const Visible: boolean); class procedure TQtWSMenuItem.SetVisible(const AMenuItem: TMenuItem; const Visible: boolean);
begin begin
{ Here the menu item has a QMenuH handle } {$ifdef VerboseQt}
WriteLn('[TQtWSMenuItem.SetVisible] SetShortCut: ' + AMenuItem.Caption + ' Visible: ', Visible);
{$endif}
if not WSCheckMenuItem(AMenuItem, 'SetEnable') then
Exit;
TQtMenu(AMenuItem.Handle).setVisible(Visible); TQtMenu(AMenuItem.Handle).setVisible(Visible);
end; end;
@ -298,7 +274,13 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
class function TQtWSMenuItem.SetCheck(const AMenuItem: TMenuItem; const Checked: boolean): boolean; class function TQtWSMenuItem.SetCheck(const AMenuItem: TMenuItem; const Checked: boolean): boolean;
begin begin
Result := False;
if not WSCheckMenuItem(AMenuItem, 'SetEnable') then
Exit;
TQtMenu(AMenuItem.Handle).setChecked(Checked); TQtMenu(AMenuItem.Handle).setChecked(Checked);
Result := True; Result := True;
end; end;
@ -309,7 +291,13 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
class function TQtWSMenuItem.SetEnable(const AMenuItem: TMenuItem; const Enabled: boolean): boolean; class function TQtWSMenuItem.SetEnable(const AMenuItem: TMenuItem; const Enabled: boolean): boolean;
begin begin
Result := False;
if not WSCheckMenuItem(AMenuItem, 'SetEnable') then
Exit;
TQtMenu(AMenuItem.Handle).setEnabled(Enabled); TQtMenu(AMenuItem.Handle).setEnabled(Enabled);
Result := True; Result := True;
end; end;
@ -320,7 +308,7 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
class function TQtWSMenuItem.SetRadioItem(const AMenuItem: TMenuItem; const RadioItem: boolean): boolean; class function TQtWSMenuItem.SetRadioItem(const AMenuItem: TMenuItem; const RadioItem: boolean): boolean;
begin begin
Result := True; Result := SetCheck(AMenuItem, AMenuItem.Checked);
end; end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
@ -330,6 +318,8 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
class function TQtWSMenuItem.SetRightJustify(const AMenuItem: TMenuItem; const Justified: boolean): boolean; class function TQtWSMenuItem.SetRightJustify(const AMenuItem: TMenuItem; const Justified: boolean): boolean;
begin begin
if not WSCheckMenuItem(AMenuItem, 'SetEnable') then
Exit;
Result := True; Result := True;
end; end;
@ -359,7 +349,6 @@ class function TQtWSMenu.CreateHandle(const AMenu: TMenu): HMENU;
var var
MenuBar: TQtMenuBar; MenuBar: TQtMenuBar;
Menu: TQtMenu; Menu: TQtMenu;
Parent: QWidgetH;
begin begin
{ If the menu is a main menu, there is no need to create a handle for it. { If the menu is a main menu, there is no need to create a handle for it.
It´s already created on the window } It´s already created on the window }
@ -371,13 +360,8 @@ begin
end end
else if (AMenu is TPopUpMenu) then else if (AMenu is TPopUpMenu) then
begin begin
if (AMenu.Owner <> nil) and (AMenu.Owner is TWinControl) then Menu := TQtMenu.Create(AMenu.Items);
Parent := TQtWidget(TWinControl(AMenu.Owner).Handle).Widget //Menu.setParent(Parent);
else
Parent := nil;
Menu := TQtMenu.Create(Parent);
Menu.MenuItem := AMenu.Items;
Menu.AttachEvents; Menu.AttachEvents;
Result := HMENU(Menu); Result := HMENU(Menu);

View File

@ -46,7 +46,7 @@ uses
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
Menus, Graphics, Menus, Graphics,
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
WSLCLClasses, LCLType; WSLCLClasses, LCLType, LCLProc;
type type
{ TWSMenuItem } { TWSMenuItem }
@ -86,6 +86,8 @@ type
end; end;
TWSPopupMenuClass = class of TWSPopupMenu; TWSPopupMenuClass = class of TWSPopupMenu;
function WSCheckMenuItem(const AMenuItem: TMenuItem;
const AProcName: String): Boolean;
implementation implementation
@ -164,6 +166,19 @@ class procedure TWSPopupMenu.Popup(const APopupMenu: TPopupMenu; const X, Y: int
begin begin
end; end;
function WSCheckMenuItem(const AMenuItem: TMenuItem;
const AProcName: String): Boolean;
procedure Warn;
begin
DebugLn('[WARNING] %s called without handle for %s(%s)', [AProcName, AMenuItem.Name, AMenuItem.ClassName]);
end;
begin
Result := AMenuItem.HandleAllocated;
if Result then Exit;
Warn;
end;
initialization initialization
//////////////////////////////////////////////////// ////////////////////////////////////////////////////