Release of Kube 0.3.1

“Kube is a modern communication and collaboration client built with QtQuick on top of a high performance, low resource usage core. It provides online and offline access to all your mail, contacts, calendars, notes, todo’s and more. With a strong focus on usability, the team works with designers and UX experts from the ground up, to build a product that is not only visually appealing but also a joy to use.”

For more info, head over to: kube.kde.org

Kube 0.3.1 is out the door.

Over the past months we’ve been working hard on turning Kube into something more useful than a pure techpreview, and while Kube 0.3.1 still isn’t anywhere near production ready, I can finally say that I can use it for most of my email needs.

First, let’s get out of the way what doesn’t work just yet so you know what you can expect.

  • We don’t provide any upgrade path, so with every release it is necessary to run “sinksh upgrade” manually, which currently simply nukes all your local caches (but not the config, so you’ll just have to resync).
  • Email sending is limited to plaintext (we convert html mails to plaintext on reply).
  • Passwords are stored in plaintext in configuration files, which may not be acceptable to you.
  • It’s of course also possible that you will experience unpleasant surprises if you use it for any relevant emailing.
  • The scrolling experience depends a lot on your input devices. This seems to be a Qt internal defect that we hope will resolve itself with Qt 5.9.

What we do have though is:

  • A working composer that is right now very basic but has a lot of potential (more about that in a separate blogpost).
  • Support for reading encrypted and and signed mails (although the UI support is still very basic for details on validitiy etc).
  • A basic CardDAV based Addressbook.
  • A fairly pleasant reading experience (IMO anyways).

Lot’s of work also went into the application architecture, UI feedback for user interactions (e.g. progress during synchronization), cleanup of our dependency tree and the concept of how we will continue to evolve Kube.

The UI team did excellent work on the UI front (surprise!) and has cleaned up the look considerably. Due to the realization that our look depends a lot on the looks of the icon theme, we are now shipping an icon theme with Kube (based on breeze). This will also further our goal to work equally well on a variety of platforms where we cannot assume a specific icon theme to be available.

We have also transitioned mostly to QtQuickControls2, the remaining bits will require Qt 5.9. We’ll then plan on staying on this LTS release for the time being.

Overall, while not quite ready for prime time, this release marks a very important milestone on our road to a production ready release and I’m very happy to have a lot of issues, that have been bothering us for long, finally resolved.
I also think that while we’ll still have to do one or the other large change every now and then, the codebase can now start to settle as we have resolved our largest problems.

If you’d like to read more or give it a shot, please head over to kube.kde.org for installation instructions for experimental builds for Fedora 25 and Archlinux.

Tarballs

https://download.kde.org/unstable/sink/0.3.0/src/sink-0.3.0.tar.xz.mirrorlist
https://download.kde.org/unstable/kube/0.3.1/src/kube-0.3.1.tar.xz.mirrorlist

Randa

Unfortunately I can’t attend Akademy this year, but if you’d like to work on Kube, talk to us, have a Beer or just go for a hike, make sure to come to Randa for the annual Randa Meetings from the 10.09.2017 – 16.09.2017. To register click here.

Release of KDav2 0.1.0

I’m pleased to announce the release of KDav2 0.1.0.

KDav2 is a KJob based DAV protocol implementation.

KDav2’s major improvement is a vastly reduced dependency chain as we no longer depend on KIO. KDav2 depends only on Qt and KF5CoreAddons.
For more information please refer to the README.

While KDav2 the successor of KDav, KDav will stick around for the time being for Kontact.
KDav and KDav2 are completely coinstallable: library names, namespaces, environment variables etc. have all been adjusted accordingly.

KDav2 is actively used in sink and is fully functional, but we do not yet guarantee API or ABI stability (this will mark the 1.0 release).
If you need API stability rather sooner than later, please do get in touch with me.

If you’d like to help out with KDav2 or have feedback or comments, please use the comment section, the kde-pim mailinglist or the phabricator page.

Tarball

https://download.kde.org/unstable/kdav2/0.1.0/src/kdav2-0.1.0.tar.xz.mirrorlist

Kube’s dependency situation is finally resolved

We’ve worked on this for the past two years and have finally reached an acceptable state where we don’t end up pulling in hundreds of packages.

While initial implementations of things like the email message parser and the DAV and IMAP library brought huge dependencies like KIO, DBus and even Akonadi (that would arguably have been resolvable on a packaging level, but… not a great situation anyways). With all that removed Kube now depends on ~75 packages less (the exact number will depend on factors such as your distros packaging), as well as drastically reducing it’s runtime entanglement (we no longer need dbus, klauncher, external KIO processes, …).

The new dependency situation looks approximately like this:

  • Qt: (We’ll bump that soon to 5.9 for some Qt Quick Controls2 improvements, and then plan on staying on this LTS release)
  • KIMAP2: Used for IMAP access, depending on KMime and Qt.
  • KDav2: Used for DAV access, depending on Qt.
  • KAsync: A pure Qt library that is extensively used in Sink.
  • KMime: Used for mailparsing, depending on Qt.
  • KContacts: Used for parsing VCard, depending on Qt.
  • lmdb: Our key value-store that is a simple C library.
  • flatbuffers: Also part of our storage and a simple self-contained C++ library.
  • QGpgme: Part of gpgme, used for crypto stuff.
  • KCodecs: A tier1 framework used for some parsing tasks.
  • KPackage: A tier2 framework for packaging qml.
  • KCoreAddons: A tier1 framework that we need for KJob.
  • libcurl: Currently used for its SMTP implementation.

And that’s about it. This means we’re now in a situation where each and every dependency that we have is justified and there for a reason. We’re also in a position where most dependencies can be individually replaced should there be a need to so.
This not only makes me much more confident that we can maintain this system in the long run and makes porting to other platforms feasible, it’s also just a much, much healthier situation to be in for a software project.

In case you are wondering, here’s an incomplete list of packages that we used to depend on and no longer do (based on Fedora 25 packaging, check out rpmreaper to recursively query dependencies):

 grantlee-qt5
 kdepim-apps-libs
 kf5-akonadi-contacts
 kf5-akonadi-mime
 kf5-akonadi-search
 kf5-akonadi-server
 kf5-akonadi-server-mysql
 kf5-grantleetheme
 kf5-kauth
 kf5-kbookmarks
 kf5-kcalendarcore
 kf5-kcompletion
 kf5-kconfig-gui
 kf5-kconfigwidgets
 kf5-kdbusaddons
 kf5-kded
 kf5-kdelibs4support
 kf5-kdelibs4support-libs
 kf5-kdoctools
 kf5-kemoticons
 kf5-kiconthemes
 kf5-kidentitymanagement
 kf5-kimap
 kf5-kinit
 kf5-kio-file-widgets
 kf5-kitemmodels
 kf5-kldap
 kf5-kmailtransport
 kf5-kmbox
 kf5-knewstuff
 kf5-knotifications
 kf5-kparts
 kf5-kpimtextedit
 kf5-krunner
 kf5-kservice
 kf5-ktextwidgets
 kf5-kunitconversion
 kf5-kwallet-libs
 kf5-kwidgetsaddons
 kf5-kwindowsystem
 kf5-kxmlgui
 kf5-libgravatar
 kf5-libkdepim
 kf5-libkleo
 kf5-messagelib
 kf5-pimcommon
 kf5-solid-libs
 kf5-sonnet-ui
 kf5-syntax-highlighting
 kf5-threadweaver
 libaio
 libical
 libsphinxclient
 lsof
 m4
 mariadb
 mariadb-common
 mariadb-config
 mariadb-errmsg
 mariadb-libs
 mariadb-server
 mariadb-server-utils
 net-tools
 perl-DBD-MySQL
 perl-DBI
 perl-Math-BigInt
 perl-Math-Complex
 perl-Storable
 postgresql-libs
 qt5-qtbase-mysql
 rsync
 sphinx

Kube: Views and Workflows

“Kube is a modern communication and collaboration client built with QtQuick on top of a high performance, low resource usage core. It provides online and offline access to all your mail, contacts, calendars, notes, todo’s and more. With a strong focus on usability, the team works with designers and UX experts from the ground up, to build a product that is not only visually appealing but also a joy to use.”

For more info, head over to: kube.kde.org

Ever since we started working on Kube we faced the conundrum of how to allow Kube to innovate and to provide actual additional value to whatever is already existing out there, while not ending up being a completely theoretical exercise of what could be done, but doesn’t really work in practice. In other words, we want to solve actual problems, but do so in “better” ways than what’s already out there, because otherwise, why bother?

I put “better” into quotes because this is of course subjective, but let me elaborate a bit on what I mean by that.

Traditionally, communication and organization has been dealt with using fairly disjoint tools, that we as users then combine in whatever arbitrary fashion that is useful to us.

For instance:

  • EMail
  • Chat
  • Voice/Video Chat
  • Calendaring
  • Taskmanagement
  • Notetaking

However, these are just tools that may help us work towards a goal, but often don’t support us directly in what we’re actually trying to accomplish.

My goto example; Jane wants to have a meeting with Jim and Bob:

  • Jane tries to find a timeslot that works for all of them (by mail, phone, personally…)
  • She then creates an event in her calendar and invites Jim and Bob, who can in turn accept or decline (scheduling)
  • The meeting will probably have an Agenda that is perhaps distributed over email, or within the event description
  • A meeting room might need to be booked, or an online service might need to be decided.
  • Once the meeting takes place the agenda needs to be followed and notes need to be taken.
  • Meeting minutes and some actionable items come out of the meeting, that then, depending on the type of meeting, may need to be approved by all participants.
  • So finally the approved meeting minutes are distributed and the actionable items are assigned, and perhaps the whole thing is archived somewhere for posterity.

As you can see, a seemingly simple task can actually become a fairly complex workflow, and while we do have a toolbox that helps with some of those steps, nothing really ties the whole thing together.

And that’s precisely where I think we can improve.

Instead of trying to do yet another IMAP client, or yet another calendaring application a far more interesting aspect is how can we improve our workflows, whatever tools that might involve.
Will that involve some email, and some calendaring and some notetaking? Probably, but it’s just a means to and end and not an end by itself.

So if we think about the meeting scheduling workflow there is a variety of ways how we can support Jane:

  • The scheduling can be supported by:
    • Traditional iCal based scheduling
    • An email message to invite someone by text.
    • Some external service like doodle.com
  • The agenda can be structured as a todo-list that you can check off during the meeting (perhaps with time limits assigend for each agenda item)
  • An online meeting space can be integrated, directly offering the agenda and collaborative note-taking.
  • The distribution and approval of meeting minutes can be automated, resulting in a timeline of past meetings, including meeting minutes and actionable items (tasks) that fell out of it.

That means however that rather than building disjoint views for email, calendar and chat, perhaps we would help Jane more if we built and actual UI for that specific purpose, and other UI’s for other purposes.

Views

So in an ideal world we’d have an ideal tool for every task the user ever has to execute which would mean we fully understand each individual user and all his responsibilities and favorite workflows….
Probably not going to happen anytime soon.

While there are absolutely reachable goals like Jane’s meeting workflow above, they all come at significant implementation cost and we can’t hope to implement enough of them right off the bat in adequate quality.
What we can do however is keeping that mindset of building workflows rather than IMAP/iCal/… clients and setting a target somewhere far off on the horizon and try to build useful stuff along the way.

For us that means that we’ve now set the basic structure of Kube as a set of “Views” that are used as containers for those workflows.

KubeViewSwitcher

This is a purposefully loose concept that will allow us to transition gradually from fairly traditional and generic views to more purposeful and specific views because we can introduce new views and phase out old ones, once their purpose is helped better by a more specific view.

Some of our initial view ideas are drafted up here: https://phabricator.kde.org/T6029

What we’re starting out with is this:

  • A Conversations view:
    While this initially is a fairly standard email view, it will eventually become a conversation centric view where you can follow and pick up on ongoing conversations no matter on what medium (email, chat, …).

kube_mailview

  • A People view:
    While also serving the purpose of an addressbook it is first and foremost a people centric way to interact with Kube.
    Perhaps you just want to start a conversation that way, or perhaps you want to lookup past interactions you had with the person.

kube_addressbook

  • A composer view:
    Initially a fairly standard email composer but eventually this will be much more about content creation and less about email specifically.
    The idea is that what you actually want to do if you’re opening the composer is to write some content. Perhaps this content will end up as email,
    or perhaps it will just end up on a note that will eventually be turned into a blogpost, chances are you don’t even know before you’re done writing.
    This is why the composer implements a workflow that starts with the starting point (your drafts) then goes over to the actual composer to create the content, and finally allows you to do something with the content, i.e. publish or store it somewhere (for now that only supports sending it by email or saving it as draft, but a note/blog/… could be equally viable goals).

The idea of all this is that we can initially build fairly standard and battle-tested layouts and over time work our way towards more specialized, better solutions. It also allows us to offload some perhaps necessary, but not central features to a secondary view, keeping us from having to stuff all available features into the single “email” view, and allowing us to specialize the views for the usecases they’re built for.

Kube::Fabric

“Kube is a modern communication and collaboration client built with QtQuick on top of a high performance, low resource usage core. It provides online and offline access to all your mail, contacts, calendars, notes, todo’s and more. With a strong focus on usability, the team works with designers and UX experts from the ground up, to build a product that is not only visually appealing but also a joy to use.”

For more info, head over to: kube.kde.org

One of the key features of QML is to be able to describe the UI in a declarative fashion, resulting in code that closely represents the visual hierarchy.
This is nice for writing UI’s because you can think very visually and then just turn that into code.
A couple of trial and error cycles later you typically end up with a result that reflects approximately what you sketched out on paper.

However, interactions with the UI are also handled from QML, and this is where this becomes problematic. User interactions with QML result in some signals or API calls on some component, typically some signal handler, and that’s where your application code takes over and tries to do something useful with that interaction. Perhaps we trigger some visual change, or we call a function on a controller object that does further work. Because we try to encapsulate and build interfaces we might build an API for the complete component that can then be used by the users of the component to further interact with the system.
This can quickly get complex with a growing number of interactions and components.

The straightforward implementation is to just forward the necessary API through your components, but that creates a lot of friction in the development process. A simple move of a button may result in drastic changes where that button is within the visual hierarchy, and if we have to forward the API for that we end up writing a lot of boilerplate code for what ought to be a trivial change.

Item {
    id: root
    property signal reply
    Button {
        onClicked: root.reply()
    }
}

One alternative approach is to abuse the QML Context to avoid forwarding the API (so we just call to some magic component id), but this results in components that are not self-contained and that just call to some magic “singleton” objects to communicate with the rest of the application.
Not great in my opinion.

Item {
    id: root
    Button {
        onClicked: applicationController.reply() //Let's hope applicationController is defined somewhere
    }
}

The approach we’ve chosen in Kube is to introduce a mechanism that is orthogonal to the visual hierarchy. Kube::Fabric is a simple messagebus where messages can be published and subscribed to. A clicked button may for instance post a message to the bus that is called “Kube.Messages.reply”. This message may then be handled by any component listening on the messagebus. Case in point; the main component has a handler that will open a composer and fill it with the quoted message so you can fill in your reply.

So the “Fabric” creates a separate communication plane that “weaves” the various UI components together into something functional. It allows us to concentrate on the user experience when working on the UI without having to worry how we can eventually wire up the component to the other bits required (and it gives us an explicit point where we interconnect parts over the fabric), and thus allows us to write cleaner code while moving faster.

Item {
    id: root
    Button {
        onClicked: Kube.Fabric.postMessage(Kube.Messages.reply, {"mail": model.mail, "isDraft": model.draft})
    }
}

API vs. Protocols

The API approach tightly couples components together and eventually leads to situations where we i.e. have multiple versions of the same API call because we’re dealing with some new requirements but we have to maintain compatibility for existing users of the API. This problem is then further amplified by duplicating API’s throughout the visual hierarchy.

The Fabric rather builds a protocol approach. The fabric becomes the transport layer, the messages posted form the protocol. While the messages form the contract and thus also require that no parameter is removed or changed, they can be expanded without affecting existing users of the message.
New parameters don’t bother any existing users and thus allow for much more flexibility with little (development) overhead.

Other applications

Another part where we started to use the fabric extensively is for notifications. A component that listens for notifications from Sink (Error/Progress/Status/…), simply feeds those notifications into the fabric, allowing various UI components to react to those notifications as a appropriate. This approach allows us to feed notifications from a variety of sources into the system, so they can be dealt with in a uniform way.

Code

In actual code it is used like this.

Posting a message from QML:

 Kube.Fabric.postMessage(Kube.Messages.reply, {"mail": model.mail, "isDraft": model.draft})

Posting a message from C++ (message being a QVariantMap):

Fabric::Fabric{}.postMessage("errorNotification", message);

Listening for messages in QML:

Kube.Listener {
    filter: Kube.Messages.reply
    onMessageReceived: kubeViews.openComposerWithMail(message.mail, false)
}

Lookout

The fabric is right now rather simplistic and we’ll keep it that way until we see actual requirements for more. However, I think there is interesting potential in separating message-buses by assigning different fabrics to different components, with a parent fabric to hold everything together. This would enable components to first handle a message locally before resorting to a parent fabric if necessary. For the reply button that could mean spawning an inline-reply editor instead of switching the whole application state into compose mode.

Release of Kube 0.1.0

It’s finally done! Kube 0.1.0 is out the door.

First off, this is a tech preview really and not meant for production use.

However, this marks a very important step for us, as it lifts us out of a rather long stretch of doing the ground work to get regular development up and running. With that out of the way we can now move in a steadier fashion, milestone by milestone.

That said, it’s also the perfect time to get involved!
We’re planning our milestones on phabricator, at least the ones within reach, so that’s the place to follow development along and where you can contribute, be it with ideas, feedback, packaging, builds on new platforms or, last but not least, code.

So what is there yet?

You can setup an IMAP account, you can read your mail (even encrypted), you can move messages around or delete them, and you can even write some mails.

kube_main

BUT there are of course a lot of missing bits:

  • GMail support is not great (it needs some extra treatment because GMail IMAP doesn’t really behave like IMAP), so you’ll see some duplicated messages.
  • We don’t offer an upgrade path between versions yet. You’ll have to nuke your local cache from time to time and resync.
  • User feedback in the UI is limited.
  • A lot of commonly expected functions are not existing yet.
  • ….

As you see… tech preview =)

What’s next?

We’ll focus on getting a solid mail client together first, so that’s what the next few milestones are all about.

The next milestone will focus on getting an addressbook ready, and after that we’ll focus on search for a bit.

I hope we can scope the milestones approximately ~1 month, but we’ll have to see how well that works. In any case releases will be done only once the milestone is reached, and if that takes a little longer, so be it.

Packaging

This also marks the point where it starts to make sense to package Kube.
I’ve built some packages on copr already which might help packagers as a start. I’ll also maintain a .spec file in the dist/ subdirectory for the kube and sink repositories (that you are welcome to use).

Please note that the codebase is not yet prepared for translations, so please wait with any translation efforts (of course patches to get translation going are very welcome).

In order to release Kube a couple of other dependencies are released with it (see also their separate release announcements):

  • sink-0.1.0: Being the heart of Kube, it will also see regular releases in the near future.
  • kimap2-0.1.0: The brushed up imap library that we use in sink.
  • kasync-0.1.0: Heavily used in sink for writing asynchronous code.

Tarballs

Release of KAsync 0.1.0

I’m pleased to announce KAsync 0.1.0.

KAsync is a library to write composable asynchronous code using lambda-based continuations.

In a nutshell:

Instead of:

class Test : public QObject {
    Q_OBJECT
public:
    void start() {
        step1();
    }
public signals:
    void complete();
private:

    void step1() {
        .... execute step one
        QObject::connect(step1, Step1::result, this, Test::step2);
    }

    void step2() {
        .... execute step two
        QObject::connect(step1, Step1::result, this, Test::done);
    }

    void done() {
        emit complete();
    }

};

you write:

KAsync::Job step1() {
    return KAsync::start([] {
        //execute step one
    });
}

KAsync::Job step2() {
    return KAsync::start([] {
        //execute step two
    });
}

KAsync::Job test() {
    return step1().then(step2());
}

The first approach is the typical “job” object (e.g. KJob), using the object for encapsulation but otherwise just chaining various slots together.

This is however very verbose (because what typically would be a function now has to be a class), resulting in huge functional components implemented in a single class, which is really the same as having a huge function.

The problem get’s even worse with asynchronous for-loops and other constructs, because at that point member variables have to be used as the “stack” of your “function” and the chaining of slots resembles a function with lot’s and lot’s of goto statements (It becomes really hard to decipher what’s going on.

KAsync allows you to write such code in a much more compact fashion and also brings the necessary tools to write things like asynchronous for loops.

There’s a multitude of benefits with this:

  • The individual steps become composable functions again (that can also have input and output). Just like with regular functions.
  • The full assembly of steps (the test() function), becomes composable as well. Just like with regular functions.
  • Your function’s stack doesn’t leak to class member variables.

Additional features:

  • The job execution handles error propagation. Errors just bubble up through all error handlers unless a job reconciles the error (in which case the normal execution continues).
  • Each job has a “context” that can be used to manage the lifetime of objects that need to be available for the whole duration of the execution.

Please note that for the time being KAsync doesn’t offer any API/ABI guarantees.
The implementation heavily relies on templates and is thus mostly implemented in the header, thus most changes will require recompilation of your source code.

If you’d like to help out with KAsync or have feedback or comments, please use the comment section, or the phabricator page.

If you’d like to see KAsync in action, please see Sink.

Thanks go to Daniel Vrátil who did most of the initial implementation.

Tarball