Digikam/CodingSprint2014
KDE Framework Port
Branches Creation
All port code must be stored in dedicated "frameworks" git branch for each project. Branch must be created from master.
$>git checkout master
$>git pull --rebase
$>git checkout -b frameworks
$>git push origin frameworks:frameworks
$>git branch -a
* frameworks
master
remotes/origin/HEAD -> origin/master
remotes/origin/frameworks
remotes/origin/master
KF5 Repositories list is given below :
Kipi-plugins Refactoring
A lots of tools are not maintained since a while, other one have been never finalized. See the list of plugins which will be ported or not :
- Tools which can be ported as well :
- panorama
- expoblending
- gpssync
- sendimages
- timeadjust
- metadataedit
- videoslideshow
- advancedslideshow
- flashexport
- kmlexport
- acquireimages
- calendar
- dngconverter
- printimages
- imageviewer
- Tools in pending stage :
- dlnaexport <=== Needs HUpnp lib Qt5 port
- htmlexport <=== Nobody maintain this code since a while, but tool still used.
- photolayoutseditor <=== A complex but powerful tool. Will be complex to port.
- removeredeyes <=== We can share red eyes removal core implementation in libkface in way to share with other KDE applications and replace digiKam Image Editor tool by this code. A new digiKam BQM tool must be created. A GSoC 2015 project can be planned about this topic.
- Web export tools which must be factored (same settings widgets, common dialog, common high level interface to process import/export). Another GSoC 2015 project can be planned about this topic.
- picasawebexport
- rajceexport
- shwup
- debianscreenshots
- dropbox
- googledrive
- imageshackexport
- kioexportimport
- piwigoexport
- smug
- flickrexport
- yandexfotki
- mediawiki <=== need to port libmediawiki from extragear/libs/.
- vkontakte <=== require libkvkontakte from extragear/libs/.
- Tools never finalized (can be moved to attic for the moment) :
- imgurexport <=== require libqtkoauth from SF.net
- photivointegration
- jalbumexport
- wallpaper
- Tools obsolete (can be moved to attic for the moment) :
- batchprocessimages <=== replaced by digiKam BQM
- rawconverter <=== replaced by digiKam BQM
- jpeglossless <=== replaced by new digiKam core tool
- kopete <=== KF5 will use new API
- ipodexport <=== work only with very old Apple devices.
- galleryexport <=== Gallery web service is not maintained since a while. Gallery project is dead.
KF5/Qt5 Port Status
Libkexiv2
Component | Cmake port | pure Qt5 port | pure KF5 port | compile | warnings | Who | Remarks |
---|---|---|---|---|---|---|---|
libkexiv2/src | done | done | done | yes | no | Gilles, Laurent |
|
libkexiv2/tests | done | done | done | yes | no | Gilles, Laurent | Code do not depend of KF5 |
Libkdcraw
Component | Cmake port | pure Qt5 port | pure KF5 port | compile | warnings | Who | Remarks |
---|---|---|---|---|---|---|---|
libkdcraw/src | done | done | done | yes | no | Gilles, Laurent, Veaceslav |
|
libkdcraw/tests | done | done | done | yes | no | Gilles, Laurent, Veaceslav |
|
Libkipi
Component | Cmake port | pure Qt5 port | pure KF5 port | compile | warnings | Who | Remarks |
---|---|---|---|---|---|---|---|
libkipi/src | done | done | done | yes | no | Gilles, Laurent, Mohamed |
|
libkipi/test | done | done | done | yes | no | Gilles, Laurent, Mohamed |
|
Libkface
Component | Cmake port | pure Qt5 port | pure KF5 port | compile | warnings | Who | Remarks |
---|---|---|---|---|---|---|---|
libkface/src | done | done | done | yes | no | Gilles, Laurent, Teemu | Library only depend of KF5::I18n |
libkface/tests | done | done | done | yes | no | Gilles, Laurent, Teemu | Code do not depend of KF5 |
Libkgeomap
Component | Cmake port | pure Qt5 port | pure KF5 port | compile | warnings | Who | Remarks |
---|---|---|---|---|---|---|---|
libkgeomap/src | done | done | done | yes | no | Gilles, Laurent, Teemu, Alin |
|
libkgeomap/tests | done | done | done | yes | no | Gilles, Laurent, Teemu | |
libkgeomap/calibrator | done | done | done | yes | no | Gilles, Laurent, Teemu | |
libkgeomap/demo | done | done | done | yes | no | Gilles, Laurent, Teemu |
|
Kipi-plugins
Component | Cmake port | pure Qt5 port | pure KF5 port | compile | warnings | Who | Remarks |
---|---|---|---|---|---|---|---|
Kipi-plugins/common | done | uncomplete | uncomplete | yes | yes | Gilles, Laurent |
|
Kipi-plugins/tests | done | uncomplete | uncomplete | yes | no | Gilles, Laurent | |
Kipi-plugins Documentation | done | not applicable | not applicable | yes | no | Gilles | |
Kipi-plugins/timeadjust | done | uncomplete | uncomplete | yes | no | Gilles, Laurent | |
Kipi-plugins/sendimages | done | uncomplete | uncomplete | yes | no | Gilles, Laurent | |
Kipi-plugins/kmlexport | done | uncomplete | uncomplete | yes | no | Gilles, Laurent | |
Kipi-plugins/printimages | done | uncomplete | uncomplete | yes | no | Gilles, Laurent | Postscript support have been removed from QPrinter. Option is now removed from assistant. |
Kipi-plugins/flashexport | done | uncomplete | uncomplete | yes | no | Gilles, Laurent |
digiKam Software Compilation
Component | Cmake port | pure Qt5 port | pure KF5 port | compile | warnings | Who | Remarks |
---|---|---|---|---|---|---|---|
digiKam Software Compilation | done | not applicable | not applicable | not applicable | not applicable | Gilles |
|
digiKam Documentation | done | not applicable | not applicable | yes | no | Gilles |
digiKam Core
Component | Cmake port | pure Qt5 port | pure KF5 port | compile | warnings | Who | Remarks |
---|---|---|---|---|---|---|---|
digiKam/data | done | not applicable | not applicable | yes | no | Gilles, Laurent | |
digiKam/libs | done | under progress | under progress | yes | yes | Gilles, Laurent, Teemu, Alin |
|
digiKam/app | done | under progress | under progress | yes | yes | Gilles, Laurent, Teemu, Alin |
|
digiKam/utilities | done | under progress | under progress | yes | yes | Gilles, Laurent, Teemu, Alin |
|
digiKam/imageplugins | done | under progress | under progress | yes | yes | Gilles, Laurent, Teemu | |
digiKam/kioslave | done | under progress | under progress | yes | yes | Gilles, Laurent, Teemu | |
digiKam/showfoto | done | under progress | under progress | yes | yes | Gilles, Laurent, Teemu | |
digiKam/databaseserver | done | under progress | under progress | yes | yes | Gilles, Laurent, Teemu | |
digiKam/tests | done | under progress | under progress | no | Gilles, Laurent, Teemu |
Recommendations
Porting to KF5 is divided in 4 stages:
1/ Change CMake files. Some Laurent scripts do this stuff. We use now ECM scripts collection from KDE core to manage dependencies and report on the console. Some macros disappear, and are replaced by new ones. For this job, it's recommended to look well all done in CMake files from libkexiv2 and libkdcraw already ported and polished.
2/ Port C++ code using KDE4Support. This include older classes from Qt4 and KDE4 to make transition faster. This will help to have quickly a code compilable, but this will generate a lots of deprecated warnings. First regression tests must be done at this stage to see if nothing is broken.
3/ Port C++ code to pure KF5. The goal of KF5 is to reduce KDELibs fingerprint everywhere, when it's possible. Qt API will be used in priority against KF5 API. But sometime, this will be not possible as well, without big changes. A lot of KDE API have migrated to Qt5 (as for ex : KUrl -> QUrl and kDebug ->qDebug). It's sound like KDELibs will become an incubator for new implementations which will move later to Qt. Also, to have the most of code using pure Qt5 will simplify future transitions more easy to do. Removing KDE4Support dependency will force to use non-deprecated KF5 API.
4/ Port C++ code to pure Qt5. Porting most of KF5 Api to use Qt5 instead is prefered, when it's possible. Another important change in Qt5 is the non-support of char pointer with QString.
In first stage we must use remove_definitions(-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII) in CMake script to compile code. These definitions force to not use deprecated QString methods.
Another definition to add while Qt5 porting is add_definitions(-DQT_NO_URL_CAST_FROM_STRING) about cast between QString and QUrl.
In last stage we must use remove_definition(-DQT_DEPRECATED_SINCE(5,0)) in CMake script to compile code. These definitions force to disable deprecated methods in Qt API.
Common changes to port code
Original Code | Ported Code | Remarks |
---|---|---|
...section of code not yet ported... |
#pragma message("PORT QT5")
/*
...section of code not yet ported...
*/ |
Not yet ported code sections must be commented with compiler warnings printed on the console |
KDE4_BUILD_TESTS=ON | BUILD_TESTING=ON | CMake flag to build tests sub-dir. |
CMAKE_BUILD_TYPE=debugfull | CMAKE_BUILD_TYPE=debug | CMake flag to build code with debug symbols. |
kDebug() / kWarning() / kError() | qCDebug(FOO_LOG) / qCWarning(FOO_LOG) / qCCritical(FOO_LOG) |
|
#include "foo.moc" |
#include "foo.h" |
|
KUrl::directory() |
QUrl::adjusted(QUrl::RemoveFilename).path() |
|
KDiskFreeSpaceInfo |
QStorageInfo |
|
KUrl::setFileName(newFileName) |
QUrl::setPath(QUrl::path() + newFileName) |
|
KUrl url;
url.adjustPath(KUrl::AddTrailingSlash); |
QUrl url;
url.setPath(url.path() + '/'); |
|
KDialog::spacingHint() |
QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing) |
|
KDialog::marginHint() |
QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin) |
|
KComponentData::mainComponent().componentName() |
QApplication::applicationName() |
|
KComponentData::mainComponent().aboutData()->homepage() |
KAboutData::applicationData().homepage() |
|
KIconLoader::SmallIcon("icon_name", size) or KIconLoader::global()->loadIcon("icon_name", size) |
QIcon::fromTheme("icon_name").pixmap(size) |
|
KStandardDirs::installPath("data") + QString("filename") |
QStandardPaths::locate(QStandardPaths::GenericDataLocation,
QString("filename")) |
File to open in read-only. File already exist. |
KStandardDirs::installPath("xdgdata-apps") + QString("filename") |
QStandardPaths::locate(QStandardPaths::ApplicationsLocation,
QString("filename")) |
File to open in read-only. File already exist. |
KStandardDirs::locateLocal("data", QString("filename")) |
QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ '/' + QString("filename") |
File to open in read-only. File already exist. |
QString dir = KStandardDirs::locateLocal("data",
QString("dirname"), true) |
QString dir =
QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ '/' + QString("dirname");
QDir().mkpath(dir); |
Dir to open in read-write. Create dir if it do not exist. |
KUrlLabel |
KDcrawIface::RActiveLabel |
|
KSeparator |
KDcrawIface::RLineWidget |
|
KXmlGuiWindow::restoreWindowSize(group);
KDialog::restoreDialogSize(group); and KXmlGuiWindow::saveWindowSize(group);
KDialog::saveDialogSize(group); |
KWindowConfig::restoreWindowSize(windowHandle(), group); and KWindowConfig::saveWindowSize(windowHandle(), group); |
|
KVBox* const vbox = new KVBox(this); |
KDcrawIface::RVBox* const vbox = new KDcrawIface::RVBox(this); |
|
KHBox* const hbox = new KHBox(this); |
KDcrawIface::RHBox* const hbox = new KDcrawIface::RHBox(this); |
|
KIO::NetAccess::del(url, QApplication::activeWindow());
KIO::NetAccess::mkdir(url, QApplication::activeWindow());
KIO::NetAccess::dircopy(srcUrl, dstUrl, QApplication::activeWindow()) |
auto deleteJob = KIO::file_delete(url);
KJobWidgets::setWindow(deleteJob, QApplication::activeWindow());
deleteJob->exec();
auto mkdirJob = KIO::mkdir(url);
KJobWidgets::setWindow(mkdirJob, QApplication::activeWindow());
mkdirJob->exec();
auto dircopyJob = KIO::copy(srcUrl, dstUrl);
KJobWidgets::setWindow(dircopyJob, QApplication::activeWindow());
dircopyJob->exec(); |
|
KD::rename(src, dst) |
QFile::rename(src, dst) |
|
KToolInvocation::invokeBrowser(url) |
QDesktopServices::openUrl(url) |
|
KGlobalSettings::singleClick() |
qApp->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) |
|
KUrl::directory(KUrl::ObeyTrailingSlash) |
QUrl url = adjusted(QUrl::RemoveFilename);
url.adjusted(QUrl::StripTrailingSlash).path() |
|
KImageIO::typeForMime(str) |
QMimeDatabase().mimeTypeForName(str) |
|
KTemporaryFile temp;
temp.setPrefix(prefixStr);
temp.setSuffix(suffixStr); |
QTemporaryFile temp;
temp.setFileTemplate(prefixStr + QLatin1String("XXXXXX") + suffixStr); |
|
K_GLOBAL_STATIC |
Q_GLOBAL_STATIC |
|
KMenu::addTitle() |
QMenu::addSection() |
|
KStandardDirs::locate("data", "file") |
QStandardPaths::locate(QStandardPaths::GenericDataLocation, "file") |
|
KStandardDirs::locateLocal("data", "file") |
QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ QChar('/') + QString("file") |
|
KStandardDirs::locateLocal("appdata", "file") |
QStandardPaths::writableLocation(QStandardPaths::DataLocation)
+ QChar('/') + QString("file") |
|
KStandardDirs::locateLocal("cache", "file") |
QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)
+ QChar('/') + QString("file") |
|
KStandardDirs::locateLocal("tmp", "file") |
QDir::tempPath() + QChar('/') + QString("file") |
|
KStandardDirs::makeDir(path, permission); |
if (!QDir(path).exists())
{
if (QDir().mkpath(path))
{
QFile f(path);
f.setPermissions(permission);
}
} |
permission = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser = 0700 |
KUrlRequester |
KDcrawIface::RFileSelector |
To select local only file or path, no need KUrlRequester. |
KActionMenu |
QMenu |
Use QMenu::menuAction() to get Action instance of menu to plug in action collection. |
KToggleAction |
QAction |
Use QAction::setCheckable(true) to switch Action as toggle state. |
QUrl url;
url.addQueryItem(key, value); |
QUrl url;
QUrlQuery q(url);
q.addQueryItem(key, value);
url.setQuery(q); |
|
QPixmap pix, alphaMask;
pix.setAlphaChannel(mask); |
QPixmap pix, alphaMask;
QPainter p(&pix);
p.setOpacity(0.2);
p.drawPixmap(0, 0, alphaMask);
p.end(); |
Link to documentation to port code
Scripts to port code
Laurent Montel has written scripts to port CMake and C++ code to KF5/Qt5 and remove kdelibs4support dependency. There are available in this repository (see kf5 sub-dir).
Scripts must be applied in this order, with a test compilation between each one :
- Full safe scripts :
- convert-to-k4aboutdata.pl (first one to apply, this help to compile)
- adapt_cmakelists_file.pl (to convert CMake scripts, but code must don't be capititalized)
- remove-kde4support.pl
- convert-kicon.pl
- convert-kmenu.pl
- convert-kshortcut.pl
- convert-kcolordialog.pl
- convert-klistwidget.pl
- convert-kmd5.pl
- convert-kmenubar.pl
- convert-ksplashscreen.pl
- convert-kdebug.pl
- Less safe scripts :
- convert-kintnuminput.pl
- convert-kintspinbox.pl
- convert-ktextbrowser.pl
- convert-kfontcombobox.pl
- Scripts which need to check in-deep all changes :
- convert-kvbox.pl
- convert-kdialog.pl
- convert-kcmdlineargs.pl
- convert-kdebug-with-argument.sh (this one change kDebug(1556) en qCDebug with some info after to convert)
- convert-kmimetype.pl
- Last scripts to apply :
- clean-forward-declaration.sh (remove forward declaration, to do when all compile fine)
- clean-includes.sh (try to remove not used includes, not safe to 100%)
- port_to_autogenerate_export_header.sh (convert to new signal/slot API, not safe to 100%)
digiKam Coding Sprint 2014
The event
It had been almost three years since the last time the digiKam team had an opportunity to meet, talk, code and spend some time together. Gilles Caulier, the lead coordinator, was a victim of a serious car crash two years ago and was thus unable to organize or attend such an event. Now, we finally had an opportunity to meet again. After a lot of effort finding a suitable place and a date where and when all developers could work together under optimal conditions, the digiKam coding sprint 2014 finally took place in Berlin, Germany, between November 14th and 16th 2014.
Before going through what happened during these days, we would like to sincerely thank Digia, the company in charge of Qt development, for hosting the event, and also in particular Tobias Hunger, who welcomed us at Digia's offices located in the South of Berlin.
People participating the sprint (from the left to right) :
- Gilles Caulier from France
- Teemu Rytilahti from Finland
- Shourya Singh Gupta from India
- Marcel Wiesweg from Germany
- Veaceslav Munteanu from Republic of Moldova
- Dmitri Popov (taking the Photo)
Tasks Details
The next major task is to port digiKam to Qt5. Approx. Originally, 10% is already ported by Gilles. Objectives for this coding sprint:
- Specify timeline for porting digiKam
- Identify priorities (what should be ported first)
- Delegate porting tasks to developers (who does what)
A long discussion evolved around these topics. Gilles explained the experience he already gained with this sort of work, which tools are available to facilitate the porting, and where manual work is required. The libraries which are part of the digikam project were prioritized for the port, and tasks assigned.
There were also discussions about the KIPI framework and its plugins. After many years of development, some plugins are essentially unmaintained and no longer needed as there functionality was superseded or moved, so they will not be ported. We also talked about APIs to provide better integration between KIPI and digikam for a task-based framework such as digikam's batch queue manager. The KF5 port seems like the right point in time to integrate binary incompatible, architectural changes.
Shourya Singh Gupta consequentially worked on implementing the KIPI tools functionality in the Batch Queue Manager (Tools Settings). To do this, discussions were done regarding what API changes must be done in core, libkipi and kipi-plugins to be able to develop a generic way to plug kipi-plugins into BQM. By the end of Coding Sprint, he was able to make changes in the API that allowed generic way to plug kipi-plugins' settings widgets into BQM. To testing this, settings widgets of DNGConverter and KioImportExport were plugged into BQM. Later on, he was also able to make changes in the API that would allow background processing of kipi-plugins to be plugged into BQM. To test this, background processing of DNGConverter was successfully plugged into BQM.
Marcel worked on memory consumption in database and several reported memory leaks. As soon as he could reproduce the problems under valgrind, many cleanups were committed. See also https://bugs.kde.org/show_bug.cgi?id=205776.
He also worked to complete the Removable Collection support. The goal is to show thumbnails from disconnected media, without actually having access to the full file. Users can continue to search and preview collections through the database, and thumbnails are shown. A feedback to the user is provided to indicate that items and collection are not available for editing. See bugs https://bugs.kde.org/show_bug.cgi?id=191494 and https://bugs.kde.org/show_bug.cgi?id=114539. This feature was completed during the train ride back from berlin, and committed Sunday evening.
MySQL support is now disabled by default because it's not fully functional and still experimental. MySQL support is still fully available of course, but as an optional feature.
Gilles polished the whole libkgeomap public API to be ready for the KF5 port. A lot of changes have been applied to reduce binary compatibility issues. This is especially needed if a library is to be moved somewhere into KDE core to be more easily reused by other projects. Such a move has recently been performed with libkface to be available for KPhotoAlbum.
Veaceslav worked on porting libkdcraw from old KDE4 Threadweaver api, to new KF5 Threadweaver implementation. Unfortunately, the new api was not quite stable and Gilles decided to port it one more time, to Qt thread pool implementation.
After long days of coding, the tired developers went out in search for food in the quarter around the hotel at Rosenthaler Straße. Sushi on Friday and Vietnamese food on Saturday managed to support the developers for another day of coding.
Final Words
digiKam core 5.0.0 is now ported to 90% on Qt5/KF5 and start to run. Code will switch to beta in a near future to start regression tests an report from end users. However, It still a lots of work especially into kipi-plugins where only 20% of port is only done.
Event photos have been published to this Flickr repository.