Welcome to the first in hopefully a row of little tutorials showing how you can yourself add the features you need to Okteta, the KDE 4 hex editor.
Although, after writing this one, which took way too much time, I will see how I can make this more economic for me.
For now, you simply have to make use of this tutorial, so my time was well spent!
Setup of the development environment
Unless you already have a development environment, including the sources of kdeutils, e.g. after following the instructions from TechBase, the following little setup should work for you, too:
You need to have installed a proper compiler, cmake, a subversion client and the development packages of qt4 and kdelibs4. You might not need the kdelibs from trunk, version 4.3, perhaps even 4.2 should do it, I do not remember to have used any newer kdelibs API in Okteta so far. (Please report if you experience problems.)
Now get the sources of Okteta:
svn co svn://anonsvn.kde.org/home/kde/trunk/KDE/kdeutils -N
svn up kdeutils/okteta
Build the program in a separate directory (replace “yourinstallpath” with a proper path as useful for personal development, e.g. the output of kde4-config --prefix):
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=yourinstallpath ../kdeutils
cd okteta
make
The build will take a while as all those files you just saw when doing the checkout want to get compiled…
Do a make install to see if the installation works, too.
Then testrun Okteta with yourinstallpath/okteta.
(Or just okteta if you are sure your shell does not outsmart you and instead starts okteta from a path it has cached from a previous start when this version of Okteta was not yet installed)
Hoping that all went smooth we can now turn to…
Adding a Binary Filter
In this tutorial you write a filter which will turn all bytes either to 0×00 or 0xFF, depending on whether their old value is below or above a given level. It will look like this:

To do so you follow the instructions found in okteta/kasten/controllers/view/libbytearrayfilter/README.developers:
Step 1: Creating source files
Commands to get this done:
cd ../../kdeutils/okteta/kasten/controllers/view/libbytearrayfilter/filter/
cp template/template_bytearrayfilter.h levelbytearrayfilter.h
cp template/template_bytearrayfilter.cpp levelbytearrayfilter.cpp
Step 2: Adapting the code from the template
“levelbytearrayfilter.h” should end up like this:
#ifndef LEVELBYTEARRAYFILTER_H
#define LEVELBYTEARRAYFILTER_H
// lib
#include "nobytearrayfilterparameterset.h"
#include [abstractbytearrayfilter.h]
class LevelByteArrayFilter : public AbstractByteArrayFilter
{
public:
LevelByteArrayFilter();
virtual ~LevelByteArrayFilter();
public: // AbstractByteArrayFilter API
virtual bool filter( Okteta::Byte* result, Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range ) const;
virtual AbstractByteArrayFilterParameterSet* parameterSet();
protected:
NoByteArrayFilterParameterSet mParameterSet;
};
#endif
And the file “levelbytearrayfilter.cpp” should end like this:
#include "levelbytearrayfilter.h"
// Okteta core
#include [abstractbytearraymodel.h]
// KDE
#include [KLocale]
LevelByteArrayFilter::LevelByteArrayFilter()
: AbstractByteArrayFilter(
i18nc("name of the filter; sets the byte to 0 or 255, depending on a level",
"LEVEL data") )
{}
AbstractByteArrayFilterParameterSet* LevelByteArrayFilter::parameterSet() { return &mParameterSet; }
bool LevelByteArrayFilter::filter( Okteta::Byte* result,
Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range ) const
{
const unsigned int level = 127;
int r = 0;
Okteta::Address m = range.start();
int nextBlockEnd = FilteredByteCountSignalLimit;
while( m byte( m++ );
const Okteta::Byte resultByte = ( byte > level ) ? 255 : 0;
result[r++] = resultByte;
if( r >= nextBlockEnd )
{
nextBlockEnd += FilteredByteCountSignalLimit;
emit filteredBytes( r );
}
}
return true;
}
LevelByteArrayFilter::~LevelByteArrayFilter() {}
Step 3: Adding the filter to the library
The file “okteta/kasten/controllers/view/libbytearrayfilter/bytearrayfilterfactory.cpp” should now as both have an include for the file “filter/levelbytearrayfilter.h”
#include "filter/levelbytearrayfilter.h"
as well create a filter “LevelByteArrayFilter”
result
<< new AndByteArrayFilter()
<< new OrByteArrayFilter()
<< new XOrByteArrayFilter()
<< new InvertByteArrayFilter()
<< new ReverseByteArrayFilter()
<< new RotateByteArrayFilter()
<< new ShiftByteArrayFilter()
// new:
<< new LevelByteArrayFilter();
In the file “okteta/kasten/controllers/CMakeLists.txt” the list “LIBFILTER_SRCS” should now also include the file “levelbytearrayfilter.cpp”:
view/libbytearrayfilter/filter/reversebytearrayfilter.cpp view/libbytearrayfilter/filter/rotatebytearrayfilter.cpp view/libbytearrayfilter/filter/shiftbytearrayfilter.cpp # new: view/libbytearrayfilter/filter/levelbytearrayfilter.cpp
Step 4: Compile, install and run
Commands to get this done:
cd ../../../../../../../build/
make
make install
If the build and install went well, start Okteta with yourinstallpath/okteta (cmp. remarks at end of section “Setup of the development environment” above).
Load some file, select a range, open the Binary Filter tool and select “LEVEL data” as filter. It should look like this:

Now press the “Filter” button. It should look like this:

Now let’s turn to…
Making the Level an editable Parameter
Step 1: Creating source files
Commands to get this done:
cd ../kdeutils/okteta/kasten/controllers/view/libbytearrayfilter/filter/
cp template/template_bytearrayfilterparameterset.h levelbytearrayfilterparameterset.h
cp template/template_bytearrayfilterparameterset.cpp levelbytearrayfilterparameterset.cpp
cp template/template_bytearrayfilterparametersetedit.h levelbytearrayfilterparametersetedit.h
cp template/template_bytearrayfilterparametersetedit.cpp levelbytearrayfilterparametersetedit.cpp
Step 2: Adapting the code from the template
“levelbytearrayfilterparameterset.h” should end up like this:
#ifndef LEVELBYTEARRAYFILTERWITHPARAMETERSET_H
#define LEVELBYTEARRAYFILTERWITHPARAMETERSET_H
// lib
#include [abstractbytearrayfilterparameterset.h]
class LevelByteArrayFilterParameterSet : public AbstractByteArrayFilterParameterSet
{
public:
LevelByteArrayFilterParameterSet();
virtual ~LevelByteArrayFilterParameterSet();
public: // AbstractByteArrayFilterParameterSet API
virtual const char* id() const;
public: // getters
unsigned char level() const;
public: // setters
void setLevel( unsigned int level );
protected: // parameters
unsigned char mLevel;
};
#endif
“levelbytearrayfilterparameterset.cpp” should end up like this:
#include "levelbytearrayfilterparameterset.h"
static const unsigned int DefaultLevel = 127;
LevelByteArrayFilterParameterSet::LevelByteArrayFilterParameterSet()
: mLevel( DefaultLevel )
{}
const char* LevelByteArrayFilterParameterSet::id() const { return "Level"; }
unsigned char LevelByteArrayFilterParameterSet::level() const { return mLevel; }
void LevelByteArrayFilterParameterSet::setLevel( unsigned int level ) { mLevel = level; }
LevelByteArrayFilterParameterSet::~LevelByteArrayFilterParameterSet() {}
“levelbytearrayfilterparametersetedit.h” should end up like this:
#ifndef LEVELBYTEARRAYFILTERPARAMETERSETEDIT_H
#define LEVELBYTEARRAYFILTERPARAMETERSETEDIT_H
// lib
#include [abstractbytearrayfilterparametersetedit.h]
class KIntNumInput;
class LevelByteArrayFilterParameterSetEdit : public AbstractByteArrayFilterParameterSetEdit
{
Q_OBJECT
public:
static const char* const Id;
public:
LevelByteArrayFilterParameterSetEdit( QWidget* parent = 0 );
virtual ~LevelByteArrayFilterParameterSetEdit();
public: // AbstractByteArrayFilterParameterSetEdit API
virtual void setValues( const AbstractByteArrayFilterParameterSet* parameterSet );
virtual void getParameterSet( AbstractByteArrayFilterParameterSet* parameterSet ) const;
virtual bool isValid() const;
protected Q_SLOTS:
void onLevelChanged( int value );
protected:
KIntNumInput* mLevelEdit;
bool mIsValid :1;
};
#endif
“levelbytearrayfilterparametersetedit.cpp” should end up like this:
#include "levelbytearrayfilterparametersetedit.h"
// parameterset
#include "levelbytearrayfilterparameterset.h"
// KDE
#include [KLocale]
#include [KIntNumInput]
// Qt
#include [QtGui/QFormLayout]
const char* const LevelByteArrayFilterParameterSetEdit::Id = "Level";
LevelByteArrayFilterParameterSetEdit::LevelByteArrayFilterParameterSetEdit( QWidget* parent )
: AbstractByteArrayFilterParameterSetEdit( parent )
{
QFormLayout* baseLayout = new QFormLayout( this );
// margin is provided by the container for this widget
baseLayout->setMargin( 0 );
mLevelEdit = new KIntNumInput( this );
// For demonstration purpose we start at -1, not 0, to show handling of an invalid state
// Otherwise the range should start at 0 and there is no need to connect to the valueChanged signal
mLevelEdit->setRange( -1, 256 );
// start with the invalid number
mLevelEdit->setValue( -1 );
connect( mLevelEdit, SIGNAL(valueChanged( int )), SLOT(onLevelChanged( int )) );
const QString levelLabelText =
i18nc( "@label:spinbox decimal value up to which bytes are set to 0",
"Level:" );
baseLayout->addRow( levelLabelText, mLevelEdit );
// note start state
mIsValid = isValid();
}
bool LevelByteArrayFilterParameterSetEdit::isValid() const { return mLevelEdit->value() != -1; }
void LevelByteArrayFilterParameterSetEdit::setValues( const AbstractByteArrayFilterParameterSet* parameterSet )
{
const LevelByteArrayFilterParameterSet* template_ParameterSet =
static_cast( parameterSet );
mLevelEdit->setValue( template_ParameterSet->level() );
}
void LevelByteArrayFilterParameterSetEdit::getParameterSet( AbstractByteArrayFilterParameterSet* parameterSet ) const
{
LevelByteArrayFilterParameterSet* template_ParameterSet =
static_cast( parameterSet );
template_ParameterSet->setLevel( mLevelEdit->value() );
}
void LevelByteArrayFilterParameterSetEdit::onLevelChanged( int value )
{
const bool isValid = ( value != -1 );
if( mIsValid == isValid )
return;
mIsValid = isValid;
emit validityChanged( isValid );
}
LevelByteArrayFilterParameterSetEdit::~LevelByteArrayFilterParameterSetEdit()
{}
Also make the “LevelByteArrayFilter” use the “LevelByteArrayFilterParameterSet”, by adapting the include notion and the used parameter set class in the file “levelbytearrayfilter.h” to now be:
#include "levelbytearrayfilterparameterset.h"
LevelByteArrayFilterParameterSet mParameterSet;
In the file “levelbytearrayfilter.cpp” change the variable “level” to be not the hardcoded 127, but to take its value from the parameter set:
const unsigned int level = mParameterSet.level();
Step 3: Adding the parameterset to the library
The file “okteta/kasten/controllers/view/libbytearrayfilter/bytearrayfilterparameterseteditfactory.cpp” should now as both have an include for the file “filter/levelbytearrayfilterparametersetedit.h”
#include "filter/levelbytearrayfilterparametersetedit.h"
as well create a widget “LevelByteArrayFilterParameterSetEdit” for the “LevelByteArrayFilterParameterSetEdit::Id”:
[...]
else if( qstrcmp(id,RotateByteArrayFilterParameterSetEdit::Id) == 0 )
result = new RotateByteArrayFilterParameterSetEdit();
// new:
else if( qstrcmp(id,LevelByteArrayFilterParameterSetEdit::Id) == 0 )
result = new LevelByteArrayFilterParameterSetEdit();
[...]
In the file “okteta/kasten/controllers/CMakeLists.txt” the list “LIBFILTER_SRCS” should now also include the files “levelbytearrayfilterparameterset.cpp” and “levelbytearrayfilterparametersetedit.cpp”:
[...] view/libbytearrayfilter/filter/rotatebytearrayfilterparameterset.cpp # new: view/libbytearrayfilter/filter/levelbytearrayfilterparameterset.cpp [...] view/libbytearrayfilter/filter/rotatebytearrayfilterparametersetedit.cpp # new: view/libbytearrayfilter/filter/levelbytearrayfilterparametersetedit.cpp [...]
Step 4: Compile, install and run
Commands to get this done:
cd ../../../../../../../build/
make
make install
Running Okteta now should get you this:

It did? Hurra
Now, please go and write your own special filters! Then share your work and send them to me for inclusion in the next Okteta release
Next tutorial will be: Add a Checksum/Hashsum algorithm

[...] tutorial will appear on sunday (September 27th) and teach you how to write a binary filter (Update: online now). So stay tuned if you are in need of a hex editor like Okteta and interested to give the [...]
Pingback by Call for action: Write your own plugins for Okteta « Attracted by virtual constructs — September 27, 2009 @ 12:15 pm |
[...] Tutorial: Add a Checksum/Hashsum Algorithm to Okteta Filed under: KDE, Okteta, Tutorial — by frinring @ 7:29 pm Here comes the second in a row of little tutorials showing how you can yourself add the features you need to Okteta, the KDE 4 hex editor (the first one was about Adding a Binary Filter). [...]
Pingback by Tutorial: Add a Checksum/Hashsum Algorithm to Okteta « Attracted by virtual constructs — October 14, 2009 @ 7:30 pm |