Category Archives: Developers

Memory Leak Continued

There was some confusion with regard to my last blog about leaking memory. Suppose the ui_mywidget.h files looks like this:

class Ui_Widget
{
public:
   QGridLayout *gridLayout;
   QGroupBox *groupBox;
   QGridLayout *gridLayout1;
   QListWidget *listWidget;
   QSpacerItem *spacerItem;
   QPushButton *pushButton;

   void setupUi(QWidget *Widget);
   void retranslateUi(QWidget *Widget);
};

Of course, those 6 QObject derived classes are deleted. But the sizeof(Ui_Widget) = 6 * sizeof(void*) = 24 bytes are not deleted. As Ui_Widget is not QObject derived those 24 bytes leak. Confirmed by valgrind.

In a comment to my last blog Paolo suggested to use auto_ptr or scoped_ptr, which is more elegant than an extra wrapper class :)

Memory leak: Ui files and direct approach

The KDE codebase often uses a forward declaration in the .h-file to speedup compilation. The code often looks like this:

// header file
namespace Ui { class MyWidget; }
class MyDialog : public KDialog {
  // ...
  private:
    Ui::MyWidget *ui;
};

The impl looks like this:

// source file
#include "mydialog.h"
#include "ui_mywidget.h"
MyDialog::MyDialog() : KDialog()
{
  QWidget *w = new QWidget(this);
  setMainWidget(w);
  ui = new Ui::MyWidget(); // allocation
  ui->setupUi(w);
  // ui->...
}

See the memory leak? You have to call »delete ui;« in the destructor if you use the »direct approach«. Searching in lxr.kde.org shows lots of results, and in some places this delete is missing indeed. Happy fixing :)


Update: The really correct fix is to guard the pointer with an auto_ptr or scoped_ptr. For further details read the comments below. Or use another approach to include your ui-file.


If you do not want to delete it manually, you can for instance use a workaround like this:

// header file
namespace Ui { class MyWidget; }
class MyWidget;
class MyDialog : public KDialog {
  // ...
  private:
    Ui::MyWidget *ui;
};

Source file:

// source file
#include "mydialog.h"
#include "ui_mywidget.h"

class MyWidget : public QWidget, public Ui::MyWidget {
public:
    MyWidget( QWidget * parent = 0 ) : QWidget( parent )
    { setupUi(this); }
};

MyDialog::MyDialog() : KDialog()
{
  ui = new MyWidget(this);
  setMainWidget(ui);
  QWidget *w = new QWidget(this);
  setMainWidget(w);
  ui = new Ui::MyDialog(); // allocation
  ui->setupUi(w);
  // ui->...
}

Kate Scripting: Indentation

Kate Part in KDE4 supports the ECMAScript (JavaScript) language by using kjs. In KDE3 we had several hard-coded indenters in C++, the idea is to let scripts do all the indentation in KDE4.
How does it work? It is similar to vim: You simply create a script in the directory $KDEDIR/share/apps/katepart/jscript. An indentation script has to follow several rules:

  1. it must have a valid script header (the first line must include the string kate-script and indentation scripts must have the type: indentation)
  2. it must define some variables and functions

Whenever the user types a character, the flow in Kate Part works like this

  1. check the indentation script’s trigger characters, i.e. whether the script wants to indent code for the typed character
  2. if yes, call the indentation function
  3. the return value of the indentation function is an integer value representing the new indentation depth in spaces.

In the 3rd step there are 2 special cases for the return value:

  1. return value = -1: Kate keeps the indentation, that is it searches for the last non-empty line and uses its indentation for the current line
  2. return value < -1 tells Kate to do nothing

So how does a script look like exactly?
The name does not really matter, so let’s call it foobar.js:

/* kate-script
 * name: MyLanguage Indenter
 * license: LGPL
 * author: Foo Bar
 * version: 1
 * kate-version: 3.0
 * type: indentation
 *
 * optional bla bla here
 */

// specifies the characters which should trigger indent() beside the default '\n'
triggerCharacters = "{}";

// called for the triggerCharacters {} and
function indent(line, indentWidth, typedChar)
{
  // do calculations here
  // if typedChar is an empty string, the user hit enter/return

  // todo: Implement your indentation algorithms here.
  return -1; // keep indentation
}

More details on the header:

  • name [required]: the name will appear in Kate’s menus
  • license [optional]: not visible in gui, but should be specified in js-files. it is always better to have a defined license
  • author [optional]: name
  • version [optional]: recommended. an integer
  • kate-version [required]: the minimum required kate-version (e.g. for api changes)
  • type [required]: must be set to indentation

The only missing part is the API which Kate Part exports to access the document and the view. Right now, there is no API documentation, so you have to look at the code:

You will find, that the current document exports functions like

  • document.fileName()
  • document.isModified()
  • document.charAt(line, column)
  • etc…

The view exports functions like

  • view.cursorPosition()
  • view.hasSelection()
  • view.clearSelection()

That’s the boring part of this blog. The interesting one is unfortunately shorter: we are looking for contributors who want to write scripts or help in the C++ implementation :)