Archive for the ‘Programming’ Category

Little debugging helper

Just wanted to share this code with you:

#ifndef DBGHELPER_H
#include <QString>
#ifndef QT_NO_DEBUG
#    define DEBUG_FUNC_NAME DbgHelper dbgHelper(Q_FUNC_INFO);
#else
#    define DEBUG_FUNC_NAME
#endif
 
class DbgHelper {
public:
    DbgHelper(const QString &t);
    ~DbgHelper();
private:
    QString txt;
    static int indent;
    static int colorIndex;
    int myColor;
};
#endif
#include "dbghelper.h"
#ifdef DBGHELPER_USES_PRINTF
#include <stdio.h>
#else
#include <QtDebug>
#endif
 
int DbgHelper::indent = 0;
int DbgHelper::colorIndex = 0;
 
 
static void DbgHelper_output(int color, int indent, 
                             const QString &prefix, const QString &funcName) {
  QString text = QString(4*indent, ' ')+QString(prefix+" "+funcName);
  if(color>=0){
    text.prepend("\x1b[3"+QString::number(1+color)+"m");
    text.append("\x1b[39m");
  }
#ifndef DBGHELPER_USES_PRINTF
  qDebug() << text;
#else
  fprintf(stderr, "%s\n", qPrintable(text));
#endif
}
 
DbgHelper::DbgHelper(const QString &t) {
    txt = t;
#ifdef NO_COLOR
    myColor=-1;
#else
    myColor = colorIndex;
    colorIndex = (colorIndex+1) % 7;
#endif
    DbgHelper_output(myColor, indent, "BEGIN", txt);
    ++indent;
}
 
DbgHelper::~DbgHelper() {
    --indent;
    DbgHelper_output(myColor, indent, "END", txt);
}

Now you can do this:

#include "dbghelper.h"
#include <QtDebug>
 
class Cls {
public:
  Cls(){
    DEBUG_FUNC_NAME
  }
  ~Cls() {
    DEBUG_FUNC_NAME
  }
  void method(const QString &str) {
    DEBUG_FUNC_NAME
    int x = anotherMethod();
  }
  int anotherMethod() {
    DEBUG_FUNC_NAME
    qDebug() << "Regular output";
    return 7;
  }
};
 
int main(){
 Cls c;
 c.method("foobar");
 return 0;
}

And obtain a nice colorful (where ANSI escape sequences are supported) output:

BEGIN Cls::Cls()
END Cls::Cls()
BEGIN void Cls::method(const QString&)
    BEGIN int Cls::anotherMethod()
Regular output
    END int Cls::anotherMethod()
END void Cls::method(const QString&)
BEGIN Cls::~Cls()
END Cls::~Cls()

If you want, you can extend it to take argument values as well or print the file and line numbers where a particular method is defined.

What do you think? Do you have your own macros or classes that help you with debugging?

QwwSmtpClient released

I decided to release QwwSmtpClient I blogged about two months ago.

The sources are available for download: qwwsmtpclient.

Next to do is the “QNetworkAccessManager-like” API for easier handling…

If you have any comments about the library, feel free to leave them under this post. Any feedback is appreciated, especially that I didn’t have a chance to test the library in practice.

QwwSmtpClient

It’s often good to improve your mood by “doing something nice for yourself” which in my case often means “implement something interesting even if it’s currently completely useless for you but provides a challenge for your brain”.

As some time ago I felt really bad, I did follow that advice and implemented a class for Qt to handle SMTP connections. Only yesterday I noticed J-P Nurmi has implemented a library to handle the IRC protocol which means the family of protocols supported by plain Qt is now at least HTTP, FTP (both internally via QHttp and QFtp), IRC (via LibIrcClient-Qt) and SMTP (QwwSmtpClient). I have plans to also implement POP3 as it’s very simple but I’m waiting for the next wave of bad mood to do it.

So… what does QwwSmtpClient do? It mimics QHttp, so it’s command-based which means you have to issue a few commands and monitor their result to be able to do something useful. I know that sucks a bit, but I wanted to have a similar architecture to QHttp and the next step is to implement a wrapper around the class to provide an interface similar to QNetworkAccessManager which should be quite easy and should not require bad mood to do it.

QwwSmtpClient currently supports:

  • plain connections to SMTP (port 25 by default),
  • SSL connections to SMTP (port 465 by default),
  • TLS connections (STARTTLS command after a plaintext connection),
  • Authentication via PLAIN or LOGIN methods,
  • sending mail using low-level commands (MAIL, RCPT, DATA),
  • HELO or EHLO conversations.

The library is not yet foul-proof nor very idiot-proof but it works allowing one to send mails directly from within Qt applications. I’ll release the code to the public soon.

Here is a small example:

#include <QApplication>
#include <QStringList>
#include "qwwsmtpclient.h"
 
int main(int argc, char **argv){
    QApplication app(argc, argv);
    QwwSmtpClient client;
    // ignore certificate errors as suggested by ssl socket docs:
    app.connect(&client, SIGNAL(sslErrors(const QList &)), 
                &client, SLOT(ignoreSslErrors())); 
    // start plain-text connection:
    client.connectToHost("mail.example.com");
    // start encryption handshake:
    client.startTls();
    // when that's done authenticate yourself to the server:
    client.authenticate("user", "pass", QwwSmtpClient::AuthLogin);
    // send an email:
    client.sendMail("sender@example.com", "receiver@example.com", 
                           "From:    sender@example.com\r\n"
                           "To:      receiver@example.com\r\n"
                           "Subject: testing QwwSmtpClient\r\n"
                           "\r\n" // blank line to denote end of headers
                           "Does it work?");
    // disconnect afterwards:
    client.disconnectFromHost();
    // quit when you're done:
    app.connect(&client, SIGNAL(disconnected()), &app, SLOT(quit()));
    return app.exec();
}

wwWidgets 0.8 released

Two days ago I released version 0.8 of my Qt4 widget set called wwWidgets. The release is Qt 4.2-Qt4.4 compatible and consists of over 20 different widgets. The main focus was put on making the set compilable on all major platforms. The set also contains a Qt Designer plugin that makes it possible to use the widgets directly from Designer.

Visit http://www.wysota.eu.org/wwwidgets to find out more. Any feedback is greatly appreciated.

Multipage Qt container widgets problem solved

In relation to what I wrote earlier I am happy to say that it seems that finally the problem of UIC not being able to handle custom container widgets has been solved – at least partially.

I’ve been playing with Qt 4.4 Technical Preview and I noticed that finally the issue of being unable to create correct Designer forms with multipage widgets has a solution.

In your domXml() method of the custom widget plugin you need to inform UIC about the name of the method your class uses to add pages to itself. The solution is limited as it expects the name of a method taking a pointer to QWidget only, but at least that will render containers usable.

To have a working container widget plugin you need to make sure domXml() returns something like the following:


  
    QwwNavigationBar
    QWidget
    addWidget
  

This informs UIC that QwwNavigationBar is a widget derived from QWidget that uses QwwNavigationBar::addWidget() for adding pages.

Itemviews data redundancy

Encouraged by some recent posts on Qt Centre I decided to point out a common issue when dealing with Qt model-view framework.

Many people often treat models as a burden that needs to be carried to be able to display some data using Itemviews. One needs to perform a tedious task of implementing the QAbstractItemModel interface or filling one of the ready made models such as QStandardItemModel with data. Most often the model needs to represent some data which is contained in some structure and it is not rare to spot people write code similar to this one:

struct MyStruct {
  int x;
  int y;
};
 
class Model : ... {
  //...
  QList <MyStruct> export() const { ... }
  void import(const QList <MyStruct> &){  ... }
  //...
};

What happens here is that they provide export and import functions to convert between their own storage format and the model. It’s a similar thing if they instantiate QStandardItems and feed it with data from some datasource. In both cases the data is duplicated – it is kept both in the model and in the external container.

Instead the model should be perceived only as an interface to an existing data – no matter if it is kept inside or outside the model object, a good example being QSqlTableModel and family – however the data is cached within the model, it is really kept on some remote server.

Instead of the above snippet of code, the skeleton could look like the following:

class Model : public QAbstractItemModel {
public:
  Model(QList<MyStruct> *dat, QObject *parent=0)
  : QAbstractItemModel(parent){
    m_data = dat;
  }
  QVariant rowCount(const QModelIndex &parent) const {
    if(parent.isValid() || m_data.isNull()) return 0;
    return m_data->count();
  }
  //...
private:
  QPointer<QList <MyStruct> > m_data;
};

As you can see the model operates on an external list of items and as long as the list is valid, it will return correct data. Of course the same applies to the rest of the interface – one can add rows and modify data kept in the list.

The only problem that remains is that the list can be modified outside the model, causing all components using the model (views included) to not update themselves upon changes in the list. Fortunately there are ways to overcome it.

The first good solution is to use a data source that can emit changes made to it using Qt signals. Then one can connect those signals to the model to be able to emit proper signals from the model to its environment.

The second solution is to disallow access to the data source outside the model, but then it makes more sense to embed the source within the model itself, either with “has-a” or “is-a” relation (remember, multiple inheritance is a beautiful thing 😎 ). It is probably the best solution if you fully control the data source and you can modify the code that uses it. It is worth mentioning that you don’t have to use the methods provided by QAbstractItemModel to access the data if it feels odd or difficult in your situation. You can define custom methods to access the data through the model – both in read and write mode (for example using MyStruct as the carrier). As long as you emit proper model signals from those methods, your views will continue to work properly.

The third option is to trigger manual or periodic updates of the model – for flat models things like row and column count can be cached and compared against the real source. If they are out of sync, one can try emiting one of generic signals – layoutChanged() or modelReset() to save the situation. Just remember that calling modelReset() will cause all your views to loose selections and item visibility. For simpler models (or better data sources) it might be possible to trace exact changes in the source and emit proper signals upon detecting changes.

Remember, the more complex the data gets, the easier to fall out of sync when using two separate data structures. Save yourself time and nerves and use a single data set instead of two whenever you can, even if it doesn’t seem obvious from the start how to do it. A good design always pays off.

QRetargetScale

Of course I couldn’t resist myself from implementing the algorithm I have written about in the previous post.

Images below have been scaled to fit on the page. The second one was scaled down using the application.


QRetargetScale download

Image retargetting

I just stumbled upon descriptions of an innovative image scaling algorithm. I’m pretty impressed with the results. How about adding Qt::RetargetTransformation to Qt::TransformationMode? 😉

 

And an obligatory movie:

 

Qt book review

The Book of Qt4 coverSome time ago I’ve been asked if I wanted to write a review of one of the new books related to Qt. I agreed and soon after I had a copy of the book in my hands. Thanks go to Camille Herrera of No Starch Press for letting me do this. I’m certainly waiting for more!

 

The Book of Qt4 – The Art of Building Qt Applications review

 

If you do or don’t agree with my review, please leave your comment. Another review of the book is available here (the site seems to be currently down though).

DomElementContainer

I often write code that iterates over an XML document and performs actions on elements with some specifig tag. Usually I do it using code like the following:

for(QDomElement elem = parent.firstChildElement("tag");
                !elem.isNull();
                elem = elem.nextSiblingElement("tag")){
    doSomething(elem);
}

This is fine, but I thought it’d be nicer to do it using the foreach() loop offered by Qt. Out of the box Qt doesn’t allow to use foreach with xml documents, so I decided to do something about it :)

After 15 minutes the class was ready:

#include 
#include 
#include 

class DomElementContainer {
public:
  class const_iterator {
    friend class DomElementContainer;
  public:
      const_iterator(){}
      const_iterator &operator++(){
        m_e = m_e.nextSiblingElement(m_t);
        return *this;
      }
      const QDomElement & operator*(){
        return m_e;
      }
      bool operator==(const const_iterator &other) const {
        return (m_e==other.m_e && m_t==other.m_t);
      }
      bool operator!=(const const_iterator &other) const {
        return (m_e!=other.m_e || m_t!=other.m_t);
      }
  private:
      const_iterator(const QDomElement &e, const QString &t){
        m_e = e;
        m_t = t;
      }
      QDomElement m_e;
      QString m_t;
  };

  DomElementContainer(const QDomElement &e, const QString &tag=QString::null){
    m_tag = tag;
    m_elem = e;
  }
  DomElementContainer(const QDomDocument &d, const QString &tag=QString::null){
    m_tag = tag;
    m_elem = d.documentElement();
  }
  const_iterator begin() const{
    return const_iterator(m_elem.firstChildElement(m_tag), m_tag);
  }
  const_iterator end() const {
    return const_iterator(QDomElement(), m_tag);
  }
private:
  QDomElement m_elem;
  QString m_tag;
};

Now it’s possible to do the following:

#include "domelementcontainer.h"

const char *xml = "content 1content 2 "
                  "wrongcontent"
                  "content 3";

int main(){
    QDomDocument doc;
    doc.setContent(QString(xml));
    DomElementContainer c(doc, "tag");
    foreach(QDomElement e, c)
      qDebug("%s", qPrintable(e.text()));
    return 0;
}

Download available here.