technical

WebIssues 2.0 coming soon

Submitted by mimec on 2020-02-26

It's been almost two years since I announced that I'm working on version 2.0 of WebIssues. I even wrote an article on Medium about it. In fact, in the second half of 2018 it was almost finished. And then the unexpected happened. Just when I thought that the time of commercial side projects is over and I would be focusing on open-source projects again, Bulletcode got two big projects in a short time. So there's a 7-month long gap in the project's git log, not to mention that it took a while before I got back to full speed with WebIssues.

I usually applied the "release early and release often" approach to open-source projects, but this time it was such big technological leap that I decided to postpone the initial release until everything is finished, polished and tested. So even though the first version will be a "beta" version, the only thing that's really missing is the translations (by the way, please join the WebIssues project on Crowdin if you want to help). We're already using that beta version for our Bulletcode projects and everything works fine, but of course there is such diversity of platforms and configurations that it's impossible to catch every bug.

What can you expect from the new version? It has a completetly new user interface, not only when it comes to technology, but also the overall design. The well known tree of projects and folders is now gone; obviously you can still filter issues by project and folder, but the new UI is built around issue types and views. The native desktop client is also gone and replaced with an Electron application. Yes, I know, the desktop client was a major selling point of WebIssues, but it was also the main reason why it was so hard to make changes and introduce new features.

I tried to do my best to make the new application as lean and fast as possible, because like everyone else, I hate heavy and bloated single-page applications which are the reality of today's web. And, most importantly, it remains an open-source application that you can host on your own server, requiring nothing more than PHP and a database, because not everyone likes to store all their data in the cloud.

The first beta version will be available on March 2nd, so I encourage everyone to take a look and try it; there will be an online demo available. The official version will follow soon after, depending on how quickly the translations will be updated and how many bugs will be found.

Migration to GitHub

Submitted by mimec on 2018-03-02

In the last few months I've been quite busy working on the prototype of version 2.0 of WebIssues. My plan was to reach a point where the new web UI is functional, at least in the most important areas, before migrating the code repository to GitHub. However, with the recent series of outages and problems with SourceForge, I decided not to wait any longer. Honestly I don't blame those guys who work for SF. I suspect that these problems have more to do with politics than with technical reasons. The truth is that in today's digital world the largest company wipes out the competition sooner or later, so this was inevitable. But it doesn't change the fact that SourceForge played a very important role in the popularization of open-source software and after using it for at least 13 years, I feel a little bit of sentiment.

Also, I've been using Subversion for so long that I was a little bit reluctant to switch to Git. Believe it or not, but I've never really used it before. I know that in theory it works more or less the same, but such transition always requires some mental processing which distracts from the actual work. Fortunately, thanks to Visual Studio Code and it's built-in integration with Git, this transition went quite smoothly. So the first project is now available at https://github.com/mimecorg/webissues. Please note that this is the current development version of WebIssues 2.0, so it's very far from being functional and stable. In the following days, I will move my other projects to GitHub, including the latest stable version of WebIssues.

Soon I will also publish an article on Medium in which I will describe my initial experiences with Vue.js and my general thoughts about the benefits (and drawbacks) of working on an open-source side project. I will also use this opportunity to reveal some of my plans regarding version 2.0 of WebIssues.

New incarnation of mimec.org

Submitted by mimec on 2017-11-19

Today is the beginning of a new chapter in the history of the mimec.org website, which I created almost twelve years ago, and the related websites dedicated to my open source projects. I moved these sites to a new server, but I also completely redesigned them and migrated them to the latest version of Drupal. I actually built them completely from scratch and imported the old content using some hand-crafted tools, so the whole conversion took about six weeks of work. I hope that you like the result.

If you look closely at my blog, you will notice that there hasn’t been much going on recently. I mainly focused on Bulletcode, the company which I founded three years ago with my friends. We had a lot of ups and downs, but the important thing is that we created a few projects that help thousands of people. Even though it was always just a side project for us, it was definitely one of the greatest experiences in our lives. Each of us moved on to different projects, but we’re still a great team and when the time comes, we may work on something new again.

Personally, the last few years were very hard for me, so the company was one of the things that kept me alive. But now I’m ready to begin a new chapter in my life, start building a new relationship and become the person who I really want to be. I’m more aware of myself. I rediscovered many things that I lost along the way, things that inspire me and drive me to become better at what I do. I am grateful for what I have and I look into the future with optimism and curiosity.

So what are my plans now? A few months ago, I started working on a new, experimental version of WebIssues, with a new user interface based on Vue.js. Those of you who follow me on Twitter could already see some screenshots of that prototype. I also wrote a series of articles on Medium dedicated to programming in Vue.js and to my great surprise, they were very well received. I found a way to create the new version of WebIssues with as little effort as possible. However, I felt that this wasn’t the right approach, so I decided to take a step back and rethink this.

The truth is that it took me many years to learn PHP and C++ before WebIssues could become what it is today. Now I must gain a similar level of skills with the new technologies, even if it takes a similar amount of time. I also want to make a really good use of them instead of just doing a simple face lifting. So instead of rushing toward releasing a new version, I’m going to keep experimenting until I’m satisfied with the results. Of course, I will continue to write about new things that I learn along the way on Medium. I will also share my progress in this blog.

I’m very excited about this new plan, because I think that personal development and improving our skills is the best thing that we can do in our lives. Especially if they allow us to do something both creative and useful. With that goal in mind, I’m sure that the next months and years will be an amazing time.

Happy 10th anniversary, mimec.org!

Submitted by mimec on 2015-12-15

Today is a very special day. Excactly ten years ago, on December 15th 2005, I wrote the first post on the mimec.org website. It's become a tradition that I write a short summary of the past year on each anniversary, and I will do it again today, because it was also a very special year for me.

First of all, there were a lot of round anniversaries this year. Almost exactly 10 years ago I graduated from college. WebIssues turned 10 years old in November, although technically it wasn't officially released until September 2006. Fraqtive turned 10 years old in January. And in March it was 10 years since I started my first job - and after those 10 years I still work for the same company, although it grew in size from a few developers to a few hundred, changed its name and relocated its headquarters. Even my primary day job project is still the same after 10 years. So, looking at those numbers, one might think that my life is very stagnant, and I will most likely spend the rest of it in the same place, doing the same things…

But even though a lot of things remained the same for such a long time, the last year also brought a lot of substantial changes. I overcame a serious crisis in my family, and we are back together, although a year ago nothing indicated that this would ever be possible. I think that this is my greatest personal accomplishment, and I simply owed this to my son. Obviously it doesn't mean that it's all a bed of roses now, quite on the contrary, but it was a very valuable lesson for all of us, and I will definitely not let the most important things get out of control again.

Today is also the first anniversary of Bulletcode, a software company founded by me and two of my friends. At the moment it's still more of a hobby than a real business, we put more money into it than we make, and we try to put as much work into it as our day jobs allow. But the whole year was a huge, invaluable experience for us all. We started the company to work on a very promising project, which unfortunately failed miserably for reasons that were beyond our control. So we ended up with a company which generated costs, without any projects, with no business partners, and with no idea what to do next. But instead of shutting it down, we took the challenge and started looking for new ideas and opportunities. I cannot reveal yet what we are working on, it's all a bit of a mistery and conspiracy, but it's definitely the most interesting project I've ever participated in, and we're all waiting impatiently to release our first product.

Model-View-Presenter in QtQuick pt. 2

Submitted by mimec on 2015-06-03

In the previous article I explained the basics of a simple Model-View-Presenter architecture in QtQuick. Now it's time to explain the implementation details. I will start with the Presenter QML component which is the base component of all presenters:

FocusScope {
    id: root

    property Item view
    property QtObject model

    property var modelToViewBindings: []
    property var viewToModelBindings: []

    Component.onCompleted: {
        root.view.anchors.fill = root;
        root.view.focus = true;

        for ( i in root.modelToViewBindings ) {
            name = root.modelToViewBindings[ i ];
            dynamicBinding.createObject( root, {
                target: root.view, property: name, source: root.model, sourceProperty: name
            } );
        }

        for ( var i in root.viewToModelBindings ) {
            var name = root.viewToModelBindings[ i ];
            dynamicBinding.createObject( root, {
                target: root.model, property: name, source: root.view, sourceProperty: name
            } );
        }
    }

    Component {
        id: dynamicBinding

        Binding {
            id: binding

            property var source
            property string sourceProperty

            value: binding.source[ binding.sourceProperty ]
        }
    }
}

As you can see, the presenter is a FocusScope, so that it can be used as a top-level visual component of a window or can be embedded in some more complex layout. The presenter contains a view property which holds a reference to the embedded view component and a model property which holds a reference to the model object. The Component.onCompleted function makes sure that the view fills the entire presenter and that it has keyboard focus enabled.

The remaining code is related to binding properties between the model and the view and vice versa in a simplified way. The modelToViewBindings property contains an array of names of properties that should be bound from the model to the view. The first loop in the Component.onCompleted function creates a Binding object for each property binding. The target of the binding is a property of the view. The value of that property is bound to the corresponding source property in the model. Note that JavaScript makes it possible to access a property of an object with a given name using the [] operator, because an object is essentially an associative array. The binding from the view to the model works in exactly the same way. As demonstrated in the example in the previous article, it's even possible to create bi-directional bindings.

The view and model objects are created in the actual presenter component which inherits Presenter. As I explained in the previous article, we want to be able to switch both the view and the model as easily as possible. In order to do that, I implemented a simple factory, which is basically a shared library implemented in JavaScript:

.pragma library

var config = {
    modules: {},
    urls: { views: "views/", models: "models/" }
};

function createObject( type, name, parent ) {
    var module = config.modules[ type ];
    if ( module !== undefined ) {
        var qml = "import " + module + "; " + name + " {}";
        return Qt.createQmlObject( qml, parent );
    } else {
        var url = config.urls[ type ];
        if ( url !== undefined ) {
            var component = Qt.createComponent( url + name + ".qml", parent );
            var object = component.createObject( parent );
            if ( object === null )
                console.log( "Could not create " + name + ":\n" + component.errorString() );
            return object;
        } else {
            console.log( "Factory is not configured for " + type );
            return null;
        }
    }
}

function createView( name, parent ) {
    return createObject( "views", name, parent );
}

function createModel( name, parent ) {
    return createObject( "models", name, parent );
}

The config variable specifies the names of C++ modules and/or URLs of directories that contain QML files with the implementation of views and models. By default, the models can be simple mock-ups written in QML, which makes it possible to run the whole application directly using the qmlscene tool without writing a single line of code in C++.

The createObject() function first looks for a registered C++ module of the given type. If present, it creates a simple component declaration in QML and calls Qt.createQmlObject() to create the instance of the component. When there is no C++ module registered, the function tries to load the component from the QML file in the given location. The createView() and createModel() functions are wrappers that can be used for simplicity.

By changing the default configuration of the factory at run-time, you can not only switch between mock-up models and real models implemented in C++, but also, for example, to use different views in mobile and desktop versions of the application. For example, the Component.onCompleted function of your top-level QML component could contain the following code to override the default configuration:

if ( typeof models !== 'undefined' )
    Factory.config.modules.models = models;

The C++ application can register the classes which implement the models in a module and pass the name of that module to the QML engine as a property of the root context, like this:

qmlEngine->rootContext()->setContextProperty( "models", "MyApp.Models 1.0" );

Unfortunately, it's not possible to pass variables from C++ code directly to shared JavaScript libraries which use the ".pragma library" directive (according to this thread, this is done this way on purpose). The method shown above can be used to work around this limitation; just keep in mind that the factory needs to be configured before any objects are actually created.