> On Sept. 15, 2014, 2:45 a.m., Ian Wadham wrote:
> > I cannot see how "static void setTextWithCorrectMenuRole()" could work in 
> > all languages.
> > 
> > Does not the "text" parameter come translated into the user's language, not 
> > necessarily English? So how can the ".contains" checks work with all 
> > languages?
> > 
> > I see that the code does translate the string "Configure %1..." before 
> > comparing it to "text". I am not sure that would work either if there are 
> > non-standard spacings or punctuations in "text". That string is not a 
> > hard-and-fast standard in all KDE apps, just a default that is provided by 
> > KStandardAction or KStandardGameAction. The developer is quite at liberty 
> > to change it to "<appname> Settings..." or "<appname> Game Settings...", 
> > for example. Also some languages might have different orders of words or 
> > numbers of words. I suppose Qt-Mac's QMenuBar class must have some way to 
> > take care of that in this situation.
> > 
> > Finally, if something other than a combination of "Configure" and <appname> 
> > does match, should you leave it at QAction::NoRole? Maybe set 
> > QAction::PreferencesRole or leave it at QAction::TextHeuristicRole and let 
> > QMenuBar do its thing?
> 
> René J.V. Bertin wrote:
>     I've wondered about that myself, and was hoping to get constructive 
> feedback here. I should have mentioned it, because I've never really done any 
> "internationalised" coding...
>     
>     Qt's documentation for QMenuBar mentions it uses `QObject::tr` to 
> translate the trigger patterns, but that only works for C strings. The text 
> objects I'm scanning are already QStrings, and presumably either in a 
> language-independent representation, or in English.
>     
>     Maybe I should do something like `text.contains( QObject::tr("config") )` 
> ?
>     
>     Of course I'm not claiming that the present patch is a catch-all for all 
> possible use cases. In fact, being a patch to the base library, it only 
> pretends to catch standard use cases, and cases that correspond to those 
> close enough (i.e. someone creating a "Configure <appname>..." action outside 
> of KStandardAction). Qt tries to be more generic, catching the examples Ian 
> gives, but it goes about it too randomly.
>     
>     @Ian: check my "companion" RR for KDevelop: it shows exactly what to do 
> when this patch here isn't enough.
>     
>     And I could of course check what happens when I switch my own KDE 
> environment to a different language ... I probably have the French language 
> installed ...
> 
> René J.V. Bertin wrote:
>     Bummer, indeed, switching kmail to another language makes its "Configure 
> KMail..." action pop back in the Settings menu instead of under the 
> Preferences item. This is an example of an application for which the explicit 
> check against "Configure <appname>..." is included.
>     
>     So ... how should I improve this patch to apply to all installed 
> languages?

Here's what Qt does, in `qmenu_mac.mm` (that's ObjC++ ... best of both worlds, 
sadly not recognised by KDevelop's parsers ...)

    case QAction::TextHeuristicRole: {
        QString aboutString = QMenuBar::tr("About").toLower();
        if (t.startsWith(aboutString) || t.endsWith(aboutString)) {
            if (t.indexOf(QRegExp(QString::fromLatin1("qt$"), 
Qt::CaseInsensitive)) == -1) {
#ifndef QT_MAC_USE_COCOA
                ret = kHICommandAbout;
#else
                ret = [loader aboutMenuItem];
#endif
            } else {
#ifndef QT_MAC_USE_COCOA
                ret = kHICommandAboutQt;
#else
                ret = [loader aboutQtMenuItem];
#endif
            }
        } else if (t.startsWith(QMenuBar::tr("Config").toLower())
                   || t.startsWith(QMenuBar::tr("Preference").toLower())
                   || t.startsWith(QMenuBar::tr("Options").toLower())
                   || t.startsWith(QMenuBar::tr("Setting").toLower())
                   || t.startsWith(QMenuBar::tr("Setup").toLower())) {
#ifndef QT_MAC_USE_COCOA
            ret = kHICommandPreferences;
#else
            ret = [loader preferencesMenuItem];
#endif
        } else if (t.startsWith(QMenuBar::tr("Quit").toLower())
                   || t.startsWith(QMenuBar::tr("Exit").toLower())) {
#ifndef QT_MAC_USE_COCOA
            ret = kHICommandQuit;
#else
            ret = [loader quitMenuItem];
#endif
        }


- René J.V.


-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://git.reviewboard.kde.org/r/120149/#review66503
-----------------------------------------------------------


On Sept. 15, 2014, 1:03 p.m., René J.V. Bertin wrote:
> 
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://git.reviewboard.kde.org/r/120149/
> -----------------------------------------------------------
> 
> (Updated Sept. 15, 2014, 1:03 p.m.)
> 
> 
> Review request for KDE Software on Mac OS X, kdelibs, KDEPIM, Marco Martin, 
> and Olivier Goffart.
> 
> 
> Repository: kdelibs
> 
> 
> Description
> -------
> 
> This review is for 2 sets of changes; an initial one to the way "system tray" 
> are rendered, and a newer set that protects the Preferences menu from getting 
> linked to any action with an appropriate title.
> 
> -- the system tray:
> Until now, "system tray" menus had some rendering issues on Mac OS X:
> 
> - The menu title, the 1st menu item that on Linux shows the application name, 
> remained empty
> - Menu items that can (in principle, potentially) show an icon always showed 
> the icon
> 
> Point 1 was resolved by emulating the Linux addTitle/setTitle action in 
> `KStatusNotifierItemPrivate::init()` : the menu title is implemented as a 
> deactive standard menuitem followed by a separator. This makes the item stand 
> out on a GUI that doesn't support the kind of formatting in menus as used in 
> the Linux implementation.
> 
> Point 2 was identified as a Qt issue: `isIconVisibleInMenu` is ignored for 
> systray menus. It was resolved by adding `KMenu::addAction` methods that 
> overload the ones from QMenu that were hitherto inherited unchanged by KMenu. 
> The only different method is `addAction(QAction*)` which removes the icon 
> from the `QAction` if `isIconVisibleInMenu()` is false. The other `addAction` 
> methods are "overloaded with themselves" with `using QMenu::addAction;` in 
> the header file.
> 
> -- the Preferences menu item
> This is a menu item living in the Application menu, a menu that sits in the 
> menubar between the Apple (?) menu and the File menu. This menu also contains 
> the Quit command.
> KDE and Qt applications typically do not set up their menus in this fashion, 
> so Qt provides an automatic way to put relevant menu items (actions) in the 
> Application menu, using Apple's naming. The algorithm is described under 
> QMenuBar in the Qt documentation: for the Preferences action, it will 
> consider any action that has a text containing `config`, `options`, 
> `settings` or `preferences`, and put it under the Preferences label if its 
> menu role is set to `heuristic` (which appears to be the default).
> In practice, many applications provide a series of menu actions with names 
> that trigger this method, and they do not always create their own 
> preferences/settings/configuration menu first. Yet it is the first menu 
> action that matches that will be installed under the Preferences menu, with 
> the Command-, shortcut. A good example is KDevelop: it will have a 
> Preferences menu that activates the `Configure Selection` action - which does 
> not open a settings dialog but launches the configure or cmake procedure for 
> the selected project ...
> 
> My proposed solution overrides this Qt behaviour. On OS X, the `KAction(const 
> QString &text, QObject *parent)` constructor calls a modified (static) 
> function `setTextWithCorrectMenuRole` which checks the text against the 
> patterns Qt will consider for `PreferencesRole`. If it finds a match, it will 
> force the role to `NoRole`, unless it is a perfect match with the standard 
> KDE configuration action for the application (`"&Configuration appName..."`) 
> in which case it sets the role to `PreferencesRole`. This latter 
> consideration allows kdelibs to "catch" the configuration menu for 
> applications like KMail, which appear not to be created using 
> KStandardActions.
> This approach can be extended to other menu actions that end up incorrectly 
> in the OS X Application menu.
> 
> Applications that create menu actions using QAction or a different KAction 
> constructor will see no change (and should use `setMenuRole` selectively on 
> OS X).
> 
> 
> Diffs
> -----
> 
>   kdeui/actions/kaction.cpp 9e8f7fb 
>   kdeui/actions/kstandardaction.cpp 7de0c6f 
>   kdeui/notifications/kstatusnotifieritem.cpp 1b15d40 
>   kdeui/widgets/kmenu.h f96e263 
>   kdeui/widgets/kmenu.cpp 7dab149 
> 
> Diff: https://git.reviewboard.kde.org/r/120149/diff/
> 
> 
> Testing
> -------
> 
> Testing was done with kdelibs git/master and KDE/MacPorts on OS X 10.6.8 . 
> The modified code is in compile-time conditional blocks used only on OS X, so 
> no regressions are to be expected on other platforms.
> 
> KF5 is not production ready on OS X, so I am not currently able to port these 
> modifications beyond KDE4. However, I did see that Qt5 has a new approach to 
> adding titles to menus, which can be described as a "labelled separator". 
> Backporting that function from the Qt5 source to kdelibs gave menu items that 
> had the separator but not the text (title) label. It is thus likely that some 
> kind of emulation will also be required with KF5, on OS X.
> 
> I considered doing the addTitle/setTitle emulation in kmenu.cpp, but decided 
> against that for now. Menu titles are rendered as under Linux in menus that 
> are not attached to the OS X toplevel menubar (say in context menus). Without 
> knowing how to distinguish the kind of menu in KMenu methods the emulation 
> will have to remain in the client code.
> 
> The Preferences menu protection should carry over easily to KF5, supposing 
> Qt5 uses the same heuristics to place relevant menu actions under the OS X 
> application menu, and supposing `KAction` has made the transition to KF5.
> 
> 
> Thanks,
> 
> René J.V. Bertin
> 
>

Reply via email to