Some Tips for Hacking on Valknut

Checking out subversion

See the svn page.

Coding Conventions

Dclib and Valknut have been coded using a style I believe is known as Hungarian Notation. This means variables that are members of a class are prefixed with letters that indicate their type. For example, a string member of DCConfig is m_sValknutDataPath, and a boolean is m_bClientColumnSUPPORTS. Generally this is only used for class members, local variabales usually have much shorter names without type prefixes.

There are doxygen comments /** */ throughout the source but they are usually empty. However I try to fill them in for new code such as the CFileHasher and CCaseFolder classes, at least giving a description of the class.

Frequently changed files

dclib - cconfig.h/.cpp

The configuration settings for dclib. Typically when adding a new setting you need to add inline GetFoo() and SetFoo(type value) methods, and a new private member variable to the .h file. You then add a new XML_FOO_SETTING define and code for the default value, and loading and saving, to the .cpp file.

This is actually a terrible system as every new setting adds new API and requires you to recompile valknut (breaks ABI), but dclib never had any API/ABI stability. Valknut also stores a few settings (mainly window geometry) in QMaps which is a much better system.

valknut - dcchat.cpp

Most often changed section is the chat commands bit.

valknut - dcconfig.h/.cpp

Stores, saves and loads settings for valknut. Individual settings are added in the same way as for dclib's cconfig.h/.cpp.

valknut - ui/DCDialogOptions.ui and dcoptions.cpp

The options dialog. When adding a new option, you need to add lines to GetValues(), to set the config value to the one entered, and SetValues() to set the dialog to the configured value.

Common operations

Accessing the config (examples)

Dclib: use CConfig::Instance()

long i = CConfig::Instance()->GetAutoSearchInterval();

Valknut: use g_pConfig

g_pConfig->SetEmoticonTheme(ComboBox_EMOTICONS->currentText());

Converting between a CString and a QString

Dclib uses it's own objects for common data types, in dclib/core. You often need to convert between a CString used in dclib and a QString used in the GUI. You will find numerous examples of this by browsing through any part of the code. For example, from code I added to dcchat.cpp

QString pressedNick;

CString cPressedNick;

pressedNick = QString::fromAscii(m_sNick.Data()) // CString to QString via Data()

cPressedNick = pressedNick.ascii(); // QString to CString via ascii() Qt3

cPressedNick = pressedNick.toAscii().constData(); // QString to CString via toAscii().constData() Qt4

Converting a string to a number

Use functions such as CString::asINT() or QString::toInt(). See cstring.h or the Qt API documentation for more functions that convert to a particular type.

Adding columns

Be very careful if you add columns to a dialog such as the filelist browser or the search results dialog. If the newly added column is not the rightmost column, you will need to go through all the code and change column numbers to the new values. Some defines were added to dchubsearch.cpp to make this job easier for the search results dialog.

Using Qt Designer

You can use Qt Designer to change the user interface of valknut using a drag and drop graphical tool. Unfortunately, this does not produce neat patches and it is necessary to run diff on the original and changed files, and pick out the useful part of the diff, then manually edit the .ui file with a text editor. The result can then be checked by viewing the manually editted .ui file in Qt Designer.

Current / Future plans

CStringList is being replaced in dclib with std::map, std::set or where more suitable, std::tr1::unordered_map or std::tr1::unordered_set which are faster. The new code is usually much clearer, possibly faster and does not generate all those type-punned pointer compiler warnings.

The use of dclib classes inside valknut is being minimized, using classes such as QString, QMap and QList (Qt3 QPtrList / QValueList) is usually more memory efficient - especially with QString - since Qt uses implict sharing which automatically avoids unnecessary data copying.

The Qt4 version still needs those Q3ListViews for the filelist browser, search results and transfers lists replacing with QtreeView and models, then the Qt3Support library will no longer be needed.

Currently the Qt4 version only requires Qt 4.3, although the Qt 4.4 documentation is consulted. There is an annoying issue which causes the hublist manager to be raised when you close a window rather than focus moving to the previous window. This is now fixed if you run with Qt 4.4, even if you compiled against Qt 4.3. Future versions may require Qt 4.4 once this is the standard version provided by Linux distributions.