Merge lp:~nick-dedekind/qtubuntu/menuTheme into lp:qtubuntu

Proposed by Nick Dedekind
Status: Merged
Approved by: Gerry Boland
Approved revision: 319
Merged at revision: 362
Proposed branch: lp:~nick-dedekind/qtubuntu/menuTheme
Merge into: lp:qtubuntu
Diff against target: 2206 lines (+1850/-36)
28 files modified
README (+3/-2)
debian/control (+12/-0)
debian/gles-patches/convert-to-gles.patch (+23/-10)
debian/qtubuntu-appmenutheme.install (+1/-0)
debian/rules (+1/-0)
src/src.pro (+1/-1)
src/ubuntuappmenu/com.ubuntu.MenuRegistrar.xml (+83/-0)
src/ubuntuappmenu/gmenumodelexporter.cpp (+350/-0)
src/ubuntuappmenu/gmenumodelexporter.h (+83/-0)
src/ubuntuappmenu/gmenumodelplatformmenu.cpp (+526/-0)
src/ubuntuappmenu/gmenumodelplatformmenu.h (+181/-0)
src/ubuntuappmenu/logging.h (+27/-0)
src/ubuntuappmenu/menuregistrar.cpp (+137/-0)
src/ubuntuappmenu/menuregistrar.h (+59/-0)
src/ubuntuappmenu/registry.cpp (+97/-0)
src/ubuntuappmenu/registry.h (+56/-0)
src/ubuntuappmenu/theme.cpp (+46/-13)
src/ubuntuappmenu/theme.h (+9/-4)
src/ubuntuappmenu/themeplugin.cpp (+36/-0)
src/ubuntuappmenu/themeplugin.h (+34/-0)
src/ubuntuappmenu/ubuntuappmenu.json (+3/-0)
src/ubuntuappmenu/ubuntuappmenu.pro (+41/-0)
src/ubuntumirclient/integration.cpp (+24/-3)
src/ubuntumirclient/nativeinterface.cpp (+3/-0)
src/ubuntumirclient/plugin.cpp (+3/-0)
src/ubuntumirclient/ubuntumirclient.pro (+4/-3)
src/ubuntumirclient/window.cpp (+5/-0)
src/ubuntumirclient/window.h (+2/-0)
To merge this branch: bzr merge lp:~nick-dedekind/qtubuntu/menuTheme
Reviewer Review Type Date Requested Status
Gerry Boland (community) Approve
Unity8 CI Bot continuous-integration Approve
Timo Jyrinki Approve
Review via email: mp+296997@code.launchpad.net

Commit message

Added a QPlatformTheme for exporting gmenumodel for qt menus.

Description of the change

Added a QPlatformTheme for exporting a gmenumodel for qt menus.

Theme packaged in qtubuntu-appmenutheme

Theme is loadable through QT_QPA_PLATFORMTHEME=ubuntuappmenu, and automatically loaded from ubuntumirclient if the theme is installed.
Changed categories logging to ubuntu.mirclient, ubuntu.appmenu

Requires registry implementation to function:
https://code.launchpad.net/~nick-dedekind/unity8/menu.registrar/+merge/298109

To post a comment you must log in.
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:284
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/74/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/1944/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1970
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1904
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1904
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1904
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1895/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1895/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1895/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1895/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1895/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1895/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1895/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1895/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1895/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/74/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:285
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/75/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/1946/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1972
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1905
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1905
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1905
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1896/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1896/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1896/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1896/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1896/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1896/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1896/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1896/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1896/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/75/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:287
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/76/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/1947/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1973
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1907
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1907
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1907
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1898/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1898/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1898/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1898/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1898/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1898/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1898/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1898/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1898/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/76/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:288
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/77/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/1954/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1980
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1914
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1914
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1914
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1905/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1905/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1905/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1905/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1905/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1905/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1905/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1905/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1905/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/77/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:292
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/79/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2006
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2034
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1951
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1951
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1951
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1942
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1942/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1942
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1942/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1942
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1942/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1942
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1942/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1942
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1942/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1942
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1942/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1942
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1942/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1942
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1942/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1942
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1942/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/79/rebuild

review: Approve (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:293
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/84/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2083
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2111
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2023
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2023
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2023
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2014
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2014/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2014
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2014/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2014
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2014/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2014
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2014/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2014
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2014/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2014
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2014/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2014
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2014/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2014
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2014/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2014
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2014/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/84/rebuild

review: Approve (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:296
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/87/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/2106/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2134
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2044
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2044
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2044
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2035/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2035/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/87/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:297
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/88/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/2107/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2135
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2045
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2045
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2045
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2036/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2036
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2036/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2036
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2036/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2036/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2036
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2036/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2036
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2036/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2036/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2036
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2036/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2036
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2036/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/88/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:298
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/89/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2109
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2137
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2046
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2046
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2046
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2037
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2037/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2037
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2037/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2037
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2037/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2037
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2037/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2037
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2037/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2037
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2037/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2037
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2037/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2037
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2037/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2037
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2037/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/89/rebuild

review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

Hey,
this was bigger than I was expecting!

Questions:
1. how do I test this?
2. is the theme plugin totally independent from the QPA plugin? I see you moved the QPA's theme code into the Integration code. Why? Just to indicate the majority of the theming is elsewhere?

~/dev/projects/qtubuntu/menuTheme/src ⮀ l
src.pro ubuntuappmenu/ ubuntumirclient/
~/dev/projects/qtubuntu/menuTheme/src ⮀ cd ubuntu<TAB><TAB>
ubuntuappmenu/ ubuntumirclient/
/me hating how we prefix everything with "ubuntu".

I'm just looking at the QPA for now
- you add persistentSurfaceId - can it be a QByteArray instead of QString?

+ // queue the windowPropertyChanged signal. If it's emitted directly, the platformWindow will not yet be set for the window.
+ QMetaObject::invokeMethod(mNativeInterface, "windowPropertyChanged", Qt::QueuedConnection,
+ Q_ARG(QPlatformWindow*, this),
+ Q_ARG(QString, "persistentSurfaceId"));
How does a persistent Surface ID ever change?

+ return QStringList("ubuntuappmenu");
QStringLiteral please.

-Q_LOGGING_CATEGORY(ubuntumirclientInput, "ubuntumirclient.input", QtWarningMsg)
+Q_LOGGING_CATEGORY(ubuntumirclientInput, "ubuntu.mirclient.input", QtWarningMsg)
Why? This breaks the standard elsewhere in the code. Check the README too.

review: Needs Fixing
Revision history for this message
Gerry Boland (gerboland) wrote :

=== modified file 'debian/control'
What dependency will pull in this new qtubuntu-appmenutheme? The QPAs?

+Build-Depends: ${misc:Depends},
+ ${shlibs:Depends},
bad indent

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> === modified file 'debian/control'
> What dependency will pull in this new qtubuntu-appmenutheme? The QPAs?

I would probably say it's whatever pulls in unity8/qtubuntu. unity8-desktop-session/ubuntu-touch-session?

>
> +Build-Depends: ${misc:Depends},
> + ${shlibs:Depends},
> bad indent

Fixed.

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:300
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/107/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2644
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2672
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2546
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2546
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2546
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2540
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2540/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2540
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2540/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2540
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2540/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2540
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2540/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2540
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2540/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2540
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2540/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2540
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2540/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2540
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2540/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2540
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2540/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/107/rebuild

review: Approve (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

>
> I'm just looking at the QPA for now
> - you add persistentSurfaceId - can it be a QByteArray instead of QString?

Done.

>
> + // queue the windowPropertyChanged signal. If it's emitted directly, the
> platformWindow will not yet be set for the window.
> + QMetaObject::invokeMethod(mNativeInterface, "windowPropertyChanged",
> Qt::QueuedConnection,
> + Q_ARG(QPlatformWindow*, this),
> + Q_ARG(QString, "persistentSurfaceId"));
> How does a persistent Surface ID ever change?

It doesn't change but the platform window is created after the QWindow, and therefore could be created after an attached menubar; so when the exporter initially asks for the surface id, it wont be set yet, therefore we need to be notified when it is.

>
> + return QStringList("ubuntuappmenu");
> QStringLiteral please.

Done

>
> -Q_LOGGING_CATEGORY(ubuntumirclientInput, "ubuntumirclient.input",
> QtWarningMsg)
> +Q_LOGGING_CATEGORY(ubuntumirclientInput, "ubuntu.mirclient.input",
> QtWarningMsg)
> Why? This breaks the standard elsewhere in the code. Check the README too.

I've changed it everywhere in the code now. Since it's kind of like a url i think it should be this way for better "domain" control.
We also have "ubuntu.appmenu" so to get all the logging from qtubuntu, we can do "QT_LOGGING_RULES=ubuntu.*=true"

* I think it should really be "qtubuntu.mirclient/appmenu"

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

If you'd rather just leave the log categories as ubuntumirclient/ubuntuappmenu, let me know and i'll change them all back.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> Hey,
> this was bigger than I was expecting!
>
> Questions:
> 1. how do I test this?

I'll sort out something to test with.

> 2. is the theme plugin totally independent from the QPA plugin? I see you
> moved the QPA's theme code into the Integration code. Why? Just to indicate
> the majority of the theming is elsewhere?

They're both independent of each other, but ubuntuappmenu relies on a persistent surface id to be set to work correctly, so there is a "soft" dependence their.

The theme in the integration is just a fallback theme in case ubuntuappmenu isn't installed. I didn't think it really needed it's own files since it isn't instantiable outside the integration (No QT_QPA_PLATFORMTHEME option).
The reason for separating the theme into a different package was so that it is very easy to revert or replace. Just uninstall the package.

>
>
> ~/dev/projects/qtubuntu/menuTheme/src ⮀ l
> src.pro ubuntuappmenu/ ubuntumirclient/
> ~/dev/projects/qtubuntu/menuTheme/src ⮀ cd ubuntu<TAB><TAB>
> ubuntuappmenu/ ubuntumirclient/
> /me hating how we prefix everything with "ubuntu".
>

yes...

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:302
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/109/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2649
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2677
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2550
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2550
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2550
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2544
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2544/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2544
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2544/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2544
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2544/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2544
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2544/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2544
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2544/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2544
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2544/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2544
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2544/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2544
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2544/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2544
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2544/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/109/rebuild

review: Approve (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

Righty'O

I've added a testing file to https://code.launchpad.net/~nick-dedekind/unity8/menus.
You'll need to build this because it has the server side of the menu registry, but otherwise the test file sits in isolation to any thing else.
The test file is in "qml/ApplicationMenus/Test.qml"

So:
1) Get and build deps for unity8 branch.
   lp:~unity-team/unity-api/persistent_surface_id
2) Get and build lp:~nick-dedekind/unity8/menus.
3) Start test with: QML2_IMPORT_PATH=./builddir/plugins qmlscene qml/ApplicationMenus/Test.qml

4) new term
5) mir_demo_server

6) new term
7) create a qml example with menus. (MenuAPI.qml example graciously provided by dednick http://pastebin.ubuntu.com/23084706/)
8) Build and install this qtubuntu branch
9) QT_LOGGING_RULES=ubuntu.appmenu*=true QT_QPA_PLATFORMTHEME= QT_QPA_PLATFORM=ubuntumirclient qmlscene MenuAPI.qml

Tadaa. hopefully. you should see a bunch of log output from ubuntu.appmenu, and from ubuntu.appmenu.registrar if it successfully connected to the registry.
The Test.qml should also contain a pretty printed output of the exported menus it's picked up from dbus.

Revision history for this message
Gerry Boland (gerboland) wrote :

=== modified file 'README'
+ * ubuntu.mirclient - For all other messages frm the ubuntumirclient QPA.
+ * ubuntu.appmenu - For all messages frm the ubuntuappmenu QPA theme.
typo: "from"

=== modified file 'debian/control'
+ appmenutheme provides you with an integrated application menu in your global
+ menu bar. It functions as a QPA platformtheme plugin.
I just want to edit this to remove the subject from the sentence:
Appmenutheme enables the export of application menus to a global menu bar. It is implemented in a QPA platform theme plugin.

=== added file 'src/ubuntuappmenu/com.ubuntu.MenuRegistrar.xml'
+ main interface is docuemented here: @ref com::ubuntu::MenuRegistrar.
typo: "documented"

+ ensure this method is called with the same connection that implmenets the object.
and one more "implements"

+ Associates a gmenumodel with a application
typo: "an application"

+ <arg name="menuObjectPath" type="o" direction="in">
+ <dox:d>The object on the dbus interface implementing the gmenumodel interface</dox:d>
+ </arg>
+ <arg name="actionObjectPath" type="o" direction="in">
+ <dox:d>The object on the dbus interface implementing the gmenumodel interface</dox:d>
Documentation text could be slightly better (in both RegisterAppMenu and RegisterSurfaceMenu)

+ A method to allow removing a application menu from the database.
same typo: "an application"

+ ensure this method is called with the same connection that implmenets the object.
"implements" again

review: Needs Fixing
Revision history for this message
Gerry Boland (gerboland) wrote :
Download full text (3.8 KiB)

+++ src/ubuntuappmenu/gmenumodelexporter.h
+class GMenuModelExporter : public QObject
I was curious if this really needed to be a QObject, but you do use that fact to ensure lifetimes of the objects in signal/lambda connections are correct. So it's ok.

+ QList<QMetaObject::Connection> m_propertyConnections;
I understand why you do this, because QObject::disconnect must have a sender (i.e. first argument) set.

But GMenuModelPlatformMenuItem are QObjects, so on deletion they will clean up their connections. Is that not enough? Do they clean up too late?

+++ src/ubuntuappmenu/gmenumodelexporter.cpp
+inline QString getActionString(const QString& label) {
opening brace on newline - just for consistency.

+ for(auto iter = parts.begin(); iter != parts.end(); ++iter) {
space after the "for" - could you not use Q_FOREACH(const auto &part, parts) and save messing with iterators?

I'd also appreciate an explanatory comment of what "getActionString" is doing.

+ auto item = (GMenuModelPlatformMenuItem*)user_data;
Use C++ static_cast<> please

+#define MENU_OBJECT_PATH QString("/com/ubuntu/Menu/%1")
QStringLiteral would work. But odd to define more than a character constant here,
#define MENU_OBJECT_PATH "/com/ubuntu/Menu/%1"
would be more typical

+ GMenuModelBarExporter::GMenuModelBarExporter(GMenuModelPlatformMenuBar * bar)
+ auto iter = bar->menus().begin();
+ for (; iter != bar->menus().end(); ++iter) {
Q_FOREACH nicer, no? You use these style loops everywhere, any reason?

Also, a quick comment explaining the purpose of these classes and each method would help other readers. I'm especially obsessed with documenting methods that return GThing* pointers, to clearly indicate if or how the returned GThings* should be cleaned up by the consumer.

+ GError *error = NULL;
I see lots of NULL here, can we not use nullptr, or is G stuff incompatible with it? /me obsessed with C++11 goodies

+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
leak, is never unref-ed.

+ m_exportedModel = g_dbus_connection_export_menu_model(bus, menuPath.constData(), G_MENU_MODEL(m_gmainMenu), &error);
g_dbus_connection_export_menu_model returns a guint, unsigned int. m_exportedModel is an int. Implicit lossy conversion here, definitely safe?

+ error = NULL;
Leak, you should be doing g_error_free (err)

+ GMenuModelPlatformMenu* gplatformMenu = qobject_cast<GMenuModelPlatformMenu*>(platformMenu);
I see this a bunch of places, it can be simpler:
auto gplatformMenu = static_cast<GMenuModelPlatformMenu*>(platformMenu);

+void GMenuModelExporter::addSubmenuItems(GMenuModelPlatformMenu* gplatformMenu, GMenu* menu)
There's a lot going on here, quick comment explaining the intention would be good. I'm just looking at the code, it appears fine. Q_FOREACH not suitable, but you can use static_cast instead of qobject_cast here.

+ bool checkable(GMenuModelPlatformMenuItem::get_checkable(gplatformMenuItem));
I prefer = instead of () assignment for simple types - same line could be misinterpreted as a function declaration
same for "checked" inside the conditional.

+ std::function<void(bool)> updateChecked = [gplatformMenuItem, action](bool checked) {
perf...

Read more...

review: Needs Fixing
Revision history for this message
Gerry Boland (gerboland) wrote :

QList<QMetaObject::Connection> m_propertyConnections;

Please use QVector instead of QList here. Ref:
http://stackoverflow.com/questions/33609406/qlist-vs-qvector-revisited
as I suspect (not 100%) that the type is bigger than a pointer

Revision history for this message
Gerry Boland (gerboland) wrote :

=== added file 'src/ubuntuappmenu/gmenumodelplatformmenu.h'

+ GMenuModelExporter* m_exporter;
+ MenuRegistrar* m_registrar;
If you used QScopedPointer, you would not need to worry about deleting them in a destructor. And then can have a trivial destructor

+class Q_DECL_EXPORT GMenuModelPlatformMenu : public QPlatformMenu
+ GMenuModelExporter* m_exporter;
+ MenuRegistrar* m_registrar;
same as above, but you'll need to set them with reset(). Note you're leaking these currently.

=== added file 'src/ubuntuappmenu/gmenumodelplatformmenu.cpp'
+int logRecusion = 0;
polluting the global namespace, please stuck in an anonymous NS.

+ connect(menu, SIGNAL(structureChanged()), this, SIGNAL(structureChanged()));
new style connect statement gives us compile-time checking of this, please convert. I see this 2 times

for (auto iter = m_menus.begin(); iter != m_menus.end(); ++iter) {
I think there's the odd loop you could convert to Q_FOREACH. menuForTag & menuItemForTag anyway

+QDebug GMenuModelPlatformMenuBar::operator<<(QDebug stream)
+ auto myMenu = qobject_cast<GMenuModelPlatformMenu*>(menu);
static_cast works

+void GMenuModelPlatformMenuBar::setReady(bool _ready)
underscore, yuk! :) Just "ready" please

=== added file 'src/ubuntuappmenu/menuregistrar.cpp'
+bool isMirClient() {
+ return qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient";
+}
move to anonymous NS please, and qGuiApp->platformName() would be a safer thing to check.

+ : m_registeredProcessId(~0)
Putting my security hat on for a second, it is not impossible for an application to have a pid ~0, and also pid 0 (I believe pids can wrap around). Highly unlikely, but an attack vector. Consequences here aren't dire, so I'm ok with it.

std::optional is nice to avoid such munging of set/unset with value.

+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
leaked again here. NULLs!

+ if (!bus) {
+ qCWarning(ubuntuappmenuRegistrar, "Failed to retreive session bus - %s", error ? error->message : "unknown error");
error leaked here

+void MenuRegistrar::unregisterApplicationMenu()
+{
+ if (!UbuntuMenuRegistry::instance()->isConnected()) {
+ m_registeredProcessId = ~0;
+ return;
+ }
+ UbuntuMenuRegistry::instance()->unregisterApplicationMenu(m_registeredProcessId, m_path);
+ m_registeredProcessId = ~0;
+}

m_registeredProcessId = ~0; happens nonetheless, an if/else would save the duplicate line.

review: Needs Fixing
Revision history for this message
Gerry Boland (gerboland) wrote :

=== added file 'src/ubuntuappmenu/registry.h'
+ #include <QObject>
space, and please have a newline between it and the class declarations

+ QDBusServiceWatcher* m_serviceWatcher;
+ ComUbuntuMenuRegistrarInterface* m_interface;
QScopedPointer to ease lifetime (even though they'll probably leak anyway since it is a singleton) and simplify destructor

=== added file 'src/ubuntuappmenu/registry.cpp'
+ Q_UNUSED(oldOwner);
+ if (serviceName != REGISTRAR_SERVICE) return;
+
+ if (oldOwner != newOwner) {
this is why I don't like Q_UNUSED. oldOwner is actually used.

I prefer commenting out the variable name in the method if it really is unused.

+++ src/ubuntuappmenu/theme.cpp
+bool useLocalMenu() {
anonymous NS please

- return QVariant(QStringLiteral("ubuntu-mobile"));
+ return QVariant(QStringLiteral("suru"));
How is this related to this MP? And who decided to change the icon theme?

+++ src/ubuntuappmenu/themeplugin.cpp
learning our lesson about Q_UNUSED, please comment out the variable names instead

review: Needs Fixing
Revision history for this message
Gerry Boland (gerboland) wrote :

+ // queue the windowPropertyChanged signal. If it's emitted directly, the platformWindow will not yet be set for the window.
+ QMetaObject::invokeMethod(mNativeInterface, "windowPropertyChanged", Qt::QueuedConnection,
+ Q_ARG(QPlatformWindow*, this),
+ Q_ARG(QString, "persistentSurfaceId"));

Why pass the PlatformWindow, why not the QWindow? I see you only using the QWindow in the appmenu stuff:

+ connect(nativeInterface, &QPlatformNativeInterface::windowPropertyChanged, this, [this](QPlatformWindow* window, const QString &property) {
+ if (property != QStringLiteral("persistentSurfaceId")) {
+ return;
+ }
+ if (window->window() == m_window) {
+ registerMenuForWindow(m_window, m_path);
+ }

review: Needs Information
Revision history for this message
Gerry Boland (gerboland) wrote :

I think for name collision safety all of ubuntuappmenu should be either within its own namespace, or all the class names prefixed with "Ubuntu"

This is something the mirclient QPA needs to do too

Revision history for this message
Gerry Boland (gerboland) wrote :

> If you'd rather just leave the log categories as
> ubuntumirclient/ubuntuappmenu, let me know and i'll change them all back.

Can you just put the ubuntumirclient ones back? This MP is big enough as it is.

I do agree with your thinking that the category names should be better namespaced.

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:306
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/132/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3006
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3034
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2891
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2891/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2891
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2891/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2891
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2891/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2891
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2891/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2891
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2891/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2891
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2891/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2891
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2891/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2891
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2891/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2891
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2891/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/132/rebuild

review: Approve (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> + // queue the windowPropertyChanged signal. If it's emitted directly, the
> platformWindow will not yet be set for the window.
> + QMetaObject::invokeMethod(mNativeInterface, "windowPropertyChanged",
> Qt::QueuedConnection,
> + Q_ARG(QPlatformWindow*, this),
> + Q_ARG(QString, "persistentSurfaceId"));
>
> Why pass the PlatformWindow, why not the QWindow? I see you only using the
> QWindow in the appmenu stuff:
>
> + connect(nativeInterface,
> &QPlatformNativeInterface::windowPropertyChanged, this,
> [this](QPlatformWindow* window, const QString &property) {
> + if (property != QStringLiteral("persistentSurfaceId")) {
> + return;
> + }
> + if (window->window() == m_window) {
> + registerMenuForWindow(m_window, m_path);
> + }

Because the QPlatformNativeInterface::windowPropertyChanged signal takes a QPlatformWindow,* not a QWindow*.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :
Download full text (4.3 KiB)

> +++ src/ubuntuappmenu/gmenumodelexporter.h
> +class GMenuModelExporter : public QObject
> I was curious if this really needed to be a QObject, but you do use that fact
> to ensure lifetimes of the objects in signal/lambda connections are correct.
> So it's ok.
>
> + QList<QMetaObject::Connection> m_propertyConnections;
> I understand why you do this, because QObject::disconnect must have a sender
> (i.e. first argument) set.
>
> But GMenuModelPlatformMenuItem are QObjects, so on deletion they will clean up
> their connections. Is that not enough? Do they clean up too late?

When the structure of the menu changes (for additions/removals from menu), we re-process all the menus so need to re-connect. Just because we remove a menu doesn't mean it's necessarily been deleted.

>
>
> +++ src/ubuntuappmenu/gmenumodelexporter.cpp
> +inline QString getActionString(const QString& label) {
> opening brace on newline - just for consistency.
>
> + for(auto iter = parts.begin(); iter != parts.end(); ++iter) {
> space after the "for" - could you not use Q_FOREACH(const auto &part, parts)
> and save messing with iterators?
>
> I'd also appreciate an explanatory comment of what "getActionString" is doing.
>
>
> + auto item = (GMenuModelPlatformMenuItem*)user_data;
> Use C++ static_cast<> please
>
> +#define MENU_OBJECT_PATH QString("/com/ubuntu/Menu/%1")
> QStringLiteral would work. But odd to define more than a character constant
> here,
> #define MENU_OBJECT_PATH "/com/ubuntu/Menu/%1"
> would be more typical
>
>
> + GMenuModelBarExporter::GMenuModelBarExporter(GMenuModelPlatformMenuBar *
> bar)
> + auto iter = bar->menus().begin();
> + for (; iter != bar->menus().end(); ++iter) {
> Q_FOREACH nicer, no? You use these style loops everywhere, any reason?
>
> Also, a quick comment explaining the purpose of these classes and each method
> would help other readers. I'm especially obsessed with documenting methods
> that return GThing* pointers, to clearly indicate if or how the returned
> GThings* should be cleaned up by the consumer.
>
>
> + GError *error = NULL;
> I see lots of NULL here, can we not use nullptr, or is G stuff incompatible
> with it? /me obsessed with C++11 goodies
>
> + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
> leak, is never unref-ed.
>
> + m_exportedModel = g_dbus_connection_export_menu_model(bus,
> menuPath.constData(), G_MENU_MODEL(m_gmainMenu), &error);
> g_dbus_connection_export_menu_model returns a guint, unsigned int.
> m_exportedModel is an int. Implicit lossy conversion here, definitely safe?
>
>
> + error = NULL;
> Leak, you should be doing g_error_free (err)
>
>
> + GMenuModelPlatformMenu* gplatformMenu =
> qobject_cast<GMenuModelPlatformMenu*>(platformMenu);
> I see this a bunch of places, it can be simpler:
> auto gplatformMenu = static_cast<GMenuModelPlatformMenu*>(platformMenu);
>
>
> +void GMenuModelExporter::addSubmenuItems(GMenuModelPlatformMenu*
> gplatformMenu, GMenu* menu)
> There's a lot going on here, quick comment explaining the intention would be
> good. I'm just looking at the code, it appears fine. Q_FOREACH not suitable,
> but you can use static_cast instead of qobje...

Read more...

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> === added file 'src/ubuntuappmenu/gmenumodelplatformmenu.h'
>
> + GMenuModelExporter* m_exporter;
> + MenuRegistrar* m_registrar;
> If you used QScopedPointer, you would not need to worry about deleting them in
> a destructor. And then can have a trivial destructor
>
> +class Q_DECL_EXPORT GMenuModelPlatformMenu : public QPlatformMenu
> + GMenuModelExporter* m_exporter;
> + MenuRegistrar* m_registrar;
> same as above, but you'll need to set them with reset(). Note you're leaking
> these currently.
>
>
>
> === added file 'src/ubuntuappmenu/gmenumodelplatformmenu.cpp'
> +int logRecusion = 0;
> polluting the global namespace, please stuck in an anonymous NS.
>
> + connect(menu, SIGNAL(structureChanged()), this, SIGNAL(structureChanged()));
> new style connect statement gives us compile-time checking of this, please
> convert. I see this 2 times
>
>
> for (auto iter = m_menus.begin(); iter != m_menus.end(); ++iter) {
> I think there's the odd loop you could convert to Q_FOREACH. menuForTag &
> menuItemForTag anyway
>
> +QDebug GMenuModelPlatformMenuBar::operator<<(QDebug stream)
> + auto myMenu = qobject_cast<GMenuModelPlatformMenu*>(menu);
> static_cast works
>
> +void GMenuModelPlatformMenuBar::setReady(bool _ready)
> underscore, yuk! :) Just "ready" please
>
>
> === added file 'src/ubuntuappmenu/menuregistrar.cpp'
> +bool isMirClient() {
> + return qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient";
> +}
> move to anonymous NS please, and qGuiApp->platformName() would be a safer
> thing to check.
>
>
> + : m_registeredProcessId(~0)
> Putting my security hat on for a second, it is not impossible for an
> application to have a pid ~0, and also pid 0 (I believe pids can wrap around).
> Highly unlikely, but an attack vector. Consequences here aren't dire, so I'm
> ok with it.
>
> std::optional is nice to avoid such munging of set/unset with value.
>

C++17 only.

>
> + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
> leaked again here. NULLs!
>
> + if (!bus) {
> + qCWarning(ubuntuappmenuRegistrar, "Failed to retreive session bus - %s",
> error ? error->message : "unknown error");
> error leaked here
>
> +void MenuRegistrar::unregisterApplicationMenu()
> +{
> + if (!UbuntuMenuRegistry::instance()->isConnected()) {
> + m_registeredProcessId = ~0;
> + return;
> + }
> + UbuntuMenuRegistry::instance()->unregisterApplicationMenu(m_registeredPro
> cessId, m_path);
> + m_registeredProcessId = ~0;
> +}
>
> m_registeredProcessId = ~0; happens nonetheless, an if/else would save the
> duplicate line.

Done.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

Think I got everything.

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:309
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/133/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/3016/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3044
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2901
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2901/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2901
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2901/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2901
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2901/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2901
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2901/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2901
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2901/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2901
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2901/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2901
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2901/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2901
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2901/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2901
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2901/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/133/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:310
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/134/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/3019/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3047
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2904
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2904/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2904
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2904/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2904
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2904/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2904
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2904/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2904
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2904/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2904
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2904/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2904
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2904/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2904
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2904/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2904
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2904/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/134/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

I'll sort out the namespacing in another MP I; along with changes to the logging categories. For now i've just left them in the current format.

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:311
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/135/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3021
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3049
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2906
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2906/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2906
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2906/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2906
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2906/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2906
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2906/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2906
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2906/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2906
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2906/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2906
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2906/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2906
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2906/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2906
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2906/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/135/rebuild

review: Approve (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:312
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/136/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3022
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3050
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2907
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2907/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2907
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2907/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2907
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2907/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2907
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2907/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2907
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2907/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2907
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2907/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2907
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2907/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2907
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2907/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2907
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2907/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/136/rebuild

review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

> > std::optional is nice to avoid such munging of set/unset with value.
> >
>
> C++17 only.

Damnit yes.

> I'll sort out the namespacing in another MP I; along with changes to
> the logging categories. For now i've just left them in the current format.

Ok.

Revision history for this message
Gerry Boland (gerboland) wrote :

Only 1 thing missed:

=== added file 'src/ubuntuappmenu/menuregistrar.cpp'
+bool isMirClient() {
+ return qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient";
+}
qGuiApp->platformName() would be a safer thing to check.

You've addressed everything else

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> Only 1 thing missed:
>
> === added file 'src/ubuntuappmenu/menuregistrar.cpp'
> +bool isMirClient() {
> + return qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient";
> +}
> qGuiApp->platformName() would be a safer thing to check.
>
> You've addressed everything else

Fixed.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

You will also need lp:~nick-dedekind/qmenumodel/desktop_menus to test.

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:313
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/137/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3026
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3054
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2911
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2911/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2911
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2911/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2911
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2911/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2911
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2911/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2911
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2911/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2911
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2911/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2911
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2911/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2911
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2911/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2911
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2911/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/137/rebuild

review: Approve (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:314
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/138/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3027
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3055
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2912
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2912/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2912
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2912/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2912
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2912/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2912
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2912/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2912
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2912/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2912
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2912/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2912
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2912/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2912
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2912/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2912
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2912/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/138/rebuild

review: Approve (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:315
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/141/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3061
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3089
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2946
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2946/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2946
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2946/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2946
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2946/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2946
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2946/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2946
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2946/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2946
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2946/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2946
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2946/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2946
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2946/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2946
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2946/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/141/rebuild

review: Approve (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:316
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/142/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3093
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3121
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2977
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2977/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2977
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2977/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2977
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2977/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2977
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2977/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2977
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2977/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2977
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2977/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2977
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2977/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2977
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2977/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2977
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2977/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/142/rebuild

review: Approve (continuous-integration)
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote :

The gles version of qtubuntu-appmenutheme should only build for amd64 and i386 like the others.

review: Needs Fixing
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:317
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/143/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3112
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3140
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2996
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2996/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2996
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2996/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2996
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2996/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2996
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2996/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2996
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2996/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2996
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2996/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2996
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2996/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2996
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2996/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2996
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2996/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/143/rebuild

review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

Overall this looks good, can approve

review: Approve
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote :

Looks fine to me too.

review: Approve
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:319
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/168/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3755
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3783
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3627
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3627/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3627
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3627/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3627
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3627/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3627
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3627/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3627
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3627/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3627
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3627/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/168/rebuild

review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README'
2--- README 2016-06-22 17:16:33 +0000
3+++ README 2016-12-09 17:04:44 +0000
4@@ -48,7 +48,9 @@
5 * ubuntumirclient.input - Messages related to input and other Mir events.
6 * ubuntumirclient.graphics - Messages related to graphics, GL and EGL.
7 * ubuntumirclient.swapBuffers - Messages related to surface buffer swapping.
8- * ubuntumirclient - For all other messages.
9+ * ubuntumirclient - For all other messages form the ubuntumirclient QPA.
10+ * ubuntuappmenu.registrar - Messages related to application menu registration.
11+ * ubuntuappmenu - For all other messages form the ubuntuappmenu QPA theme.
12
13 The QT_QPA_EGLFS_DEBUG environment variable prints a little more information
14 from Qt's internals.
15@@ -99,4 +101,3 @@
16
17 [1] http://doc-snapshot.qt-project.org/5.0/qabstractnativeeventfilter.html
18 [2] http://doc-snapshot.qt-project.org/5.0/qcoreapplication.html#installNativeEventFilter
19-
20
21=== modified file 'debian/control'
22--- debian/control 2016-09-22 19:45:30 +0000
23+++ debian/control 2016-12-09 17:04:44 +0000
24@@ -66,3 +66,15 @@
25 plugins.
26 .
27 This variant of the package is for GNU-based desktops.
28+
29+Package: qtubuntu-appmenutheme
30+Architecture: any
31+Multi-Arch: same
32+Depends: ${misc:Depends},
33+ ${shlibs:Depends},
34+Description: Qt platform theme for exported application menus
35+ Appmenutheme enables the export of application menus to a global menu bar.
36+ It is implemented in a QPA platform theme plugin.
37+ .
38+ This package will work for applications designed for Qt5, as well as QML
39+ applications
40
41=== modified file 'debian/gles-patches/convert-to-gles.patch'
42--- debian/gles-patches/convert-to-gles.patch 2016-06-03 10:36:39 +0000
43+++ debian/gles-patches/convert-to-gles.patch 2016-12-09 17:04:44 +0000
44@@ -1,14 +1,14 @@
45-Index: cross-build-support/debian/control
46+Index: qtubuntu/debian/control
47 ===================================================================
48---- cross-build-support.orig/debian/control
49-+++ cross-build-support/debian/control
50+--- qtubuntu.orig/debian/control
51++++ qtubuntu/debian/control
52 @@ -1,4 +1,4 @@
53 -Source: qtubuntu
54 +Source: qtubuntu-gles
55 Priority: optional
56 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
57 Build-Depends: debhelper (>= 9),
58-@@ -11,11 +11,20 @@ Build-Depends: debhelper (>= 9),
59+@@ -12,11 +12,20 @@ Build-Depends: debhelper (>= 9),
60 libinput-dev,
61 libmirclient-dev (>= 0.13.0),
62 libmtdev-dev,
63@@ -29,7 +29,7 @@
64 quilt,
65 # if you don't have have commit access to this branch but would like to upload
66 # directly to Ubuntu, don't worry: your changes will be merged back into the
67-@@ -25,7 +34,7 @@ Standards-Version: 3.9.6
68+@@ -26,7 +35,7 @@ Standards-Version: 3.9.6
69 Section: libs
70
71 Package: qtubuntu-android
72@@ -38,7 +38,7 @@
73 Multi-Arch: same
74 Conflicts: qtubuntu-desktop,
75 Replaces: qtubuntu (<< 0.52),
76-@@ -36,31 +45,12 @@ Provides: qtubuntu,
77+@@ -37,43 +46,12 @@ Provides: qtubuntu,
78 Depends: ubuntu-application-api3-touch,
79 ${misc:Depends},
80 ${shlibs:Depends},
81@@ -71,13 +71,25 @@
82 - plugins.
83 - .
84 - This variant of the package is for GNU-based desktops.
85+-
86+-Package: qtubuntu-appmenutheme
87+-Architecture: any
88+-Multi-Arch: same
89+-Depends: ${misc:Depends},
90+- ${shlibs:Depends},
91+-Description: Qt platform theme for exported application menus
92+- Appmenutheme enables the export of application menus to a global menu bar.
93+- It is implemented in a QPA platform theme plugin.
94+- .
95+- This package will work for applications designed for Qt5, as well as QML
96+- applications
97 + This variant of the package is for Android-based phones and tablets (built
98 + against the OpenGLES variant of qtbase).
99-Index: cross-build-support/debian/rules
100+Index: qtubuntu/debian/rules
101 ===================================================================
102---- cross-build-support.orig/debian/rules
103-+++ cross-build-support/debian/rules
104-@@ -5,60 +5,35 @@ export DPKG_GENSYMBOLS_CHECK_LEVEL=4
105+--- qtubuntu.orig/debian/rules
106++++ qtubuntu/debian/rules
107+@@ -5,61 +5,35 @@ export DPKG_GENSYMBOLS_CHECK_LEVEL=4
108 export QT_SELECT=5
109
110 ANDROID_DIR = build-android
111@@ -139,3 +151,4 @@
112 dh_install --sourcedir=$(TMP1_DIR) -pqtubuntu-android
113 -endif
114 - dh_install --sourcedir=$(TMP2_DIR) -pqtubuntu-desktop
115+- dh_install --sourcedir=$(TMP2_DIR) -pqtubuntu-appmenutheme
116
117=== added file 'debian/qtubuntu-appmenutheme.install'
118--- debian/qtubuntu-appmenutheme.install 1970-01-01 00:00:00 +0000
119+++ debian/qtubuntu-appmenutheme.install 2016-12-09 17:04:44 +0000
120@@ -0,0 +1,1 @@
121+usr/lib/*/qt5/plugins/platformthemes/*
122
123=== modified file 'debian/rules'
124--- debian/rules 2016-06-03 09:38:55 +0000
125+++ debian/rules 2016-12-09 17:04:44 +0000
126@@ -62,3 +62,4 @@
127 dh_install --sourcedir=$(TMP1_DIR) -pqtubuntu-android
128 endif
129 dh_install --sourcedir=$(TMP2_DIR) -pqtubuntu-desktop
130+ dh_install --sourcedir=$(TMP2_DIR) -pqtubuntu-appmenutheme
131
132=== modified file 'src/src.pro'
133--- src/src.pro 2014-06-18 23:10:00 +0000
134+++ src/src.pro 2016-12-09 17:04:44 +0000
135@@ -1,3 +1,3 @@
136 TEMPLATE = subdirs
137
138-SUBDIRS += ubuntumirclient
139+SUBDIRS += ubuntumirclient ubuntuappmenu
140
141=== added directory 'src/ubuntuappmenu'
142=== added file 'src/ubuntuappmenu/com.ubuntu.MenuRegistrar.xml'
143--- src/ubuntuappmenu/com.ubuntu.MenuRegistrar.xml 1970-01-01 00:00:00 +0000
144+++ src/ubuntuappmenu/com.ubuntu.MenuRegistrar.xml 2016-12-09 17:04:44 +0000
145@@ -0,0 +1,83 @@
146+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
147+<node xmlns:dox="http://www.ayatana.org/dbus/dox.dtd">
148+ <dox:d><![CDATA[
149+ @mainpage
150+
151+ An interface to register menus that are associated with a window in an application. The
152+ main interface is documented here: @ref com::ubuntu::MenuRegistrar.
153+
154+ The actual menus are transported using the gmenumodel protocol
155+ ]]></dox:d>
156+ <interface name="com.ubuntu.MenuRegistrar" xmlns:dox="http://www.ayatana.org/dbus/dox.dtd">
157+ <dox:d>
158+ An interface to register a menu from an application to be displayed in another
159+ window. This manages that association between processes and/or Mir surface IDs and the dbus
160+ address and object that provides the menus using the org.gtk.Menus interface.
161+ </dox:d>
162+ <method name="RegisterAppMenu">
163+ <dox:d><![CDATA[
164+ Associates a gmenumodel with an application
165+
166+ /note this method assumes that the connection from the caller is the DBus connection
167+ to use for the object. Applications that use multiple DBus connections will need to
168+ ensure this method is called with the same connection that implements the object.
169+ ]]></dox:d>
170+ <arg name="pid" type="u" direction="in">
171+ <dox:d>The process ID of the application for which the menu is associated</dox:d>
172+ </arg>
173+ <arg name="menuObjectPath" type="o" direction="in">
174+ <dox:d>The dbus path where the gmenumodel interface for the application menu has been exported</dox:d>
175+ </arg>
176+ <arg name="actionObjectPath" type="o" direction="in">
177+ <dox:d>The dbus path where the gactionmenu interface for the application menu actions has been exported</dox:d>
178+ </arg>
179+ <arg name="service" type="s" direction="in">
180+ <dox:d>The dbus conection name of the client application to be registered (e.g. :1.23 or org.example.service)</dox:d>
181+ </arg>
182+ </method>
183+ <method name="UnregisterAppMenu">
184+ <dox:d>
185+ A method to allow removing an application menu from the database.
186+ </dox:d>
187+ <arg name="pid" type="u" direction="in">
188+ <dox:d>The process id of the application</dox:d>
189+ </arg>
190+ <arg name="menuObjectPath" type="o" direction="in">
191+ <dox:d>The dbus path for the registered application menu to be unregistered</dox:d>
192+ </arg>
193+ </method>
194+
195+ <method name="RegisterSurfaceMenu">
196+ <dox:d><![CDATA[
197+ Associates a gmenumodel with a surface
198+
199+ /note this method assumes that the connection from the caller is the DBus connection
200+ to use for the object. Applications that use multiple DBus connections will need to
201+ ensure this method is called with the same connection that implements the object.
202+ ]]></dox:d>
203+ <arg name="surface" type="s" direction="in">
204+ <dox:d>The surface ID of the surface</dox:d>
205+ </arg>
206+ <arg name="menuObjectPath" type="o" direction="in">
207+ <dox:d>The dbus path where the gmenumodel interface for the surface menu has been exported</dox:d>
208+ </arg>
209+ <arg name="actionObjectPath" type="o" direction="in">
210+ <dox:d>The dbus path where the gactionmenu interface for the surface menu actions has been exported</dox:d>
211+ </arg>
212+ <arg name="service" type="s" direction="in">
213+ <dox:d>The dbus conection name of the client application to be registered (e.g. :1.23 or org.example.service)</dox:d>
214+ </arg>
215+ </method>
216+ <method name="UnregisterSurfaceMenu">
217+ <dox:d>
218+ A method to allow removing a surface menu from the database.
219+ </dox:d>
220+ <arg name="surfaceId" type="s" direction="in">
221+ <dox:d>The surface id of the surface</dox:d>
222+ </arg>
223+ <arg name="menuObjectPath" type="o" direction="in">
224+ <dox:d>The dbus path for the registered surface menu to be unregistered</dox:d>
225+ </arg>
226+ </method>
227+ </interface>
228+</node>
229
230=== added file 'src/ubuntuappmenu/gmenumodelexporter.cpp'
231--- src/ubuntuappmenu/gmenumodelexporter.cpp 1970-01-01 00:00:00 +0000
232+++ src/ubuntuappmenu/gmenumodelexporter.cpp 2016-12-09 17:04:44 +0000
233@@ -0,0 +1,350 @@
234+/*
235+ * Copyright (C) 2016 Canonical, Ltd.
236+ *
237+ * This program is free software: you can redistribute it and/or modify it under
238+ * the terms of the GNU Lesser General Public License version 3, as published by
239+ * the Free Software Foundation.
240+ *
241+ * This program is distributed in the hope that it will be useful, but WITHOUT
242+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
243+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
244+ * Lesser General Public License for more details.
245+ *
246+ * You should have received a copy of the GNU Lesser General Public License
247+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
248+ */
249+
250+// Local
251+#include "gmenumodelexporter.h"
252+#include "registry.h"
253+#include "logging.h"
254+
255+#include <QDebug>
256+
257+#include <functional>
258+
259+namespace {
260+
261+// Derive an action name from the label by removing spaces and Capitilizing the words.
262+// Also remove mnemonics from the label.
263+inline QString getActionString(QString label)
264+{
265+ QRegExp re("\\W");
266+ label = label.replace(QRegExp("(&|_)"), "");
267+ QStringList parts = label.split(re, QString::SkipEmptyParts);
268+
269+ QString result;
270+ Q_FOREACH(const QString& part, parts) {
271+ result += part[0].toUpper();
272+ result += part.right(part.length()-1);
273+ }
274+ return result;
275+}
276+
277+static void activate_cb(GSimpleAction *action, GVariant *, gpointer user_data)
278+{
279+ qCDebug(ubuntuappmenu, "Activate menu action '%s'", g_action_get_name(G_ACTION(action)));
280+ auto item = static_cast<UbuntuPlatformMenuItem*>(user_data);
281+ item->activated();
282+}
283+
284+static uint s_menuId = 0;
285+
286+#define MENU_OBJECT_PATH "/com/ubuntu/Menu/%1"
287+
288+} // namespace
289+
290+
291+UbuntuMenuBarExporter::UbuntuMenuBarExporter(UbuntuPlatformMenuBar * bar)
292+ : UbuntuGMenuModelExporter(bar)
293+{
294+ qCDebug(ubuntuappmenu, "UbuntuMenuBarExporter::UbuntuMenuBarExporter");
295+
296+ connect(bar, &UbuntuPlatformMenuBar::structureChanged, this, [this]() {
297+ m_structureTimer.start();
298+ });
299+ connect(&m_structureTimer, &QTimer::timeout, this, [this, bar]() {
300+ clear();
301+ Q_FOREACH(QPlatformMenu *platformMenu, bar->menus()) {
302+ GMenuItem* item = createSubmenu(platformMenu, nullptr);
303+ if (item) {
304+ g_menu_append_item(m_gmainMenu, item);
305+ g_object_unref(item);
306+ }
307+ }
308+ });
309+
310+ connect(bar, &UbuntuPlatformMenuBar::ready, this, [this]() {
311+ exportModels();
312+ });
313+}
314+
315+UbuntuMenuBarExporter::~UbuntuMenuBarExporter()
316+{
317+ qCDebug(ubuntuappmenu, "UbuntuMenuBarExporter::~UbuntuMenuBarExporter");
318+}
319+
320+UbuntuMenuExporter::UbuntuMenuExporter(UbuntuPlatformMenu *menu)
321+ : UbuntuGMenuModelExporter(menu)
322+{
323+ qCDebug(ubuntuappmenu, "UbuntuMenuExporter::UbuntuMenuExporter");
324+
325+ connect(menu, &UbuntuPlatformMenu::structureChanged, this, [this]() {
326+ m_structureTimer.start();
327+ });
328+ connect(&m_structureTimer, &QTimer::timeout, this, [this, menu]() {
329+ clear();
330+ addSubmenuItems(menu, m_gmainMenu);
331+ });
332+ addSubmenuItems(menu, m_gmainMenu);
333+}
334+
335+UbuntuMenuExporter::~UbuntuMenuExporter()
336+{
337+ qCDebug(ubuntuappmenu, "UbuntuMenuExporter::~UbuntuMenuExporter");
338+}
339+
340+UbuntuGMenuModelExporter::UbuntuGMenuModelExporter(QObject *parent)
341+ : QObject(parent)
342+ , m_connection(nullptr)
343+ , m_gmainMenu(g_menu_new())
344+ , m_gactionGroup(g_simple_action_group_new())
345+ , m_exportedModel(0)
346+ , m_exportedActions(0)
347+ , m_menuPath(QStringLiteral(MENU_OBJECT_PATH).arg(s_menuId++))
348+{
349+ m_structureTimer.setSingleShot(true);
350+ m_structureTimer.setInterval(0);
351+}
352+
353+UbuntuGMenuModelExporter::~UbuntuGMenuModelExporter()
354+{
355+ unexportModels();
356+ clear();
357+
358+ g_object_unref(m_gmainMenu);
359+ g_object_unref(m_gactionGroup);
360+}
361+
362+// Clear the menu and actions that have been created.
363+void UbuntuGMenuModelExporter::clear()
364+{
365+ Q_FOREACH(const QMetaObject::Connection& connection, m_propertyConnections) {
366+ QObject::disconnect(connection);
367+ }
368+
369+ g_menu_remove_all(m_gmainMenu);
370+
371+ Q_FOREACH(const QByteArray& action, m_actions) {
372+ g_action_map_remove_action(G_ACTION_MAP(m_gactionGroup), action.constData());
373+ }
374+ m_actions.clear();
375+}
376+
377+// Export the model on dbus
378+void UbuntuGMenuModelExporter::exportModels()
379+{
380+ GError *error = nullptr;
381+ m_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, &error);
382+ if (!m_connection) {
383+ qCWarning(ubuntuappmenu, "Failed to retreive session bus - %s", error ? error->message : "unknown error");
384+ g_error_free (error);
385+ return;
386+ }
387+
388+ QByteArray menuPath(m_menuPath.toUtf8());
389+
390+ if (m_exportedModel == 0) {
391+ m_exportedModel = g_dbus_connection_export_menu_model(m_connection, menuPath.constData(), G_MENU_MODEL(m_gmainMenu), &error);
392+ if (m_exportedModel == 0) {
393+ qCWarning(ubuntuappmenu, "Failed to export menu - %s", error ? error->message : "unknown error");
394+ g_error_free (error);
395+ error = nullptr;
396+ } else {
397+ qCDebug(ubuntuappmenu, "Exported menu on %s", g_dbus_connection_get_unique_name(m_connection));
398+ }
399+ }
400+
401+ if (m_exportedActions == 0) {
402+ m_exportedActions = g_dbus_connection_export_action_group(m_connection, menuPath.constData(), G_ACTION_GROUP(m_gactionGroup), &error);
403+ if (m_exportedActions == 0) {
404+ qCWarning(ubuntuappmenu, "Failed to export actions - %s", error ? error->message : "unknown error");
405+ g_error_free (error);
406+ error = nullptr;
407+ } else {
408+ qCDebug(ubuntuappmenu, "Exported actions on %s", g_dbus_connection_get_unique_name(m_connection));
409+ }
410+ }
411+}
412+
413+// Unexport the model
414+void UbuntuGMenuModelExporter::unexportModels()
415+{
416+ GError *error = nullptr;
417+ if (!m_connection) {
418+ qCWarning(ubuntuappmenu, "Failed to retreive session bus - %s", error ? error->message : "unknown error");
419+ return;
420+ }
421+
422+ if (m_exportedModel != 0) {
423+ g_dbus_connection_unexport_menu_model(m_connection, m_exportedModel);
424+ m_exportedModel = 0;
425+ }
426+ if (m_exportedActions != 0) {
427+ g_dbus_connection_unexport_action_group(m_connection, m_exportedActions);
428+ m_exportedActions = 0;
429+ }
430+ g_object_unref(m_connection);
431+ m_connection = nullptr;
432+}
433+
434+// Create a submenu for the given platform menu.
435+// Returns a gmenuitem entry for the menu, which must be cleaned up using g_object_unref.
436+// If forItem is suplied, use it's label.
437+GMenuItem *UbuntuGMenuModelExporter::createSubmenu(QPlatformMenu *platformMenu, UbuntuPlatformMenuItem *forItem)
438+{
439+ UbuntuPlatformMenu* gplatformMenu = static_cast<UbuntuPlatformMenu*>(platformMenu);
440+ if (!gplatformMenu) return nullptr;
441+ GMenu* menu = g_menu_new();
442+
443+ QByteArray label;
444+ if (forItem) {
445+ label = UbuntuPlatformMenuItem::get_text(forItem).toUtf8();
446+ } else {
447+ label = UbuntuPlatformMenu::get_text(gplatformMenu).toUtf8();
448+ }
449+
450+ addSubmenuItems(gplatformMenu, menu);
451+
452+ GMenuItem* gmenuItem = g_menu_item_new_submenu(label.constData(), G_MENU_MODEL(menu));
453+ g_object_unref(menu);
454+ return gmenuItem;
455+}
456+
457+// Add a platform menu's items to the given gmenu.
458+// The items are inserted into menus sections, split by the menu separators.
459+void UbuntuGMenuModelExporter::addSubmenuItems(UbuntuPlatformMenu* gplatformMenu, GMenu* menu)
460+{
461+ auto iter = gplatformMenu->menuItems().begin();
462+ auto lastSectionStart = iter;
463+ // Iterate through all the menu items adding sections when a separator is found.
464+ for (; iter != gplatformMenu->menuItems().end(); ++iter) {
465+ UbuntuPlatformMenuItem* gplatformMenuItem = static_cast<UbuntuPlatformMenuItem*>(*iter);
466+ if (!gplatformMenuItem) continue;
467+
468+ // don't add a section until we have separator
469+ if (UbuntuPlatformMenuItem::get_separator(gplatformMenuItem)) {
470+ if (lastSectionStart != gplatformMenu->menuItems().begin()) {
471+ GMenuItem* section = createSection(lastSectionStart, iter);
472+ g_menu_append_item(menu, section);
473+ g_object_unref(section);
474+ }
475+ lastSectionStart = iter + 1;
476+ } else if (lastSectionStart == gplatformMenu->menuItems().begin()) {
477+ processItemForGMenu(gplatformMenuItem, menu);
478+ }
479+ }
480+
481+ // Add the last section
482+ if (lastSectionStart != gplatformMenu->menuItems().begin() &&
483+ lastSectionStart != gplatformMenu->menuItems().end()) {
484+ GMenuItem* gsectionItem = createSection(lastSectionStart, gplatformMenu->menuItems().end());
485+ g_menu_append_item(menu, gsectionItem);
486+ g_object_unref(gsectionItem);
487+ }
488+}
489+
490+// Create and return a gmenu item for the given platform menu item.
491+// Returned GMenuItem must be cleaned up using g_object_unref
492+GMenuItem *UbuntuGMenuModelExporter::createMenuItem(QPlatformMenuItem *platformMenuItem)
493+{
494+ UbuntuPlatformMenuItem* gplatformMenuItem = static_cast<UbuntuPlatformMenuItem*>(platformMenuItem);
495+ if (!gplatformMenuItem) return nullptr;
496+
497+ QByteArray label(UbuntuPlatformMenuItem::get_text(gplatformMenuItem).toUtf8());
498+ QByteArray actionLabel(getActionString(UbuntuPlatformMenuItem::get_text(gplatformMenuItem)).toUtf8());
499+ QByteArray shortcut(UbuntuPlatformMenuItem::get_shortcut(gplatformMenuItem).toString(QKeySequence::NativeText).toUtf8());
500+
501+ GMenuItem* gmenuItem = g_menu_item_new(label.constData(), nullptr);
502+ g_menu_item_set_attribute(gmenuItem, "accel", "s", shortcut.constData());
503+ g_menu_item_set_detailed_action(gmenuItem, ("unity." + actionLabel).constData());
504+
505+ addAction(actionLabel, gplatformMenuItem);
506+ return gmenuItem;
507+}
508+
509+// Create a menu section for a section of separated menu items.
510+// Returned GMenuItem must be cleaned up using g_object_unref
511+GMenuItem *UbuntuGMenuModelExporter::createSection(QList<QPlatformMenuItem *>::const_iterator iter, QList<QPlatformMenuItem *>::const_iterator end)
512+{
513+ GMenu* gsectionMenu = g_menu_new();
514+ for (; iter != end; ++iter) {
515+ processItemForGMenu(*iter, gsectionMenu);
516+ }
517+ GMenuItem* gsectionItem = g_menu_item_new_section("", G_MENU_MODEL(gsectionMenu));
518+ g_object_unref(gsectionMenu);
519+ return gsectionItem;
520+}
521+
522+// Add the given platform menu item to the menu.
523+// If it has an attached submenu, then create and add the submenu.
524+void UbuntuGMenuModelExporter::processItemForGMenu(QPlatformMenuItem *platformMenuItem, GMenu *gmenu)
525+{
526+ UbuntuPlatformMenuItem* gplatformMenuItem = static_cast<UbuntuPlatformMenuItem*>(platformMenuItem);
527+ if (!gplatformMenuItem) return;
528+
529+ GMenuItem* gmenuItem = gplatformMenuItem->menu() ? createSubmenu(gplatformMenuItem->menu(), gplatformMenuItem) :
530+ createMenuItem(gplatformMenuItem);
531+ if (gmenuItem) {
532+ g_menu_append_item(gmenu, gmenuItem);
533+ g_object_unref(gmenuItem);
534+ }
535+}
536+
537+// Create and add an action for a menu item.
538+void UbuntuGMenuModelExporter::addAction(const QByteArray &name, UbuntuPlatformMenuItem *gplatformMenuItem)
539+{
540+ disconnect(gplatformMenuItem, &UbuntuPlatformMenuItem::checkedChanged, this, 0);
541+ disconnect(gplatformMenuItem, &UbuntuPlatformMenuItem::enabledChanged, this, 0);
542+
543+ if (m_actions.contains(name)) {
544+ g_action_map_remove_action(G_ACTION_MAP(m_gactionGroup), name.constData());
545+ m_actions.remove(name);
546+ }
547+
548+ bool checkable = UbuntuPlatformMenuItem::get_checkable(gplatformMenuItem);
549+
550+ GSimpleAction* action = nullptr;
551+ if (checkable) {
552+ bool checked = UbuntuPlatformMenuItem::get_checked(gplatformMenuItem);
553+ action = g_simple_action_new_stateful(name.constData(), nullptr, g_variant_new_boolean(checked));
554+
555+ std::function<void(bool)> updateChecked = [gplatformMenuItem, action](bool checked) {
556+ auto type = g_action_get_state_type(G_ACTION(action));
557+ if (type && g_variant_type_equal(type, G_VARIANT_TYPE_BOOLEAN)) {
558+ g_simple_action_set_state(action, g_variant_new_boolean(checked ? TRUE : FALSE));
559+ }
560+ };
561+ // save the connection to disconnect in UbuntuGMenuModelExporter::clear()
562+ m_propertyConnections << connect(gplatformMenuItem, &UbuntuPlatformMenuItem::checkedChanged, this, updateChecked);
563+ } else {
564+ action = g_simple_action_new(name.constData(), nullptr);
565+ }
566+
567+ // Enabled update
568+ std::function<void(bool)> updateEnabled = [gplatformMenuItem, action](bool enabled) {
569+ GValue value = G_VALUE_INIT;
570+ g_value_init (&value, G_TYPE_BOOLEAN);
571+ g_value_set_boolean(&value, enabled ? TRUE : FALSE);
572+ g_object_set_property(G_OBJECT(action), "enabled", &value);
573+ };
574+ updateEnabled(UbuntuPlatformMenuItem::get_enabled(gplatformMenuItem));
575+ // save the connection to disconnect in UbuntuGMenuModelExporter::clear()
576+ m_propertyConnections << connect(gplatformMenuItem, &UbuntuPlatformMenuItem::enabledChanged, this, updateEnabled);
577+
578+ g_signal_connect(action, "activate", G_CALLBACK(activate_cb), gplatformMenuItem);
579+
580+ m_actions.insert(name);
581+ g_action_map_add_action(G_ACTION_MAP(m_gactionGroup), G_ACTION(action));
582+ g_object_unref(action);
583+}
584
585=== added file 'src/ubuntuappmenu/gmenumodelexporter.h'
586--- src/ubuntuappmenu/gmenumodelexporter.h 1970-01-01 00:00:00 +0000
587+++ src/ubuntuappmenu/gmenumodelexporter.h 2016-12-09 17:04:44 +0000
588@@ -0,0 +1,83 @@
589+/*
590+ * Copyright (C) 2016 Canonical, Ltd.
591+ *
592+ * This program is free software: you can redistribute it and/or modify it under
593+ * the terms of the GNU Lesser General Public License version 3, as published by
594+ * the Free Software Foundation.
595+ *
596+ * This program is distributed in the hope that it will be useful, but WITHOUT
597+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
598+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
599+ * Lesser General Public License for more details.
600+ *
601+ * You should have received a copy of the GNU Lesser General Public License
602+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
603+ */
604+
605+#ifndef GMENUMODELEXPORTER_H
606+#define GMENUMODELEXPORTER_H
607+
608+#include "gmenumodelplatformmenu.h"
609+
610+#include <gio/gio.h>
611+
612+#include <QTimer>
613+#include <QSet>
614+#include <QMetaObject>
615+
616+// Base class for a gmenumodel exporter
617+class UbuntuGMenuModelExporter : public QObject
618+{
619+ Q_OBJECT
620+public:
621+ virtual ~UbuntuGMenuModelExporter();
622+
623+ void exportModels();
624+ void unexportModels();
625+
626+ QString menuPath() const { return m_menuPath;}
627+
628+protected:
629+ UbuntuGMenuModelExporter(QObject *parent);
630+
631+ GMenuItem *createSubmenu(QPlatformMenu* platformMenu, UbuntuPlatformMenuItem* forItem);
632+ GMenuItem *createMenuItem(QPlatformMenuItem* platformMenuItem);
633+ GMenuItem *createSection(QList<QPlatformMenuItem*>::const_iterator iter, QList<QPlatformMenuItem*>::const_iterator end);
634+ void addAction(const QByteArray& name, UbuntuPlatformMenuItem* gplatformItem);
635+
636+ void addSubmenuItems(UbuntuPlatformMenu* gplatformMenu, GMenu* menu);
637+ void processItemForGMenu(QPlatformMenuItem* item, GMenu* gmenu);
638+
639+ void clear();
640+
641+protected:
642+ GDBusConnection *m_connection;
643+ GMenu *m_gmainMenu;
644+ GSimpleActionGroup *m_gactionGroup;
645+ QSet<QByteArray> m_actions;
646+ guint m_exportedModel;
647+ guint m_exportedActions;
648+ QTimer m_structureTimer;
649+ QString m_menuPath;
650+
651+ QVector<QMetaObject::Connection> m_propertyConnections;
652+};
653+
654+// Class which exports a qt platform menu bar.
655+class UbuntuMenuBarExporter : public UbuntuGMenuModelExporter
656+{
657+public:
658+ UbuntuMenuBarExporter(UbuntuPlatformMenuBar *parent);
659+ ~UbuntuMenuBarExporter();
660+};
661+
662+// Class which exports a qt platform menu.
663+// This will allow exporting of context menus.
664+class UbuntuMenuExporter : public UbuntuGMenuModelExporter
665+{
666+public:
667+ UbuntuMenuExporter(UbuntuPlatformMenu *parent);
668+ ~UbuntuMenuExporter();
669+};
670+
671+#endif // GMENUMODELEXPORTER_H
672
673=== added file 'src/ubuntuappmenu/gmenumodelplatformmenu.cpp'
674--- src/ubuntuappmenu/gmenumodelplatformmenu.cpp 1970-01-01 00:00:00 +0000
675+++ src/ubuntuappmenu/gmenumodelplatformmenu.cpp 2016-12-09 17:04:44 +0000
676@@ -0,0 +1,526 @@
677+/*
678+ * Copyright (C) 2016 Canonical, Ltd.
679+ *
680+ * This program is free software: you can redistribute it and/or modify it under
681+ * the terms of the GNU Lesser General Public License version 3, as published by
682+ * the Free Software Foundation.
683+ *
684+ * This program is distributed in the hope that it will be useful, but WITHOUT
685+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
686+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
687+ * Lesser General Public License for more details.
688+ *
689+ * You should have received a copy of the GNU Lesser General Public License
690+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
691+ */
692+
693+// Local
694+#include "gmenumodelplatformmenu.h"
695+#include "gmenumodelexporter.h"
696+#include "registry.h"
697+#include "menuregistrar.h"
698+#include "logging.h"
699+
700+// Qt
701+#include <QDebug>
702+#include <QWindow>
703+#include <QCoreApplication>
704+
705+#define BAR_DEBUG_MSG qCDebug(ubuntuappmenu).nospace() << "UbuntuPlatformMenuBar[" << (void*)this <<"]::" << __func__
706+#define MENU_DEBUG_MSG qCDebug(ubuntuappmenu).nospace() << "UbuntuPlatformMenu[" << (void*)this <<"]::" << __func__
707+#define ITEM_DEBUG_MSG qCDebug(ubuntuappmenu).nospace() << "UbuntuPlatformMenuItem[" << (void*)this <<"]::" << __func__
708+
709+namespace {
710+
711+int logRecusion = 0;
712+
713+}
714+
715+QDebug operator<<(QDebug stream, UbuntuPlatformMenuBar* bar) {
716+ if (bar) return bar->operator<<(stream);
717+ return stream;
718+}
719+QDebug operator<<(QDebug stream, UbuntuPlatformMenu* menu) {
720+ if (menu) return menu->operator<<(stream);
721+ return stream;
722+}
723+QDebug operator<<(QDebug stream, UbuntuPlatformMenuItem* menuItem) {
724+ if (menuItem) return menuItem->operator<<(stream);
725+ return stream;
726+}
727+
728+UbuntuPlatformMenuBar::UbuntuPlatformMenuBar()
729+ : m_exporter(new UbuntuMenuBarExporter(this))
730+ , m_registrar(new UbuntuMenuRegistrar())
731+ , m_ready(false)
732+{
733+ BAR_DEBUG_MSG << "()";
734+
735+ connect(this, &UbuntuPlatformMenuBar::menuInserted, this, &UbuntuPlatformMenuBar::structureChanged);
736+ connect(this,&UbuntuPlatformMenuBar::menuRemoved, this, &UbuntuPlatformMenuBar::structureChanged);
737+}
738+
739+UbuntuPlatformMenuBar::~UbuntuPlatformMenuBar()
740+{
741+ BAR_DEBUG_MSG << "()";
742+}
743+
744+void UbuntuPlatformMenuBar::insertMenu(QPlatformMenu *menu, QPlatformMenu *before)
745+{
746+ BAR_DEBUG_MSG << "(menu=" << menu << ", before=" << before << ")";
747+
748+ if (m_menus.contains(menu)) return;
749+
750+ if (!before) {
751+ m_menus.push_back(menu);
752+ } else {
753+ for (auto iter = m_menus.begin(); iter != m_menus.end(); ++iter) {
754+ if (*iter == before) {
755+ m_menus.insert(iter, menu);
756+ break;
757+ }
758+ }
759+ }
760+ connect(static_cast<UbuntuPlatformMenu*>(menu), &UbuntuPlatformMenu::structureChanged,
761+ this, &UbuntuPlatformMenuBar::structureChanged);
762+ Q_EMIT menuInserted(menu);
763+}
764+
765+void UbuntuPlatformMenuBar::removeMenu(QPlatformMenu *menu)
766+{
767+ BAR_DEBUG_MSG << "(menu=" << menu << ")";
768+
769+ QMutableListIterator<QPlatformMenu*> iterator(m_menus);
770+ while(iterator.hasNext()) {
771+ if (iterator.next() == menu) {
772+ iterator.remove();
773+ break;
774+ }
775+ }
776+ disconnect(static_cast<UbuntuPlatformMenu*>(menu), &UbuntuPlatformMenu::structureChanged,
777+ this, &UbuntuPlatformMenuBar::structureChanged);
778+ Q_EMIT menuRemoved(menu);
779+}
780+
781+void UbuntuPlatformMenuBar::syncMenu(QPlatformMenu *menu)
782+{
783+ BAR_DEBUG_MSG << "(menu=" << menu << ")";
784+
785+ Q_UNUSED(menu)
786+}
787+
788+void UbuntuPlatformMenuBar::handleReparent(QWindow *parentWindow)
789+{
790+ BAR_DEBUG_MSG << "(parentWindow=" << parentWindow << ")";
791+
792+ setReady(true);
793+ m_registrar->registerMenuForWindow(parentWindow, QDBusObjectPath(m_exporter->menuPath()));
794+}
795+
796+QPlatformMenu *UbuntuPlatformMenuBar::menuForTag(quintptr tag) const
797+{
798+ Q_FOREACH(QPlatformMenu* menu, m_menus) {
799+ if (menu->tag() == tag) {
800+ return menu;
801+ }
802+ }
803+ return nullptr;
804+}
805+
806+const QList<QPlatformMenu *> UbuntuPlatformMenuBar::menus() const
807+{
808+ return m_menus;
809+}
810+
811+QDebug UbuntuPlatformMenuBar::operator<<(QDebug stream)
812+{
813+ stream.nospace().noquote() << QString("%1").arg("", logRecusion, QLatin1Char('\t'))
814+ << "UbuntuPlatformMenuBar(this=" << (void*)this << ")" << endl;
815+ Q_FOREACH(QPlatformMenu* menu, m_menus) {
816+ auto myMenu = static_cast<UbuntuPlatformMenu*>(menu);
817+ if (myMenu) {
818+ logRecusion++;
819+ stream << myMenu;
820+ logRecusion--;
821+ }
822+ }
823+
824+ return stream;
825+}
826+
827+#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
828+QPlatformMenu *UbuntuPlatformMenuBar::createMenu() const
829+{
830+ return new UbuntuPlatformMenu();
831+}
832+#endif
833+
834+void UbuntuPlatformMenuBar::setReady(bool isReady)
835+{
836+ if (m_ready != isReady) {
837+ m_ready = isReady;
838+ Q_EMIT ready();
839+ }
840+}
841+
842+//////////////////////////////////////////////////////////////
843+
844+UbuntuPlatformMenu::UbuntuPlatformMenu()
845+ : m_parentWindow(nullptr)
846+ , m_exporter(nullptr)
847+ , m_registrar(nullptr)
848+{
849+ MENU_DEBUG_MSG << "()";
850+
851+ connect(this, &UbuntuPlatformMenu::menuItemInserted, this, &UbuntuPlatformMenu::structureChanged);
852+ connect(this, &UbuntuPlatformMenu::menuItemRemoved, this, &UbuntuPlatformMenu::structureChanged);
853+}
854+
855+UbuntuPlatformMenu::~UbuntuPlatformMenu()
856+{
857+ MENU_DEBUG_MSG << "()";
858+}
859+
860+void UbuntuPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
861+{
862+ MENU_DEBUG_MSG << "(menuItem=" << menuItem << ", before=" << before << ")";
863+
864+ if (m_menuItems.contains(menuItem)) return;
865+
866+ if (!before) {
867+ m_menuItems.push_back(menuItem);
868+ } else {
869+ for (auto iter = m_menuItems.begin(); iter != m_menuItems.end(); ++iter) {
870+ if (*iter == before) {
871+ m_menuItems.insert(iter, menuItem);
872+ break;
873+ }
874+ }
875+ }
876+
877+ Q_EMIT menuItemInserted(menuItem);
878+}
879+
880+void UbuntuPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem)
881+{
882+ MENU_DEBUG_MSG << "(menuItem=" << menuItem << ")";
883+
884+ QMutableListIterator<QPlatformMenuItem*> iterator(m_menuItems);
885+ while(iterator.hasNext()) {
886+ if (iterator.next() == menuItem) {
887+ iterator.remove();
888+ break;
889+ }
890+ }
891+ Q_EMIT menuItemRemoved(menuItem);
892+}
893+
894+void UbuntuPlatformMenu::syncMenuItem(QPlatformMenuItem *menuItem)
895+{
896+ MENU_DEBUG_MSG << "(menuItem=" << menuItem << ")";
897+
898+ Q_UNUSED(menuItem)
899+}
900+
901+void UbuntuPlatformMenu::syncSeparatorsCollapsible(bool enable)
902+{
903+ MENU_DEBUG_MSG << "(enable=" << enable << ")";
904+ Q_UNUSED(enable)
905+}
906+
907+void UbuntuPlatformMenu::setTag(quintptr tag)
908+{
909+ MENU_DEBUG_MSG << "(tag=" << tag << ")";
910+ m_tag = tag;
911+}
912+
913+quintptr UbuntuPlatformMenu::tag() const
914+{
915+ return m_tag;
916+}
917+
918+void UbuntuPlatformMenu::setText(const QString &text)
919+{
920+ MENU_DEBUG_MSG << "(text=" << text << ")";
921+ if (m_text != text) {
922+ m_text = text;
923+ Q_EMIT propertyChanged();
924+ }
925+}
926+
927+void UbuntuPlatformMenu::setIcon(const QIcon &icon)
928+{
929+ MENU_DEBUG_MSG << "(icon=" << icon.name() << ")";
930+
931+ if (!icon.isNull() || (!m_icon.isNull() && icon.isNull())) {
932+ m_icon = icon;
933+ Q_EMIT propertyChanged();
934+ }
935+}
936+
937+void UbuntuPlatformMenu::setEnabled(bool enabled)
938+{
939+ MENU_DEBUG_MSG << "(enabled=" << enabled << ")";
940+
941+ if (m_enabled != enabled) {
942+ m_enabled = enabled;
943+ Q_EMIT propertyChanged();
944+ }
945+}
946+
947+void UbuntuPlatformMenu::setVisible(bool isVisible)
948+{
949+ MENU_DEBUG_MSG << "(visible=" << isVisible << ")";
950+
951+ if (m_visible != isVisible) {
952+ m_visible = isVisible;
953+ Q_EMIT propertyChanged();
954+ }
955+}
956+
957+void UbuntuPlatformMenu::setMinimumWidth(int width)
958+{
959+ MENU_DEBUG_MSG << "(width=" << width << ")";
960+
961+ Q_UNUSED(width)
962+}
963+
964+void UbuntuPlatformMenu::setFont(const QFont &font)
965+{
966+ MENU_DEBUG_MSG << "(font=" << font << ")";
967+
968+ Q_UNUSED(font)
969+}
970+
971+void UbuntuPlatformMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item)
972+{
973+ MENU_DEBUG_MSG << "(parentWindow=" << parentWindow << ", targetRect=" << targetRect << ", item=" << item << ")";
974+
975+ if (!m_exporter) {
976+ m_exporter.reset(new UbuntuMenuExporter(this));
977+ m_exporter->exportModels();
978+ }
979+
980+ if (parentWindow != m_parentWindow) {
981+ if (m_parentWindow) {
982+ m_registrar->unregisterMenu();
983+ }
984+
985+ m_parentWindow = parentWindow;
986+
987+ if (m_parentWindow) {
988+ if (!m_registrar) m_registrar.reset(new UbuntuMenuRegistrar);
989+ m_registrar->registerMenuForWindow(const_cast<QWindow*>(m_parentWindow),
990+ QDBusObjectPath(m_exporter->menuPath()));
991+ }
992+ }
993+
994+ Q_UNUSED(targetRect);
995+ Q_UNUSED(item);
996+ setVisible(true);
997+}
998+
999+void UbuntuPlatformMenu::dismiss()
1000+{
1001+ MENU_DEBUG_MSG << "()";
1002+
1003+ if (m_registrar) { m_registrar->unregisterMenu(); }
1004+ if (m_exporter) { m_exporter->unexportModels(); }
1005+}
1006+
1007+QPlatformMenuItem *UbuntuPlatformMenu::menuItemAt(int position) const
1008+{
1009+ if (position < 0 || position >= m_menuItems.count()) return nullptr;
1010+ return m_menuItems.at(position);
1011+}
1012+
1013+QPlatformMenuItem *UbuntuPlatformMenu::menuItemForTag(quintptr tag) const
1014+{
1015+ Q_FOREACH(QPlatformMenuItem* menuItem, m_menuItems) {
1016+ if (menuItem->tag() == tag) {
1017+ return menuItem;
1018+ }
1019+ }
1020+ return nullptr;
1021+}
1022+
1023+QPlatformMenuItem *UbuntuPlatformMenu::createMenuItem() const
1024+{
1025+ return new UbuntuPlatformMenuItem();
1026+}
1027+
1028+#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
1029+QPlatformMenu *UbuntuPlatformMenu::createSubMenu() const
1030+{
1031+ return new UbuntuPlatformMenu();
1032+}
1033+#endif
1034+
1035+const QList<QPlatformMenuItem *> UbuntuPlatformMenu::menuItems() const
1036+{
1037+ return m_menuItems;
1038+}
1039+
1040+QDebug UbuntuPlatformMenu::operator<<(QDebug stream)
1041+{
1042+ stream.nospace().noquote() << QString("%1").arg("", logRecusion, QLatin1Char('\t'))
1043+ << "UbuntuPlatformMenu(this=" << (void*)this << ", text=\"" << m_text << "\")" << endl;
1044+ Q_FOREACH(QPlatformMenuItem* item, m_menuItems) {
1045+ logRecusion++;
1046+ auto myItem = static_cast<UbuntuPlatformMenuItem*>(item);
1047+ if (myItem) {
1048+ stream << myItem;
1049+ }
1050+ logRecusion--;
1051+ }
1052+ return stream;
1053+}
1054+
1055+//////////////////////////////////////////////////////////////
1056+
1057+UbuntuPlatformMenuItem::UbuntuPlatformMenuItem()
1058+ : m_menu(nullptr)
1059+{
1060+ ITEM_DEBUG_MSG << "()";
1061+}
1062+
1063+UbuntuPlatformMenuItem::~UbuntuPlatformMenuItem()
1064+{
1065+ ITEM_DEBUG_MSG << "()";
1066+}
1067+
1068+void UbuntuPlatformMenuItem::setTag(quintptr tag)
1069+{
1070+ ITEM_DEBUG_MSG << "(tag=" << tag << ")";
1071+ m_tag = tag;
1072+}
1073+
1074+quintptr UbuntuPlatformMenuItem::tag() const
1075+{
1076+ return m_tag;
1077+}
1078+
1079+void UbuntuPlatformMenuItem::setText(const QString &text)
1080+{
1081+ ITEM_DEBUG_MSG << "(text=" << text << ")";
1082+ if (m_text != text) {
1083+ m_text = text;
1084+ Q_EMIT propertyChanged();
1085+ }
1086+}
1087+
1088+void UbuntuPlatformMenuItem::setIcon(const QIcon &icon)
1089+{
1090+ ITEM_DEBUG_MSG << "(icon=" << icon.name() << ")";
1091+
1092+ if (!icon.isNull() || (!m_icon.isNull() && icon.isNull())) {
1093+ m_icon = icon;
1094+ Q_EMIT propertyChanged();
1095+ }
1096+}
1097+
1098+void UbuntuPlatformMenuItem::setVisible(bool isVisible)
1099+{
1100+ ITEM_DEBUG_MSG << "(visible=" << isVisible << ")";
1101+ if (m_visible != isVisible) {
1102+ m_visible = isVisible;
1103+ Q_EMIT propertyChanged();
1104+ }
1105+}
1106+
1107+void UbuntuPlatformMenuItem::setIsSeparator(bool isSeparator)
1108+{
1109+ ITEM_DEBUG_MSG << "(separator=" << isSeparator << ")";
1110+ if (m_separator != isSeparator) {
1111+ m_separator = isSeparator;
1112+ Q_EMIT propertyChanged();
1113+ }
1114+}
1115+
1116+void UbuntuPlatformMenuItem::setFont(const QFont &font)
1117+{
1118+ ITEM_DEBUG_MSG << "(font=" << font << ")";
1119+ Q_UNUSED(font);
1120+}
1121+
1122+void UbuntuPlatformMenuItem::setRole(QPlatformMenuItem::MenuRole role)
1123+{
1124+ ITEM_DEBUG_MSG << "(role=" << role << ")";
1125+ Q_UNUSED(role);
1126+}
1127+
1128+void UbuntuPlatformMenuItem::setCheckable(bool checkable)
1129+{
1130+ ITEM_DEBUG_MSG << "(checkable=" << checkable << ")";
1131+ if (m_checkable != checkable) {
1132+ m_checkable = checkable;
1133+ Q_EMIT propertyChanged();
1134+ }
1135+}
1136+
1137+void UbuntuPlatformMenuItem::setChecked(bool isChecked)
1138+{
1139+ ITEM_DEBUG_MSG << "(checked=" << isChecked << ")";
1140+ if (m_checked != isChecked) {
1141+ m_checked = isChecked;
1142+ Q_EMIT checkedChanged(isChecked);
1143+ Q_EMIT propertyChanged();
1144+ }
1145+}
1146+
1147+void UbuntuPlatformMenuItem::setShortcut(const QKeySequence &shortcut)
1148+{
1149+ ITEM_DEBUG_MSG << "(shortcut=" << shortcut << ")";
1150+ if (m_shortcut != shortcut) {
1151+ m_shortcut = shortcut;
1152+ Q_EMIT propertyChanged();
1153+ }
1154+}
1155+
1156+void UbuntuPlatformMenuItem::setEnabled(bool enabled)
1157+{
1158+ ITEM_DEBUG_MSG << "(enabled=" << enabled << ")";
1159+ if (m_enabled != enabled) {
1160+ m_enabled = enabled;
1161+ Q_EMIT enabledChanged(enabled);
1162+ Q_EMIT propertyChanged();
1163+ }
1164+}
1165+
1166+void UbuntuPlatformMenuItem::setIconSize(int size)
1167+{
1168+ ITEM_DEBUG_MSG << "(size=" << size << ")";
1169+ Q_UNUSED(size);
1170+}
1171+
1172+void UbuntuPlatformMenuItem::setMenu(QPlatformMenu *menu)
1173+{
1174+ ITEM_DEBUG_MSG << "(menu=" << menu << ")";
1175+ if (m_menu != menu) {
1176+ m_menu = menu;
1177+ Q_EMIT propertyChanged();
1178+ }
1179+}
1180+
1181+QPlatformMenu *UbuntuPlatformMenuItem::menu() const
1182+{
1183+ return m_menu;
1184+}
1185+
1186+QDebug UbuntuPlatformMenuItem::operator<<(QDebug stream)
1187+{
1188+ QString properties = "text=\"" + m_text + "\"";
1189+
1190+ stream.nospace().noquote() << QString("%1").arg("", logRecusion, QLatin1Char('\t'))
1191+ << "UbuntuPlatformMenuItem(this=" << (void*)this << ", "
1192+ << (m_separator ? "Separator" : properties) << ")" << endl;
1193+ if (m_menu) {
1194+ auto myMenu = static_cast<UbuntuPlatformMenu*>(m_menu);
1195+ if (myMenu) {
1196+ logRecusion++;
1197+ stream << myMenu;
1198+ logRecusion--;
1199+ }
1200+ }
1201+ return stream;
1202+}
1203
1204=== added file 'src/ubuntuappmenu/gmenumodelplatformmenu.h'
1205--- src/ubuntuappmenu/gmenumodelplatformmenu.h 1970-01-01 00:00:00 +0000
1206+++ src/ubuntuappmenu/gmenumodelplatformmenu.h 2016-12-09 17:04:44 +0000
1207@@ -0,0 +1,181 @@
1208+/*
1209+ * Copyright (C) 2016 Canonical, Ltd.
1210+ *
1211+ * This program is free software: you can redistribute it and/or modify it under
1212+ * the terms of the GNU Lesser General Public License version 3, as published by
1213+ * the Free Software Foundation.
1214+ *
1215+ * This program is distributed in the hope that it will be useful, but WITHOUT
1216+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
1217+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1218+ * Lesser General Public License for more details.
1219+ *
1220+ * You should have received a copy of the GNU Lesser General Public License
1221+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1222+ */
1223+
1224+#ifndef EXPORTEDPLATFORMMENUBAR_H
1225+#define EXPORTEDPLATFORMMENUBAR_H
1226+
1227+#include <qpa/qplatformmenu.h>
1228+
1229+// Local
1230+class UbuntuGMenuModelExporter;
1231+class UbuntuMenuRegistrar;
1232+class QWindow;
1233+
1234+class UbuntuPlatformMenuBar : public QPlatformMenuBar
1235+{
1236+ Q_OBJECT
1237+public:
1238+ UbuntuPlatformMenuBar();
1239+ ~UbuntuPlatformMenuBar();
1240+
1241+ QString exportedPath() const;
1242+
1243+ virtual void insertMenu(QPlatformMenu *menu, QPlatformMenu* before) override;
1244+ virtual void removeMenu(QPlatformMenu *menu) override;
1245+ virtual void syncMenu(QPlatformMenu *menu) override;
1246+ virtual void handleReparent(QWindow *newParentWindow) override;
1247+ virtual QPlatformMenu *menuForTag(quintptr tag) const override;
1248+
1249+ const QList<QPlatformMenu*> menus() const;
1250+
1251+ QDebug operator<<(QDebug stream);
1252+
1253+#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
1254+ virtual QPlatformMenu *createMenu() const override;
1255+#endif
1256+
1257+Q_SIGNALS:
1258+ void menuInserted(QPlatformMenu *menu);
1259+ void menuRemoved(QPlatformMenu *menu);
1260+
1261+ void structureChanged();
1262+ void ready();
1263+
1264+private:
1265+ void setReady(bool);
1266+
1267+ QList<QPlatformMenu*> m_menus;
1268+ QScopedPointer<UbuntuGMenuModelExporter> m_exporter;
1269+ QScopedPointer<UbuntuMenuRegistrar> m_registrar;
1270+ bool m_ready;
1271+};
1272+
1273+#define MENU_PROPERTY(class, name, type, defaultValue) \
1274+ static type get_##name(const class *menuItem) { return menuItem->m_##name; } \
1275+ type m_##name = defaultValue;
1276+
1277+class Q_DECL_EXPORT UbuntuPlatformMenu : public QPlatformMenu
1278+{
1279+ Q_OBJECT
1280+public:
1281+ UbuntuPlatformMenu();
1282+ ~UbuntuPlatformMenu();
1283+
1284+ virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) override;
1285+ virtual void removeMenuItem(QPlatformMenuItem *menuItem) override;
1286+ virtual void syncMenuItem(QPlatformMenuItem *menuItem) override;
1287+ virtual void syncSeparatorsCollapsible(bool enable) override;
1288+
1289+ virtual void setTag(quintptr tag) override;
1290+ virtual quintptr tag() const override;
1291+
1292+ virtual void setText(const QString &text) override;
1293+ virtual void setIcon(const QIcon &icon) override;
1294+ virtual void setEnabled(bool isEnabled) override;
1295+ virtual void setVisible(bool isVisible) override;
1296+ virtual void setMinimumWidth(int width) override;
1297+ virtual void setFont(const QFont &font) override;
1298+
1299+ virtual void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item);
1300+
1301+ virtual void dismiss(); // Closes this and all its related menu popups
1302+
1303+ virtual QPlatformMenuItem *menuItemAt(int position) const override;
1304+ virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const override;
1305+
1306+ virtual QPlatformMenuItem *createMenuItem() const override;
1307+#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
1308+ virtual QPlatformMenu *createSubMenu() const override;
1309+#endif
1310+
1311+ int id() const;
1312+
1313+ const QList<QPlatformMenuItem*> menuItems() const;
1314+
1315+ QDebug operator<<(QDebug stream);
1316+
1317+Q_SIGNALS:
1318+ void menuItemInserted(QPlatformMenuItem *menuItem);
1319+ void menuItemRemoved(QPlatformMenuItem *menuItem);
1320+ void structureChanged();
1321+ void propertyChanged();
1322+
1323+private:
1324+ MENU_PROPERTY(UbuntuPlatformMenu, visible, bool, true)
1325+ MENU_PROPERTY(UbuntuPlatformMenu, text, QString, QString())
1326+ MENU_PROPERTY(UbuntuPlatformMenu, enabled, bool, true)
1327+ MENU_PROPERTY(UbuntuPlatformMenu, icon, QIcon, QIcon())
1328+
1329+ quintptr m_tag;
1330+ QList<QPlatformMenuItem*> m_menuItems;
1331+ const QWindow* m_parentWindow;
1332+ QScopedPointer<UbuntuGMenuModelExporter> m_exporter;
1333+ QScopedPointer<UbuntuMenuRegistrar> m_registrar;
1334+
1335+ friend class UbuntuGMenuModelExporter;
1336+};
1337+
1338+
1339+class Q_DECL_EXPORT UbuntuPlatformMenuItem : public QPlatformMenuItem
1340+{
1341+ Q_OBJECT
1342+public:
1343+ UbuntuPlatformMenuItem();
1344+ ~UbuntuPlatformMenuItem();
1345+
1346+ virtual void setTag(quintptr tag) override;
1347+ virtual quintptr tag() const override;
1348+
1349+ virtual void setText(const QString &text) override;
1350+ virtual void setIcon(const QIcon &icon) override;
1351+ virtual void setMenu(QPlatformMenu *menu) override;
1352+ virtual void setVisible(bool isVisible) override;
1353+ virtual void setIsSeparator(bool isSeparator) override;
1354+ virtual void setFont(const QFont &font) override;
1355+ virtual void setRole(MenuRole role) override;
1356+ virtual void setCheckable(bool checkable) override;
1357+ virtual void setChecked(bool isChecked) override;
1358+ virtual void setShortcut(const QKeySequence& shortcut) override;
1359+ virtual void setEnabled(bool enabled) override;
1360+ virtual void setIconSize(int size) override;
1361+
1362+ QPlatformMenu* menu() const;
1363+
1364+ QDebug operator<<(QDebug stream);
1365+
1366+Q_SIGNALS:
1367+ void checkedChanged(bool);
1368+ void enabledChanged(bool);
1369+ void propertyChanged();
1370+
1371+private:
1372+ MENU_PROPERTY(UbuntuPlatformMenuItem, separator, bool, false)
1373+ MENU_PROPERTY(UbuntuPlatformMenuItem, visible, bool, true)
1374+ MENU_PROPERTY(UbuntuPlatformMenuItem, text, QString, QString())
1375+ MENU_PROPERTY(UbuntuPlatformMenuItem, enabled, bool, true)
1376+ MENU_PROPERTY(UbuntuPlatformMenuItem, checkable, bool, false)
1377+ MENU_PROPERTY(UbuntuPlatformMenuItem, checked, bool, false)
1378+ MENU_PROPERTY(UbuntuPlatformMenuItem, shortcut, QKeySequence, QKeySequence())
1379+ MENU_PROPERTY(UbuntuPlatformMenuItem, icon, QIcon, QIcon())
1380+ MENU_PROPERTY(UbuntuPlatformMenuItem, iconSize, int, 16)
1381+ MENU_PROPERTY(UbuntuPlatformMenuItem, menu, QPlatformMenu*, nullptr)
1382+
1383+
1384+ quintptr m_tag;
1385+ friend class UbuntuGMenuModelExporter;
1386+};
1387+
1388+#endif // EXPORTEDPLATFORMMENUBAR_H
1389
1390=== added file 'src/ubuntuappmenu/logging.h'
1391--- src/ubuntuappmenu/logging.h 1970-01-01 00:00:00 +0000
1392+++ src/ubuntuappmenu/logging.h 2016-12-09 17:04:44 +0000
1393@@ -0,0 +1,27 @@
1394+/*
1395+ * Copyright (C) 2016 Canonical, Ltd.
1396+ *
1397+ * This program is free software: you can redistribute it and/or modify it under
1398+ * the terms of the GNU Lesser General Public License version 3, as published by
1399+ * the Free Software Foundation.
1400+ *
1401+ * This program is distributed in the hope that it will be useful, but WITHOUT
1402+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
1403+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1404+ * Lesser General Public License for more details.
1405+ *
1406+ * You should have received a copy of the GNU Lesser General Public License
1407+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1408+ */
1409+
1410+#ifndef QUBUNTUTHEMELOGGING_H
1411+#define QUBUNTUTHEMELOGGING_H
1412+
1413+#include <QLoggingCategory>
1414+
1415+#define ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
1416+
1417+Q_DECLARE_LOGGING_CATEGORY(ubuntuappmenu)
1418+Q_DECLARE_LOGGING_CATEGORY(ubuntuappmenuRegistrar)
1419+
1420+#endif // QUBUNTUTHEMELOGGING_H
1421
1422=== added file 'src/ubuntuappmenu/menuregistrar.cpp'
1423--- src/ubuntuappmenu/menuregistrar.cpp 1970-01-01 00:00:00 +0000
1424+++ src/ubuntuappmenu/menuregistrar.cpp 2016-12-09 17:04:44 +0000
1425@@ -0,0 +1,137 @@
1426+/*
1427+ * Copyright (C) 2016 Canonical, Ltd.
1428+ *
1429+ * This program is free software: you can redistribute it and/or modify it under
1430+ * the terms of the GNU Lesser General Public License version 3, as published by
1431+ * the Free Software Foundation.
1432+ *
1433+ * This program is distributed in the hope that it will be useful, but WITHOUT
1434+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
1435+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1436+ * Lesser General Public License for more details.
1437+ *
1438+ * You should have received a copy of the GNU Lesser General Public License
1439+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1440+ */
1441+
1442+#include "menuregistrar.h"
1443+#include "registry.h"
1444+#include "logging.h"
1445+
1446+#include <QDebug>
1447+#include <QDBusObjectPath>
1448+#include <QGuiApplication>
1449+#include <qpa/qplatformnativeinterface.h>
1450+#include <qpa/qplatformwindow.h>
1451+
1452+namespace {
1453+
1454+bool isMirClient() {
1455+ return qGuiApp->platformName() == "ubuntumirclient";
1456+}
1457+
1458+}
1459+
1460+UbuntuMenuRegistrar::UbuntuMenuRegistrar()
1461+ : m_connection(nullptr)
1462+ , m_registeredProcessId(~0)
1463+{
1464+ GError *error = NULL;
1465+ m_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1466+ if (!m_connection) {
1467+ qCWarning(ubuntuappmenuRegistrar, "Failed to retreive session bus - %s", error ? error->message : "unknown error");
1468+ g_error_free (error);
1469+ return;
1470+ }
1471+ m_service = g_dbus_connection_get_unique_name(m_connection);
1472+ connect(UbuntuMenuRegistry::instance(), &UbuntuMenuRegistry::serviceChanged, this, &UbuntuMenuRegistrar::onRegistrarServiceChanged);
1473+
1474+ if (isMirClient()) {
1475+ auto nativeInterface = qGuiApp->platformNativeInterface();
1476+ connect(nativeInterface, &QPlatformNativeInterface::windowPropertyChanged, this, [this](QPlatformWindow* window, const QString &property) {
1477+ if (property != QStringLiteral("persistentSurfaceId")) {
1478+ return;
1479+ }
1480+ if (window->window() == m_window) {
1481+ registerMenuForWindow(m_window, m_path);
1482+ }
1483+ });
1484+ }
1485+}
1486+
1487+UbuntuMenuRegistrar::~UbuntuMenuRegistrar()
1488+{
1489+ if (m_connection) {
1490+ g_object_unref(m_connection);
1491+ }
1492+ unregisterMenu();
1493+}
1494+
1495+void UbuntuMenuRegistrar::registerMenuForWindow(QWindow* window, const QDBusObjectPath& path)
1496+{
1497+ unregisterMenu();
1498+
1499+ m_window = window;
1500+ m_path = path;
1501+
1502+ registerMenu();
1503+}
1504+
1505+void UbuntuMenuRegistrar::registerMenu()
1506+{
1507+ if (UbuntuMenuRegistry::instance()->isConnected() && m_window) {
1508+ if (isMirClient()) {
1509+ registerSurfaceMenu();
1510+ } else {
1511+ registerApplicationMenu();
1512+ }
1513+ }
1514+}
1515+
1516+void UbuntuMenuRegistrar::unregisterMenu()
1517+{
1518+ if (!m_registeredSurfaceId.isEmpty()) {
1519+ unregisterSurfaceMenu();
1520+ } else if (m_registeredProcessId != ~0) {
1521+ unregisterApplicationMenu();
1522+ }
1523+}
1524+
1525+void UbuntuMenuRegistrar::registerSurfaceMenu()
1526+{
1527+ auto nativeInterface = qGuiApp->platformNativeInterface();
1528+ QByteArray persistentSurfaceId = nativeInterface->windowProperty(m_window->handle(), "persistentSurfaceId", QByteArray()).toByteArray();
1529+ if (persistentSurfaceId.isEmpty()) return;
1530+
1531+ UbuntuMenuRegistry::instance()->registerSurfaceMenu(persistentSurfaceId, m_path, m_service);
1532+ m_registeredSurfaceId = persistentSurfaceId;
1533+}
1534+
1535+void UbuntuMenuRegistrar::unregisterSurfaceMenu()
1536+{
1537+ if (UbuntuMenuRegistry::instance()->isConnected()) {
1538+ UbuntuMenuRegistry::instance()->unregisterSurfaceMenu(m_registeredSurfaceId, m_path);
1539+ }
1540+ m_registeredSurfaceId.clear();
1541+}
1542+
1543+void UbuntuMenuRegistrar::registerApplicationMenu()
1544+{
1545+ pid_t pid = getpid();
1546+ UbuntuMenuRegistry::instance()->registerApplicationMenu(pid, m_path, m_service);
1547+ m_registeredProcessId = pid;
1548+}
1549+
1550+void UbuntuMenuRegistrar::unregisterApplicationMenu()
1551+{
1552+ if (UbuntuMenuRegistry::instance()->isConnected()) {
1553+ UbuntuMenuRegistry::instance()->unregisterApplicationMenu(m_registeredProcessId, m_path);
1554+ }
1555+ m_registeredProcessId = ~0;
1556+}
1557+
1558+void UbuntuMenuRegistrar::onRegistrarServiceChanged()
1559+{
1560+ unregisterMenu();
1561+ registerMenu();
1562+}
1563
1564=== added file 'src/ubuntuappmenu/menuregistrar.h'
1565--- src/ubuntuappmenu/menuregistrar.h 1970-01-01 00:00:00 +0000
1566+++ src/ubuntuappmenu/menuregistrar.h 2016-12-09 17:04:44 +0000
1567@@ -0,0 +1,59 @@
1568+/*
1569+ * Copyright (C) 2016 Canonical, Ltd.
1570+ *
1571+ * This program is free software: you can redistribute it and/or modify it under
1572+ * the terms of the GNU Lesser General Public License version 3, as published by
1573+ * the Free Software Foundation.
1574+ *
1575+ * This program is distributed in the hope that it will be useful, but WITHOUT
1576+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
1577+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1578+ * Lesser General Public License for more details.
1579+ *
1580+ * You should have received a copy of the GNU Lesser General Public License
1581+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1582+ */
1583+
1584+#ifndef MENUREGISTRAR_H
1585+#define MENUREGISTRAR_H
1586+
1587+#include <QObject>
1588+#include <QWindow>
1589+#include <QPointer>
1590+#include <QDBusObjectPath>
1591+
1592+#include <gio/gio.h>
1593+
1594+class UbuntuMenuRegistrar : public QObject
1595+{
1596+ Q_OBJECT
1597+public:
1598+ UbuntuMenuRegistrar();
1599+ ~UbuntuMenuRegistrar();
1600+
1601+ void registerMenuForWindow(QWindow* window, const QDBusObjectPath& path);
1602+ void unregisterMenu();
1603+
1604+private Q_SLOTS:
1605+ void registerSurfaceMenu();
1606+ void onRegistrarServiceChanged();
1607+
1608+private:
1609+ void registerMenu();
1610+
1611+ void registerApplicationMenu();
1612+ void unregisterApplicationMenu();
1613+
1614+ void unregisterSurfaceMenu();
1615+
1616+ GDBusConnection *m_connection;
1617+ QString m_service;
1618+ QDBusObjectPath m_path;
1619+ QPointer<QWindow> m_window;
1620+ QString m_registeredSurfaceId;
1621+ pid_t m_registeredProcessId;
1622+};
1623+
1624+
1625+#endif // MENUREGISTRAR_H
1626+
1627
1628=== added file 'src/ubuntuappmenu/registry.cpp'
1629--- src/ubuntuappmenu/registry.cpp 1970-01-01 00:00:00 +0000
1630+++ src/ubuntuappmenu/registry.cpp 2016-12-09 17:04:44 +0000
1631@@ -0,0 +1,97 @@
1632+/*
1633+ * Copyright (C) 2016 Canonical, Ltd.
1634+ *
1635+ * This program is free software: you can redistribute it and/or modify it under
1636+ * the terms of the GNU Lesser General Public License version 3, as published by
1637+ * the Free Software Foundation.
1638+ *
1639+ * This program is distributed in the hope that it will be useful, but WITHOUT
1640+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
1641+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1642+ * Lesser General Public License for more details.
1643+ *
1644+ * You should have received a copy of the GNU Lesser General Public License
1645+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1646+ */
1647+
1648+#include "registry.h"
1649+#include "logging.h"
1650+#include "menuregistrar_interface.h"
1651+
1652+#include <QDBusObjectPath>
1653+#include <QDBusServiceWatcher>
1654+
1655+Q_LOGGING_CATEGORY(ubuntuappmenuRegistrar, "ubuntuappmenu.registrar", QtWarningMsg)
1656+
1657+#define REGISTRAR_SERVICE "com.ubuntu.MenuRegistrar"
1658+#define REGISTRY_OBJECT_PATH "/com/ubuntu/MenuRegistrar"
1659+
1660+UbuntuMenuRegistry *UbuntuMenuRegistry::instance()
1661+{
1662+ static UbuntuMenuRegistry* registry(new UbuntuMenuRegistry());
1663+ return registry;
1664+}
1665+
1666+UbuntuMenuRegistry::UbuntuMenuRegistry(QObject* parent)
1667+ : QObject(parent)
1668+ , m_serviceWatcher(new QDBusServiceWatcher(REGISTRAR_SERVICE, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this))
1669+ , m_interface(new ComUbuntuMenuRegistrarInterface(REGISTRAR_SERVICE, REGISTRY_OBJECT_PATH, QDBusConnection::sessionBus(), this))
1670+ , m_connected(m_interface->isValid())
1671+{
1672+ connect(m_serviceWatcher.data(), &QDBusServiceWatcher::serviceOwnerChanged, this, &UbuntuMenuRegistry::serviceOwnerChanged);
1673+}
1674+
1675+UbuntuMenuRegistry::~UbuntuMenuRegistry()
1676+{
1677+}
1678+
1679+void UbuntuMenuRegistry::registerApplicationMenu(pid_t pid, QDBusObjectPath menuObjectPath, const QString &service)
1680+{
1681+ qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::registerMenu(pid=%d, menuObjectPath=%s, service=%s)",
1682+ pid,
1683+ qPrintable(menuObjectPath.path()),
1684+ qPrintable(service));
1685+
1686+ m_interface->RegisterAppMenu(pid, menuObjectPath, menuObjectPath, service);
1687+}
1688+
1689+void UbuntuMenuRegistry::unregisterApplicationMenu(pid_t pid, QDBusObjectPath menuObjectPath)
1690+{
1691+ qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::unregisterSurfaceMenu(pid=%d, menuObjectPath=%s)",
1692+ pid,
1693+ qPrintable(menuObjectPath.path()));
1694+
1695+ m_interface->UnregisterAppMenu(pid, menuObjectPath);
1696+}
1697+
1698+void UbuntuMenuRegistry::registerSurfaceMenu(const QString &surfaceId, QDBusObjectPath menuObjectPath, const QString &service)
1699+{
1700+ qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::registerMenu(surfaceId=%s, menuObjectPath=%s, service=%s)",
1701+ qPrintable(surfaceId),
1702+ qPrintable(menuObjectPath.path()),
1703+ qPrintable(service));
1704+
1705+ m_interface->RegisterSurfaceMenu(surfaceId, menuObjectPath, menuObjectPath, service);
1706+}
1707+
1708+void UbuntuMenuRegistry::unregisterSurfaceMenu(const QString &surfaceId, QDBusObjectPath menuObjectPath)
1709+{
1710+ qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::unregisterSurfaceMenu(surfaceId=%s, menuObjectPath=%s)",
1711+ qPrintable(surfaceId),
1712+ qPrintable(menuObjectPath.path()));
1713+
1714+ m_interface->UnregisterSurfaceMenu(surfaceId, menuObjectPath);
1715+}
1716+
1717+
1718+void UbuntuMenuRegistry::serviceOwnerChanged(const QString &serviceName, const QString& oldOwner, const QString &newOwner)
1719+{
1720+ qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::serviceOwnerChanged(newOwner=%s)", qPrintable(newOwner));
1721+
1722+ if (serviceName != REGISTRAR_SERVICE) return;
1723+
1724+ if (oldOwner != newOwner) {
1725+ m_connected = !newOwner.isEmpty();
1726+ Q_EMIT serviceChanged();
1727+ }
1728+}
1729
1730=== added file 'src/ubuntuappmenu/registry.h'
1731--- src/ubuntuappmenu/registry.h 1970-01-01 00:00:00 +0000
1732+++ src/ubuntuappmenu/registry.h 2016-12-09 17:04:44 +0000
1733@@ -0,0 +1,56 @@
1734+/*
1735+ * Copyright (C) 2016 Canonical, Ltd.
1736+ *
1737+ * This program is free software: you can redistribute it and/or modify it under
1738+ * the terms of the GNU Lesser General Public License version 3, as published by
1739+ * the Free Software Foundation.
1740+ *
1741+ * This program is distributed in the hope that it will be useful, but WITHOUT
1742+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
1743+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1744+ * Lesser General Public License for more details.
1745+ *
1746+ * You should have received a copy of the GNU Lesser General Public License
1747+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1748+ */
1749+
1750+#ifndef UBUNTU_MENU_REGISTRY_H
1751+#define UBUNTU_MENU_REGISTRY_H
1752+
1753+#include <QObject>
1754+#include <QScopedPointer>
1755+
1756+class ComUbuntuMenuRegistrarInterface;
1757+class QDBusObjectPath;
1758+class QDBusServiceWatcher;
1759+
1760+class UbuntuMenuRegistry : public QObject
1761+{
1762+ Q_OBJECT
1763+public:
1764+ UbuntuMenuRegistry(QObject* parent = nullptr);
1765+ virtual ~UbuntuMenuRegistry();
1766+
1767+ static UbuntuMenuRegistry *instance();
1768+
1769+ void registerApplicationMenu(pid_t pid, QDBusObjectPath menuObjectPath, const QString &service);
1770+ void unregisterApplicationMenu(pid_t pid, QDBusObjectPath menuObjectPath);
1771+
1772+ void registerSurfaceMenu(const QString &surfaceId, QDBusObjectPath menuObjectPath, const QString &service);
1773+ void unregisterSurfaceMenu(const QString &surfaceId, QDBusObjectPath menuObjectPath);
1774+
1775+ bool isConnected() const { return m_connected; }
1776+
1777+Q_SIGNALS:
1778+ void serviceChanged();
1779+
1780+private Q_SLOTS:
1781+ void serviceOwnerChanged(const QString &serviceName, const QString& oldOwner, const QString &newOwner);
1782+
1783+private:
1784+ QScopedPointer<QDBusServiceWatcher> m_serviceWatcher;
1785+ QScopedPointer<ComUbuntuMenuRegistrarInterface> m_interface;
1786+ bool m_connected;
1787+};
1788+
1789+#endif // UBUNTU_MENU_REGISTRY_H
1790
1791=== renamed file 'src/ubuntumirclient/theme.cpp' => 'src/ubuntuappmenu/theme.cpp'
1792--- src/ubuntumirclient/theme.cpp 2014-06-18 23:10:00 +0000
1793+++ src/ubuntuappmenu/theme.cpp 2016-12-09 17:04:44 +0000
1794@@ -1,5 +1,5 @@
1795 /*
1796- * Copyright (C) 2014 Canonical, Ltd.
1797+ * Copyright (C) 2016 Canonical, Ltd.
1798 *
1799 * This program is free software: you can redistribute it and/or modify it under
1800 * the terms of the GNU Lesser General Public License version 3, as published by
1801@@ -15,20 +15,35 @@
1802 */
1803
1804 #include "theme.h"
1805+#include "gmenumodelplatformmenu.h"
1806+#include "logging.h"
1807
1808 #include <QtCore/QVariant>
1809-
1810-const char *UbuntuTheme::name = "ubuntu";
1811-
1812-UbuntuTheme::UbuntuTheme()
1813-{
1814-}
1815-
1816-UbuntuTheme::~UbuntuTheme()
1817-{
1818-}
1819-
1820-QVariant UbuntuTheme::themeHint(ThemeHint hint) const
1821+#include <QDebug>
1822+
1823+Q_LOGGING_CATEGORY(ubuntuappmenu, "ubuntuappmenu", QtWarningMsg)
1824+const char *UbuntuAppMenuTheme::name = "ubuntuappmenu";
1825+
1826+namespace {
1827+
1828+bool useLocalMenu() {
1829+ QByteArray menuProxy = qgetenv("UBUNTU_MENUPROXY");
1830+ bool menuProxyIsZero = !menuProxy.isEmpty() && menuProxy.at(0) == '0';
1831+ return menuProxyIsZero;
1832+}
1833+
1834+}
1835+
1836+UbuntuAppMenuTheme::UbuntuAppMenuTheme()
1837+{
1838+ qCDebug(ubuntuappmenu, "UbuntuAppMenuTheme::UbuntuAppMenuTheme() - useLocalMenu=%s", useLocalMenu() ? "true" : "false");
1839+}
1840+
1841+UbuntuAppMenuTheme::~UbuntuAppMenuTheme()
1842+{
1843+}
1844+
1845+QVariant UbuntuAppMenuTheme::themeHint(ThemeHint hint) const
1846 {
1847 if (hint == QPlatformTheme::SystemIconThemeName) {
1848 QByteArray iconTheme = qgetenv("QTUBUNTU_ICON_THEME");
1849@@ -41,3 +56,21 @@
1850 return QGenericUnixTheme::themeHint(hint);
1851 }
1852 }
1853+
1854+QPlatformMenuItem *UbuntuAppMenuTheme::createPlatformMenuItem() const
1855+{
1856+ if (useLocalMenu()) return QGenericUnixTheme::createPlatformMenuItem();
1857+ return new UbuntuPlatformMenuItem();
1858+}
1859+
1860+QPlatformMenu *UbuntuAppMenuTheme::createPlatformMenu() const
1861+{
1862+ if (useLocalMenu()) return QGenericUnixTheme::createPlatformMenu();
1863+ return new UbuntuPlatformMenu();
1864+}
1865+
1866+QPlatformMenuBar *UbuntuAppMenuTheme::createPlatformMenuBar() const
1867+{
1868+ if (useLocalMenu()) return QGenericUnixTheme::createPlatformMenuBar();
1869+ return new UbuntuPlatformMenuBar();
1870+}
1871
1872=== renamed file 'src/ubuntumirclient/theme.h' => 'src/ubuntuappmenu/theme.h'
1873--- src/ubuntumirclient/theme.h 2014-06-18 23:10:00 +0000
1874+++ src/ubuntuappmenu/theme.h 2016-12-09 17:04:44 +0000
1875@@ -1,5 +1,5 @@
1876 /*
1877- * Copyright (C) 2014 Canonical, Ltd.
1878+ * Copyright (C) 2016 Canonical, Ltd.
1879 *
1880 * This program is free software: you can redistribute it and/or modify it under
1881 * the terms of the GNU Lesser General Public License version 3, as published by
1882@@ -19,15 +19,20 @@
1883
1884 #include <QtPlatformSupport/private/qgenericunixthemes_p.h>
1885
1886-class UbuntuTheme : public QGenericUnixTheme
1887+class UbuntuAppMenuTheme : public QGenericUnixTheme
1888 {
1889 public:
1890 static const char* name;
1891- UbuntuTheme();
1892- virtual ~UbuntuTheme();
1893+ UbuntuAppMenuTheme();
1894+ virtual ~UbuntuAppMenuTheme();
1895
1896 // From QPlatformTheme
1897 QVariant themeHint(ThemeHint hint) const override;
1898+
1899+ // For the menus
1900+ virtual QPlatformMenuItem* createPlatformMenuItem() const override;
1901+ virtual QPlatformMenu* createPlatformMenu() const override;
1902+ virtual QPlatformMenuBar* createPlatformMenuBar() const override;
1903 };
1904
1905 #endif // UBUNTU_THEME_H
1906
1907=== added file 'src/ubuntuappmenu/themeplugin.cpp'
1908--- src/ubuntuappmenu/themeplugin.cpp 1970-01-01 00:00:00 +0000
1909+++ src/ubuntuappmenu/themeplugin.cpp 2016-12-09 17:04:44 +0000
1910@@ -0,0 +1,36 @@
1911+/*
1912+ * Copyright (C) 2016 Canonical, Ltd.
1913+ *
1914+ * This program is free software: you can redistribute it and/or modify it under
1915+ * the terms of the GNU Lesser General Public License version 3, as published by
1916+ * the Free Software Foundation.
1917+ *
1918+ * This program is distributed in the hope that it will be useful, but WITHOUT
1919+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
1920+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1921+ * Lesser General Public License for more details.
1922+ *
1923+ * You should have received a copy of the GNU Lesser General Public License
1924+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1925+ */
1926+
1927+#include "themeplugin.h"
1928+#include "theme.h"
1929+
1930+#include <QDebug>
1931+
1932+///////////////////////////////////////////////////////////
1933+
1934+UbuntuAppMenuThemePlugin::UbuntuAppMenuThemePlugin(QObject *parent)
1935+ : QPlatformThemePlugin(parent)
1936+{
1937+}
1938+
1939+QPlatformTheme *
1940+UbuntuAppMenuThemePlugin::create(const QString &key, const QStringList&)
1941+{
1942+ if (key.compare(QLatin1String(UbuntuAppMenuTheme::name), Qt::CaseInsensitive))
1943+ return 0;
1944+
1945+ return new UbuntuAppMenuTheme();
1946+}
1947
1948=== added file 'src/ubuntuappmenu/themeplugin.h'
1949--- src/ubuntuappmenu/themeplugin.h 1970-01-01 00:00:00 +0000
1950+++ src/ubuntuappmenu/themeplugin.h 2016-12-09 17:04:44 +0000
1951@@ -0,0 +1,34 @@
1952+/*
1953+ * Copyright (C) 2016 Canonical, Ltd.
1954+ *
1955+ * This program is free software: you can redistribute it and/or modify it under
1956+ * the terms of the GNU Lesser General Public License version 3, as published by
1957+ * the Free Software Foundation.
1958+ *
1959+ * This program is distributed in the hope that it will be useful, but WITHOUT
1960+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
1961+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1962+ * Lesser General Public License for more details.
1963+ *
1964+ * You should have received a copy of the GNU Lesser General Public License
1965+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1966+ */
1967+
1968+#ifndef UBUNTUTHEMEPLUGIN_H
1969+#define UBUNTUTHEMEPLUGIN_H
1970+
1971+#include <qpa/qplatformthemeplugin.h>
1972+
1973+class UbuntuAppMenuThemePlugin : public QPlatformThemePlugin
1974+{
1975+ Q_OBJECT
1976+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformThemeFactoryInterface.5.1" FILE "ubuntuappmenu.json")
1977+public:
1978+ UbuntuAppMenuThemePlugin(QObject *parent = 0);
1979+
1980+ virtual QPlatformTheme *create(const QString &key, const QStringList &paramList);
1981+
1982+ static const char *name;
1983+};
1984+
1985+#endif
1986
1987=== added file 'src/ubuntuappmenu/ubuntuappmenu.json'
1988--- src/ubuntuappmenu/ubuntuappmenu.json 1970-01-01 00:00:00 +0000
1989+++ src/ubuntuappmenu/ubuntuappmenu.json 2016-12-09 17:04:44 +0000
1990@@ -0,0 +1,3 @@
1991+{
1992+ "Keys": [ "ubuntuappmenu" ]
1993+}
1994
1995=== added file 'src/ubuntuappmenu/ubuntuappmenu.pro'
1996--- src/ubuntuappmenu/ubuntuappmenu.pro 1970-01-01 00:00:00 +0000
1997+++ src/ubuntuappmenu/ubuntuappmenu.pro 2016-12-09 17:04:44 +0000
1998@@ -0,0 +1,41 @@
1999+TARGET = ubuntuappmenu
2000+TEMPLATE = lib
2001+
2002+QT -= gui
2003+QT += core-private platformsupport-private dbus
2004+
2005+CONFIG += plugin no_keywords
2006+
2007+# CONFIG += c++11 # only enables C++0x
2008+QMAKE_CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Werror -Wall
2009+QMAKE_LFLAGS += -std=c++11 -Wl,-no-undefined
2010+
2011+CONFIG += link_pkgconfig
2012+PKGCONFIG += gio-2.0
2013+
2014+DBUS_INTERFACES += com.ubuntu.MenuRegistrar.xml
2015+
2016+HEADERS += \
2017+ theme.h \
2018+ gmenumodelexporter.h \
2019+ gmenumodelplatformmenu.h \
2020+ logging.h \
2021+ menuregistrar.h \
2022+ registry.h \
2023+ themeplugin.h
2024+
2025+SOURCES += \
2026+ theme.cpp \
2027+ gmenumodelexporter.cpp \
2028+ gmenumodelplatformmenu.cpp \
2029+ menuregistrar.cpp \
2030+ registry.cpp \
2031+ themeplugin.cpp
2032+
2033+OTHER_FILES += \
2034+ ubuntuappmenu.json
2035+
2036+# Installation path
2037+target.path += $$[QT_INSTALL_PLUGINS]/platformthemes
2038+
2039+INSTALLS += target
2040
2041=== modified file 'src/ubuntumirclient/integration.cpp'
2042--- src/ubuntumirclient/integration.cpp 2016-12-01 22:28:20 +0000
2043+++ src/ubuntumirclient/integration.cpp 2016-12-09 17:04:44 +0000
2044@@ -25,7 +25,6 @@
2045 #include "logging.h"
2046 #include "nativeinterface.h"
2047 #include "screen.h"
2048-#include "theme.h"
2049 #include "window.h"
2050
2051 // Qt
2052@@ -39,6 +38,7 @@
2053 #include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
2054 #include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
2055 #include <QtPlatformSupport/private/qeglpbuffer_p.h>
2056+#include <QtPlatformSupport/private/qgenericunixthemes_p.h>
2057 #include <QtPlatformSupport/private/bridge_p.h>
2058 #include <QOpenGLContext>
2059 #include <QOffscreenSurface>
2060@@ -48,6 +48,27 @@
2061 #include <ubuntu/application/id.h>
2062 #include <ubuntu/application/options.h>
2063
2064+
2065+class UbuntuIconTheme : public QGenericUnixTheme
2066+{
2067+public:
2068+ UbuntuIconTheme() {}
2069+
2070+ // From QPlatformTheme
2071+ QVariant themeHint(ThemeHint hint) const override {
2072+ if (hint == QPlatformTheme::SystemIconThemeName) {
2073+ QByteArray iconTheme = qgetenv("QTUBUNTU_ICON_THEME");
2074+ if (iconTheme.isEmpty()) {
2075+ return QVariant(QStringLiteral("ubuntu-mobile"));
2076+ } else {
2077+ return QVariant(QString(iconTheme));
2078+ }
2079+ } else {
2080+ return QGenericUnixTheme::themeHint(hint);
2081+ }
2082+ }
2083+};
2084+
2085 static void resumedCallback(const UApplicationOptions */*options*/, void *context)
2086 {
2087 auto integration = static_cast<UbuntuClientIntegration*>(context);
2088@@ -294,13 +315,13 @@
2089
2090 QStringList UbuntuClientIntegration::themeNames() const
2091 {
2092- return QStringList(UbuntuTheme::name);
2093+ return QStringList(QStringLiteral("ubuntuappmenu"));
2094 }
2095
2096 QPlatformTheme* UbuntuClientIntegration::createPlatformTheme(const QString& name) const
2097 {
2098 Q_UNUSED(name);
2099- return new UbuntuTheme;
2100+ return new UbuntuIconTheme;
2101 }
2102
2103 QVariant UbuntuClientIntegration::styleHint(StyleHint hint) const
2104
2105=== modified file 'src/ubuntumirclient/nativeinterface.cpp'
2106--- src/ubuntumirclient/nativeinterface.cpp 2016-06-21 12:17:55 +0000
2107+++ src/ubuntumirclient/nativeinterface.cpp 2016-12-09 17:04:44 +0000
2108@@ -162,6 +162,7 @@
2109 if (w) {
2110 propertyMap.insert("scale", w->scale());
2111 propertyMap.insert("formFactor", w->formFactor());
2112+ propertyMap.insert("persistentSurfaceId", w->persistentSurfaceId());
2113 }
2114 return propertyMap;
2115 }
2116@@ -177,6 +178,8 @@
2117 return w->scale();
2118 } else if (name == QStringLiteral("formFactor")) {
2119 return w->formFactor();
2120+ } else if (name == QStringLiteral("persistentSurfaceId")) {
2121+ return w->persistentSurfaceId();
2122 } else {
2123 return QVariant();
2124 }
2125
2126=== modified file 'src/ubuntumirclient/plugin.cpp'
2127--- src/ubuntumirclient/plugin.cpp 2016-06-24 12:36:24 +0000
2128+++ src/ubuntumirclient/plugin.cpp 2016-12-09 17:04:44 +0000
2129@@ -17,6 +17,7 @@
2130 #include "plugin.h"
2131 #include "integration.h"
2132 #include "logging.h"
2133+#include "qpa/qplatformwindow.h"
2134
2135 Q_LOGGING_CATEGORY(ubuntumirclient, "ubuntumirclient", QtWarningMsg)
2136
2137@@ -24,6 +25,8 @@
2138 const QStringList &/*paramList*/,
2139 int &argc, char **argv)
2140 {
2141+ qRegisterMetaType<QPlatformWindow*>("QPlatformWindow*");
2142+
2143 if (system.toLower() == QLatin1String("ubuntumirclient")) {
2144 #ifdef PLATFORM_API_TOUCH
2145 setenv("UBUNTU_PLATFORM_API_BACKEND", "touch_mirclient", 1);
2146
2147=== modified file 'src/ubuntumirclient/ubuntumirclient.pro'
2148--- src/ubuntumirclient/ubuntumirclient.pro 2016-11-04 13:20:58 +0000
2149+++ src/ubuntumirclient/ubuntumirclient.pro 2016-12-09 17:04:44 +0000
2150@@ -28,7 +28,6 @@
2151 plugin.cpp \
2152 screen.cpp \
2153 screenobserver.cpp \
2154- theme.cpp \
2155 window.cpp \
2156 appstatecontroller.cpp
2157
2158@@ -41,17 +40,19 @@
2159 glcontext.h \
2160 input.h \
2161 integration.h \
2162- logging.h \
2163 nativeinterface.h \
2164 orientationchangeevent_p.h \
2165 platformservices.h \
2166 plugin.h \
2167 screenobserver.h \
2168 screen.h \
2169- theme.h \
2170 window.h \
2171+ logging.h \
2172 appstatecontroller.h
2173
2174+OTHER_FILES += \
2175+ ubuntumirclient.json
2176+
2177 # Installation path
2178 target.path += $$[QT_INSTALL_PLUGINS]/platforms
2179
2180
2181=== modified file 'src/ubuntumirclient/window.cpp'
2182--- src/ubuntumirclient/window.cpp 2016-11-23 12:11:14 +0000
2183+++ src/ubuntumirclient/window.cpp 2016-12-09 17:04:44 +0000
2184@@ -712,6 +712,11 @@
2185 w, w->screen()->handle(), input, mSurface.get(), qPrintable(window()->title()), roleFor(window()));
2186
2187 updatePanelHeightHack(mSurface->state() != mir_surface_state_fullscreen);
2188+
2189+ // queue the windowPropertyChanged signal. If it's emitted directly, the platformWindow will not yet be set for the window.
2190+ QMetaObject::invokeMethod(mNativeInterface, "windowPropertyChanged", Qt::QueuedConnection,
2191+ Q_ARG(QPlatformWindow*, this),
2192+ Q_ARG(QString, "persistentSurfaceId"));
2193 }
2194
2195 UbuntuWindow::~UbuntuWindow()
2196
2197=== modified file 'src/ubuntumirclient/window.h'
2198--- src/ubuntumirclient/window.h 2016-11-23 12:11:14 +0000
2199+++ src/ubuntumirclient/window.h 2016-12-09 17:04:44 +0000
2200@@ -92,4 +92,6 @@
2201 MirFormFactor mFormFactor;
2202 };
2203
2204+Q_DECLARE_METATYPE(QPlatformWindow*);
2205+
2206 #endif // UBUNTU_WINDOW_H

Subscribers

People subscribed via source and target branches