Let’s create Europe’s own military branch

Merkel and Macron should use everything in their economic power to invest in our own European Military.

For example whenever the ECB must pump money in the EU-system, it could do that by increased spending on European military.

This would be a great way to increase the EURO inflation to match the ‘below but near two percent annual inflation’ target.

However. The EU budget for military should not go to NATO. Right now it should go to EU’s own national armies. NATO is more or less the United State’s military influence in Europe. We’ve seen last G7 that we can’t rely on the United States’ help.

Therefor, it should use exclusively European suppliers for military hardware. We don’t want to spend EUROs outside of our EU system. Let the money circulate within our EU economy. This implies no F-35 for Belgium. Instead, for example the Eurofighter Typhoon. The fact that Belgium can’t deliver the United States’s nuclear weapons without their F-35, means that the United States should take their nuclear bombs back. There is no democratic legitimacy to keep them in Belgium anyway.

It’s also time to create a pillar similar to the European Union: a military branch of the EU.

Already are Belgium and The Netherlands sharing military marine and air force resources. Let’s extend this principle to other EU countries.

PGP voor militaire zaken, nee?

Wordt het eens geen tijd dat ons centrum voor cybersecurity overheidsdiensten zoals het Belgisch leger oplegt om steeds a.d.h.v. met bv. PGP (minimaal) getekende (en hopelijk ook geëncrypteerde) E-mails te communiceren? Ja ja. We kunnen ze zelfs encrypteren. Hightech at Belgium. Stel je dat maar eens voor. Waanzin!

Stel je voor. Men zou zowel de E-mail (de content, het bericht zelf) kunnen verifiëren, als de afzender als dat men tijdens de transit én opslag van het bericht de inhoud zou kunnen encrypteren. Bij een eventueel “onafhankelijk” onderzoek zouden we (wiskundige) garanties hebben dat één en ander nu exact is zoals hoe het toen verstuurd werd.

Allemaal zaken die erg handig zouden geweest zijn in de saga over de E-mails over of onze F-16 vliegtuigen langer kunnen vliegen of niet.

Bij de ICT diensten van de oppositiepartijen zou men dan een opleiding van een halfuurtje kunnen krijgen over hoe ze met PGP in de hand één en ander cryptografisch kunnen verifiëren.

ps. Ik weet ook wel dat, in het wereldje waar het over gaat, nu net het feit dat bepaalde zaken achteraf niet meer te achterhalen zijn als waardevolle feature gezien wordt.

Wij hebben in Leuven de beste cryptografen van de wereld zitten. Maar ons Belgisch leger kan dit niet implementeren voor hun E-mails?

To be able to think, you have to risk being offensive

I mean, look at the conversation we’re having right now. You’re certainly willing to risk offending me in the pursuit of truth. Why should you have the right to do that? It’s been rather uncomfortable.

– Jordan Peterson, 2018

Clowns to the right of me

Wat ontbreekt* in de aanpassingen van het voorstel voor de aftapwet van de Nederlandse overheid is een rechterlijke toetsing van de proportionaliteit om al dan niet over te gaan tot een digitale zoeking. Zo’n zoeking is wat mij betreft gelijkaardig aan een huiszoeking.

Dit is onontbeerlijk in een verlichte samenleving waar de drie machten gescheiden zijn.

Spinoza, dé bodemvoorbereider voor de bodem waarop de verlichtingsfilosofie werd gebaseerd, was een Amsterdammer. Het is dus een aardshock voor zij die zich met filosofie bezig houden mee te maken dat Nederland niet meer mee doet.

Noot* dat de toetsingscommissie bestaat uit twee Nederlandse rechters. Twee zulke rechters kunnen nooit een degelijk proportionaliteitsonderzoek uitvoeren voor alle aanvragen.

 

Eigenlijk he

Eigenlijk moet ik nog eens iets posten over hoe we allerlei dingen met Qt en QML doen he?

Na zoveel jaren recruiters te vragen om naar een Duitstalige Qt/QML ontwikkelaar in Eindhoven te zoeken, zou Heidenhain er goed aan doen eens wat te laten zien waar wij aan toe zijn. Vind ik. Maar ja. Het is en blijft een bedrijf dat zelf een beetje geheimzinnig wil zijn.

De laatste tijd zijn het de details van die Klartext-editor die aan beurt zijn. M.a.w. dat wat er wel toe doet: dat wat werkers moeten gebruiken om een werkstuk in te geven in een CNC machine. Dat duurt even. Want de TNC640 heeft best wel veel specifieke dingetjes die al vele jaren ingeleerd zijn bij gebruikers van de machines.

Ik heb m.a.w. veel dingen die ik zou kunnen posten. Maar ik ben lui, plus ik moet wat opletten wat ik wel en wat ik niet publiek maak. Het grappigste daarvan is dat Nokia veel stricter was. Maar ook veel duidelijker. Daarom kon ik veel meer tijdens Nokia zeggen als nu. Nokia was kei streng in haar NDA’s (tot 180000 Euro schadevergoeding, en meer), maar wel duidelijk: dit mag je zeggen, dit niet.

Verkoop met verlies

Vandaag wil ik de aandacht op een Belgische wet over het verkopen met verlies. Ons land verbiedt, bij wet, elke handelaar een goed met verlies te verkopen. Dat is de regel, in ons België.

Die regel heeft (terecht) uitzonderingen. De definitie van de uitzondering wil zeggen dat ze niet de regel zijn: de verkoop met verlies is in België slechts per uitzondering toegestaan:

  • naar aanleiding van soldenverkoop of uitverkoop;
  • met als doel de goederen die vatbaar zijn voor snel bederf van de hand te doen als hun bewaring niet meer kan worden verzekerd;
  • ten gevolge externe omstandigheden;
  • goederen die technisch voorbijgestreefd zijn of beschadigd zijn;
  • de noodzakelijkheid van concurrentie.

Ik vermoed dat onze wet bestaat om oneerlijke concurrentie te bestrijden. Een handelaar kan dus niet een bepaald product (bv. een game console) tegen verlies verkopen om zo marktdominantie te verkrijgen voor een ander product uit zijn gamma (bv. games), bv. met als doel concurrenten uit de markt te weren.

Volgens mij is het daarom zo dat, moest een game console -producent met verlies een console verkopen, dit illegaal is in België.

Laten we aannemen dat game console producenten, die actief zijn in (de verkoop in) België, de Belgische wet volgen. Dan volgt dat ze hun game consoles niet tegen verlies verkopen. Ze maken dus winst. Moesten ze dat niet doen dan moeten ze voldoen aan uitzonderlijke voorwaarden, in de (eerder vermelde) Belgische wet, die hen toelaat wel verlies te maken. In alle andere gevallen zouden ze in de ontwettigheid verkeren. Dat is de Belgische wet.

Dat maakt dat de aanschaf van zo’n game console, als Belgisch consument, betekent dat de producent -en verkoper een zekere winst hebben gemaakt door mijn aankoop. Er is dus geen sprake van verlies. Tenzij de producent -of verkoper in België betrokken is bij onwettige zaken.

Laten we aannemen dat we op zo’n console, na aanschaf, een andere software willen draaien. Dan kan de producent/verkoper dus niet beweren dat zijn winst gemaakt wordt door zaken die naderhand verkocht zouden worden (a.d.h.v. bv. originele software).

Hun winst is met andere woorden al gemaakt. Op de game console zelf. Indien niet, dan zou de producent of verkoper in onwettigheid verkeren (in België). Daarvan nemen we aan dat dit zo niet verlopen is. Want anders zou men het goed niet mogen verkopen. Het goed is wel verkocht. Volgens Belgische wetgeving (toch?).

Indien niet, dan is de producent -en of verkoper verantwoordelijk. In geen geval de consument.

This one should probably go down in history

From	Tom Lendacky 
Subject	[PATCH] x86/cpu, x86/pti: Do not enable PTI on AMD processors
Date	Tue, 26 Dec 2017 23:43:54 -0600

AMD processors are not subject to the types of attacks that the kernel
page table isolation feature protects against.  The AMD microarchitecture
does not allow memory references, including speculative references, that
access higher privileged data when running in a lesser privileged mode
when that access would result in a page fault.

Disable page table isolation by default on AMD processors by not setting
the X86_BUG_CPU_INSECURE feature, which controls whether X86_FEATURE_PTI
is set.

Signed-off-by: Tom Lendacky 
---
 arch/x86/kernel/cpu/common.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index c47de4e..7d9e3b0 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -923,8 +923,8 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
 
 	setup_force_cpu_cap(X86_FEATURE_ALWAYS);
 
-	/* Assume for now that ALL x86 CPUs are insecure */
-	setup_force_cpu_bug(X86_BUG_CPU_INSECURE);
+	if (c->x86_vendor != X86_VENDOR_AMD)
+		setup_force_cpu_bug(X86_BUG_CPU_INSECURE);
 
 	fpu__init_system(c);

Asynchronous commands

With asynchronous commands we have typical commands from the Model View ViewModel world that return asynchronously.

Whenever that happens we want result reporting and progress reporting. We basically want something like this in QML:

Item {
  id: container
  property ViewModel viewModel: ViewModel {}

  Connections {
    target: viewModel.asyncHelloCommand
    onExecuteProgressed: {
        progressBar.value = value
        progressBar.maximumValue = maximum
    }
  }
  ProgressBar {
     id: progressBar
  }
  Button {
    enabled: viewModel.asyncHelloCommand.canExecute
    onClicked: viewModel.asyncHelloCommand.execute()
  }
}

How do we do this? First we start with defining a AbstractAsyncCommand (impl. of protected APIs here):

class AbstractAsyncCommand : public AbstractCommand {
    Q_OBJECT
public:
    AbstractAsyncCommand(QObject *parent=0);

    Q_INVOKABLE virtual QFuture<void*> executeAsync() = 0;
    virtual void execute() Q_DECL_OVERRIDE;
signals:
    void executeFinished(void* result);
    void executeProgressed(int value, int maximum);
protected:
    QSharedPointer<QFutureInterface<void*>> start();
    void progress(QSharedPointer<QFutureInterface<void*>> fut, int value, int total);
    void finish(QSharedPointer<QFutureInterface<void*>> fut, void* result);
private:
    QVector<QSharedPointer<QFutureInterface<void*>>> m_futures;
};

After that we provide an implementation:

#include <QThreadPool>
#include <QRunnable>

#include <MVVM/Commands/AbstractAsyncCommand.h>

class AsyncHelloCommand: public AbstractAsyncCommand
{
    Q_OBJECT
public:
    AsyncHelloCommand(QObject *parent=0);
    bool canExecute() const Q_DECL_OVERRIDE { return true; }
    QFuture<void*> executeAsync() Q_DECL_OVERRIDE;
private:
    void* executeAsyncTaskFunc();
    QSharedPointer<QFutureInterface<void*>> current;
    QMutex mutex;
};

#include "asynchellocommand.h"

#include <QtConcurrent/QtConcurrent>

AsyncHelloCommand::AsyncHelloCommand(QObject* parent)
    : AbstractAsyncCommand(parent) { }

void* AsyncHelloCommand::executeAsyncTaskFunc()
{
    for (int i=0; i<10; i++) {
        QThread::sleep(1);
        qDebug() << "Hello Async!";
        mutex.lock();
        progress(current, i, 10);
        mutex.unlock();
    }
    return nullptr;
}

QFuture<void*> AsyncHelloCommand::executeAsync()
{
    mutex.lock();
    current = start();
    QFutureWatcher<void*>* watcher = new QFutureWatcher<void*>(this);
    connect(watcher, &QFutureWatcher<void*>::progressValueChanged, this, [=]{
        mutex.lock();
        progress(current, watcher->progressValue(), watcher->progressMaximum());
        mutex.unlock();
    });
    connect(watcher, &QFutureWatcher<void*>::finished, this, [=]{
        void* result=watcher->result();
        mutex.lock();
        finish(current, result);
        mutex.unlock();
        watcher->deleteLater();
    });
    watcher->setFuture(QtConcurrent::run(this, &AsyncHelloCommand::executeAsyncTaskFunc));
    QFuture<void*> future = current->future();
    mutex.unlock();

    return future;
}

You can find the complete working example here.

200 cybersoldaten nodig?

Hoe lok je de gepassioneerde computernerds?

  • Zorg ervoor dat ze opleiding krijgen. Ook in zaken die niet technisch zijn. Laat toe dat ze zich verdiepen in dieptechnische zaken. Bv. low level softwareontwikkeling, electronica, en zo verder. Combineer hun (bestaande) kennis met nieuwe toepassingen. Een gepassioneerde (computer)nerd wil een leven lang bijleren en vooral: al hun kennis combineren met andere ideeën;
  • Laat toe dat ze publiek laten zien wie ze zijn en wat ze kunnen. Laat zij die dat graag doen toe dat ze op bv. radio, Internet en TV komen vertellen hoe hun werk maatschappelijk relevant is. Spreek duidelijk af wat wel en wat niet geheim moet blijven, uiteraard;
  • Zorg ervoor dat ze met regelmaat naar een hackercon of een andere conference kunnen gaan. Uiteraard zowizo bv. FOSDEM (niet echt een hackercon, maar ga er toch maar met z’n allen naartoe). Maar bv. de CCC conferences in Duitsland, SHA2017 in Nederland, en zo verder. Wees daar in ieder geval, zonder schroom, aanwezig;
  • Organiseer misschien een eigen hackercon in België. Waarom niet?
  • Maak het niet te gemakkelijk om toe te treden. Dat je er 200 nodig hebt wil niet zeggen dat de eerste de beste goed genoeg zijn;
  • Zorg ervoor dat ze goed verdienen. Begrijp dat de privé hen meer biedt dan de overheid;
  • Publiceer met regelmaat (hun) code als open source op bv. github. Bv. een Wireshark plugin of log analysetools die onze overheid gebruikt? Laat ze helpen met andere open source projecten. Kijk bv. naar hoe we onze eID software (FireFox plugins, e.d.) publiceren;
  • We hebben veel kennis van encryptie in onze universiteiten (Rijndael), stuur ze op cursus daarover bij onze cryptografen;
  • Zorg ervoor dat onze diensten géén fouten maken tegen de Belgische wetgeving. Alle echte goei zijn zo idealistisch als Edward Snowden en willen goed doen voor de samenleving. M.a.w. De wet, de privacy commissie en het Comité I doen er toe.

Veel success. Ik ben erg benieuwd.

Have confidence in yourself – technology will never replace human beings

Children aren’t worried about the future. Young people aren’t worried about the future; they’re worried about us: us leading them into the future we envision

Jack Ma — Oct 2017, keynote speech at Alibaba Cloud’s Computing Conference in Hangzhou

The RelayCommand in Qt

A few days ago I explained how we can do MVVM techniques like ICommand in Qt.

Today I’ll explain how to make and use a simple version of the, in the XAML MVVM world quite famous, RelayCommand. In the Microsoft Prism4 & 5 world this is DelegateCommand. Both are equivalent. I will only show a non-templated RelayCommand, so no RelayCommand<T> for now. Perhaps I’ll add a templated one to that mvvm project some other day.

What people call a delegate in C# is what C++ people call a Functor. Obviously we will use functors, then. Note that for people actually reading all those links: in C# the Action<T> and Func<T,G> are basically also C# delegates (or, functors, if you fancy C++’s names for this more).

Here is the RelayCommand.h:

#include <functional>
#include <QSharedPointer>
#include <MVVM/Commands/AbstractCommand.h>

class RelayCommand : public AbstractCommand
{
    Q_OBJECT
public:
    RelayCommand(std::function<void()> executeDelegatep,
                 std::function<bool()> canExecuteDelegatep,
                 QObject *parent = 0)
    : AbstractCommand(parent)
    , executeDelegate(executeDelegatep)
    , canExecuteDelegate(canExecuteDelegatep) {}

    void execute() Q_DECL_OVERRIDE;
    bool canExecute() const Q_DECL_OVERRIDE;
public slots:
    void evaluateCanExecute();
private:
    std::function<void()> executeDelegate;
    std::function<bool()> canExecuteDelegate;
};

The implementation is too simple to be true:

#include "RelayCommand.h"

bool RelayCommand::canExecute() const
{
    return canExecuteDelegate();
}

void RelayCommand::evaluateCanExecute()
{
    emit canExecuteChanged( canExecute() );
}

void RelayCommand::execute()
{
    executeDelegate();
}

Okay, so how do we use this? First we make a ViewModel. Because in this case we will define the command in C++. That probably means you want a ViewModel.

I added a CompositeCommand in the mix. For a Q_PROPERTY isn’t a CommandProxy really needed, as ownership stays in C++ (when for example you pass this as parent). For a Q_INVOKABLE you would need it to wrap the QSharedPointer<AbstractCommand>.

Note. I already hear you think: wait a minute, you are not passing this to the QObject’s constructor, it’s not a QScopedPointer and you have a new but no delete. That’s because CommandProxy converts the ownership rules to QQmlEngine::setObjectOwnership (this, QQmlEngine::JavaScriptOwnership) for itself. I don’t necessarily recommend its usage here (for it’s not immediately clear), but at the same time this is just a demo. You can try printing a warning in the destructor and you’ll see that the QML garbage collector takes care of it.

#include <QObject>
#include <QScopedPointer>

#include <MVVM/Commands/CommandProxy.h>
#include <MVVM/Commands/CompositeCommand.h>
#include <MVVM/Commands/RelayCommand.h>
#include <MVVM/Models/CommandListModel.h>

class ViewModel: public QObject
{
    Q_OBJECT

    Q_PROPERTY(CommandProxy* helloCommand READ helloCommand CONSTANT)
public:
    ViewModel(QObject *parent=0):QObject(parent),
        helloCmd(new CompositeCommand()){

        QSharedPointer<CompositeCommand> cCmd = helloCmd.dynamicCast<CompositeCommand>();
        cCmd->add( new RelayCommand ([=] { qWarning() << "Hello1 from C++ RelayCommand"; },
                            [=]{ return true; }));
        cCmd->add( new RelayCommand ([=] { qWarning() << "Hello2 from C++ RelayCommand"; },
                            [=]{ return true; }));
        proxyCmd = new CommandProxy (helloCmd);
    }
    CommandProxy* helloCommand() {
        return proxyCmd;
    }
private:
    QSharedPointer<AbstractCommand> helloCmd;
    CommandProxy *proxyCmd;
};

Let’s also make a very simple View.qml that uses the ViewModel

import QtQuick 2.3
import QtQuick.Window 2.0
import QtQuick.Controls 1.2

import Example 1.0

Item {
    property ViewModel viewModel: ViewModel {}

    Button {
        enabled: viewModel.helloCommand.canExecute
        onClicked: viewModel.helloCommand.execute()
    }
}

AbstractCommand Model View ViewModel techniques

In the .NET XAML world, you have the ICommand, the CompositeCommand and the DelegateCommand. You use these commands to in a declarative way bind them as properties to XAML components like menu items and buttons. You can find an excellent book on this titled Prism 5.0 for WPF.

The ICommand defines two things: a canExecute property and an execute() method. The CompositeCommand allows you to combine multiple commands together, the DelegateCommand makes it possible to pass two delegates (functors or lambda’s); one for the canExecute evaluation and one for the execute() method.

The idea here is that you want to make it possible to put said commands in a ViewModel and then data bind them to your View (so in QML that’s with Q_INVOKABLE and Q_PROPERTY). Meaning that the action of the component in the view results in execute() being called, and the component in the view being enabled or not is bound to the canExecute bool property.

In QML that of course corresponds to a ViewModel.cpp for a View.qml. Meanwhile you also want to make it possible to in a declarative way use certain commands in the View.qml without involving the ViewModel.cpp.

So I tried making exactly that. I’ve placed it on github in a project I plan to use more often to collect MVVM techniques I come up with. And in this article I’ll explain how and what. I’ll stick to the header files and the QML file.

We start with defining a AbstractCommand interface. This is very much like .NET’s ICommand, of course:

#include <QObject>

class AbstractCommand : public QObject {
    Q_OBJECT
    Q_PROPERTY(bool canExecute READ canExecute NOTIFY canExecuteChanged)
public:
    AbstractCommand(QObject *parent = 0):QObject(parent){}
    Q_INVOKABLE virtual void execute() = 0;
    virtual bool canExecute() const = 0;
signals:
    void canExecuteChanged(bool canExecute);
};

We will also make a command that is very easy to use in QML, the EmitCommand:

#include <MVVM/Commands/AbstractCommand.h>

class EmitCommand : public AbstractCommand
{
    Q_OBJECT
    Q_PROPERTY(bool canExecute READ canExecute WRITE setCanExecute NOTIFY privateCanExecuteChanged)
public:
    EmitCommand(QObject *parent=0):AbstractCommand(parent){}

    void execute() Q_DECL_OVERRIDE;
    bool canExecute() const Q_DECL_OVERRIDE;
public slots:
    void setCanExecute(bool canExecute);
signals:
    void executes();
    void privateCanExecuteChanged();
private:
    bool canExe = false;
};

We make a command that allows us to combine multiple commands together as one. This is the equivalent of .NET’s CompositeCommand, here you have our own:

#include <QSharedPointer>
#include <QQmlListProperty>

#include <MVVM/Commands/AbstractCommand.h>
#include <MVVM/Commands/ListCommand.h>

class CompositeCommand : public AbstractCommand {
    Q_OBJECT

    Q_PROPERTY(QQmlListProperty<AbstractCommand> commands READ commands NOTIFY commandsChanged )
    Q_CLASSINFO("DefaultProperty", "commands")
public:
    CompositeCommand(QObject *parent = 0):AbstractCommand (parent) {}
    CompositeCommand(QList<QSharedPointer<AbstractCommand> > cmds, QObject *parent=0);
    ~CompositeCommand();
    void execute() Q_DECL_OVERRIDE;
    bool canExecute() const Q_DECL_OVERRIDE;
    void remove(const QSharedPointer<AbstractCommand> &cmd);
    void add(const QSharedPointer<AbstractCommand> &cmd);

    void add(AbstractCommand *cmd);
    void clearCommands();
    QQmlListProperty<AbstractCommand> commands();

signals:
    void commandsChanged();
private slots:
    void onCanExecuteChanged(bool canExecute);
private:
    QList<QSharedPointer<AbstractCommand> > cmds;
    static void appendCommand(QQmlListProperty<AbstractCommand> *lst, AbstractCommand *cmd);
    static AbstractCommand* command(QQmlListProperty<AbstractCommand> *lst, int idx);
    static void clearCommands(QQmlListProperty<AbstractCommand> *lst);
    static int commandCount(QQmlListProperty<AbstractCommand> *lst);
};

We also make a command that looks a lot like ListElement in QML’s ListModel:

#include <MVVM/Commands/AbstractCommand.h>

class ListCommand : public AbstractCommand
{
    Q_OBJECT
    Q_PROPERTY(AbstractCommand *command READ command WRITE setCommand NOTIFY commandChanged)
    Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
public:
    ListCommand(QObject *parent = 0):AbstractCommand(parent){}
    void execute() Q_DECL_OVERRIDE;
    bool canExecute() const Q_DECL_OVERRIDE;
    AbstractCommand* command() const;
    void setCommand(AbstractCommand *newCommand);
    void setCommand(const QSharedPointer<AbstractCommand> &newCommand);
    QString text() const;
    void setText(const QString &newValue);
signals:
    void commandChanged();
    void textChanged();
private:
    QSharedPointer<AbstractCommand> cmd;
    QString txt;
};

Let’s now also make the equivalent for QML’s ListModel, CommandListModel:

#include <QObject>
#include <QQmlListProperty>

#include <MVVM/Commands/ListCommand.h>

class CommandListModel:public QObject {
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<ListCommand> commands READ commands NOTIFY commandsChanged )
    Q_CLASSINFO("DefaultProperty", "commands")
public:
    CommandListModel(QObject *parent = 0):QObject(parent){}
    void clearCommands();
    int commandCount() const;
    QQmlListProperty<ListCommand> commands();
    void appendCommand(ListCommand *command);
    ListCommand* command(int idx) const;
signals:
    void commandsChanged();
private:
    static void appendCommand(QQmlListProperty<ListCommand> *lst, ListCommand *cmd);
    static ListCommand* command(QQmlListProperty<ListCommand> *lst, int idx);
    static void clearCommands(QQmlListProperty<ListCommand> *lst);
    static int commandCount(QQmlListProperty<ListCommand> *lst);

    QList<ListCommand* > cmds;
};

Okay, let’s now put all this together in a simple example QML:

import QtQuick 2.3
import QtQuick.Window 2.0
import QtQuick.Controls 1.2

import be.codeminded.mvvm 1.0

import Example 1.0 as A

Window {
    width: 360
    height: 360
    visible: true

    ListView {
        id: listView
        anchors.fill: parent

        delegate: Item {
            height: 20
            width: listView.width
            MouseArea {
                anchors.fill: parent
                onClicked: if (modelData.canExecute) modelData.execute()
            }
            Text {
                anchors.fill: parent
                text: modelData.text
                color: modelData.canExecute ? "black" : "grey"
            }
        }

        model: comsModel.commands

        property bool combineCanExecute: false

        CommandListModel {
            id: comsModel

            ListCommand {
                text: "C++ Lambda command"
                command:  A.LambdaCommand
            }

            ListCommand {
                text: "Enable combined"
                command: EmitCommand {
                    onExecutes: { console.warn( "Hello1");
                        listView.combineCanExecute=true; }
                    canExecute: true
                }
            }

            ListCommand {
                text: "Disable combined"
                command: EmitCommand {
                    onExecutes: { console.warn( "Hello2");
                        listView.combineCanExecute=false; }
                    canExecute: true
                }
            }

            ListCommand {
                text: "Combined emit commands"
                command: CompositeCommand {
                    EmitCommand {
                        onExecutes: console.warn( "Emit command 1");
                        canExecute: listView.combineCanExecute
                    }
                    EmitCommand {
                        onExecutes: console.warn( "Emit command 2");
                        canExecute: listView.combineCanExecute
                    }
                }
            }
        }
    }
}

I made a task-bug for this on Qt, here.

Comité I deelt informatie met De Tijd. Waarom niet met de burger?

Onze inlichtingendiensten en Comité I geven dit jaar enkele cijfers over het speurwerk van staatsveiligheid, blijkbaar ‘vertrouwelijk’, aan een Belgische krant.

Het is spijtig dat gewone burgers dit niet zelf (eenvoudig) kunnen vinden op de website van Comité I. Wel kon ik een ouder verslag vinden van 2014 – 2015.

Misschien moet men bijzondere opsporingsmethoden gebruiken om officiële informatie vrijgegeven door Comité I te vinden? Laat ik dat maar niet doen. Ik heb er eigenlijk geen idee van waarom we dan maar De Tijd moeten vertrouwen, en waarom we als burger niet meteen zelf het originele verslag kunnen lezen?

Ik heb altijd gevonden dat het vrijgeven van zulke informatie perfect kan zonder één en ander te onthullen wat het criminelen gemakkelijker maakt. Deze vrijgave van cijfers bewijst dat, volgens mij. Ons land blijkt vrij uniek te zijn met het vrijgeven van dit soort gegevens. Zulke openbaarheid van bestuur van onze overheid is iets waar wij burgers dan ook trots op mogen zijn, vind ik. Het siert de medewerkers van de inlichtingendiensten, en Comité I, dat dit in ons land mogelijk is.

Hoewel er een forse toename is in terrorisme dossiers, wat te verwachten was na wat er gebeurd is in Zaventem, blijkt er geen sprake te zijn van grootschalig aftappen of van grote inbreuken, of zo iets. Slechts één procent van de operaties moest door Comité I stopgezet worden. Dat is één procent te veel, maar dat is eerlijk gezegd ook vrij weinig. Een vraag is hoe Comité I er voor zorgt dat dit a) zo weinig blijft en b) steeds minder wordt? Worden er cursussen gegeven aan de medewerkers van de diensten? Wordt men desnoods gesanctioneerd bij (herhaaldelijke) inbreuken?

Er wordt meer gebruik gemaakt van het inbreken op computersystemen, en ook dat lijkt me logisch: heel wat criminaliteit verhuist de dag van vandaag naar de digitale wereld. Ik vraag me daar wel bij af of onze inlichtingendiensten voldoende scholing en recruitering van specialisten ter zake doet. Het is ook eenvoudiger inbreuken tegen de wet te verbergen dan bij gebruik van meer conventionele bijzondere inlichtingendiensten. Snel een tap afzetten en de logs en data verwijderen is eenvoudiger dan officiële verslagen te vernietigen. Toch moet ook dit allemaal volgens de wet gebeuren. Uiteraard.

Een vraag blijft voor mij wel welk percentage van de operaties Comité I heeft gemonitord? Want, indien er slechts één procent van de operaties door Comité I moest stopgezet worden, maar het Comité I onderzoekt maar twee procent van alle gevoerde operaties, dan zou dat willen zeggen dat de helft van alle operaties foutief uitgevoerd worden. Vermoedelijk onderzoekt men veel meer. Maar hoe weet de burger dat? Ik zie ook niet hoe het onthullen van dat percentage het criminelen eenvoudiger maakt. Misschien, vond ik ook deze informatie gewoon nog niet?

Leuk dat Comité I meldt dat er vorig jaar geen enkele journalist, arts of advocaat een doelwit is geweest. Dat zal journalist Lars van De Tijd heel leuk vinden. Het is vermoedelijk een reactie op dit nieuwsfeitOnze wet is hier, terecht, heel specifiek in. Ze moet, uiteraard, gevolgd worden. Éénieder in dit land, ook criminelen, moeten in vertrouwen medische verzorging kunnen genieten. Het afluisteren van een arts kan slechts in zeer uitzonderlijke gevallen (bv. wanneer de arts zelf betrokken is bij de criminele activiteiten van zijn of haar patiënt). Journalisten en advocaten moeten voorts ook altijd hun werk onafhankelijk kunnen doen.

Ik zou willen herhalen wat Peter Buysrogge, N-VA-Kamerlid, ook al liet weten: Het stelt ons gerust dat de inlichtingendiensten hun bevoegdheden, blijkbaar, correct toepassen. Maar voor mij mag hieraan toegevoegd worden dat het ons land zou sieren, en haar burgers nog meer geruststellen, moest er meer informatie over de werking van controleorgaan Comité I zelf gepubliceerd worden.

Colleague tells me I write blogs in chats while I explain how to write a producer-consumer

I’m at home now. I don’t do non-public unpaid work. So let’s blog the example I’m making for him.

workplace.h

#ifndef Workplace_H
#define Workplace_H

#include <QObject>
#include <QFuture>
#include <QWaitCondition>
#include <QMutex>
#include <QStack>
#include <QList>
#include <QThread>
#include <QFutureWatcher>

class Workplace;

typedef enum {
    WT_INSERTS,
    WT_QUERY
} WorkplaceWorkType;

typedef struct {
    WorkplaceWorkType type;
    QList<int> values;
    QString query;
    QFutureInterface<bool> insertIface;
    QFutureInterface<QList<QStringList> > queryIface;
} WorkplaceWork;

class WorkplaceWorker: public QThread {
    Q_OBJECT
public:
    WorkplaceWorker(QObject *parent = NULL)
        : QThread(parent), m_running(false) { }
    void run() Q_DECL_OVERRIDE;
    void pushWork(WorkplaceWork *a_work);
private:
    QStack<WorkplaceWork*> m_ongoing;
    QMutex m_mutex;
    QWaitCondition m_waitCondition;
    bool m_running;
};

class Workplace: public QObject {
    Q_OBJECT
public:
    explicit Workplace(QObject *a_parent=0) : QObject (a_parent) {}
    bool insert(QList<int> a_values);
    QList<QStringList> query(const QString &a_param);
    QFuture<bool> insertAsync(QList<int> a_values);
    QFuture<QList<QStringList> > queryAsync(const QString &a_param);
private:
    WorkplaceWorker m_worker;
};

class App: public QObject {
    Q_OBJECT
public slots:
    void perform();
    void onFinished();
private:
    Workplace m_workplace;
};

#endif// Workplace_H

workplace.cpp

#include "workplace.h"

void App::onFinished()
{
    QFutureWatcher<bool> *watcher = static_cast<QFutureWatcher<bool>* > ( sender() );
    delete watcher;
}

void App::perform()
{
    for (int i=0; i<10; i++) {
       QList<int> vals;
       vals.append(1);
       vals.append(2);
       QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>;
       connect (watcher, &QFutureWatcher<bool>::finished, this, &App::onFinished);
       watcher->setFuture( m_workplace.insertAsync( vals ) );
    }

    for (int i=0; i<10; i++) {
       QList<int> vals;
       vals.append(1);
       vals.append(2);
       qWarning() << m_workplace.insert( vals );
       qWarning() << m_workplace.query("test");
    }
}

void WorkplaceWorker::pushWork(WorkplaceWork *a_work)
{
    if (!m_running) {
        start();
    }

    m_mutex.lock();
    switch (a_work->type) {
    case WT_QUERY:
        m_ongoing.push_front( a_work );
    break;
    default:
        m_ongoing.push_back( a_work );
    }
    m_waitCondition.wakeAll();
    m_mutex.unlock();
}

void WorkplaceWorker::run()
{
    m_mutex.lock();
    m_running = true;
    while ( m_running ) {
        m_mutex.unlock();
        m_mutex.lock();
        if ( m_ongoing.isEmpty() ) {
            m_waitCondition.wait(&m_mutex);
        }
        WorkplaceWork *work = m_ongoing.pop();
        m_mutex.unlock();

        // Do work here and report progress
        sleep(1);

        switch (work->type) {
        case WT_QUERY: {
            // Report result here
            QList<QStringList> result;
            QStringList row;
            row.append("abc"); row.append("def");
            result.append(row);
            work->queryIface.reportFinished( &result );
            } break;

        case WT_INSERTS:
        default: {
            // Report result here
            bool result = true;
            work->insertIface.reportFinished( &result );
            } break;
        }

        m_mutex.lock();
        delete work;
    }
    m_mutex.unlock();
}

bool Workplace::insert(QList<int> a_values)
{
    WorkplaceWork *work = new WorkplaceWork;;
    QFutureWatcher<bool> watcher;
    work->type = WT_INSERTS;
    work->values = a_values;
    work->insertIface.reportStarted();
    watcher.setFuture ( work->insertIface.future() );
    m_worker.pushWork( work );
    watcher.waitForFinished();
    return watcher.result();
}

QList<QStringList> Workplace::query(const QString &a_param)
{
    WorkplaceWork *work = new WorkplaceWork;
    QFutureWatcher<QList<QStringList> > watcher;
    work->type = WT_QUERY;
    work->query = a_param;
    work->queryIface.reportStarted();
    watcher.setFuture ( work->queryIface.future() );
    m_worker.pushWork( work );
    watcher.waitForFinished();
    return watcher.result();
}

QFuture<bool> Workplace::insertAsync(QList<int> a_values)
{
    WorkplaceWork *work = new WorkplaceWork;
    work->type = WT_INSERTS;
    work->values = a_values;
    work->insertIface.reportStarted();
    QFuture<bool> future = work->insertIface.future();
    m_worker.pushWork( work );
    return future;
}

QFuture<QList<QStringList> > Workplace::queryAsync(const QString &a_param)
{
    WorkplaceWork *work = new WorkplaceWork;
    work->type = WT_QUERY;
    work->query = a_param;
    work->queryIface.reportStarted();
    QFuture<QList<QStringList> > future = work->queryIface.future();
    m_worker.pushWork( work );
    return future;
}