Archive for the 'condescending' Category

The future of the European community, a European Monetary Fund.

Monday, March 8th, 2010

I’m worried about the EURO’s M3 if a European version of the IMF (a EMF) is to be installed.

Nonetheless, I think the European community should do it just to strengthen Europe’s economy. I’m not satisfied by Europe’s economic strength: I want it to be undefeatable.

We must not let the IMF solve our problems. Europe might be a political dwarf, but we Europeans should show that we will solve our own problems. We’re an adult composition of cultures with vast amounts of experience. We know how to solve any imaginable problem. And let’s not, in our defeatism, pretend we don’t.

A EMF is a commitment to future member states: Europe often asks them fundamental changes; economic strength is what Europe offers in return. This needs to come at a highest price: Greece will have to fix their deficit problem. Even if their entire population goes on strike. Greece will be an example for countries like my own: Belgium has to fix a serious deficit problem, too.

An EMF comes at an equally high price, and that frightens me a bit: I don’t want the ECB to go as ballistic on money creation as the FED has been last two years. I want the EURO to be the strongest relevant currency mankind has ever created. No matter how insane the rest of the world thinks that ambition is: I believe that keeping the EURO’s M3 in check is a key to creating a wealthy society in Europe.

Politically I want European nations to negotiate more and more often. The European Union is a political dwarf only because finding agreement is hard. But in the long run will our solution be the most negotiated, most tested on this planet.

Together we can deal with anything. That doesn’t mean it’ll be easy; it has never been easy: just seventy years ago we were still killing each other. We’re all guilty of that one way or another. And before that it wasn’t any better. Today, not that many people still care: “it wasn’t me”, right? So stop being a bitch about it, then.

It’s time to let it be. It’s time to start a new European century that will be better. With respect for all European cultures, languages, nations, nationalities, values, borders and interests.

But also a European century with economic responsibilities for each member. It’s our strength: we figured out how to keep our population wealthy: let’s continue doing so in the future.

The Euro skeptics and pro Europeans are finally united in an opinion!

Thursday, February 25th, 2010

We both agree that Nigel Farage is a complete moron.

Perhaps we should put a damp rag like the one he mentions in his mouth next time he opens it?

Nigel Farage, you’re an disgrace to yourself. The European parliament is no place for personal attacks, and you aren’t fit to carry the title Member of the European Parliament. Please keep the honour to yourself and resign.

Every sensible person outside of the U.K. thinks you should. Even the Euro skeptics do. You’re an embarrassment for your country and its culture, so I hope for the people in the U.K. that they’ll kick you out of politics.

I fear you’re just playing the populist card, and that you’ll even get votes for this from other morons.

Please don’t rewrite softwares (that are) written in .NET

Tuesday, February 9th, 2010

This (super) cool .NET developer and good friend came to me at the FOSDEM bar to tell me he was confused about why during the Tracker presentation I was asking people to replace F-Spot and Banshee.

I hope I didn’t say it like that, I would never intent to say that. But I’ll review the video of the presentation as soon as Rob publishes it.

Anyway, to ensure everybody understood correctly what I did wanted to say (whether or not I did, is another question):

The call was to inspire people to reimplement or to provide different implementations of F-Spot’s and Banshee’s data backends, so that they would use an RDF store like tracker-store instead of each app its own metadata database.

I think I also mentioned Rhythmbox in the same sentence because the last thing I would want is to turn this into a .NET vs. anti-.NET debate. It just happens to be that the best GNOME softwares for photo and music management are written in .NET (and that has a good reason).

People who know me also know that I think those anti-.NET people are disruptive ignorable people. I also actively and willingly ignore them (and they should know this). I’m actually a big fan of the Mono platform.

I’ll try to ensure that I don’t create this confusion during presentations anymore.

Tough talk

Friday, January 29th, 2010

Not all discussions are easy. If discussions were to be easy, the bar wouldn’t be high enough for your bullshit filter to be effective here.

During dark hours of discussions the nineties syndrome of wanting immediate results plays its role among spectators: It’s not a popular job to be a dissident. It’s not popular to be critical about a (the leader of a) popular idea. This is illustrated by the intellectually absurd criticisms David Schlesinger receives.

Yet is the critic who monitors the organs of a society key to that organ either producing for its stakeholders, or failing and dragging the entire society it serves down with it.

In Western Europe we traded Kings and Popes for a government that is held accountable by an opposition. Many countries and cultures adopted this system of governance. That’s because it undeniably works. If you have a better system in mind, that can be put to the test, please come forward.

It is good that the GNOME foundation board has decided to increase the amount of surveys. But I have one request which I didn’t succeed in raising before the end of last year:

Although I accept the decisive role a group of leadership has to take, I want foundation board members and employees to be held accountable for the decisions they make. Especially the ones where they go against the results of such a survey.

But this is not up to me.

*edit* They are showing an old episode of Married with Children on TV, I’ll be back in half an hour!

Dear France

Tuesday, January 26th, 2010

Thank you for trying to forbid the burka. I hope my country will also forbid it. We need to protect (but not overprotect) the women of Muslim cultures, cultures who are massively migrating to Western Europe at this moment, against the oppressive anti-woman and religious nature of the burka.

I don’t believe, at all, that the burka is an expression of free speech. I believe it’s an instrument to oppress woman, and that this is its only purpose. There is no place for that in Western European culture. None. And we must be assertive about it.

I’d also like to ask Muslim countries to stay out of the debate: we decide about Western European values, you don’t. Equality between men and woman is a Western European value. If you don’t like that, sorry, it’s not negotiable.

The role of media in the USA

Monday, January 18th, 2010

Two posts ago I wrote that something like The Real news is quite unique in the U.S.’s completely broken media.

Today I found an interesting double interview on AlJazeeraEnglish by Riz Khan titled Has the mainstream media in the US replaced serious coverage with “junk news” and tabloidism?


Debian, wtf! @#**&#

Friday, November 27th, 2009

We all woke up with a broken debian testing this morning.

You fix it by removing /boot from the Grub entries. You type ‘e’ and then you go to the vmlinuz line, and you remove “/boot” from that line.

Thanks Debian guys! Remember that normal people would have reformatted their computer and called debian “junk”. You’re even making the software developers nervous. We install debian testing because we don’t like Ubuntu’s broken upgrades. You don’t have to copy this.

Cheers.

ps. I of course understand that testing != stable. But still, Grub? That’s a drastic way to make your point about Debian testing being unstable :-)
Edit: Apparently I was on unstable for the system where this failed. That might explain it.

Handling triplets arriving in tracker-store, CouchDB integration as use-case

Sunday, November 22nd, 2009

At GCDS Jamie told us that he wants to make a plugin for tracker-store that writes all the triplets to a CouchDB instance.

Letting a CouchDB be a sort of offline backup isn’t very interesting. You want triples to go into the CouchDB at the moment of guaranteed storage: at commit time.

For the purpose of developing this we provide the following internal API.

typedef void (*TrackerStatementCallback) (const gchar *graph,
                                          const gchar *subject,
                                          const gchar *predicate,
                                          const gchar *object,
                                          GPtrArray   *rdf_types,
                                          gpointer     user_data);
typedef void (*TrackerCommitCallback)    (gpointer     user_data);

tracker_data_add_insert_statement_callback (TrackerStatementCallback callback,
                                            gpointer                 user_data);
tracker_data_add_delete_statement_callback (TrackerStatementCallback callback,
                                            gpointer                 user_data);
tracker_data_add_commit_statement_callback (TrackerCommitCallback callback,
                                            gpointer              user_data);

You’ll need to make a plugin for tracker-store and make the hook at the initialization of your plugin.

Current behaviour is when graph is NULL, it means that the default graph is being used. If it’s not NULL, it means that you probably don’t want the data in CouchDB: it’s data that’s coming from a miner. You probably only want to store data that is coming from the user. His applications won’t use FROM and INTO for their SPARQL Update queries, meaning that graph is NULL.

Very important is that your callback handler works with bottom halves: put your expensive task on a queue and handle the queued item somewhere else. You can for example use a GThreadPool or a GQueue plus a g_idle_add_full with G_PRIORITY_LOW callback picking items one by one on the mainloop. You should never have a TrackerStatementCallback or a TrackerCommitCallback that blocks. Not even a tiny tiny bit of blocking: it’ll bring everything in tracker-store on its knees. It’s why we aren’t giving you a public plugin API with a way to install your own plugins outside of the Tracker project.

By the way: we want to see code instead of talk before we further optimize things for this purpose.

Who the fuck is this guy?!

Thursday, November 19th, 2009

While you guys are all wondering who he is, we in Belgium are wondering who’s going to replace Herman Van Rompuy as our prime minister.

He’s the only prime minister who managed to give Belgium non-chaotic federal politics, for a few months.

I fear that Belgium will now plunge into a new political crisis. Not because the former prime-minister, Yves Leterme, is a bad one, but because the Walloons simply don’t want him. We know they’ll do everything in their power to discredit Yves. Especially their media will. Le Soir already publicly said that they’ll “veto” Yves Leterme as prime minister. As if a newspaper elects ministers. Arrogance.

Anyway.

If the price for delivering the first president of Europe is that we must pay with a new political crisis, I guess that we are so used to politic crisis that it’s okay. We’ll survive. You guys can have him.

He’s quite intelligent. He’s not a media guy. We don’t know more about him ourselves. Use wikipedia.

The real bad thing about Herman is that in the past he let religion influence his politics. He was for example against abortion laws. And he is against Turkey joining the union because of religious differences.

However. For the people from the United Kingdom: fuck your conservative tabloid magazines. To the idiot editors of those tabloids: discrediting Van Rompuy was easy, still you guys screwed up with retarded articles about Belgium.

ps. I don’t care that you don’t want politics on planet.gnome. It pulls from my blog, so ask the administrators of planet.gnome to pick the right categories. I say this because I know that people will otherwise comment about it. I want them to know that I don’t care.

Writeback, writing metadata back into your files

Wednesday, November 11th, 2009

Today, I feel like exposing you to some bleeding edge development going on as we speak at the Tracker team. I know you’re scared of that and that’s precisely why I want to expose you! Hah.

We are prototyping writeback support for Tracker.

With writeback we mean writing metadata that the user passes to us via SPARQL UPDATE into the file that he’s describing.

This means that it must be about a thing that is stored, that it must update a property that we want to writeback and it means that we need to support the format.

OK, that’s three requirements before we write anything back. Let’s explain how this stuff works in the prototype!

In our prototype you mark properties that are eligible for being written into the files using tracker:writeback.

It goes like this:

nie:title a rdf:Property ;
   rdfs:label "Title" ;
   rdfs:comment "The title of the document" ;
   rdfs:subPropertyOf dc:title ;
   nrl:maxCardinality 1 ;
   rdfs:domain nie:InformationElement ;
   rdfs:range xsd:string ;
   tracker:fulltextIndexed true ;
   tracker:weight 10 ;
   tracker:writeback true .

Next you need a writeback module for tracker-writeback. We implemented a prototype one that can only write the title of MP3 files. It uses ID3lib’s C API.

When the user is describing a file, the resource must have nie:isStoredAs. The property being changed ’s tracker:writeback must be true. We want the value of the property too. That’s simple in SPARQL, right? Sure it is!

SELECT ?url ?predicate ?object {
    <$subject> ?predicate ?object ;
               nie:isStoredAs ?url .
    ?predicate tracker:writeback true
 }

You’ll find this query in the code, go look!

Now it’s simple: using ID3lib we map Nepomuk to ID3 and write it.

No don’t be afraid, we’re not going to writeback metadata that we found ourselves. We’ll only writeback data that the user provided in the form of a SPARQL Update on the default graph. No panic. Besides, using tracker-writeback is going to be completely optional (just don’t run it).

This is a prototype, I repeat, this is a prototype. No expectations yet please. Just feel exposed to scary stuff, get overly excited and then join us by contributing. It’s all public what we’re doing in the branch ‘writeback’.

ps. Whether this will be Maemo’s future metadata-write stuff? Hmm, I don’t know. Do you know? ;-)

Keeping the autotools guys happy with qmake

Tuesday, October 20th, 2009

I’m still figuring out how to do the same thing with cmake, but various bloggers and comments appear to be promising that it’ll be even more easy.

But this is a message for probably all Nokia teams who are making Qt-based libraries:

First open your src/src.pro file and add this stuff:

CONFIG += create_pc create_prl
QMAKE_PKGCONFIG_REQUIRES = QtGui
pkgconfig.files = packagename.pc
pkgconfig.path = $$(DESTDIR)$$[QT_INSTALL_LIBS]/pkgconfig
INSTALLS += target headers pkgconfig

Now open your debian/$package-dev.install file and add this line:

usr/lib/pkgconfig

You’ll be doing all the autotools people a tremendous favor.

Next, open the README file and document that you need to use qmake-qt4 on Debian or make either qmake-qt3 or qmake-qt4 work flawlessly with your build environment. Perhaps also mention how to set the install prefix, how to make qmake find and install .pc files in another location, stuff like that. I find that this is lacking for almost every Qt-based library.

You’ll be doing everybody who wants to use your software a tremendous favor.

The act of making …

Sunday, October 4th, 2009

To be a Rubens, is to make paintings

Indentation

Friday, September 25th, 2009

People,

Let’s all stop doing this:

static void
my_calling_function_wrong (void)
{
[tab]MyItem1 *item1;
[tab]MyItem2 *item2;
[tab]MyItem3 *item3;

[tab]my_long_funcion (item1,
[tab][tab][tab][tab]..item2,
[tab][tab][tab][tab]..item3);
}

And start doing this:

static void
my_calling_function_right (void)
{
[tab]MyItem1 *item1;
[tab]MyItem2 *item2;
[tab]MyItem3 *item3;

[tab]my_long_funcion (item1,
[tab].................item2,
[tab].................item3);
}

The former doesn’t make sense unless each and every code viewing text display understands Mode lines’ tab-width property. The latter just always works, with every normal text editor.

ps. The super cool guys at Anjuta have already fixed this for me. I’m sure the even more cool EMacsers and the uber cool vimers can also fix their text editors?

Unnecessary note: [tab] is a tab and . is a space in the examples.

Melk

Thursday, September 17th, 2009

Veel mensen beweren dat indien je de prijs van een product artificieel verhoogt dat je daardoor de producent ervan rijker maakt. Laten we melk als voorbeeld nemen om dit gesprek wat minder abstract te maken.

Europese overheden worden momenteel door belangengroepen en stakende boeren gedwongen om de prijs van melk artificieel te maken. Met andere woorden wordt de overheid gevraagd om het concept van vrije marktprijzen voor melk los te laten. Dus zelf maar te gaan bepalen wat de prijs voor melk hoort te zijn. Niet de markt maar wel politici en belangengroepen moeten dan bepalen wat die prijs zou moeten zijn.

Het probleem is dat volgorde van nut, van melk, niet wijzigt wanneer incompetente mensen een prijs vastleggen.

Met melk kan veel gedaan worden. Je kan er yoghurt mee maken, je kan het gewoon drinken, je kan er een kind een gezond drankje mee geven, je kan er kaas mee maken, je kan er chocolade mee maken, en zo verder. Zoals bijna alle producten is het veelzijdig.

Ieder individu heeft een voorkeurenladder voor zijn melk doelen. Tegenwoordig hebben we een ruilmiddel dat we geld noemen. Maar laten we voor de grap minuten werk gebruiken als eenheidsprijs. Je kan stellen dat een mens een zekere hoeveelheid werktijd over heeft voor ieder van zijn melk doelen.

Laat me een voorbeeld maken. Deze lijst hangt af van persoon tot persoon, maar kan slechts enkel objectief vastgesteld worden door naar handelingen te kijken. Niet door naar iemand zijn beweringen te luisteren. Stel dat we de volgende vaststelling doen bij de man:

  • Zijn kind melk geven - 8 minuten werk voor over
  • Zelf melk drinken - 6 minuten werk voor over
  • Yoghurt eten - 4 minuten werk voor over
  • Kaas eten - 4 minuten werk voor over
  • Chocolade eten - 3 minuten werk voor over

Dit betekent dat de persoon 8 minuten wil werken om zijn kind een gezonde drank te geven. Hij wil echter maximaal 6 minuten werken om zelf melk te kunnen drinken. Yoghurt vindt hij wel lekker, maar minder belangrijk. Dus heeft de man 4 minuten werk voor yoghurt over. En zo verder.

We zullen om het eenvoudig te houden elk van deze handelingen gelijk stellen aan één liter melk. Dit is in werkelijkheid niet het geval maar het maakt het voorbeeld eenvoudig zonder af te doen aan de logica.

Stel dat we in totaal 10 liter melk hebben voor één man. Hij wil het kind melk geven en heeft daar 8 minuten voor over. Daarna wil hij zelf melk drinken. In totaal verbruikt hij nu 2 liter melk. Hij wil ook yoghurt eten. Hij wil kaas eten, en zelfs chocolade. Al die doelen zijn mogelijk want er is voldoende melk.

De man zal nu al zijn doelen invullen door de melk te kopen aan 3 minuten per liter. Met andere woorden koopt hij in totaal 5 liter melk voor 15 minuten werk. Er is een melk overschot van 5 liter. De producent heeft dus 5 liter teveel geproduceerd. Maar de producent heeft ook werkuren in die melk moeten stoppen. Hij zal dus niet toelaten dat de man oneindig laag gaat in wat hij over heeft voor melk.

Stel nu dat de regering bij wet vastlegt dat een liter melk niet 3 minuten maar wel 5 minuten werk moet kosten. We herhalen ons voorbeeld.

Hij wil nog steeds zijn kind melk geven. Daar heeft hij 8 minuten werk voor over. Daarna drinkt hij zelf melk, daar zou hij 6 minuten werk voor over hebben. Maar voor yoghurt heeft hij niet meer de prijs van 5 minuten werk over, dat is immers meer dan de 4 minuten die hij er voor over heeft. De persoon koopt dus géén yoghurt. Hij koopt ook géén kaas en hij koopt géén chocolade. Die producten kosten allemaal meer dan wat hij over heeft voor de liter melk die ze vereisen. In totaal heeft hij 2 liter melk gekocht voor 10 minuten werk en is er 8 liter overschot.

Door de prijs van melk vast te leggen zorgt de regering er dus voor dat bedrijven die yoghurt, kaas en chocolade maken failliet gaan en creëert het een nog grotere melk overschot.

Het kost ons allen belastingen om die melk op te kopen, en meer aan sociale zekerheid om werkloosheidsuitkeringen uit te betalen voor mensen in de sectoren kaas, chocolade en yoghurt.

Daarbovenop creëert men armoede in landen waar Europa de opgekochte overschot aan melk aan dumpingprijzen op de markt gooit. Hierdoor kunnen plaatselijke boeren niet concurrentieel zijn en worden ze werkloos. In tegenstelling tot werkloos zijn in ons land, wat werkelijk het paradijs op aarde is met brugpensioenen, gratis huisvesting, een legioen aan mensen die werk voor je zoeken en een royale uitkering, betekent het daarginds dat de boer, zijn vrouw en zijn kinderen sterven van de honger.

Dus wanneer we er dan toch ideologie bij roepen dan blijkt dat in een geglobaliseerde samenleving zoals de onze het vastleggen van prijzen door de regering immoreel is.

Ook de boeren die melk produceren gaan mee moeten opdraaien voor extra belastingen. Dat is het enige dat de regering heeft gedaan voor de boer: meer belastingen opgelegd.

Het is dus niet logisch te stellen dat wanneer je de prijs van melk artificieel maakt, dat de producent dan meer geld krijgt. Het enige wat wijzigt, is de omvang van de persoonlijke tabellen van doelen die mensen hebben die in aanmerkingen komen voor melk.

Heel wat leiders van belangengroepen, vooral socialistische, moeten hoogdringend enkele basis lessen economie volgen en moeten nog dringender ophouden met populisme. Zij maken ons land er werkelijk mee kapot en creëren armoede in andere landen.

Iedereen heeft het moeilijk, boeren hoeven geen voorkeursbehandeling te krijgen ten koste van anderen.

Database cursors used in Tracker

Monday, August 31st, 2009

A cursor on a query of a database is a finger pointing to the current row. Most databases do this without pulling the entire resultset into memory. It’s indeed much like a C/C++ pointer, except that a pointer can only point to memory in your process’ virtual memory. A cursor is a bit more abstract.

POSIX developers can compare a cursor with a pointer to a region in an mmap. For people who don’t know about mmap, mmap can be used to map a file into your process’ memory. You get a C/C++ pointer back, from which you can read the data as-if it’s in memory. With mmap, when you create a pagefault, the kernel will pull pages into your memory (from the file, or whichever resource is behind the mapping).

In Tracker all database operations used to be much like how using g_file_get_contents works: you read the entire thing into memory, and then you operate on that memory. Internally it used the database’s cursor API too, of course. The sqlite3_step is sqlite’s cursor API too.

First the database has filled up its pagecache with this data, then you copied it to your application’s memory, then you used it, then you freed it.

That’s kinda silly! Why not use it straight from the database’s caches instead? That’s what you use a DB cursor for.

The result is less copying of memory. This means less memory fragmentation and fewer memory operations to perform (which should result in a small performance improvement).

This effort is ongoing but a lot of Tracker’s internal loops over resultsets are now using a cursor instead of a in-memory result-set.

A reason to get up in the morning

Friday, August 28th, 2009

Ever since Nokia contacted me about improving Tinymail to make it suitable for their Modest E-mail client have they given me a reason to get up in the morning, to work on something of which I knew would someday kick ass.

With the Maemo5 based Nokia N900 device we’ll have Modest shipped by default, and Tracker being actively used by several of its softwares. Future is going to shine even brighter for Tracker. Hard to brag about it, Tracker is inherently a background thing. Ah, well, technical people know about it.

Having worked on Tracker for more than a year, I now understand Tracker’s potential. At first, while I was trying to make an API for- and store the summary of E-mail envelope headers, so that E-mail clients can access this in a memory efficient way, I was critical of this Tracker stuff.

But then I joined Ivan, Urho, Ottela, Martyn and Carlos who were working on Tracker. Later Jürg joined and at the Berlin Hackfest people like Rob Taylor, Jürg and Urho discussed replacing Tracker’s poorer own ontology with Nepomuk and replacing its query language with SPARQL.

Given the implied complexity I was again critical, but then that crazy Jürg guy in a few weeks time turned Tracker into 99.9% pure fine awesomeness. I quickly joined working on this crazy “vstore” branch. Since a few months we have convinced the other Tracker guys to just start calling it “master”.

Ever since I feel again like a student who is learning how to develop software. Jürg is utilizing so many good techniques and we’re implementing so many specifications that are just “the right thing to do”, that the beautify of it all could sometimes make me cry of happiness.

Thanks to creating the opportunity to develop on software that will be used on for example their N900 device, Nokia continues giving people like me a reason to get up in the morning.

Don’t tell the native Nokians, but that’s why the N900 announcements secretly also made me a little bit proud. To whoever of us that worked on this stuff: guys, we’re all doing a great job. Let’s make the next one even better!

As it should be

Monday, August 24th, 2009

Last week I wrote down why I believe the model should not have anything about columns. In .NET many people only ever used DataTables as their models. Because of that they often believe that in .NET the model must contain the columns.

They forget that DataGridView ’s DataSource doesn’t require a DataTable at all, DataTable just happens to implement what DataSource needs: IList. It’s correct that if the model has all information that .NET’s many databinding components will get all the information they need out of your model. But it ain’t true that this is the only way nor a by-design in .NET. In .NET the by-design is that the view has all this and the model *can* pass it, if it has it, but it doesn’t have to.

In this example I illustrate that in .NET you can do a databinding with a simple .NET array. In .NET simple arrays implement IList. When a column of the DataGridView isn’t ReadOnly the property setter of the instance in the array will be called after the user edited the cell. I’ll illustrate this in the dataGridView1_CellEndEdit method: the property setter of the property Age of the Person instance being edited will be called. The view will as a result of a Refresh fetch the model’s new values. The Changed property will be rendered as True, for the Person that got changed.

People with VS.NET can drag a DataGridView and a Button on a Windows Form, and copypaste the Person class, button1_Click’s and dataGridView1_CellEndEdit’s code over. It’ll work.

// No DataTable, I'm not even importing System.Data, IList is fine
using System;
using System.Windows.Forms;

public partial class Form1 : Form
{
    public Form1() [+]

    private void button1_Click(object sender, EventArgs e) {
        dataGridView1.AutoGenerateColumns = false;

        DataGridViewColumn column;

        column = new DataGridViewTextBoxColumn();

        column.DataPropertyName = "Name";
        column.HeaderText = "The name of the person";
        column.Width = 180;

        // As you can see we are not doing anything on the model
        // to tell the view what the columns are.

        dataGridView1.Columns.Add(column);

        column = new DataGridViewTextBoxColumn();
        column.DataPropertyName = "Age";
        column.HeaderText = "The age";
        column.Width = 70;

        // Let's make this one editable
        column.ReadOnly = false;

        // We're just telling the view about the properties it
        // needs to bind, using the DataPropertyName member of
        // a DataGridViewColumn

        dataGridView1.Columns.Add(column);

        // Let's add a column that will show us that the view
        // will fetch property values at refresh

        column = new DataGridViewTextBoxColumn();
        column.DataPropertyName = "Changed";
        column.HeaderText = "?";
        column.Width = 45;

        dataGridView1.Columns.Add(column);

        // This is a normal array in .NET: it implements IList.
        // An IList is a collection with a known order. 

        Person[] people = new Person[2];

        // Let's create two people in this array

        people[0] = new Person();
        people[0].Name = "Jos";
        people[0].Age = 30;
        people[0].Changed = false;

        people[1] = new Person();
        people[1].Name = "Jan";
        people[1].Age = 25;
        people[1].Changed = false;

        // And let's set the model of the view to be that array

        dataGridView1.DataSource = people;
        dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEndEdit);
    }

    void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        // This makes the view refresh its currently visible values, by reading
        // them from the model again. This callback happens after the user is
        // done editing a cell.

        dataGridView1.Refresh();
    }
}

public class Person {
    private string name, city;
    private uint age;
    private bool changed;
    public string Name {
        get { return name; }
        set { name = value; }
    }
    public bool Changed {
        get { return changed; }
        set { changed = value; }
    }
    public uint Age {
        get { return age; }
        set {
            age = value;
            Changed = true;
        }
    }
    public string City {
        get { return city; }
        set { city = value; }
    }
}

You can compare a GtkTreeModel with a DataTable in .NET: it’s a model that has its own memory storage and it contains both rows and columns. This means that GtkTreeModel isn’t a generic model, like IList in .NET actually is. With GtkTreeModel you must always represent your data as rows and columns. Even if the data ain’t rows and columns.

I indeed believe that Microsoft got databinding right in their .NET platform, and that Gtk+’s GtkTreeView and GtkTreeModel got it wrong.

Also feel free to have a huge array of Person instances. It’ll only read property values of the visible ones (plus a few more, shouldn’t be much). Fun tip: write something to the console in the property getters of the Person class, and start scrolling. Now you can easily discover yourself how to do lazy loading tricks with MVC in .NET, and make things scale.

TreeModel ZERO, a taste of life as it should be

Monday, August 17th, 2009

If bugmasters are allowed to blog wishlists, then developers should also be allowed to write them! Which is why I wrote my wishlist!

Gtk.TreeModel was in my humble opinion designed wrong. In API design should an interface be just one thing.

A little bit of history

Many framework designers have repeated this in the past. Two of the best framework designers that we have on this planet, Krysztof Cwalina and Brad Abrams from Microsoft, added the meme to one of their books. It would be unfair to only mention those two guys and not the other people at Microsoft, and before that at the Delphi team at Borland. Brian Pepin notes at page 83 of Framework Design Guidelines: “Another sign that you’ve got a well defined interface is that the interface does exactly one thing. If you have an interface that has a grab bag of functionality, that’s a warning sign.”

The problem

What are the things a Gtk.TreeModel are or represent?

  • It’s something that is iterable
  • It’s something that is an iterator
  • It’s apparently something that has columns, which should have been at the View’s side of the story
  • It’s something that can be a tree
  • It’s something that emits row changes

That’s not one thing, and therefore we have a warning sign. If I count it correctly that’s at least five things, so that’s a big warning sign.

I’m sure I can come up with a few other things that a Gtk.TreeModel actually represents. For example its unref_node and ref_node make me think that it’s a garbage collector or something, too.

This is absolutely not good. I believe it is what makes the interface shockingly complicated. Because none of those five things can be made reusable this way.

What I think would be the right way

A prerequisite for this, and presumably also the reason why Gtk+ developers decided to do Gtk.TreeModel the way they did it a few years ago, is a collection framework.

Sadly is this proposal being ~ignored by the current GLib maintainers. Understandable because everybody is overloaded and busy, but in my opinion it’s nonetheless blocking us from heading in the right direction.

There are by the way quite a lot of other reasons mentioned on the proposal. This is just one of them.

interface GLib.Iterable {
	Iterator iterator();
}

interface GLib.Iterator {
	bool next ();
	object current;
}

Next would be recursive iterators or trees. There are many ways to represent these, but I’ll just take a simple route. Remember that when picking an API design, the most simple idea is often the most right one. But yeah, you can probably improve this.

interface GLib.TreeIterable : GLib.Iterable {
	GLib.TreeIterable get_children ();
	int n_children;
	bool has_child (GLib.TreeIterable e);
	GLib.TreeIterable parent;
}

In Gtk+ we would have the view, of course. It would hold the columns, as it should be.

class Gtk.TreeView {
	int n_columns;
	GLib.Type get_column_type (int n);
	GLib.TreeModel model;
	Gtk.ColumnBinding binding;
	Gtk.TreeView (GLib.TreeModel m);
	GLib.ColumnBinding column_binding;
}

We don’t have guaranteed introspection in Gtk+. To do the binding between a column in the view and a property of an instance in the model we need some code. In Gtk.TreeModel this is the get_value function.

It shouldn’t be part of the Gtk.TreeModel: That way it ain’t reusable and will it require each person implementing a Gtk.TreeModel to reinvent the code.

abstract class GLib.ColumnBinding {
	abstract GLib.Value get_value (GLib.TreeModel model,
	                               GLib.TreeIterable e,
	                               int column);
}

Let’s have some concrete column bindings:

class Gtk.TreeStoreColumnBinding : GLib.ColumnBinding {
}

class Gtk.ListStoreColumnBinding : Gtk.TreeStoreColumnBinding {
}

If we do have introspection we can do the same thing .NET offers: Link up the column number with a property name that can be found in the type of the instances that the model holds.

class GI.IntrospectColumnBinding : GLib.ColumnBinding {
	void add_column (int column, string prop_name);
}

These wouldn’t change at all, except that they implement GLib.TreeModel instead of Gtk.TreeModel

class Gtk.TreeStore : GLib.TreeModel {
}

class Gtk.ListStore : GLib.TreeModel {
}

And then we are at Gtk.TreeModel, of course. Well just take everything that we don’t do yet. That’s the row change emissions, right? Personally I think rows are too specific. A model is something that can be iterated. Being iterable doesn’t mean that you have rows, it just means that you have things that the consumer, the view in a model’s case, can iterate to. Let’s call them nodes.

Gtk.TreePath sounds to me like serializing and deserializing a location. It’s nothing special, just a way to formulate pointing to a node in the tree. It’s the model that exposes this capability.

I’m not sure about flags. Maybe it should just be moved to Gtk.TreeView. I don’t get the point of the flags anyway. Both ITERS_PERSIST and LIST_ONLY sound like an implementation detail to me: not something you want to expose to the API anyway. But fine, for sake of completeness I’ll put it here.

interface GLib.TreeModel : GLib.TreeIterable {
	signal node_changed (GLib.TreeIterable e);
	signal node_inserted (GLib.TreeIterable e);
	signal node_deleted  (GLib.TreeIterable e);
	signal node_reordered (GLib.TreeIterable e);
	GLib.TreeModelFlags flags;
	GLib.TreePath get_path (GLib.TreeIterable e);
	GLib.TreeIterable get_node (GLib.TreePath p);
}

Who’ll start GLib 4.0? Let’s do this stuff while the desktop guys play with GNOME 3.0? Why not?

The impact of a highly improbable event

Sunday, August 16th, 2009

Being in free time mode today I decided to continue reading Nassim Nicholas Taleb’s Black Swan book. Nassim Taleb is about as arrogant as I am, so I’m enjoying reading his book a lot.

I for example enjoyed reading how he’s pissed at today’s academic philosophers for having become exercisers in linguistics rather than getting to the point of thinking. Nassim Taleb himself needed about 350 pages of text to basically say that the Gauss curve is useless in extremistan, but usually useful in mediocristan, and that Mandelbrot’s fractals are a little bit more useful for extremistan. But not really.

Anyway, he also wrote things that we should consider thinking about. For example: We no longer believe in papal infal­li­bil­ity; we seem to believe in the infal­li­bil­ity of the Nobel prize winners. That’s a good point.

One more chapter and I’m relieved of this book. Apparently I enjoy the distress of reading Nassim Taleb’s books.

He’s going to tell me in this chapter how to deal with these highly improbable events that have a great impact, referred to as black swans. I have to congratulate Nassim Taleb for succeeding making me a hyperskeptic, which was a highly improbable event. But then again, being a software developer I’m into bottom-up acquisition of knowledge. Which means that for me it’s more easy to be Fat Tony, than to be Dr. John. You need to read the book’s chapter 17 to understand Fat Tony. I was quite a skeptic before I started reading the book. But not (always) about the kind of things Nassim Taleb asks us to be skeptic .

Pat Condell on ultra tolerant liberal left people

Monday, August 10th, 2009

Not watching youtubers very often I almost forgot about Pat Condell’s video blog. Today I decided to take a look at his latest video material.

Pat Condell is, just like me, an outspoken atheist who enjoys exercising his freedom of speech to criticize various religions. Fairly often he criticizes Islam.

Before I continue I’ll remind people that, like Pat Condell, I have nothing in particular against Islam. I don’t have anything against peaceful people in general. Christian, Muslim, atheist, Buddhist or whatever: I don’t care that much. I don’t believe any of those fairy tales, but it’s your freedom to do! I do care about it when, in for example Western countries, countless Christians try to expunge you from society because “you don’t believe in anything”. For many of them not believing is worse than believing in the wrong God, or being a Satanist, or being a sadist. I want to criticize religions and I want to stress the importance of having the right to criticize religions.

Pat takes on the ultra tolerant liberal left people in this video. Just like Pat I used to be on the liberal left. And just like Pat, because I believe in things like social justice, tolerance and respect, I am no longer on the liberal left. Here’s a quote from the video:

You people have certainly reminded me , as if I needed reminding, why my political views have changed in recent years. You see.. foolishly, perhaps, I used to take freedom for granted.

But now thanks to ultra tolerant self hating-multicultural lemmings like you, I don’t.

Politically I used to always be on the liberal left. Because I believe in things like social justice, tolerance and respect. You know, the good things in life. I still believe in those things, which is why I’m no longer on the liberal left.


Apologists for evil

In this video Pat talks about banning the burka. Given that wearing a burka in Western countries is most definitely only done to make a pathetic political statement, I think it is indeed a good idea to ban burkas. Besides you’re not allowed to wear ski masks when you enter a bank either. You’re not allowed to walk naked in the streets. Yet countless people are trying to claim that these women should have a right to wear burkas. Framing it that way is of course utter bullshit: the debate isn’t about women rights at all. Claiming that it is, is being intellectually dishonest. The debate is about the right for a Islamist husband to claim ownership over a woman or a girl. This isn’t a right in Western countries. The fact that it isn’t, is a good thing.

Pat also points out that Western feminists are rather silent about women rights in Islam. Usually feminists are assertive and confident but this time, apparently, feminists are muted on the issue. Why is that? Where are they?


Ban the burka

For the person who recently debated religion with me (you know who you are): I recently read “Letter to A Christian Nation” by Sam Harris. Very interesting read. I recommend it!