Skip to content

Reduce QtWidgets dependency#147

Merged
igorkorsukov merged 5 commits into
musescore:mainfrom
cbjeukendrup:reduce-qtwidgets-dependency
Jul 13, 2026
Merged

Reduce QtWidgets dependency#147
igorkorsukov merged 5 commits into
musescore:mainfrom
cbjeukendrup:reduce-qtwidgets-dependency

Conversation

@cbjeukendrup

Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@cbjeukendrup, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0e73dec0-1a88-4448-85c0-d9bb459ce8cd

📥 Commits

Reviewing files that changed from the base of the PR and between 302d6f5 and aae16c1.

📒 Files selected for processing (20)
  • framework/global/CMakeLists.txt
  • framework/interactive/iinteractiveuriregister.h
  • framework/tours/internal/toursprovider.cpp
  • framework/ui/CMakeLists.txt
  • framework/ui/api/themeapi.cpp
  • framework/ui/api/themeapi.h
  • framework/ui/internal/uiengine.cpp
  • framework/ui/internal/uiengine.h
  • framework/ui/iuiengine.h
  • framework/ui/qml/Muse/Ui/navigationsection.cpp
  • framework/ui/uimodule.cpp
  • framework/ui/uimodule.h
  • framework/ui/view/widgetstyle.cpp
  • framework/ui/view/widgetstyle.h
  • framework/uicomponents/qml/Muse/UiComponents/CMakeLists.txt
  • framework/uicomponents/qml/Muse/UiComponents/dialogview.cpp
  • framework/uicomponents/qml/Muse/UiComponents/internal/popupviewclosecontroller.cpp
  • framework/uicomponents/qml/Muse/UiComponents/itemmultiselectionmodel.cpp
  • framework/uicomponents/qml/Muse/UiComponents/tests/CMakeLists.txt
  • framework/vst/CMakeLists.txt
📝 Walkthrough

Walkthrough

The change introduces WidgetStyle as a dedicated Qt widget styling implementation and moves palette, stylesheet, and custom drawing logic out of ThemeApi. UiModule now manages shared theme state and initializes the widget style. The UI engine theme-update interface is removed. Dialog geometry uses actual window frame margins, and several components switch from QApplication to QGuiApplication. CMake linkage visibility and Qt dependencies are updated across modules and tests.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning No description was provided, so the required issue reference, summary, checklist, and build/test details are missing. Add the template sections, including Resolves #..., a change summary, completed checklist items, and any test/build notes.
Docstring Coverage ⚠️ Warning Docstring coverage is 5.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: reducing QtWidgets exposure and dependency propagation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@framework/ui/uimodule.cpp`:
- Around line 81-82: Construct m_widgetStyle only on the GUI initialization
path, rather than unconditionally in registerExports(). Update the relevant
GuiApp branch in onAllInited() or init() so WidgetStyle is created before
QApplication::setStyle(this) and remains available for GUI mode, while console
and test modes never allocate it.

In `@framework/ui/view/widgetstyle.cpp`:
- Around line 38-40: Update widgetstyle.cpp to include iconcodes.h directly
alongside its existing includes, ensuring the IconCode and iconCodeToChar
declarations used by the file are available without relying on transitive
headers.

In `@framework/uicomponents/qml/Muse/UiComponents/dialogview.cpp`:
- Around line 160-163: Update the content-size assignments in the geometry
update flow to use the frame-margin-removed rectangle, matching the existing
m_globalPos calculation. Set content width and height from
dlgRect.marginsRemoved(frameMargins) so viewGeometry() does not reintroduce
frame margins on subsequent updateGeometry() calls.
- Around line 134-135: Remove the redundant moveLeft and moveTop calls from the
dialog rectangle positioning logic in dialogview.cpp, leaving the existing
dlgRect calculation and subsequent behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 00586041-16c3-4eb7-827e-a4e8fdd5023e

📥 Commits

Reviewing files that changed from the base of the PR and between 3e6bfd6 and 4b6e7d3.

📒 Files selected for processing (20)
  • framework/global/CMakeLists.txt
  • framework/interactive/iinteractiveuriregister.h
  • framework/tours/internal/toursprovider.cpp
  • framework/ui/CMakeLists.txt
  • framework/ui/api/themeapi.cpp
  • framework/ui/api/themeapi.h
  • framework/ui/internal/uiengine.cpp
  • framework/ui/internal/uiengine.h
  • framework/ui/iuiengine.h
  • framework/ui/qml/Muse/Ui/navigationsection.cpp
  • framework/ui/uimodule.cpp
  • framework/ui/uimodule.h
  • framework/ui/view/widgetstyle.cpp
  • framework/ui/view/widgetstyle.h
  • framework/uicomponents/qml/Muse/UiComponents/CMakeLists.txt
  • framework/uicomponents/qml/Muse/UiComponents/dialogview.cpp
  • framework/uicomponents/qml/Muse/UiComponents/internal/popupviewclosecontroller.cpp
  • framework/uicomponents/qml/Muse/UiComponents/itemmultiselectionmodel.cpp
  • framework/uicomponents/qml/Muse/UiComponents/tests/CMakeLists.txt
  • framework/vst/CMakeLists.txt
💤 Files with no reviewable changes (3)
  • framework/ui/iuiengine.h
  • framework/ui/internal/uiengine.cpp
  • framework/ui/internal/uiengine.h

Comment thread framework/ui/uimodule.cpp Outdated
Comment on lines +81 to +82
m_theme = std::make_shared<api::ThemeApi>(nullptr);
m_widgetStyle = new WidgetStyle(m_theme);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

m_widgetStyle leaks in non-GUI run modes.

m_widgetStyle is allocated unconditionally in registerExports(), but ownership is only transferred to QApplication when init()QApplication::setStyle(this) runs, and that only happens for GuiApp mode (see onAllInited() early-return at Lines 139-141). In console/test run modes the style is never adopted and is never deleted (raw pointer, no onDeinit cleanup), leaking both the WidgetStyle and its retained ThemeApi reference.

Consider constructing it only on the GUI path:

🔧 Proposed fix
     m_theme = std::make_shared<api::ThemeApi>(nullptr);
-    m_widgetStyle = new WidgetStyle(m_theme);
     m_theme->init();
-    m_widgetStyle->init();
+
+    m_widgetStyle = new WidgetStyle(m_theme); // becomes owned by QApplication
+    m_widgetStyle->init();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
m_theme = std::make_shared<api::ThemeApi>(nullptr);
m_widgetStyle = new WidgetStyle(m_theme);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/ui/uimodule.cpp` around lines 81 - 82, Construct m_widgetStyle only
on the GUI initialization path, rather than unconditionally in
registerExports(). Update the relevant GuiApp branch in onAllInited() or init()
so WidgetStyle is created before QApplication::setStyle(this) and remains
available for GUI mode, while console and test modes never allocate it.

Comment thread framework/ui/view/widgetstyle.cpp
Comment thread framework/uicomponents/qml/Muse/UiComponents/dialogview.cpp Outdated
Comment on lines 160 to 163
m_globalPos = dlgRect.marginsRemoved(frameMargins).topLeft();

setContentWidth(dlgRect.width());
setContentHeight(dlgRect.height());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Content size set from frame-inclusive dlgRect — dialog will grow on each geometry update.

dlgRect is built at line 127–128 by adding frameMargins to the content geometry. After positioning and clamping, m_globalPos correctly removes the margins (line 160), but setContentWidth(dlgRect.width()) and setContentHeight(dlgRect.height()) (lines 162–163) still include the frame margins. Since viewGeometry() (line 166–168) reads back contentWidth/contentHeight, the next call to updateGeometry() will add the frame margins again, causing the dialog to grow by frameMargins.left() + frameMargins.right() (width) and frameMargins.top() + frameMargins.bottom() (height) on every invocation.

The old code only adjusted dlgRect height with a fixed title-bar constant, so width was unaffected. The new marginsAdded(frameMargins) adds horizontal margins too, making this a regression.

🐛 Proposed fix: remove margins before setting content size
 m_globalPos = dlgRect.marginsRemoved(frameMargins).topLeft();

-setContentWidth(dlgRect.width());
-setContentHeight(dlgRect.height());
+QRect contentRect = dlgRect.marginsRemoved(frameMargins);
+setContentWidth(contentRect.width());
+setContentHeight(contentRect.height());
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
m_globalPos = dlgRect.marginsRemoved(frameMargins).topLeft();
setContentWidth(dlgRect.width());
setContentHeight(dlgRect.height());
m_globalPos = dlgRect.marginsRemoved(frameMargins).topLeft();
QRect contentRect = dlgRect.marginsRemoved(frameMargins);
setContentWidth(contentRect.width());
setContentHeight(contentRect.height());
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/uicomponents/qml/Muse/UiComponents/dialogview.cpp` around lines 160
- 163, Update the content-size assignments in the geometry update flow to use
the frame-margin-removed rectangle, matching the existing m_globalPos
calculation. Set content width and height from
dlgRect.marginsRemoved(frameMargins) so viewGeometry() does not reintroduce
frame margins on subsequent updateGeometry() calls.

@cbjeukendrup cbjeukendrup force-pushed the reduce-qtwidgets-dependency branch 2 times, most recently from 302d6f5 to 06c063e Compare July 12, 2026 18:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@framework/ui/api/themeapi.cpp`:
- Line 25: Remove the unused widgetstyle.h include from ThemeApi so the theme
implementation no longer depends on the QtWidgets-facing WidgetStyle layer.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 83fbebd6-8746-4fb9-9eb5-a33ab0cd97a2

📥 Commits

Reviewing files that changed from the base of the PR and between 4b6e7d3 and 302d6f5.

📒 Files selected for processing (20)
  • framework/global/CMakeLists.txt
  • framework/interactive/iinteractiveuriregister.h
  • framework/tours/internal/toursprovider.cpp
  • framework/ui/CMakeLists.txt
  • framework/ui/api/themeapi.cpp
  • framework/ui/api/themeapi.h
  • framework/ui/internal/uiengine.cpp
  • framework/ui/internal/uiengine.h
  • framework/ui/iuiengine.h
  • framework/ui/qml/Muse/Ui/navigationsection.cpp
  • framework/ui/uimodule.cpp
  • framework/ui/uimodule.h
  • framework/ui/view/widgetstyle.cpp
  • framework/ui/view/widgetstyle.h
  • framework/uicomponents/qml/Muse/UiComponents/CMakeLists.txt
  • framework/uicomponents/qml/Muse/UiComponents/dialogview.cpp
  • framework/uicomponents/qml/Muse/UiComponents/internal/popupviewclosecontroller.cpp
  • framework/uicomponents/qml/Muse/UiComponents/itemmultiselectionmodel.cpp
  • framework/uicomponents/qml/Muse/UiComponents/tests/CMakeLists.txt
  • framework/vst/CMakeLists.txt
💤 Files with no reviewable changes (3)
  • framework/ui/iuiengine.h
  • framework/ui/internal/uiengine.cpp
  • framework/ui/internal/uiengine.h

Comment thread framework/ui/api/themeapi.cpp Outdated
Instead of hardcoding some value and taking some other value from QApplication (QtWidgets), we can just use the dedicated QWindow methods for this.
The comment about PCH is not relevant anymore, because PCH is nowadays its own target and does not include QtWidgets headers anymore.
@igorkorsukov igorkorsukov merged commit 7d6e9ca into musescore:main Jul 13, 2026
3 checks passed
@cbjeukendrup cbjeukendrup deleted the reduce-qtwidgets-dependency branch July 13, 2026 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants