Kde

Trying the KDE 3.2 Beta

I have been running the KDE 3.2 beta on a spare account because I wanted to see whether the next release changes daily work or merely rearranges the furniture. KDE 3.1 is already a comfortable desktop, so additions now have to earn their place.

The most visible newcomer is Kontact, which presents mail, calendar, contacts, and related information in one shell. The important word is “presents.” It is integrating existing KDE PIM components rather than replacing every application with one enormous program. KMail still behaves like KMail, but I can move between mail and appointments without managing a row of separate top-level windows.

Konqueror and KHTML also continue to improve. Pages that used to expose small layout failures are behaving better, and Safari’s use of KHTML has clearly raised both attention and expectations. I would not claim identical rendering: the engines have already diverged in places, platform code differs, and a site can always find a novel way to be broken. Still, more real-world testing is showing.

The obvious test procedure is not to click around for ten minutes and declare victory. I copied my normal profile, used it for several days, and watched the console output. I tested IMAP folders, printing, file previews, keyboard shortcuts, and the few unpleasant web applications I cannot avoid. Pretty menus are easy; preserving mail and settings is the examination.

Anyone trying a beta should keep a separate home directory or at least a backup of .kde. Configuration files can be upgraded, plugins built for another KDE release may not load, and returning to 3.1 after writing new settings is not guaranteed to be graceful. A beta is an offer to find bugs, not an unusually exciting package update.

My impression so far is that 3.2 is becoming more coherent rather than merely larger. That distinction matters. KDE has no shortage of features. What it needs is for related features to fit together, for defaults to be sensible, and for common paths to require less ceremony.

Kontact is a good example of the right sort of integration: reuse the specialised applications and give them a shared front door. If the remaining beta period concentrates on reliability, 3.2 should be a worthwhile upgrade. If it concentrates on adding twelve more buttons, I reserve the right to hide the toolbars and sulk.

Qt Layouts Before Pixel Pushing

I fixed a dialog today that looked fine in English and ridiculous in German. The original code positioned every Qt widget with coordinates, so a longer label pushed straight through the line edit beside it. Apparently translations had failed to respect our geometry. Very inconsiderate of them.

The obvious fix was not to adjust the numbers. It was to remove them.

In Qt 3, layouts already know how to negotiate widget sizes. A QVBoxLayout stacks rows, a QHBoxLayout arranges each row, and QGridLayout handles label-and-field forms without pretending every label has the same width.

QGridLayout *layout = new QGridLayout(this, 2, 2, 8, 6);
layout->addWidget(new QLabel(tr("Server name:"), this), 0, 0);
layout->addWidget(serverEdit, 0, 1);
layout->addWidget(new QLabel(tr("User:"), this), 1, 0);
layout->addWidget(userEdit, 1, 1);
layout->setColStretch(1, 1);

The margins and spacing remain explicit, but the widgets provide size hints and the second column absorbs extra room. The dialog now survives longer translations, a different font, and a user resizing it.

One small trap is mixing layouts with manual setGeometry() calls on the same children. The layout will win, usually just after the hand-tuned version looked correct on the developer’s machine.

I still use fixed sizes when the thing really is fixed, such as a small colour swatch. For forms and text, coordinates are merely tomorrow’s bug written as two integers. Let the layout do the dull arithmetic. It has more patience than I do.

What Safari Means for KHTML

I have spent enough time explaining that Konqueror is not merely a file manager with a web page bolted onto it. Now Apple has provided a rather convincing demonstration for me: Safari uses KHTML and KJS as the basis of its rendering engine.

The obvious reaction is pride. A small, portable engine built by the KDE project was good enough to become the foundation of Apple’s browser. That says more about the quality of the code than a dozen benchmark charts could.

The practical implication is more interesting. Web authors who previously tested only Internet Explorer and Mozilla now have a commercial reason to care about KHTML behaviour. Fixing a standards bug in KHTML can improve two browsers, and work done by Apple can potentially flow back to Konqueror under the LGPL.

“Potentially” is doing some work there. Apple’s first published changes arrived as large patches against old snapshots, which are not pleasant to merge. Source availability is not the same thing as easy collaboration. A patch the size of a small moon is technically useful, but it does not make the maintainer’s afternoon better.

Still, this is a very good problem to have. KHTML now has another serious user, more testing, and engineers being paid to improve it. KDE should be friendly but firm about working in manageable changes. If both sides manage that, Konqueror users may benefit every time Safari improves, and the web gets another standards-minded engine instead of another collection of browser-specific tricks.

Merging KParts Actions Without Duplicates

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.

KParts uses XMLGUI to merge the shell’s actions with the active part’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.

A part can declare an action and place it into a standard menu:

<!DOCTYPE kpartgui>
<kpartgui name="note_part" version="1">
  <MenuBar>
    <Menu name="edit"><text>Edit</text>
      <Action name="note_find"/>
    </Menu>
  </MenuBar>
</kpartgui>

The C++ action collection must use the same action name:

KAction *find = new KAction(i18n("Find"), "find", CTRL + Key_F,
                            this, SLOT(slotFind()),
                            actionCollection(), "note_find");

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++.

Activation matters too. A shell hosting several parts should add the active client’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.

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 kde-config, remove obsolete application-owned resources, and rebuild the service cache if appropriate.

Action state remains the part’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.

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.

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’s document, which is technically impressive but not helpful.

Building a Tiny KIO Slave

I had an application talking to a small read-only service and was about to put the protocol code directly into its file dialog path. A KIO slave turned out to be a cleaner experiment: teach KDE one URL scheme, then let Konqueror and any KIO-aware application use it.

The slave is a separate process driven through KIO’s protocol. A class derived from KIO::SlaveBase implements operations such as get, stat, or listDir, depending on what the scheme supports. For a tiny read-only resource, get is enough to prove the mechanism:

void NoteProtocol::get(const KURL &url)
{
    QByteArray bytes = loadNote(url.path());

    mimeType("text/plain");
    totalSize(bytes.size());
    data(bytes);
    data(QByteArray());
    finished();
}

Real code must report failures with error() rather than returning silently. It should also send data in useful chunks for large objects instead of reading everything into memory as this demonstration does. The empty data block marks the end of data before finished() completes the operation.

KIO discovers the slave through an installed protocol description and service information. Those files state the scheme, executable, supported operations, and whether the protocol works with files, directories, reading, or writing. If Konqueror says the protocol is unknown, I check installation paths and run kbuildsycoca before blaming the C++.

The process boundary is the interesting part. The client starts a KIO job. KIO selects and communicates with the slave, and the slave translates operations into the remote or special resource’s rules. A failure in the protocol handler need not take the client application down with it, and authentication or progress can use KDE’s common machinery.

I am careful not to claim operations the protocol cannot honor. Advertising rename for an immutable service only moves the error from an absent menu item to an annoyed user. stat results must also be consistent with get; applications rely on metadata for decisions before fetching.

I test the scheme directly in Konqueror and with a tiny KIO client, including a missing object, an empty object, and a path containing escaped characters. URL decoding must happen at the protocol boundary exactly once. Decoding twice turns a perfectly legal percent sign into an accidental instruction.

My preference is a KIO slave when a resource genuinely behaves like a hierarchy of files or directories and should be available across KDE. For one private command, DCOP or an application-specific class is smaller. Giving every service a URL is attractive, but some services are verbs wearing a hat.