Skip navigation.
KDE Developer's Journals

Development

bille's picture

Develop Javascript Plasmoids on openSUSE

Aaron, Sandro, moofang, Shantanu and Diego have been hacking up a Plasma storm lately on the Javascript bindings for Plasma and the Plasmate builder tool. Since good code is running code, and running code is a lot easier when somebody else builds it and packages it, I've updated the Plasmate packages in KDE:KDE4:Playground to 0.1alpha2 and have updated the javascript bindings in our KDE SC 4.4.1 packages to include Aaron's latest errata - no need to update yourselves.

So it's even easier to take part in the Plasma Javascript Jam Session competition now.

And while you're at it, how about completing the loop by using our kde-obs-generator to package your plasmoids and make them available on kde-look.org, so others can start to download and improve them directly in Plasmate? Free Software virtuous circle FTW!

lubos lunak's picture

On benchmarks

Do you know this one?

Phoronix tested md5sums of ISO images of distributions. The winner was openSUSE, scoring e29311f6f1bf1af907f9ef9f44b8328b, which gave it a noticeable lead before second Slackware (b026324c6904b2a9cb4b88d6d61c81d1), which is quite closely followed by Fedora (9ffbf43126e33be52cd2bf7e01d627f9) and Debian (9ae0ea9e3c9c6e1b9b6252c8395efdc1). The difference between these two distributions, as you can see, is only very small. Ubuntu completely flopped in this test, achieving only 1dcca23355272056f04fe8bf20edfce0, which is surprising, especially considering that its previous release scored a very nice c30f7472766d25af1dc80b3ffc9a58c7. (source).

Ok, that's just a joke, but the sad part is, as somebody pointed out, that it wouldn't be really that surprising if Phoronix actually did something like that. And, probably even more sad, there would be people who'd really take it as if it meant something and started adding comments about how last openSUSE is pretty good, last Ubuntu is so disappointing, and Fedora and Debian are not really that different.

So take this from somebody who has already done a lot of performance work: Benchmarks, on their own, mean almost nothing if you don't understand them. Especially if they are seriously flawed (I mean, testing filesystem performance by doing CPU-intensive tasks? Hallo? Probably even FAT16 could provide the same results in those tests on an SSD.), but even if the results are useful numbers, it is still necessary to understand what the numbers actually say. I think I wouldn't even have a big problem forging a "benchmark" where KDE would get better (and correct) numbers than LXDE by finding a scenario that'd be twisted enough.

And even then, it is still necessary to keep in mind what is compared. Comparing the default setup of Fedora and openSUSE means also comparing GNOME and KDE, which you may or may not want, but if you compare the distributions this way, it is affected by differences between the desktops, and if you compare the desktops, it is affected by the differences between the distributions. And in either case, it may or may not apply to another distribution or another desktop.

Yet one more thing to understand is what is measured and how it affects performance as a whole. Ages ago there was a Dot article that also mentioned performance improvements to be brought by Qt4 in some specific areas, yet even now there are numbers of people seriously disappointed by KDE4's performance only because they thought that since Qt4 improves in some areas, KDE4 will get exactly the same improvement, regardless of how much these improvements matter for the whole of KDE4 or how much of KDE4 was rewritten when porting from KDE3. When I fixed Exmap to work again and did a little benchmark as a part of it, there wasn't really much more to it than to show that Exmap works again and that it is very easy to lose a lot of advantage by a simple mistake, yet people had no problems drawing all kinds of strange conclusions from that. Since making right conclusions is unexpectedly difficult for most people when it gets to benchmarks, I really need to remember not to just post numbers again without also saying what it means.

And, finally, there is still the question of other costs and whether it is worth it. Various KDE components often have resource demands, but then they are also often worth it. I mean, we all could still use TWM, or, heck, Windows 95, but seriously, how many of us really would? This, ultimately, is always about what works the best for you.

khindenburg's picture

trudging through Konsole's reports

With only a few hours a week to work on Konsole, I often view the logs and other reports for simple issues to investigate. The compile warnings were fixed sometime ago. Most of the simple Krazy and Apidocs issues were also fixed. The remaining Krazy issues would require some heavy duty changes.

rich's picture

Tokamak4 - A New Hope

Today I'm leaving Tokamak 4, so I thought I'd write a post about what I've been up to while I've been here.

The first day or so I spent getting my machine sorted out as trunk was causing some issues with my graphics driver leading to a hang in the DRI layer of the kernel. I also had a chance to triage some ksnapshot bug reports and look over some patches.

The next day was largely taken up with talks about the current status of the various parts of plasma, kwin and related technologies. We got a little hacking done but not much as it was more important to make sure we're all coordinating our development.

The remaining days became a bit of a blur, so in no particular order:

  • I refactored the plasma javascript scriptengine to make it easier to use it with QScriptEngines that are created externally. This is required before we can integrate things like QML.
  • Worked out what is required for QML integration to be implemented in a way that is compatible with our existing javascript bindings etc. This will require some small changes to the API offered by Qt for QML, which may be a problem. If we don't get those changes then QML is likely to be trapped outside the main engine which will reduce what it can do unless we write
    another set of bindings.
  • Made some fixes to the webslice applet to improve error handling.
  • Started work on an idea I've had in the back of my head for a while, I won't say too much about it here, but I'll include a pretty picture to whet your appetite:


    In addition to this I've taken part in lots of discussions on topics ranging from activities/contexts, scripting of animations, silk and more. I'd like to thank Will and the rest of the openSuSE team for making this such a pleasant and productive sprint.

oever's picture

Silent Metronome in QML

Tonight I could not attend band rehearsal so I used the time to play with the new QML language. There is a nice tutorial online and a good screencast.

QML allows one to write flashy applications with little code. My first QML program is a metronome. The N900 has a metronome program but it is rather boring. It does not look and feel like a real metronome. So I set out to write one in QML and managed to do so in 56 lines of QML. The interaction is simple: tap it to toggle between on and off and slide up and down to move the cross-bar on the metronome which will adjust the tempo in the range 40 to 208 beats per minute.

Without further ado here is the code. You can run it in qmlviewer. Two things are lacking at the moment: a nice SVG image of a metronome and of course the ticking sound. I am keen to find out how to make the metronome produce sound to make it useful.

import Qt 4.6

Rectangle {
    width: 640
    height: 480

    Rectangle { // metronome bar
        id: bar
        x: 320; y: 100; width: 30; height: 300
        color: "#aaaaaa"
        property double tempo: 120

        Rectangle { // weight on metronome bar that determines the tempo
            x: -15; y: parent.tempo; width: 60; height: 30
            color: "#aaaaaa"
        }

        transformOrigin: Item.Bottom
        rotation: 0
        rotation: SequentialAnimation {
            id: anim
            repeat: true
            NumberAnimation { to: 35; easing: "easeInOutQuad"; duration: 60000/bar.tempo }
            NumberAnimation { to: -35; easing: "easeInOutQuad"; duration: 60000/bar.tempo }
        }
    }

    Text { // tempo indicator
        x: 0; y: 0;
        font.pointSize: 24; font.bold: true
        text: bar.tempo
    }

    MouseRegion { // logic for tempo tuning and turning metronome on and off
        anchors.fill: parent
        property int start: -1
        property bool moved: false
        property bool wasrunning: true

        onReleased: { // start or stop the metronome
            anim.running = (moved) ?wasrunning :!wasrunning
            bar.rotation = 0
            start = -1
        }
        onPositionChanged: { // adjust the tempo
            moved = start != -1
            wasrunning = (moved) ?wasrunning :anim.running
            bar.tempo += (moved) ?(mouse.y - start) :0
            bar.tempo = (bar.tempo > 208) ?208 :bar.tempo
            bar.tempo = (bar.tempo < 40) ?40 :bar.tempo
            anim.running = false;
            bar.rotation = 0
            start = mouse.y
        }
    }
}

silent metronome in qmlreal metronome

oever's picture

Silent metronome

Silent metronome
jaroslaw staniek's picture

Locus OS: Failed MS Plasma

No, Locus OS concept design, has apparently no association with MS.

The author claims:
"This interface was designed before iPhone 3.0, Palm Pre, Android etc, making the ideas original at the time :)"

Is the last sentence true at all?

rich's picture

A Simple Threading Example

A topic that I've not mentioned in any of my blog posts is threading, not because I have anything against it, simply because a simple use-case hadn't come up. Today I was coding something easy to describe, where using threads was a good solution, so let's take a look at it.

The problem I needed to solve was to calculate cryptographic hashes of files that could be very large - for example 4 gigabyte DVD isos. As with any graphical application it is very important to ensure that the GUI remains responsive while this work is done. Since the problem involves very little communication between the part of the application calculating the hash, and the rest of the code a worker thread is an ideal solution.

The code that actually does the work is very simple, it uses the handy QCryptographicHash class to do the work (stored in the variable hasher):

HasherThread::HasherThread(QObject *parent) :
    QThread(parent)
{
    hasher = new QCryptographicHash( QCryptographicHash::Sha1 );
}

void HasherThread::run()
{
    QFile f( filename );
    if ( !f.open(QIODevice::ReadOnly) ) {
        emit error( QString("Unable to open file %1").arg(filename) );
        return;
    }

    hasher->reset();

    char buffer[16*1024];
    qint64 count;
    do {
        count = f.read( buffer, sizeof(buffer) );
        if ( count == -1 ) {
            emit error( QString("Read error") );
            break;
        }
        hasher->addData( buffer, count );
    } while( !f.atEnd() );

    emit completed( hasher->result().toHex() );
}

The code opens the file to be hashed, then reads through it in 16K chunks which it passes to the hasher. If this code were executed in the application's gui thread then this would cause the interface to freeze until the hash was ready, but the code lives in a class that inherits QThread.

One important feature to note about the code above is that the communication with the rest of the application is via signals (the error and completed signals to be precise). This is very important as it means that when we use the class, we can simply use it like this:

    hasherThread = new HasherThread( this );
    connect( hasherThread, SIGNAL(error(const QString &)),
             ui->resultEdit, SLOT(setText(const QString &)) );
    connect( hasherThread, SIGNAL(completed(const QString &)),
             ui->resultEdit, SLOT(setText(const QString &)) );

The special thing in the code above, is that we didn't have to do anything special - Qt just solved our inter-thread communication issues for us. What I mean, it that if our code had simply tried to output the result by calling ui->resultEdit->setText() directly then we would be attempting to access the GUI from outside the GUI thread which would most likely cause our application to crash. Instead, since we're using the default type of connections 'AutoConnection', what this means is that Qt will spot if the thread in which a signal is emitted is different from the one in which it is received and handle the necessary synchronisation for us - nice!

krake's picture

Akonadi-like access to data in files

Some of Akonadi's resource agents (usually just called resources) work on local files, some on files containing more than one data object, some on directories containing one data object per file.

For example the "VCard Resource" has one vcf file to work with which in turn contains any number of vcards, i.e. contacts.

Those single file storage containers have a couple of things in common so of course we want to share as much of code between their respective resources as possible.

Unfortunately the data inside the different files is formatted quite differently, so the parsing and creation of C++ objects is rather type specific.
Another difference which can make common code difficult is the expected size of the files and each of its entries, i.e. a VCard file will most likely just contain a couple of dozen contacts, maybe in the lower hundret range while an MBox file can easily reach several thousands of entries and each of its entries (emails) is usually larger than one of the contacts.

So code that works well for contacts or calendars does not necessarily work well for messages and vice versa.

While thinking about possible ways to improve our situation I had the idea of using the same level of abstraction we are already using in Akonadi, i.e. generic "Items" which hold the type specific data as their "Payload".

In other words, if we had an "Akonadi Item File" we would get Akonadi items out if it and not have to care about whether those items transport contacts or emails.

This would still leave us with the problem of different file and item sizes. Again I decided to use concepts already proven useful in Akonadi: payload parts and gettings things on demand.

Payload parts refer to a concept where allow for a payload (remember that could be a contact or an email, etc) be split into parts that make sense for the respective data type, e.g. splitting an email into "Headers", "Body" and so on.

Getting things on demand refers to get whatever parts of an item you are interested in at any time, e.g. only getting headers when listing a mail folder and getting the rest when displaying a selected one.

In Akonadi we do this through jobs and telling those jobs what we expect them to return to us.

The respective Akonadi code would look similar to this:

const Collection collection = someModel->selectedCollection();

ItemFetchJob *job = new ItemFetchJob();
job->fetchScope().fetchPayloadPart( MessagePart::Header );

connect( job, SIGNAL( result( KJob* ) ), this, SLOT( collectionListed( KJob* ) );

with collectionListed() doing something like that

ItemFetchJob *job = dynamic_cast( job );

const Item::List items = job->items();
// fetch the first item as a whole

job = new ItemFetchJob( items[ 0 ] );
job->fetchScope().fetchFullPayload();

connect( job, SIGNAL( result( KJob* ) ), this, SLOT( itemFetched( KJob* ) );

In order to do something similar with files I came up with a concept I called the Akonadi Filestore.
The main interface looks like this (omtting some of the methods not important for our example above)

class StoreInterface
{
  public:
    virtual Collection topLevelCollection() const = 0;

    virtual ItemFetchJob *fetchItems( const Collection &collection, const ItemFetchScope *fetchScope = 0 ) const = 0;

    virtual ItemFetchJob *fetchItem( const Item &item, const ItemFetchScope *fetchScope = 0 ) const = 0;
};

Assuming we have an implementation that operates on a file which contains messages, e.g. an MBox store, we can implement the example above quite similar to the respective Akonadi code.
(note: all jobs are named like the ones from Akonadi but live in their own namespace. Collections, items, fetchscope are directly the classes from Akonadi)

// lets assume mStore is of type StoreInterface* and has been
// initialized properly with an MBox store implementation

// lets list the mails in the stores top level collection
ItemFetchJob *job = mStore->fetchItems( mStore->topLevelCollection() );
job->fetchScope()->fetchPayloadPart( Message::Header );

connect( job, SIGNAL( result( KJob* ) ), this, SLOT( collectionListed( KJob* ) );

with collectionListed() doing again something like that

ItemFetchJob *job = dynamic_cast( job );

const Item::List items = job->items();
// fetch the first item as a whole

job = mStore->fetchItem( items[ 0 ] );
job->fetchScope().fetchFullPayload();

connect( job, SIGNAL( result( KJob* ) ), this, SLOT( itemFetched( KJob* ) );

As you can see we get on demand, payload part fetching with the only type specific thing being the name of the header payload part.
In Akonadi resource this difference would removed because Akonadi forwards the payload part from the client requesting it, so the resource does not have to know any of those identifiers itself.

This is already quite nice but it gets better Smiling
- We no longer require the items to be of the same type, say a ZIP file containing contacts, calendars and emails (or like an Outlook PST file)

- We can include metadata that is not part of the common payload formats, e.g. flags of email messages if the store's format supports that (or if it is actually working with more than one file, e.g. KMail is saving this things into index files it keeps alongside the actual mail files).

Neither design nor implementation are fully production ready, I consider it a testbed for the concepts mentioned above.
You can find it in PIM Playground (to get correct paths either checkout playground/pim/akonadi or create a directory "akonadi" into which you checkout "filestore")

brad hards's picture

OpenChange 0.9 released

In my ongoing distraction from working on the Akonadi Exchange resource, we released OpenChange 0.9 today.

Release notes:
Improved portability, including a focus on supporting FreeBSD, OpenSolaris and other systems that do not use GNU libraries / shells; and portability fixes for use of the Intel C Compiler and Sun Studio compiler. 64 bit architectures should be better supported in this release.

Preliminary support for Exchange 2003/2007 specific protocols (EcDoConnectEx and EcDoRpcExt2) was added, and redirection support was implemented. This should fix the ecWrongServer (0x478) error that some users encountered while running openchange based software in a clustered Exchange environment. Note that OpenChange is regularly tested with Exchange 2003 and Exchange 2007.

Support for encrypted communications between client and server has been added.

Syndicate content