<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Kparts on Roberto Selbach</title><link>https://rselbach.com/tags/kparts/</link><description>Recent content in Kparts on Roberto Selbach</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Fri, 09 May 2003 13:18:44 +0000</lastBuildDate><atom:link href="https://rselbach.com/tags/kparts/index.xml" rel="self" type="application/rss+xml"/><item><title>Merging KParts Actions Without Duplicates</title><link>https://rselbach.com/merging-kparts-actions-without-duplicates/</link><pubDate>Fri, 09 May 2003 13:18:44 +0000</pubDate><guid>https://rselbach.com/merging-kparts-actions-without-duplicates/</guid><description>&lt;p&gt;I embedded a part and ended up with two Edit menus, three separators, and no obvious place to put Find. Every individual action worked. Their diplomacy was lacking.&lt;/p&gt;
&lt;p&gt;KParts uses XMLGUI to merge the shell&amp;rsquo;s actions with the active part&amp;rsquo;s actions. The shell supplies a main XML resource, the part supplies its own, and named menu locations and merge points tell the GUI factory where contributions belong. The names, not their visual positions, form the contract.&lt;/p&gt;
&lt;p&gt;A part can declare an action and place it into a standard menu:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE kpartgui&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;kpartgui&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;note_part&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;MenuBar&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;Menu&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;edit&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;text&amp;gt;&lt;/span&gt;Edit&lt;span style="color:#f92672"&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;Action&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;note_find&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/Menu&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/MenuBar&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/kpartgui&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The C++ action collection must use the same action name:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;KAction &lt;span style="color:#f92672"&gt;*&lt;/span&gt;find &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; KAction(i18n(&lt;span style="color:#e6db74"&gt;&amp;#34;Find&amp;#34;&lt;/span&gt;), &lt;span style="color:#e6db74"&gt;&amp;#34;find&amp;#34;&lt;/span&gt;, CTRL &lt;span style="color:#f92672"&gt;+&lt;/span&gt; Key_F,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;, SLOT(slotFind()),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; actionCollection(), &lt;span style="color:#e6db74"&gt;&amp;#34;note_find&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the XML name and action-collection name differ, the merge cannot place the action. If the part invents a menu name that the shell does not recognize, it may create a second menu instead of contributing to the first. I now compare the shell and part resource files side by side before touching C++.&lt;/p&gt;
&lt;p&gt;Activation matters too. A shell hosting several parts should add the active client&amp;rsquo;s GUI and remove or replace it when focus moves. Leaving an old client registered explains actions that continue targeting a document no longer visible. I test by switching parts repeatedly, not just by opening one and closing the program.&lt;/p&gt;
&lt;p&gt;Versioning the XML resource helps installed updates replace cached expectations, but it does not excuse stale files in the wrong prefix. When changes appear to be ignored, I inspect the paths reported by &lt;code&gt;kde-config&lt;/code&gt;, remove obsolete application-owned resources, and rebuild the service cache if appropriate.&lt;/p&gt;
&lt;p&gt;Action state remains the part&amp;rsquo;s responsibility. When a read-only document becomes active, its Cut action should be disabled before the GUI is merged, and selection changes should update it afterward. The shell should not infer document capabilities from menu names. It hosts the action; the part knows whether invoking it makes sense.&lt;/p&gt;
&lt;p&gt;For debugging, I temporarily give each contribution an unmistakable label and watch the terminal for XMLGUI warnings. Once placement is correct, I restore the proper translated text. This is faster than deciding which of two identical separators came from which file.&lt;/p&gt;
&lt;p&gt;I prefer a small part resource that contributes document-specific actions while the shell owns window actions such as New Window and Quit. The caveat is that the boundary requires discipline: an action should live where its state and target live. Otherwise XMLGUI can merge the menu perfectly and still dispatch Find to yesterday&amp;rsquo;s document, which is technically impressive but not helpful.&lt;/p&gt;</description></item><item><title>KParts Ownership in One Minute</title><link>https://rselbach.com/kparts-ownership-in-one-minute/</link><pubDate>Mon, 03 Jun 2002 07:54:19 +0000</pubDate><guid>https://rselbach.com/kparts-ownership-in-one-minute/</guid><description>&lt;p&gt;I embedded a viewer part, closed its window, and received a crash during shutdown. The viewer worked. My ownership did not.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;KPart&lt;/code&gt; is a &lt;code&gt;QObject&lt;/code&gt;, and its widget is usually parented into the host&amp;rsquo;s widget tree. Those are related lifetimes, but they are not an invitation to delete everything in sight. I now keep the part pointer in the host, give the constructor the intended object parent, and let that relationship determine destruction.&lt;/p&gt;
&lt;p&gt;The shape is roughly this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;KParts&lt;span style="color:#f92672"&gt;::&lt;/span&gt;ReadOnlyPart &lt;span style="color:#f92672"&gt;*&lt;/span&gt;part &lt;span style="color:#f92672"&gt;=&lt;/span&gt; factory&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;createPart(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; parentWidget, &lt;span style="color:#e6db74"&gt;&amp;#34;viewer widget&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;viewer part&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;KParts::ReadOnlyPart&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;setCentralWidget(part&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;widget());
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The factory creates the component. The part owns its document behavior and supplies a widget for presentation. The shell owns the part through the &lt;code&gt;QObject&lt;/code&gt; parent passed to the factory. I do not separately delete the widget; its parent chain handles that.&lt;/p&gt;
&lt;p&gt;The other lifetime to remember is the component factory or library handle used to create the part. KDE&amp;rsquo;s loader machinery normally keeps the code available while objects from it exist. Bypassing that machinery and unloading a library while its C++ object remains is an efficient way to make a virtual call jump into empty space.&lt;/p&gt;
&lt;p&gt;My preference is one obvious owner and no emergency deletes in destructors. If I cannot explain who owns the part without drawing several arrows, I fix that before debugging anything else. The crash at exit is rarely impressed by a beautiful toolbar.&lt;/p&gt;</description></item></channel></rss>