Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions lazpaint/lazpaintmainform.pas
Original file line number Diff line number Diff line change
Expand Up @@ -905,9 +905,9 @@ TFMain = class(TForm)

implementation

uses LCLIntf, BGRAUTF8, ugraph, math, umac, uclipboard, ucursors,
ufilters, ULoadImage, ULoading, UFileExtensions, UBrushType,
ugeometricbrush, UPreviewDialog, UQuestion, BGRALayerOriginal,
uses LCLIntf, InterfaceBase, LCLPlatformDef, BGRAUTF8, ugraph, math, umac,
uclipboard, ucursors, ufilters, ULoadImage, ULoading, UFileExtensions,
UBrushType, ugeometricbrush, UPreviewDialog, UQuestion, BGRALayerOriginal,
BGRATransform, LCVectorPolyShapes, URaw, UFileSystem,
UTranslation, UPython, BCTypes;

Expand Down Expand Up @@ -1177,7 +1177,7 @@ procedure TFMain.FormShow(Sender: TObject);
m: TMainFormMenu;
startFillControlWidth: LongInt;
iconSize: Integer;
toolbarDPI, w, h: integer;
toolbarDPI, w, h, i: integer;
begin
if FLayout.Menu = nil then
begin
Expand Down Expand Up @@ -1218,6 +1218,30 @@ procedure TFMain.FormShow(Sender: TObject);
m.Apply;
FLayout.Menu := m;

// Force Qt5/Qt6 to rebuild main menu by detaching and reattaching
// This works around menu items randomly not displaying on Qt widgetsets
// Qt6 has race conditions during early widget initialization that can
// cause menu items to not appear. Multiple ProcessMessages calls and
// explicit visibility toggling helps ensure the menu bar is fully built.
if WidgetSet.LCLPlatform in [lpQt5, lpQt6] then
begin
// First pass: detach menu and process
Self.Menu := nil;
Application.ProcessMessages;
Application.ProcessMessages;
// Second pass: reattach and force visibility on all top-level menus
Self.Menu := MainMenu1;
for i := 0 to MainMenu1.Items.Count - 1 do
begin
MainMenu1.Items[i].Visible := False;
MainMenu1.Items[i].Visible := True;
end;
Application.ProcessMessages;
// Force the form to update its menu bar
MainMenu1.HandleNeeded;
Application.ProcessMessages;
end;

SVGImageList1.Width := iconSize;
SVGImageList1.Height := iconSize;
SVGImageList1.PopulateImageList(SVGRasterImageList1, [iconSize]);
Expand Down
4 changes: 3 additions & 1 deletion lazpaint/uimageview.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
unit UImageView;

{$mode objfpc}{$H+}
{$IF defined(LINUX) and not defined(LCLqt5)}{$DEFINE IMAGEVIEW_DIRECTUPDATE}{$ENDIF}
{$IF defined(LINUX) and not defined(LCLqt5) and not defined(LCLqt6)}{$DEFINE IMAGEVIEW_DIRECTUPDATE}{$ENDIF}
{$DEFINE DRAW_TOOL_OUTSIDE_IMAGE}
// Qt5 needs neither DIRECTUPDATE nor QUICKUPDATE
// Qt6 needs QUICKUPDATE (forces repaint) but not DIRECTUPDATE (bypasses Qt paint system)
{$IF not defined(DARWIN) and not defined(LCLqt5)}{$DEFINE IMAGEVIEW_QUICKUPDATE}{$ENDIF}

interface
Expand Down
40 changes: 31 additions & 9 deletions lazpaint/umenu.pas
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,25 @@ procedure TMainFormMenu.IconSizeItemClick(Sender: TObject);
FInstance.ChangeIconSize(item.Tag);
end;

// Helper function to find action by name using direct iteration
// This works around Qt6 ActionByName issues during early initialization
function FindActionByNameDirect(AActionList: TActionList; const AName: string): TBasicAction;
var
k: Integer;
actName: string;
begin
Result := nil;
for k := 0 to AActionList.ActionCount - 1 do
begin
actName := AActionList.Actions[k].Name;
if SameText(actName, AName) then
begin
Result := AActionList.Actions[k];
Exit;
end;
end;
end;

procedure TMainFormMenu.AddMenus(AMenu: TMenuItem; AActionList: TActionList;
AActionsCommaText: string; AIndex: integer);
var actions: TStringList;
Expand Down Expand Up @@ -158,7 +177,7 @@ procedure TMainFormMenu.AddMenus(AMenu: TMenuItem; AActionList: TActionList;
item.Caption := cLineCaption
else
begin
foundAction := AActionList.ActionByName(actions[i]);
foundAction := FindActionByNameDirect(AActionList, actions[i]);
if foundAction <> nil then
item.Action := foundAction
else
Expand Down Expand Up @@ -202,13 +221,13 @@ procedure TMainFormMenu.AddMenus(AMenu: TMenuItem; AActionList: TActionList;
if Assigned(item) and (actions[i] = 'EditShapeAlign') then
begin
item.Caption := rsAlignShape;
AddSubItem(AActionList.ActionByName('EditShapeAlignLeft'));
AddSubItem(AActionList.ActionByName('EditShapeCenterHorizontally'));
AddSubItem(AActionList.ActionByName('EditShapeAlignRight'));
AddSubItem(FindActionByNameDirect(AActionList, 'EditShapeAlignLeft'));
AddSubItem(FindActionByNameDirect(AActionList, 'EditShapeCenterHorizontally'));
AddSubItem(FindActionByNameDirect(AActionList, 'EditShapeAlignRight'));
AddSubItem('-',nil,0);
AddSubItem(AActionList.ActionByName('EditShapeAlignTop'));
AddSubItem(AActionList.ActionByName('EditShapeCenterVertically'));
AddSubItem(AActionList.ActionByName('EditShapeAlignBottom'));
AddSubItem(FindActionByNameDirect(AActionList, 'EditShapeAlignTop'));
AddSubItem(FindActionByNameDirect(AActionList, 'EditShapeCenterVertically'));
AddSubItem(FindActionByNameDirect(AActionList, 'EditShapeAlignBottom'));
AMenu.Add(item);
item := nil;
end;
Expand Down Expand Up @@ -332,7 +351,7 @@ procedure TMainFormMenu.ActionShortcut(AName: string; AShortcut: TUTF8Char);
var foundAction: TBasicAction;
ShortcutStr: string;
begin
foundAction := FActionList.ActionByName(AName);
foundAction := FindActionByNameDirect(FActionList, AName);
if foundAction <> nil then
begin
ShortcutStr := AShortcut;
Expand Down Expand Up @@ -489,7 +508,10 @@ procedure TMainFormMenu.Apply;
AddMenus('MenuHelp', 'HelpIndex,-,HelpAbout');
for i := 0 to high(FMainMenus) do
if not FMainMenus[i].used then
FMainMenus[i].menu.Visible := false;
FMainMenus[i].menu.Visible := false
else
// Qt6: Force menu visibility to ensure it's displayed
FMainMenus[i].menu.Visible := true;

ApplyShortcuts;

Expand Down