All posts by Dominik

Dominik is a PhD student at the Control Theory and Robotics Lab, TU Darmstadt, as part of the Research Training Group GKMM (GRK1362). My research focuses on state estimation in distributed systems. As hobby, I contribute to the KDE project and work on the Kate application and editor component.

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 Highlighting Power

Kate’s highlighting capabilities are amazing. If you want you can highlight really complex syntax, without having to hardcode rules in C++. As an example, we’ll take a look at how Lua comments can be realized:

  • –[=[ starts a multiline comment (the '=' chars are optional)
  • ]=] ends the multiline comment
  • the number of ‘=’ chars in ]=] must match the number of –[=[

That means: When the highlighting processor matches the end of a multiline comment, it has to know how many ‘=’ chars started the comment. Thanks to the concept of dynamic rules and contexts Kate is able to do that. The highlighting file looks like this. First comes the header

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd" >
<language name="Test" version="1.0" kateversion="2.4" section="Markup" extensions="" mimetype="">
  <highlighting>

Then the body with the contexts. We start in the first context called “Normal Text”. When the regular expression –[(=*)[ matches it switches to the context Comment.

    <contexts>
      <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
        <RegExpr attribute="Comment" context="Comment" String="--\[(=*)\[" dynamic="true"/>
      </context>

The part (=*) is now available as %1 in the rule below:

      <context name="Comment" attribute="Comment" lineEndContext="#stay" dynamic="true" >
        <RegExpr attribute="Comment" context="#pop" String="\]%1\]" dynamic="true" />
      </context>
    </contexts>

The last part is the footer:

    <itemDatas>
      <itemData name="Normal Text" defStyleNum="dsNormal" />
      <itemData name="Comment"     defStyleNum="dsComment" />
    </itemDatas>
  </highlighting>
</language>

If you want to know more about Kate’s highlighting, have a look at the documentation :) There are also lots of bug reports, so if you want to contribute you can fix them!

PS: As I don’t know much about Lua, comments might work differently. That does not really matter, as the example still shows what you can do :)

Extending Kate by Scripts

We have seen how scripting basically works for indentation. It’s also possible to register commandline functions (The command line is bound to F7 by default, or invoke View > Switch to Command Line). We will consider a small example again: sort the selected text.

/* kate-script
 * name: unused
 * author: foo bar
 * license: LGPL
 * version: 1
 * kate-version: 3.0
 * functions: sorter
 */

function sorter ()
{
    if (view.hasSelection()) {
        var start = view.startOfSelection().line;
        var end = view.endOfSelection().line;

        var text = document.textRange(start, 0, end, document.lineLength(end));

        var lines = text.split(“\n”);
        lines.sort();
        text = lines.join(“\n”);

        view.clearSelection();

        document.editBegin();
        document.removeText(start, 0, end, document.lineLength(end));
        document.insertText(start, 0, text);
        document.editEnd();
    }
}

The header line functions: sorter makes Kate Part aware of the function in the script. A list of functions is supported, separated by white spaces. You can use the function by typing ‘sorter’ in the commandline.
Some todo items:

  • provide better JavaScript API. For example: document.textRange() takes 4 parameters. It would be more elegant to take one range or two cursors, just like we do in the KTextEditor interfaces in kdelibs/interfaces/ktexteditor
  • make is possible to bind scripts to shortcuts. This could be done by e.g. binding commandline functions to shortcuts or implementing a vim-like command-mode in Kate’s commandline. How to configure the shortcuts is unclear, though.
  • then, think about replacing the C++ implementations of ‘uppercase’, ‘lowercase’, ‘capitalize’ etc. with scripts
  • things I forgot…

If you are interested subscribe to kwrite-devel@kde.org and contribute :) We also need indentation scripts, of course!