Kube: Accounts

Kube is a next generation communication and collaboration client, built with QtQuick on top of a high performance, low resource usage core called Sink.
It provides online and offline access to all your mail, contacts, calendars, notes, todo’s etc.
Kube has a strong focus on usability and 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.

To learn more about Kube, please see here.

Kube’s Account System

Data ownership

Kube is a network application at its core. That doesn’t mean you can’t use it without network (even permanently), but you’d severely limit its capabilities given that it’s meant to be a communication and collaboration tool.

Since network communication typically happens over a variety of services where you have a personal account, an account provides a good starting point for our domain model. If you have a system with large amounts of data that are constantly changing it’s vital to have a clear understanding of data ownership within the system. In Kube, this is always an account.

By putting the account front and center we ensure that we don’t have any data that just belongs to the system as a whole. This is important because it becomes very complex to work with data that “belongs to everyone” once we try to synchronize that data with various backends. If we modify a dataset should that replicate to all copies of it? What if one backend already deleted that record? Would that mean we also have to remove it from the other services?
And what if we have a second client that has a different set of account connected?
If we ensure that we always only have a single owner, we can avoid all those issues and build a more reliable and predictable system.

The various views can of course still correlate data across accounts where useful, e.g. to show a single person entry instead of one contact per addressbook, but they then also have to make sure that it is clear what happens if you go and modfiy e.g. the address of that person (Do we modify all copies in all accounts? What happens if one copy goes out of sync again because you used the webinterface?).

Last but not least we ensure this way that we have a clear path to synchronize all data to a backend eventually, even if we can’t do so immediately. E.g. because the backend in use does not support that data type yet.

The only bit of data that is stored outside of the account is data specific to the device in use, such as configuration data for the application itself. Data that isn’t hard to recreate, is easy to migrate and backup, and very little data in the first place.

Account backends

Most services provide you with a variety of data for an individual account. Whether you use Kolabnow, Google or a set of local Maildirs and ICal files,
you typically have access to Contact, Mails, Events, Todos and many more. Fortunately most services provide access to most data through open protocols,
but unfortunately we often end up in a situation where we need a variety of protocols to get to all data.

Within Sink we call each backend a “Resource”. A resource typically has a process to synchronize data to an offline cache, and then makes that data accessible through a standardized interface. This ensures that even if one resource synchronizes email over IMAP and another just gathers it from a local Maildir,
the data is accessible to the application through the same interface.

Because various accounts use various combinations of protocols, accounts can mix and match various resources to provide access to all data they have.
A Kolab account for instance, could combine an IMAP resource for email, a CALDAV resource for calendars and CARDDAV resource for contacts, plus any additional resources for instant messaging, notes, … you get the idea. Alternatively we could decide to get to all data over JMAP (a potential IMAP successor with support for more datatypes than just email) and thus implement a JMAP resource instead (which again could be reused by other accounts with the same requirements).

diagram

 

Specialized accounts

While accounts within Sink are mostly an assembly of some resources with some extra configuration, on the Kube side a QML plugin is used (we’re using KPackage for that) to define the configuration UI for the account. Because accounts are ideally just an assembly of a couple of existing Sink resources with a QML file to define the configuration UI, it becomes very cheap to create account plugins specific to a service. So while a generic IMAP account settings page could look like this:

imapaccount

… a Kolabnow setup page could look like this (and this already includes the setup of all resources including IMAP, CALDAV, CARDDAV, etc.):

kolabaccount

Because we can build all we know about the service directly into that UI, the user is optimally supported and all that is left ideally, are the credentials.

Conclusion

In the end the aim of this setup is that a user first starting Kube selects the service(s) he uses, enters his credentials and he’s good to go.
In a corporate setup, login and service can of course be preconfigured, so all that is left is whatever is used for authentication (such as a password).

By ensuring all data lives under the account we ensure no data ends up in limbo with unclear ownership, so all your devices have the same dataset available, and connecting a new devices is a matter of entering credentials.

This also helps simplifying backup, migration and various deployment scenarios.

On Domain Models and Layers in kdepim

In our current kdepim code we use some classes throughout the codebase. I’m going to line out the problems with that and propose how we can do better.

The Application Domain

Each application has a “domain” it was created for. KOrganizer has for instance the calendar domain, and kmail the email domain, and each of those domains can be described with domain objects, which make up the domain model. The domain model of an application is essential, because it is what defines how we can represent the problems of that domain. If Korganizer didn’t have a domain model with attendees to events, we wouldn’t have any way to represent attendees internally, and thus couldn’t develop a feature based on that.

The logic implementing the functionality on top of those domain objects is the domain logic. It implements for instance what has to happen if we remove an event from a calendar, or how we can calculate all occurrences of a recurring event.

In the calendaring domain we use KCalCore to provide many of those domain objects and a large part of the domain logic. KCalCore::Event for instance, represents an event, can hold all necessary data of that event, and has the domain logic directly built-in to calculate recurrences.
Since it is a public library, it provides domain-objects and the domain-logic for all calendaring applications, which is awesome, right? Only if you use it right.

KCalCore

KCalCore provides additionally to the containers and the calendaring logic also serialization to the iCalendar format, which is also why it more or less tries to adhere to the iCalendar RFC, for both representation an interpretation of calendaring data. This is of course very useful for applications that deal with that, and there’s nothing particularly wrong with it. One could argue that serialization and interpretation of calendaring data should be split up, but since both is described by the same RFC I think it makes a lot of sense to keep the implementations together.

Coupling

A problem arises when classes like KCalCore::Event are used as domain objects, and interface for the storage layer, and as actual storage format, which is precisely what we do in kdepim.

The problem is that we introduce very high coupling between those components/layers and by choosing a library that adheres to an RFC the whole system is even locked down by a fully grown specification. I suppose that would be fine if only one application is using the storage layer,
and that application’s sole purpose is to implement exactly that RFC and nothing else, ever. In all other cases I think it is a mistake.

Domain Logic

The domain logic of an application has to evolve with the application by definition. The domain objects used for that are supposed to model the problem at hand precisely, in a way that a domain logic can be built that is easy to understand and evolve as requirements change. Properties that are not used by an application only hide the important bits of a domain objects, and if a new feature is added it must be possible to adjust the domain object to reflect that. By using a class like KCalCore::Event for the domain object, these adjustments become largely impossible.

The consequence is that we employ workarounds everywhere. KCalCore doesn’t provide what you need? Simply store it as “custom property”. We don’t have a class for calendars? Let’s use Akonadi::Collection with some custom attributes. Mechanisms have been designed to extend these rigid structures so we can at least work with it, but that only lead to more complex code that is ever harder to understand.

Instead we could write domain logic that expresses precisely what we need, and is easier to understand and maintain.

Zanshin for instance took the calendaring domain, and applied the GettingThingsDone (GTD) methodology to it. It takes a rather simple approach to todo’s and initially only required a description, a due date and a state. However, it introduced the notion that only “projects” can have subtodo’s. This restriction needs to be reflected in the domain model, and implemented in the domain logic.
Because there are no projects in KCalCore, it was simply defined that todo’s with a magic property “X-Project” are defined as project. There’s nothing wrong with that itself, but you don’t want to litter your code with “if (todo->hasProperty(X-Project))”. So what do you do? You create a wrapper. And that wrapper is now already your new domain object with a nice interface. Kevin fortunately realized that we can do better, and rewrote zanshin with its own custom domain objects, that simply interface with the KCalCore containers in a thin translation layer to akonadi. This made the code much clearer, and keeps those “x-property”-workarounds in one place only.

Layering

A useful approach to think about application architecture are IMO layers. It’s not a silver bullet, and shouldn’t be done too excessively I think, but in some cases layer do make a lot of sense. I suggest to think about the following layers:

  • The presentation layer: Displays stuff and nothing else. This is where you expose your domain model to the UI, and where your QML sits.
  • The domain layer: The core of the application. This is where all the useful magic happens.
  • The data access layer: A thin translation layer between domain and storage. It makes it possible to use the same storage layer from multiple domains and to replace the storage layer without replacing all the rest.
  • The storage layer: The layer that persists the domain model. Akonadi.

By keeping these layer’s in mind we can do a better job at keeping the coupling at a reasonable level, allowing individual components to  change as required.

The presentation layer is required in any case if we want to move to QML. With QML we can no longer have half of the domain logic in the UI code, and most of the domain model should probably be exposed as a model that is directly accessible by QML.

The data access layer is where akonadi provides a standardized interface for all data, so multiple applications can shared the same storage layer. This is currently made up by the i.e. KCalCore for calendars, the akonadi client API, and a couple of akonadi objects, such as Akonadi::Item and Akonadi::Collection. As this layer defines what data can be accessed by all applications, it needs to be flexible and likely has to be evolved frequently.

The way forward

For akonadi’s client API, aka the data access layer, I plan on defining a set of interfaces for things like calendars, events, mailfolders, emails, etc. This should eventually replace KCalCore, KContacts and friends from being the canonical interface to the data.

Applications should eventually move to their own domain logic implementation. For reading and structuring data, models are IMO a suitable tool, and if we design them right this will also pave the way for QML interfaces. Of course i.e. KCalCore still has its uses for its calendaring routines, or as a serialization library to create iTip messages, but we should IMO stop using it for everything. The same of course applies to KContacts.

What we still could do IMO, is share some domain logic between applications, including some domain objects. A KDEPIM::Domain::Contact could be used across applications, just like KContact::Adressee was. This keeps different applications from implementing the same logic, but of course also introduces coupling between those again.

What IMO has to stay separate is the data access layer, which implements an interface to the storage layer, and that doesn’t necessarily conform to the domain layer (you could i.e. store “Blog posts” as notes in storage). This separation is IMO useful, as I expect the application domain to evolve separately from what actual storage backends provide (see zanshin).

This is of course quite a chunk of work, that won’t happen at once. But need to know now where we want to end up in a couple of years, if we intend to ever get there.

A new folder subscription system

Wouldn’t it be great if Kontact would allow you to select a set of folders you’re interested in, that setting would automatically be respected by all your devices and you’d still be able to control for each individual folder whether it should be visible and available offline?

I’ll line out a system that allows you to achieve just that in a groupware environment. I’ll take Kolab and calendar folders as example, but the concept applies to all groupware systems and is just as well applicable to email or other groupware content.

User Scenarios

  •  Anna has access to hundreds of shared calendars, but she usually only uses a few selected ones. She therefore only has a subset of the available calendars enabled, that are shown to her in the calendar selection dialog, available for offline usage and also get synchronized to her mobile phone. If she realizes she no longer requires a calendar, she simply disables it and it disappears from the Kontact, the Webclient and her phone.
  • Joe works with a small team that shares their calendars with him. Usually he only uses the shared team-calendar, but sometimes he wants to quickly check if they are in the office before calling them, and he’s often doing this in the train with unreliable internet connection. He therefore disables the team member’s calendars but still enables synchronization for them. This hides the calendars from all his devices, but he still can quickly enable them on his laptop while being offline.
  • Fred has a mailing list folder that he always reads on his mobile, but never on his laptop. He keeps the folder enabled, but hides it on his laptop so his folder list isn’t unnecessarily cluttered.

What these scenarios tell us is that we need a flexible mechanism to specify the folders we want to see and the folders we want synchronized. Additionally we want, in today’s world where we have multiple devices, to synchronize the selection of folders that are important to us. It is likely I’d like to see the calendar I have just enabled in Kontact also on my phone. However, we always want to keep the possibility to alter that default setting on specific devices.

Current State

If you’re using a Kolab Server, you can use IMAP subscriptions to control what folders you want to see on your devices. Kontact currently respects that setting in that it makes all folders visible and available for offline usage. Additionally you have local subscriptions to disable certain folders (so they are not downloaded or displayed) on a specific device. That is not very flexible though, and personally I ended up having pretty much all folders enabled that I ever used, leading to cluttered folder selections and lot’s of bandwith and storage space used to keep everything available offline.

To change the subscription state, KMail offers to open the IMAP-subscription dialog which allows to toggle the subscription state of individual folders. This works, but is not well integrated (it’s a separate dialog), and is also not well integrable since it’s IMAP specific.

Because the solution is not well integrated, it tends to be rather static in my experience. I tend to subscribe to all folders that I ever use, which results in a very long and cluttered folder-list.

A new integrated subscription system

What would be much better, is if the back-end could provide a default setting that is synchronized to the server, and we could quickly enable or disable folders as we require them. Additionally we can override the default settings for each individual folder to optimize our setup as required.

To make the system more flexible, while not unnecessarily complex, we need a per folder setting that allows to override a backend provided default value. Additionally we need an interface for applications to alter the subscription state through Akonadi (instead of bypassing it). This allows for a well integrated solution that doesn’t rely on a separate, IMAP-specific dialog.

Each folder requires the following settings:

  • An enabled/disabled state that provides the default value for synchronizing and displaying a folder.
  • An explicit preference to synchronize a folder.
  • An explicit preference to make a folder visible.

A folder is visible if:

  • There is an explicit preference that the folder is visible.
  • There is no explicit preference on visibility and the folder is enabled.

A folder is synchronized if:

  • There is an explicit preference that the folder is synchronized.
  • There is no explicit preference on synchronization and the folder is enabled.

The resource-backend can synchronize the enabled/disabled state which should give a default experience as expected. Additionally it is possible to override that default state using the explicit preference on a per folder level.

User Interaction

By default you would be working with the enabled/disabled state, that is synchronized by the resource backend. If you enable a folder it becomes visible and synchronized, if you disable it, it becomes invisible and not synchronized. For the enabled/disabled state we can build a very easy user interface, as it is a single boolean state, that we can integrate into the primary UI.

Because the enabled/disabled state is synchronized, an enabled calendar will automatically appear on your MyKolab.com web interface and your mobile. One click, and you’re all set.

Mockup of folder sync properties
Example mockup of folder sync properties

In the advanced settings, you can then override visibility and synchronization preference at will as a local-only setting, giving you full flexibility. This can be hidden in a properties dialog, so it doesn’t clutter the primary UI.

This makes the default usecase very simple to use (you either want a folder or you don’t want it), while we keep full flexibility in overriding the default behaviour.

IMAP Synchronization

The IMAP resource will synchronize the enabled/disabled state with IMAP subscriptions if you have subscriptions enabled in the resource. This way we can use the enabled/disabled state as interface to change the subscriptions, and don’t have to use a separate dialog to toggle that state.

Interaction with existing mechanisms

This mechanism can probably replace local subscriptions eventually. However, in order not to break existing setups I plan to leave local subscriptions working as they currently are.

Conclusion

By implementing this proposal we get the required flexibility to make sure the resources of our machine are optimally used, while different clients still interact with each other as expected. Additionally we gain a uniform interface to enable/disable a collection that can be synchronized by backends (e.g. using the IMAP subscription state). This will allow applications to nicely integrate this setting, and should therefore make this feature a lot easier to use and overall more agile.

New doors are opened as this will enable us to do on-demand loading of folders. By having the complete folder list available locally (but disabled by default and thus hidden), we can use the collections to load their content temporarily and on-demand. Want to quickly look at that shared calendar you don’t have enabled? Simply search for it and have a quick look, the data is synchronized on-demand and the folder is as quickly gone as you found it, once it is no longer required. This will diminish the requirement to have folders constantly clutter your folder list even further.

So, what do you think?

Kontact-Nepomuk Integration: Why data from akonadi is indexed in nepomuk

So Akonadi is already a “cache” for your PIM-data, and now we’re trying hard to feed all that data into a second “cache” called Nepomuk, just for some searching? We clearly must be crazy.

The process of keeping these to caches in sync is not entirely trivial, storing the data in Nepomuk is rather expensive, and obviously we’re duplicating all data. Rest assured we have our reasons though.

  • Akonadi handles the payload of items stored in it transparently, meaning it has no idea what it is actually caching (apart from some hints such as mimetypes). While that is a very good design decision (great flexibility), it has the drawback that we can’t really search for anything inside the payload (because we don’t know what we’re searching through, where to look, etc)
  • The solution to the searching problem is of course building an index, which is a cache of all data optimized for searching. It essentially structures the data in a way that content->item lookups become fast (while normal usage does this the other way round). So that  already means duplicating all your data (more or less), because we’re trading disk-space and memory for searching speed. And Nepomuk is what we’re using as index for that.

Now there would of course be simpler ways to build an index for searching than using Nepomuk, but Nepomuk provides way more opportunities than just a simple, textbased index, allowing us to build awesome features on top of it, while the latter would essentially be a dead end.

To build that cache we’re doing the following:

  • analyze all items in Akonadi
  • split them up into individual parts such as (for an email example): subject, plaintext content, email addresses, flags
  • store that separated data in Nepomuk in a structured way

This results in networks of data stored in Nepomuk:

PersonA [hasEMailAddress] addressA
PersonA [hasEMailAddress] addressB
emailA [hasSender] addressA
emailB [hasSender] addressB

So this “network” relates emails to email-addresses, and email-addresses to contacts, and contacts to actual persons, and suddenly you can ask the system for all emails from a person, no matter which of the person’s email-addresses have been used in the mails. Of course we can add to that IM conversations with the same Person, or documents you exchanged during that conversation, … the possibilities are almost endless.

Based on that information much more powerful interfaces can be written. For instance one could write a communication tool which doesn’t really care anymore which communication channel you’re using and dynamically mixes IM and email depending on whether/where the other person is currently available for a chat or would rather have a mail, which can be read later on, and doing so without splitting the conversation across various mail/chat interfaces.
This is of course just one example of many (neither am I claiming the idea, it’s just a nice example for what is possible).

So that’s basically why we took the difficult route for searching (At least that is why I am working on this).

Now, we’re not quite there yet, but we already start to get the first fruits of our labor;

  • KMail can now automatically complete addresses from all emails you have ever received
  • Filtering in KMail does fulltext searching, making it a lot easier to find old conversations
  • The kpeoples library already uses this data for contacts merging, which will result in a much nicer addressbook
  • And of course having the data available in Nepomuk enables other developers to start working with it

I’ll follow up on that post with some more technical background on how the feeders are working and possibly some information on the problematic areas from a client perspective (such as the address auto-completion in KMail).

On minimalistic text editors

I think I already mentioned that I’m quite fond of minimalistic UI’s and texteditors with an undisturbing interface.
Recently I stumbled upon FocusWriter (http://gottcode.org/focuswriter/), which is now by far my favorite app for writing. It’s awesome how nice it is to work with such a tool which eleminates all distraction.
I only wish all KDE applications would have such a mode, where fullscreen really means fullscreen. Imagine how awesome this would be in KMail or even better, KDevelop. Especially KDevelop is, while an awesome IDE, just way to cluttered so far. Maybe the Kate devs eventually get around to implement a real fullscreen mode =)

Until then I’ll stick to copy paste from FocusWriter, or to what I created for Zanshin.

Updates from MindMirror

From time to time I need a little feature for my own motivation, especially after spending quite some time with the, somewhat boring, implementation of datamodels.

So this time I chose the fullscreen editor as my little feature, which allows you to use the whole screen to write some text. I use this i.e. to draft this blogpost, which gives me exactly what I need (a texteditor), and no distractions.

The mode can easily be toggled with a shortcut, which allows to go back and forth in a snap.
Just after I implemented this, I stumbled upon this neat little tool (http://www.golem.de/1105/83651.html, or just google iA Writer), which is unfortunately for mac only.
However I like the approach of the minimalistic UI and  the focus mode, which highlights always the latest sentence. Also the auto markup looks like a good way of writing structured text without spending to much time on the layout.
Overall I believe they did a very good job on stripping down an application to the essentials for a usecase, and I think this would make for some nice additions to the kde texteditor components, which are also used by MindMirror.
The limiting of the text to an area in the middle of the screen is also something which I want to add to mindmirror, otherwise the lines get very long in fullscreen mode, and/or your sticking on the left half of your monitor.

Also in MindMirror I tried to strip down the UI a bit:
It is now possible to hide the toolbar, which really clutters the UI quite a bit and is not for everyone essential.
In fullscreenmode, where the toolbar is normally shown on top, you can get now a completely white screen, which I really like for writing.
Further I replaced the toolbox on the bottom of the editor component with a custom one, which allows to collapse all boxes, instead of one being always open. As a side effect, the resizing of the toolbox works now properly, meaning there is no space wasted anymore.
I’m now relatively happy with the editor part UI (except for the edit buttons next to title and due date, etc.), but I’m sure there is still a lot to improve.


The control pane on the left on the other hand, is nowhere near where I’d like to have it, and really bad looking. I find I somewhat difficult to get it into shape though.
One thing that really bugs me, is the greyish look of almost all UI’s. I’m not aware of a remedy though, without breaking with the KDE style, or using lots of white boxes, which doesn’t look much better either.
If you have some ideas for the current UI, or know of techniques to alter the look of KDE applications, please tell me.

Apart from the UI bits, the next steps on the way to a first releasable version is a rewrite of the akonadi nepomukfeeders and the fixing of the kreparentingproxymodel so the todo hierarchy works. Also a searchview which uses the relevancy of the matches to sort the items is in the works.

I’m on holiday for the next few weeks, and afterwards I’ll have my exams, so don’t expect too much activity from my side. But afterwards I will get all parts into a releasable shape, to make sure there is a decent release ready for KDE 4.8.

On a side note: I just got a part-time employment (next to my studies) with Kolab Systems, which means I will earn my money with OpenSource software from now on!
About as awesome as it gets =)

Announcing Project MindMirror

So MindMirror is the Project I’ve been working towards for the last couple of months.
Steven already mentioned it in the report from the kdepim meeting in osnabrück, I named it notetaker back then as I couldn’t decide for a name, but here’s finally my first blog post about it.

History/Motivation

I was always unhappy with the available solutions for taskmanagement and notetaking. I tried various online tools (which just don’t cut it if you’re sitting in a train…) like evernote, toodledo, doit and some others. After figuring out that online tools are definitely not for me, I decided looking for desktop apps.

Chandler and KJots were the ones I liked the most, KJots being super simple and fast for notes, Chandler has bit more to offer (including todos) but is not really fast, and doesn’t integrate with any webservice.

So I figured out already two years ago that I will have to create my own app, to help my ridcolously bad memory and my habit of being as unorganized as possible.
What I really wanted was an application which does not differentiate between notes and todos, as the frequently evolve from one to another (at least in my world). I wanted a place where I can store my thoughts, todos, events without having to think where it belongs.
Basically just a place where I can dump everything, and retrieve it later on as needed.

Further I wanted it to integrate well with existing solutions, such as KOrganizer, GMail, Evernote, etc.

With akonadi and nepomuk slowly evolving I was finally given the tools to start this task.
So I started last year the project MindMirror.

While the inital development started at a quick pace, I soon faced difficulties in the akonadi and nepomuk internals which occupied me for quite some time.
I spent a lot of time hacking on QProxyModels (the ETM, my own section model, …), also a conceptually proper Nepomuk integration was not easy and is still work in progress. Further I got sidetracked by the trashhandling implementation in akonadi (not yet in master), after attending the kdepim meeting, but more on that in another post.

Now that the needed fixes and additions slowly make their way into master, I feel that I can start spreading the word about this new tool.

MindMirror

MindMirror is supposed to be an interface to store everything you have to remember in form of Notes, Todos and Events. It is designed to be an additional Interface to the calendarview of KOrganizer and not to replace anything.
I try to keep the UI minimalistic, far from the full blown Interface of the KOrganizer Incidence editor. This means also ignoring some features, at least for now (I’ll probably add the option to open the fullblown editor).

Idea is, that a minimum effort is needed to enter something. You can simply create a new item (note/todo/event) and start typing right away, without another click needed. The focus will automatically move to the right fields to minimize user interaction. The UI is reduced to the minimum: title, text, an (optional) due date and a status are all that is usually needed IMHO. The status is the simplified version of the 10 priority levels a task can have in korganizer (States being Later/Now/Done). This gives some simple priority management, which is actually useful.

Organizing/Workflow

So the idea is, that you don’t have to organize the information when you enter it but rather later on (i.e. end of the day), if organisation is needed at all. This avoids breaking your workflow. To further improve this i.e. a krunner can be written so you don’t even need to open MindMirror.

For simple, short term notes, fulltext search and a list of the latest created notes should be enough to find your item again (I hope at least).

If you’re working on a long term project thought, it can be useful to organize your items in a treelike structure, which is typically solved using folders and alike.

MindMirror is not much different, you can organize your items into “Topics” (which can have subtopics and so on). The main difference to a folderstructure is, that you can add an item to several topics at the same time (the UI-parts are still missing currently), which should allow for a little more flexibilty.

Also the organisation of items is done through nepomuk, meaning that the “Topics” are actually pimo:topics and the whole structure is stored in nepomuk. Of course it is also possible to tag you items in MindMirror, so I hope this allows to fill Nepomuk with some more useful information.

With the means of nepomuk it is also possible to attach/link arbitrary documents, emails, to your notes/todos, which gets us one step closer to have everything at hand to fulfil a task.

When you’re done editing an item, don’t even bother saving, everything is already saved as you finish typing.

UI

 

The Userinterface consists of a single view, with the left pane for control/sorting, the listview in the middle for display of the items, and the editor on the right. I’m not a big fan of interfaces consiting of many tabs and different windows, so I try too keep everything together.

The “Views” which you can see on the topleft control mainly the organisation of the items in the listview:

  • Work Layout:
    This layout is for crossing of items on your todo, list. Only uncompleted todos are shown and your notes are there to support what you’re doing.
  • Organize:
    The organize layout shows all items sorted by date. It’s there to organize your items.
  • Upcoming:
    A list of upcoming events/todos

In the custom view you can control the sections and the shown items manually.

The listview in the middle groups the items in sections, currently we have there ItemType (Todo/Event/Note), Status (Done, Later, Now), and Date. If I manage that items can appear in multiple sections we will have some more possibilities like:

  • by subtopics of the current topic
  • by tags

While the listview already supports showing the todos in their hierarchy, this part is still very buggy and needs quite a bit of work first.

The editor is a normal KRichTextWidget, which allows you to enter RichText. Below you can see some toolviews, most interesting is probably the “Context” view which allows you to relate notes/todos/files/etc. to this item.
Instead of using a tabbed interface or windows when opening notes from there, the breadcrumbs on top are used to navigate back.

I don’t plan to add much more to the UI, as this should be all which is needed. There probably will be a couple of changes, and the UI could use some designer’s love (It’s a bit too grey atm.), but from a feature point of view thats more or less it.
I’ll probably add a fullscreen-mode to the editor and a search view for some more searching options though.

Current State

While it is not yet releaseable and I plan the first release earliest with KDE 4.8 (because of the required dependencies), I already use it in my daily notetaking and todo management (i.e. I drafted this blogpost in MindMirror), and I’m quite happy with the result.

There is still some work to be done until it’s fully stable though.

Integration / Collaboration with other applications

Using akonadi for datastorage, namely the akonotes resource for notes and the ical resource for calendar items, you can have the same items in KOrganizer, KJots and MindMirror (and of course every other application which uses akonadi).
This is of course key for event and todo management, as MindMirror does not have it’s own calendarview: KOrganizer is the calendarview.

I do think akonadi is the way to go for data which should be synchronisable to cellphones, webservices, etc.
Nepomuk is also good candidate, but it makes perfectly sense to separate the synchronisation part in akonadi
(maybe as a long term future nepomuk could completely encapsulate akonadi, but thats another story).
Anyways thats why I do not plan to intergrate with applications not using akonadi (in short term).
Since the nepomuk feeders feed the data from akonadi to nepomuk, most of the data is also available trough nepomuk (which might be a way to work with other apps using nepomuk only).

Of course I looked at many other programs like basket, semnotes, kjots, korganizer, zanshin, etc. to see if a couple of modifications would bring my to my target, but I don’t think so. Neither interface wise nor functionality wise any of those programs suits my needs, although all of them have some very nice ideas.

Future Plans

Apart from the obvious plans like having an awsome ui and being super userfriendly, there are also some plans for akonadi in general:

  • Inline pictures in notes
  • Synchronisation plugin for evernote (akonotes resource)
  • krunner (I read there is already something cooking in the zanshin project)
  • Search View with an additional list of item (files, emails, etc.) related to the search (aka. “Contextview”)

I’m sure I won’t run out of work =)

Codebase

While the codebase is generally in an ok state, it needs some cleanup and documentation.
There are still some classes with names that don’t really make much sense anymore, but that will be fixed.

Also for building some kdelibs code is needed (trashhandling and some etm fixes), which is partially only available in my private repos. Anyways, if anyone really feels like building, contact me, but be prepared =)

The code is currently here.

Also, contributions are, as always, more than welcome =)