The hk_kdeclasses programmer's tutorial

Horst Knorr

Version 0.1.4

Abstract

Thanks to Salvatore Enrico Indiogine for proof-reading the documentation.

This is a short, quick and dirty tutorial to help you to write programs with hk_kdeclasses. For further information see the programmer's API documentation. This manual describe hk_kdeclasses version 0.5.3. To compile the source code of example.cpp use

c++ -o example example.cpp  -ldl -lhk_classes -L/usr/lib/hk_classes/ \
-I /usr/include/hk_classes  -L /opt/kde3/lib -lkdecore -lkdeui -lhk_kdeclasses \
-L/usr/lib/qt3/lib -lqt -I /opt/kde3/include -I /usr/lib/qt3/include

All examples refer to the example database "literature" described in the knoda tutorial. First you should first create this database (it is best to use knoda for this).

Please read the hk_classes tutorial first, because we take these examples and use it for KDE. You should also have some experience in programming with KDE.


Table of Contents

1. Getting started
2. A graphical login
3. Adding data sensitive widgets
The hk_kdeclasses widgets
Adding a data sensitive widget
Adding a grid with a depending data source
4. The high level widgets
Forms
Tables
5. A runtime version

List of Figures

3.1. The example application

List of Examples

1.1. The first program
2.1. Getting the messages to KDE
3.1. Adding a lineedit field
3.2. Adding a row selector
3.3. Adding a grid with a depending data source
4.1. Using a form
4.2. Using a table
5.1. Using a table - the runtime version

Chapter 1. Getting started

The following program listing is a simple KDE program (without any hk_classes parts). It just opens a main widget.

#define HAVE_SSTREAM 1
#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <qwidget.h>

static const char *description =
    I18N_NOOP("A hk_kdeclasses example Application");

static const char *version = "v0.1";


int main(int argc, char **argv)
{
    KAboutData about("hk_kdeexample", I18N_NOOP("hk_kdeexample"), version, description, KAboutData::License_GPL, "(C) 2001 Horst Knorr", 0, 0, "hk_classes@knoda.org");
    about.addAuthor( "Horst Knorr", 0, "hk_classes@knoda.org" );
    KCmdLineArgs::init(argc, argv, &about);

    KApplication app;

    QWidget* widget = new QWidget;

    app.setMainWidget(widget);
    widget->show();

    int res = app.exec();
}   return res;

And in the following program listing you see the example of chapter 2 of the hk_classes tutorial


#define HAVE_SSTREAM 1
  #include <hk_classes.h>
  #include <iostream>
  int main()
  {
  hk_drivermanager* mydrivermanager = new hk_drivermanager(false);
  if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
  hk_connection* myconnection = mydrivermanager->new_connection();
  if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
  myconnection->connect();

  hk_database* mydatabase=myconnection->new_database("exampledb");
  if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
  hk_datasource* mydatasource= mydatabase->new_table("authors");
  if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
  mydatasource->enable();
  //the following internal debugging command should not be used. It is used here for
  //demonstration purposes only!!!!
  mydatasource->dump_data(); // DON'T USE THIS COMMAND IN YOUR PROGRAMS!!!

  delete mydrivermanager;
  }

Now we merge these 2 programs.

Example 1.1. The first program

#define HAVE_SSTREAM 1
#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <qwidget.h>
#include <hk_classes.h>
#include <iostream>

static const char *description =
    I18N_NOOP("A hk_kdeclasses example Application");

static const char *version = "v0.1";


int main(int argc, char **argv)
{
    KAboutData about("hk_kdeexample", I18N_NOOP("hk_kdeexample"), version, description, KAboutData::License_GPL, "(C) 2001 Horst Knorr", 0, 0, "hk_classes@knoda.org");
    about.addAuthor( "Horst Knorr", 0, "hk_classes@knoda.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KApplication app;
    QWidget* widget = new QWidget;
    app.setMainWidget(widget);

    hk_drivermanager* mydrivermanager = new hk_drivermanager(false);
    if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
    hk_connection* myconnection = mydrivermanager->new_connection();
    if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
    myconnection->connect();

    hk_database* mydatabase=myconnection->new_database("exampledb");
    if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
    hk_datasource* mydatasource= mydatabase->new_table("authors");
    if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
    mydatasource->enable();

    widget->show();

    int res= app.exec();
    delete mydrivermanager;
    return res;
}

Compile this program and start it. It works as the 2 programs were planned to do. The hk_classes part of the application asks for login information on the console and then the widget starts. This is very unsatisfactory. When we use KDE we also want to use its functionalities.

Chapter 2. A graphical login

To get the all messages, warnings and dialogs away from the console to KDE use the function set_kdestandarddialogs() and include its header file hk_kdemessages.h.

Example 2.1. Getting the messages to KDE

#define HAVE_SSTREAM 1
#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <qwidget.h>
#include <hk_classes.h>
#include <iostream>
#include <hk_kdemessages.h>

static const char *description =
    I18N_NOOP("A hk_kdeclasses example Application");

static const char *version = "v0.1";


int main(int argc, char **argv)
{
    KAboutData about("hk_kdeexample", I18N_NOOP("hk_kdeexample"), version, description, KAboutData::License_GPL, "(C) 2001 Horst Knorr", 0, 0, "hk_classes@knoda.org");
    about.addAuthor( "Horst Knorr", 0, "hk_classes@knoda.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KApplication app;
    QWidget* widget = new QWidget;
    app.setMainWidget(widget);
    set_kdestandarddialogs();

    hk_drivermanager* mydrivermanager = new hk_drivermanager(false);
    if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
    hk_connection* myconnection = mydrivermanager->new_connection();
    if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
    myconnection->connect();

    hk_database* mydatabase=myconnection->new_database("exampledb");
    if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
    hk_datasource* mydatasource= mydatabase->new_table("authors");
    if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
    mydatasource->enable();

    widget->show();

    int res= app.exec();
    delete mydrivermanager;
    return res;
}

Compile the program. Now you see a driver selection window followed by a login window. If you already have some experience with knoda you should recognize the dialogs.

Chapter 3. Adding data sensitive widgets

It is time to display data of our previously created data source. Below you can see what we want to create in this example. It is a widget with various data sensitive fields.

Figure 3.1. The example application

The example application

Let's have a look on the widgets, hk_kdeclasses offers you.

The hk_kdeclasses widgets

The low level widgets are:

  • hk_kdelineedit a data sensitive standard field

  • hk_kdememo a data sensitive multiline field

  • hk_kdeboolean a data sensitive bool field

  • hk_kdegrid a data sensitive grid to display multiple columns and multiple rows

  • hk_kdecombobox a data sensitive combobox

  • hk_kderowselector a row selector to browse a datasource

There also exist some high level widgets to handle tables, queries and forms. If you are using knoda, you are already using them:

  • hk_kdetable a widget to display and alter data in a grid and having the capability of altering the table structure

  • hk_kdequery a widget to define and execute a SQL-statement

  • hk_kdeform a widget to view and design forms

Adding a data sensitive widget

Back to our example application. We add now a hk_kdelineedit field to display the data of the previously created data source "mydatasource". We want to see the data of the column "name".

Example 3.1. Adding a lineedit field

#define HAVE_SSTREAM 1
#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <qwidget.h>
#include <hk_classes.h>
#include <iostream>
#include <hk_kdemessages.h>
#include <hk_kdelineedit.h>

static const char *description =
    I18N_NOOP("A hk_kdeclasses example Application");

static const char *version = "v0.1";


int main(int argc, char **argv)
{
    KAboutData about("hk_kdeexample", I18N_NOOP("hk_kdeexample"), version, description, KAboutData::License_GPL, "(C) 2001 Horst Knorr", 0, 0, "hk_classes@knoda.org");
    about.addAuthor( "Horst Knorr", 0, "hk_classes@knoda.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KApplication app;
    QWidget* widget = new QWidget;
    app.setMainWidget(widget);
    set_kdestandarddialogs();

    hk_drivermanager* mydrivermanager = new hk_drivermanager(false);
    if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
    hk_connection* myconnection = mydrivermanager->new_connection();
    if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
    myconnection->connect();

    hk_database* mydatabase=myconnection->new_database("exampledb");
    if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
    hk_datasource* mydatasource= mydatabase->new_table("authors");
    if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
    hk_kdelineedit* namefield = new hk_kdelineedit(widget);
    namefield->setGeometry(50,50,150,30);
    namefield->set_datasource(mydatasource);
    namefield->set_columnname("name");
    mydatasource->enable();

    widget->show();

    int res= app.exec();
    delete mydrivermanager;
    return res;
}

Have a look at the source code. We create a hk_kdelineeditfield and then set the data source with set_datasource. With set_column the name of an existing column in this data source is set. After enabling it you can view and alter the data. What you can't do at the moment is browsing the data source. For this we add a hk_kderowselector. Refer to the knoda tutorial on how to use the row selector.

Example 3.2. Adding a row selector

#define HAVE_SSTREAM 1
#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <qwidget.h>
#include <hk_classes.h>
#include <iostream>
#include <hk_kdemessages.h>
#include <hk_kdelineedit.h>
#include <hk_kderowselector.h>

static const char *description =
    I18N_NOOP("A hk_kdeclasses example Application");

static const char *version = "v0.1";


int main(int argc, char **argv)
{
    KAboutData about("hk_kdeexample", I18N_NOOP("hk_kdeexample"), version, description, KAboutData::License_GPL, "(C) 2001 Horst Knorr", 0, 0, "hk_classes@knoda.org");
    about.addAuthor( "Horst Knorr", 0, "hk_classes@knoda.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KApplication app;
    QWidget* widget = new QWidget;
    app.setMainWidget(widget);
    set_kdestandarddialogs();

    hk_drivermanager* mydrivermanager = new hk_drivermanager(false);
    if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
    hk_connection* myconnection = mydrivermanager->new_connection();
    if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
    myconnection->connect();

    hk_database* mydatabase=myconnection->new_database("exampledb");
    if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
    hk_datasource* mydatasource= mydatabase->new_table("authors");
    if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
    hk_kdelineedit* namefield = new hk_kdelineedit(widget);
    namefield->setGeometry(50,50,150,30);
    namefield->set_datasource(mydatasource);
    namefield->set_columnname("name");

    hk_kderowselector* rowselector = new hk_kderowselector(widget);
    rowselector->setGeometry(250,50,150,30);
    rowselector->set_datasource(mydatasource);

    mydatasource->enable();

    widget->show();

    int res= app.exec();
    delete mydrivermanager;
    return res;
}

It is up to you to add the other fields of this data source to this widget.

Adding a grid with a depending data source

In the next step we want to display all the literature that Goethe (or any other author) has written. The data is in table "literature" so we have to create a new data source. Have a closer look at the code. The data source "literaturetable" is created and also a hk_kdegrid which is connected to "literaturetable". We only want to see the literature of the author who is actually displayed. The data source "literaturetable" is depending on the data source "mydatasource".

We have to inform the system which columns have connected values. In the master data source (mydatasource) it is the field "author_id" and in the actual data source (literaturetable) it is the field "author".

Important

Notice that the data source "literaturetable" is not enabled. Whenever the master data source (mydatasource) will be enabled, the depending data sources will also be enabled. When the master data source is disabled so are the depending data sources.

Example 3.3. Adding a grid with a depending data source

#define HAVE_SSTREAM 1
#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <qwidget.h>
#include <hk_classes.h>
#include <iostream>
#include <hk_kdemessages.h>
#include <hk_kdelineedit.h>
#include <hk_kderowselector.h>
#include <hk_kdegrid.h>

static const char *description =
    I18N_NOOP("A hk_kdeclasses example Application");

static const char *version = "v0.1";


int main(int argc, char **argv)
{
    KAboutData about("hk_kdeexample", I18N_NOOP("hk_kdeexample"), version, description, KAboutData::License_GPL, "(C) 2001 Horst Knorr", 0, 0, "hk_classes@knoda.org");
    about.addAuthor( "Horst Knorr", 0, "hk_classes@knoda.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KApplication app;
    QWidget* widget = new QWidget;
    app.setMainWidget(widget);
    set_kdestandarddialogs();

    hk_drivermanager* mydrivermanager = new hk_drivermanager(false);
    if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
    hk_connection* myconnection = mydrivermanager->new_connection();
    if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
    myconnection->connect();

    hk_database* mydatabase=myconnection->new_database("exampledb");
    if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
    hk_datasource* mydatasource= mydatabase->new_table("authors");
    if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
    hk_kdelineedit* namefield = new hk_kdelineedit(widget);
    namefield->setGeometry(50,50,150,30);
    namefield->set_datasource(mydatasource);
    namefield->set_columnname("name");

    hk_kderowselector* rowselector = new hk_kderowselector(widget);
    rowselector->setGeometry(250,50,150,30);
    rowselector->set_datasource(mydatasource);


    hk_datasource* literaturetable = mydatabase->new_table("literature");
    literaturetable->set_depending_on(mydatasource);
    literaturetable->add_depending_fields("author","author_id");

    hk_kdegrid* grid = new hk_kdegrid(widget);
    grid->setGeometry(50,100,250,200);
    grid->set_datasource(literaturetable);


    mydatasource->enable();

    widget->show();

    int res= app.exec();
    delete mydrivermanager;
    return res;
}

Chapter 4. The high level widgets

Table of Contents

Forms
Tables

Forms

Now we try to open the form "demo" that we created in the knoda tutorial. It is loosely based on example 2. The most important parts are again highlighted.

Example 4.1. Using a form

#define HAVE_SSTREAM 1
#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <hk_classes.h>
#include <iostream>
#include <hk_kdeform.h>
#include <hk_kdemessages.h>

static const char *description =
    I18N_NOOP("A hk_kdeclasses example Application");

static const char *version = "v0.1";


int main(int argc, char **argv)
{
    KAboutData about("hk_kdeexample", I18N_NOOP("hk_kdeexample"), version, description,
     KAboutData::License_GPL, "(C) 2001 Horst Knorr", 0, 0, "hk_classes@knoda.org");
    about.addAuthor( "Horst Knorr", 0, "hk_classes@knoda.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KApplication app;

    hk_kdeform* form = new hk_kdeform(NULL);
    app.setMainWidget(form);

    set_kdestandarddialogs();
    hk_drivermanager* mydrivermanager = new hk_drivermanager(false);
    if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
    hk_connection* myconnection = mydrivermanager->new_connection("mysql");
    if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
    myconnection->connect();

    hk_database* mydatabase=myconnection->new_database("exampledb");
    if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
    hk_datasource* mydatasource= mydatabase->new_table("authors");
    if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}

    form->set_database(mydatabase);
    form->load_form("demo");
    form->set_viewmode();
    form->show();

    int res= app.exec();
    delete mydrivermanager;
    return res;
}



The hk_kdeform needs only the database and then loads the (supposedly) existing form "demo". Finally set the view mode to see the data.

Tables

The same thing now with a table

Example 4.2. Using a table

#define HAVE_SSTREAM 1
#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <hk_classes.h>
#include <iostream>
#include <hk_kdetable.h>
#include <hk_kdemessages.h>

static const char *description =
    I18N_NOOP("A hk_kdeclasses example Application");

static const char *version = "v0.1";


int main(int argc, char **argv)
{
    KAboutData about("hk_kdeexample", I18N_NOOP("hk_kdeexample"), version, description, KAboutData::License_GPL, "(C) 2001 Horst Knorr", 0, 0, "hk_classes@knoda.org");
    about.addAuthor( "Horst Knorr", 0, "hk_classes@knoda.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KApplication app;

    hk_kdetable* table = new hk_kdetable(NULL);

    app.setMainWidget(table);
    set_kdestandarddialogs();
    hk_drivermanager* mydrivermanager = new hk_drivermanager(false);
    if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
    hk_connection* myconnection = mydrivermanager->new_connection("mysql");
    if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
    myconnection->connect();

    hk_database* mydatabase=myconnection->new_database("exampledb");
    if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
    hk_datasource* mydatasource= mydatabase->new_table("authors");
    if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}

    table->set_datasource(mydatasource);
    table->set_viewmode();
    table->show();

    int res= app.exec();
    delete mydrivermanager;
    return res;
}

Chapter 5. A runtime version

Sometimes the user should not have the possibility to change the data structure. To hide the design mode just set hk_drivermanager(true). Below is the program of the previous chapter.

Example 5.1. Using a table - the runtime version

#define HAVE_SSTREAM 1
#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <hk_classes.h>
#include <iostream>
#include <hk_kdetable.h>
#include <hk_kdemessages.h>

static const char *description =
    I18N_NOOP("A hk_kdeclasses example Application");

static const char *version = "v0.1";


int main(int argc, char **argv)
{
    KAboutData about("hk_kdeexample", I18N_NOOP("hk_kdeexample"), version, description, KAboutData::License_GPL, "(C) 2001 Horst Knorr", 0, 0, "hk_classes@knoda.org");
    about.addAuthor( "Horst Knorr", 0, "hk_classes@knoda.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KApplication app;

    set_kdestandarddialogs();
    hk_drivermanager* mydrivermanager = new hk_drivermanager(true);
    hk_kdetable* table = new hk_kdetable(NULL);

    app.setMainWidget(table);
    if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
    hk_connection* myconnection = mydrivermanager->new_connection("mysql");
    if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
    myconnection->connect();

    hk_database* mydatabase=myconnection->new_database("exampledb");
    if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
    hk_datasource* mydatasource= mydatabase->new_table("authors");
    if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}

    table->set_datasource(mydatasource);
    table->show();
    table->set_viewmode();

    int res= app.exec();
    delete mydrivermanager;
    return res;
}