diff --git a/lazpaint/lazpaintmainform.pas b/lazpaint/lazpaintmainform.pas index 25f862d0..3ab75caf 100644 --- a/lazpaint/lazpaintmainform.pas +++ b/lazpaint/lazpaintmainform.pas @@ -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; @@ -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 @@ -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]); diff --git a/lazpaint/uimageview.pas b/lazpaint/uimageview.pas index f2ed552a..3b4bad03 100644 --- a/lazpaint/uimageview.pas +++ b/lazpaint/uimageview.pas @@ -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 diff --git a/lazpaint/umenu.pas b/lazpaint/umenu.pas index 9df096ed..af70ab05 100644 --- a/lazpaint/umenu.pas +++ b/lazpaint/umenu.pas @@ -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; @@ -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 @@ -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; @@ -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; @@ -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;