aKademy 2004

Designing Qt-style APIs

Matthias Ettrich



APIs should:



Note: overloads are conceptually cheaper than other members


Rationale: if a member function is misplaced in a class, this can lead to two effects:

  1. it leads to even more functions (nasty things tend to grow on their own)
  2. many potential users of the function won't find it.

Clear and simple semantics


Intuition is based on experience, different experience and background leads to different perception on what is and is not intuitive.


A Qt-style API is intuitive...

Easy to memorize

Guidance to readable code

Rationale: Code is written once, but read/debugged/understood many many times.

=> Readable code may sometimes take longer to write, but safes time throughout the code lifecycle.

Mindset: Picture your target user

Mindset: The convenience trap


QSlider *slider = new QSlider(12, 18, 3, 13, Qt::Vertical, 0, "Convenience level");

QSlider *slider = new QSlider(Qt::Vertical);
slider->setRange(12, 18);
slider->setObjectName("Convenience level");

Also: Consider bindings to dynamically typed languages

Mindset: The boolean trap


  1. void doSomething();
  2. void doSomething(bool doSomethingElse = false);
  3. void doSomething(bool doSomethingElse = false, bool orSomethingEntirelyDifferent = false;

Broken rationale: Adds no extra function thus no extra bloat, no need to document another function, no need to adjust the class documentation, simple.

Truth: Adds bloat (to a function, not a class), hard to memorize, leads in non-intuitive code.


QWidget: widget->repaint(false);
QWidget: widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding, true);
QTextEdit: editor->insert("what does it mean?", true, true, false);

Mindset: Mind the inheritance structure

Bad example: Good old QToolButton 

In Qt 4:

Another example: QWidget::icon QButton::pixmap QToolButton::iconSet

In Qt 4: QWidget::windowIcon QAbstractButton::icon

Mindset: static polymorphism

Mindset: QA


  1. General considerations
  2. Naming classes
  3. Naming members
  4. Naming parameters
  5. Naming enums
  6. Naming boolean properties

Naming: General

Ways of finding good names

Naming: Classes

Naming: Members

Naming: Enums

Naming: Boolean properties

  1. Rule of thumb: "is" for singular adjectives, and no prefix otherwise.
  2. Never use the third person.
  3. Never prefix with "has".

Singular adjectives use "is":

Plural adjectives have no prefix:

Verbs have no prefix and don't use the third person ("s"):

Nouns generally have no prefix:

In some cases, having no prefix is misleading, in which case we prefix with "is":

Example: Naming a boolean property

Task: HTML-rendering widget should have a property that indicates whether it underlines links or not.

Obvious start: setLinkUnderline():

Start with getter:

Result: setLinksUnderlined()and linksUnderlined()


Case study: QProgressBar

Current QProgressBar API in Qt3


    int totalSteps() const;
    int progress()  const;

    const QString &progressString() const;
    bool percentageVisible() const;
    void setPercentageVisible(bool);

    void setCenterIndicator(bool on);
    bool centerIndicator() const;

    void setIndicatorFollowsStyle(bool);
    bool indicatorFollowsStyle() const;

public slots:

    void reset();
    virtual void setTotalSteps(int totalSteps);
    virtual void setProgress(int progress);
    void setProgress(int progress, int totalSteps);


    virtual bool setIndicator(QString & progress_str, int progress, int totalSteps);

Case study: QProgressBar

Case study: QProgressBar

Case study: QProgressBar

Case study: QProgressBar

New and improved QProgressBar API


    void setMinimum(int minimum);
    int minimum() const;
    void setMaximum(int maximum);
    int maximum() const;
    void setRange(int minimum, int maximum);
    int value() const;

    virtual QString text() const;
    void setTextVisible(bool visible);
    bool isTextVisible() const;
    Qt::Alignment alignment() const;
    void setAlignment(Qt::Alignment alignment);

public slots:

    void reset();
    void setValue(int value);

    void valueChanged(int value);