<html>
 <body>
  <div style="font-family: Verdana, Arial, Helvetica, Sans-Serif;">
   <table bgcolor="#f9f3c9" width="100%" cellpadding="12" style="border: 1px #c9c399 solid; border-radius: 6px; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
    <tr>
     <td>
      This is an automatically generated e-mail. To reply, visit:
      <a href="https://git.reviewboard.kde.org/r/120149/">https://git.reviewboard.kde.org/r/120149/</a>
     </td>
    </tr>
   </table>
   <br />










<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
 <p style="margin-top: 0;">On September 15th, 2014, 12:19 p.m. UTC, <b>Thomas Lübking</b> wrote:</p>
 <blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
  


<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
 <thead>
  <tr>
   <th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
    <a href="https://git.reviewboard.kde.org/r/120149/diff/2/?file=312029#file312029line149" style="color: black; font-weight: bold; text-decoration: underline;">kdeui/actions/kaction.cpp</a>
    <span style="font-weight: normal;">

     (Diff revision 2)

    </span>
   </th>
  </tr>
 </thead>

 <tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
  <tr>

   <td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">bool KAction::event(QEvent *event)</pre></td>

  </tr>
 </tbody>



 
 

 <tbody>

  <tr>
    <th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
    <th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">149</font></th>
    <td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="k">static</span> <span class="kt">void</span> <span class="n">setTextWithCorrectMenuRole</span><span class="p">(</span> <span class="n">KAction</span> <span class="o">*</span><span class="n">action</span><span class="p">,</span> <span class="k">const</span> <span class="n">QString</span> <span class="o">&</span><span class="n">text</span> <span class="p">)</span></pre></td>
  </tr>

 </tbody>

</table>

  <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">what if<br style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;" />
KAction *foo = new KAction(this);<br style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;" />
foo->setText("Foo");</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">-> you rather want to monitor the "changed()" signal?</p></pre>
 </blockquote>



 <p>On September 15th, 2014, 2 p.m. UTC, <b>René J.V. Bertin</b> wrote:</p>
 <blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
  <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">Yes, that would probably be more elegant. I'm not exactly sure how one would monitor that signal, but it seems that it might be a bit complicated in the context of something that's bound to disappear?</p></pre>
 </blockquote>





 <p>On September 15th, 2014, 9:57 p.m. UTC, <b>Thomas Lübking</b> wrote:</p>
 <blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
  <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">You'd add a private slot to KAction and "connect(this, SIGNAL(changed()), SLOT(fixMenuRole()))"<br style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;" />
Before altering the text in ::fixMenuRole(), don't forget to block (and later unblock) signals to not enter a recursion.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">Since the changed() signal is not only called for altering text (but also icons, the role and some other stuff) you also might want to keep a string member to check whether the text actually changed before updating the role.</p></pre>
 </blockquote>





 <p>On September 17th, 2014, 5:58 p.m. UTC, <b>René J.V. Bertin</b> wrote:</p>
 <blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
  <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">The NULL alternative would be to modify the default KAction ctor to do <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">setMenuRole(NoRole)</code>, which is the effective default on other platforms (where <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">TextHeuristicRole</code> is unused).</p></pre>
 </blockquote>





 <p>On September 18th, 2014, 4:36 a.m. UTC, <b>Ian Wadham</b> wrote:</p>
 <blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
  <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">I think this may be the best way to go with KDE 4 on OS X. Yesterday evening (Aust. time) I trawled through all the relevant source code in both kdelibs and Qt and I came up with the same idea, but decided to sleep on it. Maybe I sent it to you in my dreams... :-) Here's why I think it may be the neatest solution.</p>
<ol style="padding: 0;text-rendering: inherit;margin: 0 0 0 2em;line-height: inherit;white-space: normal;">
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">KDE 4 apps usually use QAction, KAction or KStandardAction, or derivative classes (e.g. KStandardGameAction?), to set up actions.</li>
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">KStandardAction sets the correct MenuRole for all standard KDE actions, including NoRole as a default.</li>
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">The problem lies with actions that are not standard KDE actions but have a similar wording (e.g. Configure Editor).</li>
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">These can be picked up as false positives by the Qt-Mac "heuristic" and will then corrupt the Preferences entry in Apple's Application menu.</li>
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">KStandardAction's create() first sets up data-values for the required action, then it creates the KAction object (or derived action object).</li>
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">Finally, it sets the MenuRole to NoRole or one of the specialised roles.</li>
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">Therefore, setting the MenuRole to NoRole in the KAction constructor would not invalidate what KStandardAction does.</li>
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">Also, no KAction objects will then be affected by Qt's heuristic, even if they are not KStandardActions (e.g. Configure Editor is KAction?).</li>
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">That will leave QActions in some KDE apps exposed, but I doubt if they will be a problem. If they are, they could be fixed manually.</li>
</ol>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">In KF5, KAction is deprecated in favour of QAction. I think the only solution there is to get into Qt5, as you and Thomas have discussed, and change the default MenuRole to be NoRole, for KDE apps, rather than the heuristic role.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">BTW, it occurs to me that the heuristic may be for the benefit of Qt's paying customers --- businesses and organisations who may have large in-house suites of apps written using Qt and may have a mix of hardware platforms and O/S's on people's desks.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">If we patched Qt5-Mac in MacPorts to change the default MenuRole, I doubt if any apps ported to Apple OS X would be adversely affected --- but you never know. I suppose it is easy enough to ask MacPorts' "port" command if any apps, other than KDE or Qt apps, depend on Qt-Mac.</p></pre>
 </blockquote>





 <p>On September 18th, 2014, 7:31 a.m. UTC, <b>René J.V. Bertin</b> wrote:</p>
 <blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
  <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">Thanks Ian for writing this down in a more concise way. It's exactly the conclusion I've came to, except maybe for the reason why the heuristics are there. There'd be a large and influential enough customerbase who have Qt code running on Macs AND 1) insist on it showing the menus in the OS-X-dictated place and 2) can't be bothered to insert 1 or 2 <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">setMenuRole</code> calls for that to happen (guided by paid support feedback? And nothing similar would ever be required on one of the more wide-spread platforms Qt supports? Personally I'd have guessed this were the oeuvre of maybe even a single person who's in love with OS X and wants to do things right without having really thought of all the potential consequences (a bit like how I killed the "icons in systray" bug at first).</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">Qt5's case is slightly more complicated because it introduces MenuRole for cut, copy, paste and select-all. That apparently is to modify the role of those "standard actions" (quote from the relevant commit message) when a QFileDialog is open. As long as they're not used to move menu items around it's probably OK, though. Marko is helping me look into that, and dfaure provided me with the name of the heuristics' author. </p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">Ian: what kind of app that's not a KDE or Qt app could possibly be affected by this?</p></pre>
 </blockquote>







</blockquote>
<pre style="margin-left: 1em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">On Apple OS X and MacPorts I use "Qt app" to mean an app provided by Qt, such as Assistant or Designer. Those can look after their own menu roles, I presume, as KDE apps do. There might also be (in MacPorts) some non-KDE apps based on Qt, e.g. some of the FOSS science applications. Their authors would not necessarily be aware of menu-role issues.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">In the world at large, I am imagining application systems with hundreds of screen-forms, background processes and printed outputs, programmed using C++ and Qt, that are required to run, say, a baggage-handling system at a major airport. I do not know whether that is the kind of complexity Qt customers have to handle in their businesses, but certainly such complexity does exist in many businesses. I am sure that the programmers working with it would welcome anything from Qt that saved them having to worry about cosmetics on the occasional Mac user's screen and left them free to concentrate on keeping the conveyors rolling and routing the baggage correctly... I use that example because there has been at least one such system that failed to run correctly and actually delayed the opening of a new airport. I have myself worked on some quite complex systems and would have welcomed C++ and Qt back in the day (60s thru 90s).</p></pre>
<br />




<p>- Ian</p>


<br />
<p>On September 17th, 2014, 5:48 p.m. UTC, René J.V. Bertin wrote:</p>









<table bgcolor="#fefadf" width="100%" cellspacing="0" cellpadding="12" style="border: 1px #888a85 solid; border-radius: 6px; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
 <tr>
  <td>

<div>Review request for KDE Software on Mac OS X, kdelibs, KDEPIM, Marco Martin, and Olivier Goffart.</div>
<div>By René J.V. Bertin.</div>


<p style="color: grey;"><i>Updated Sept. 17, 2014, 5:48 p.m.</i></p>









<div style="margin-top: 1.5em;">
 <b style="color: #575012; font-size: 10pt;">Repository: </b>
kdelibs
</div>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Description </h1>
 <table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
 <tr>
  <td>
   <pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">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.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">-- the system tray:<br style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;" />
Until now, "system tray" menus had some rendering issues on Mac OS X:</p>
<ul style="padding: 0;text-rendering: inherit;margin: 0 0 0 1em;line-height: inherit;white-space: normal;">
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">The menu title, the 1st menu item that on Linux shows the application name, remained empty</li>
<li style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;">Menu items that can (in principle, potentially) show an icon always showed the icon</li>
</ul>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">Point 1 was resolved by emulating the Linux addTitle/setTitle action in <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">KStatusNotifierItemPrivate::init()</code> : 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.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">Point 2 was identified as a Qt issue: <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">isIconVisibleInMenu</code> is ignored for systray menus. It was resolved by adding <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">KMenu::addAction</code> methods that overload the ones from QMenu that were hitherto inherited unchanged by KMenu. The only different method is <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">addAction(QAction*)</code> which removes the icon from the <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">QAction</code> if <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">isIconVisibleInMenu()</code> is false. The other <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">addAction</code> methods are "overloaded with themselves" with <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">using QMenu::addAction;</code> in the header file.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">-- the Preferences menu item<br style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;" />
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.<br style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;" />
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 <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">config</code>, <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">options</code>, <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">settings</code> or <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">preferences</code>, and put it under the Preferences label if its menu role is set to <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">heuristic</code> (which appears to be the default).<br style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;" />
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 <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">Configure Selection</code> action - which does not open a settings dialog but launches the configure or cmake procedure for the selected project ...</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">My proposed solution overrides this Qt behaviour. On OS X, the <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">KAction(const QString &text, QObject *parent)</code> constructor calls a modified (static) function <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">setTextWithCorrectMenuRole</code> which checks the text against the patterns Qt will consider for <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">PreferencesRole</code>. If it finds a match, it will force the role to <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">NoRole</code>, unless it is a perfect match with the standard KDE configuration action for the application (<code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">"&Configuration appName..."</code>) in which case it sets the role to <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">PreferencesRole</code>. This latter consideration allows kdelibs to "catch" the configuration menu for applications like KMail, which appear not to be created using KStandardActions.<br style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: normal;" />
This approach can be extended to other menu actions that end up incorrectly in the OS X Application menu.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">Applications that create menu actions using QAction or a different KAction constructor will see no change (and should use <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">setMenuRole</code> selectively on OS X).</p></pre>
  </td>
 </tr>
</table>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Testing </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
 <tr>
  <td>
   <pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">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.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">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.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">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.</p>
<p style="padding: 0;text-rendering: inherit;margin: 0;line-height: inherit;white-space: inherit;">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 <code style="text-rendering: inherit;color: #4444cc;padding: 0;white-space: normal;margin: 0;line-height: inherit;">KAction</code> has made the transition to KF5.</p></pre>
  </td>
 </tr>
</table>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Diffs</b> </h1>
<ul style="margin-left: 3em; padding-left: 0;">

 <li>kdeui/actions/kaction.cpp <span style="color: grey">(9e8f7fb)</span></li>

 <li>kdeui/notifications/kstatusnotifieritem.cpp <span style="color: grey">(1b15d40)</span></li>

</ul>

<p><a href="https://git.reviewboard.kde.org/r/120149/diff/" style="margin-left: 3em;">View Diff</a></p>






  </td>
 </tr>
</table>








  </div>
 </body>
</html>