Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re: OT: Stupid User Interfaces

by davies (Parson)
on May 31, 2017 at 10:08 UTC ( #1191685=note: print w/replies, xml ) Need Help??


in reply to OT: Stupid User Interfaces

I've been ranting about documentation for years. It's my unshakeable belief that no-one documents their own work well. In the first place, the skills are different. How many programmers have been on any sort of creative writing class? A tiny minority, and for good reason. In the second, even if the programmer is a good writer in other circumstances, s/h/it's too close to the code. Things that are absolutely obvious to the programmer are obscure to the new user. Even assuming those two hurdles away, in the case of commercial software, there s usually a rush to get it out of the door, meaning that documentation gets skimped. This is even more true now that documentation is written for the internet rather than being produced in glossy manuals.

One of the drawbacks of "free as in beer" software is that customer complaints count for less than they do in businesses. This is not to say that the writers of free software don't care about documentation. But they do have other priorities, such as earning a living, and are entitled to do the tasks that interest them (like adding features) first, even assuming that they are able to.

Never having used Qt or QML, I decided to look at one of them - Qt - to see what it does and whether you were being unreasonable. If anything, you were being generous. I have read the entire documentation for Qt.pm and still have not the slightest clue what it does. Those who find this surprising are invited to read http://search.cpan.org/~awin/Qt-0.03/Qt.pm and point out what I have missed.

Regards,

John Davies

Replies are listed 'Best First'.
Re^2: OT: Stupid User Interfaces
by hippo (Canon) on May 31, 2017 at 10:21 UTC
    Those who find this surprising are invited to read http://search.cpan.org/~awin/Qt-0.03/Qt.pm and point out what I have missed.

    I take your point. What you might have missed is that you have linked to a 20-year-old version of the dist. In fairness to the authors/maintainers, the 6-year-old version at http://search.cpan.org/~cburel/Qt-0.96.0/qtcore/lib/QtCore4.pm is a bit more prosaic.

      I hadn't missed that it was very old. But I googled for Perl Qt and that was what came up. It looked right and has nothing to indicate that it isn't the latest version. I checked specifically on the CPAN page for the usual "Latest version" link and there was none. I'm not surprised that there is a later version. Nor am I surprised that the docs I pointed to have not been amended to indicate that they are deprecated and giving a link to something better, but I am disappointed.

      By the same token, while the docs you link to are more verbose and therefore I haven't read them as thoroughly, I don't see anything in them, either, hinting at what Qt actually does. Again, I'm disappointed but not surprised. A problem I have seen in lots of documentation is that it sends the user on a massive yak shaving exercise making it extremely hard and time consuming to find the precise document that tells me what I want to know. If I were thinking of trying to contribute to the Perl community by improving documentation, Qt could not be a candidate module as I still can't see where to start or what it is supposed to do.

      I did mention that I tend to rant about documentation, didn't I? I think I'd better stop here. :-)

      Regards,

      John Davies

        I don't see anything in them, either, hinting at what Qt actually does.
        This drives me crazy. I like to check the recent uploads on CPAN, and I run into way too many modules that just say
        This module provides a Perl interface to the QtCore version 4 library.
        or some such. Come on, at least give me a hint what it's good for or where I can find more information.

      Let me show some more details. For that project, I use Qt 5.3 (C++) and QML on an embedded Linux system. The current problem was:

      There is a TableView that is fed with data by a ListModel. (To be continued ...)

      And here, things already get ugly:

      1. There seems to be no way to get documentation for a selected (i.e. my) Qt/QML version. There is a 4.x set of documentation, currently (and probably finally) at 4.8; and there is a 5.x set, currently at 5.8 or 5.9. No 5.3. Let's hope the 5.x set documents every change since 5.3. (Yes, maybe the complete documentation should come with the Linux distribution. No, it does not. The distribution sucks even more.)
      2. Then, I want a table. It should be fed by a model. Why is that model called ListModel and not TableModel? Well, it is an implementation detail. The table looks like a table, but it is really a modified ListView, where each list element is a table row.

      A new requirement: The table shall contain sections.

      Qt can do that. Nice. Less work for me, or so I thought. Here is the entire documentation of the section feature for TableViews:

      section group

      section.property : string

      section.criteria : enumeration

      section.delegate : Component

      section.labelPositioning : enumeration


      These properties determine the section labels.

      See also ListView.section.

      Isn't that great? A piece of art! To be fair, ListView.section is a link. Guess what waits behind that link:

      section group

      section.property : string

      section.criteria : enumeration

      section.delegate : Component

      section.labelPositioning : enumeration


      These properties determine the expression to be evaluated and appearance of the section labels.

      Now, where have I seen that before?

      OK, now I'm unfair. The text actually continues:

      section.property holds the name of the property that is the basis of each section.

      After that, it's talking about ListView not automatically sorting data, stacking order (which has the magical property of being 2), and performance issues. So, I need to set section.property in my TableView (that is actually a mutated ListView, or to say it nice, that inherits from ListView) to some magical name of some property. Umm, yes, the part left of the colon is obvious.

      There is a code example. And even a picture of how a sectioned ListView should look like. Let's look at the code:

      // The delegate for each section header Component { id: sectionHeading Rectangle { width: container.width height: childrenRect.height color: "lightsteelblue" Text { text: section font.bold: true font.pixelSize: 20 } } } ListView { id: view anchors.top: parent.top anchors.bottom: buttonBar.top width: parent.width model: animalsModel delegate: Text { text: name; font.pixelSize: 18 } section.property: "size" section.criteria: ViewSection.FullString section.delegate: sectionHeading }

      I'm not making this up. This is the EXACT copy of the example code.

      So, section.property is set to "size" in this example. Why? What does that mean? I know that the delegate stuff is responsible for painting onto the screen, and apart from delegates, the only other interesting thing left is the model. It's something with the ID animalsModel. So there must be something named size in that model. Let's look at that model.

      Oops, it's not in the example code. Never heard of SSCCE? Obviously not. Well, the ListView document fills a few pages, so maybe that model was previously used to explain other stuff? You wish. There is exactly one animalsModel, right in that non-working example. And that does not mean there is only one hit in that document. There is exactly one hit in the entire documentation! (Or at least Google is not able to find anything but copies of that single document and completely unrelated pages talking about experiments with animals.)

      So, what's in a model like ListModel? RTFM, where "F" is not "fine". A ListModel is documented to have two properties. One is named count, the other is named dynamicRoles. No property named size. But let's read on:

      The ListModel is a simple container of ListElement definitions, each containing data roles. The contents can be defined dynamically, or explicitly in QML.

      No size property. No property at all.

      There is also an example:

      The following example shows a ListModel containing three elements, with the roles "name" and "cost".

      import QtQuick 2.0 ListModel { id: fruitModel ListElement { name: "Apple" cost: 2.45 } ListElement { name: "Orange" cost: 3.25 } ListElement { name: "Banana" cost: 1.95 } }

      Yeah, sure. Why use animals when you can use fruits to explain that? From there on, the examples get more and more complicated, but no animals and no size property. And nothing that attempts to place fruits into groups. But the example is roughly similar to how my model looked at that time.

      Again, to be fair, there is a good hint in that document that I did not see. In this sentence from the third paragraph in the "detailed description":

      Elements can be manipulated via the model using the setProperty() method, which allows the roles of the specified element to be set and changed.

      What section.property in ListView / TableView expects is the name of a "role" in a ListElement (here's the doc), which is a user-choosen name of a property in all ListElements in a ListModel. Quoting ListElement:

      List elements are defined like other QML elements except that they contain a collection of role definitions instead of properties. Using the same syntax as property definitions, roles both define how the data is accessed and include the data itself.

      The names used for roles must begin with a lower-case letter and should be common to all elements in a given model. Values must be simple constants; either strings (quoted and optionally within a call to QT_TR_NOOP), boolean values (true, false), numbers, or enumeration values (such as AlignText.AlignHCenter).

      So, redefining names of things in every document, and reusing names used for other things is a quite clever way to force clients to hire a consultant. No, we didn't hire one. I know consultants from three former jobs. I don't want consultants in my office. Not that kind of consultants.


      I choose the hard way, searching Google for working examples, and finally found one (no animals, no fruits). Its pretty simple. Choose a name. "group" may be a good one. Add that name to each and every ListElement in the model. Choose any value you like for group, and assign the same value for all ListElements that should be in the same group / section.

      Now, section.criteria. Qt/QML must somehow compare each ListElement's group name, and insert a section into the list / table whenever it changes. Take a deep breath before reading on:

      section.criteria holds the criteria for forming each section based on section.property. This value can be one of:

      • ViewSection.FullString (default) - sections are created based on the section.property value.
      • ViewSection.FirstCharacter - sections are created based on the first character of the section.property value (for example, 'A', 'B', 'C' sections, etc. for an address book)

      A case insensitive comparison is used when determining section boundaries.

      And that's all. Either compare the entire value using some vagely specified compare function, or compare the first character using the same vagely specified compare function. There is no other way.

      I don't want to think about how that compare function compares the "normal" I/i and the turkish variants with a dot on I and no dot on i. And I also don't want to know how the code behind ListView extracts a "character" from a Unicode string. Perhaps I should think at least about the former thing, because the group names in my application are translated to various languages. For now, I won't. I've spend way too much time with that documentation, and if it breaks for some exotic language, I'll fix it later. No one will get hurt if that table does not look as pretty as it should.


      This problem may look trivial, because I've still simplified some things. Translations, generating model data from Office documents at compile time (using Perl, what else?!), look and feel of that table, optimizing for a small screen with tiny pixels, and so on. And of course, this is a propritary system, and the client will certainly be not amused if parts of the source code or significant implementation details pop up at every corner of the internet.

      Now guess how much fun I had trying to find out how to draw graphs from data in a model that automatically update when the data in the model changes. In the end, I got rid of the model for drawing and instead passed a Javascript AoH around. It may not be as nice as a model, but it gets the job done in less time.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1191685]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (2)
As of 2018-07-19 04:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?















    Results (401 votes). Check out past polls.

    Notices?