Mercurial > retraceit
changeset 0:147b08bc7d64
Initial commit of a basic Application framework.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 23 Mar 2015 12:41:52 +0100 |
parents | |
children | 7a2637c3eb83 |
files | CMakeLists.txt INSTALL cmake/HGVersion.cmake cmake/SvgToPng.cmake src/CMakeLists.txt src/constants.h src/fonts.qrc src/fonts/DejaVuSans.ttf src/l10n/l10n.qrc.in src/l10n/main_de_DE.ts src/main.cpp src/mainwindow.cpp src/mainwindow.h src/strhelp.c src/strhelp.h src/util.h src/util_linux.c src/util_win.c |
diffstat | 18 files changed, 1374 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CMakeLists.txt Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,64 @@ +# Copyright (C) 2014 by Intevation GmbH +# +# This file is Free Software under the GNU GPL (v>=2) +# and comes with ABSOLUTELY NO WARRANTY! +# See LICENSE.txt for details. + +cmake_minimum_required(VERSION 2.8.8) +project(replay-it) + + +### Generic Setup + +#Old qtmain linking behavior to be compatible with cmake versions < 2.8.11 + +if(POLICY CMP0020) + cmake_policy(SET CMP0020 OLD) +endif() + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") + +include(HGVersion) + +if(HG_REVISION) + If(HG_REVISION_DIST STREQUAL "0") + add_definitions(-DIS_TAG_BUILD) + endif() + set(PROJECT_VERSION ${HG_REVISION}) +else() + set(PROJECT_VERSION unknown) +endif() + +add_definitions(-DVERSION="${PROJECT_VERSION}") +add_definitions(-DAPPNAME="${PROJECT_NAME}") + +find_package(Qt5Widgets) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +### Hardening flags + +set(HARDENING_FLAGS " -Wall -s -fstack-protector-all -fno-exceptions") +set(HARDENING_FLAGS " ${HARDENING_FLAGS} -Wstack-protector") +set(HARDENING_FLAGS " ${HARDENING_FLAGS} --param ssp-buffer-size=4") +set(HARDENING_FLAGS " ${HARDENING_FLAGS} -D_FORTIFY_SOURCE=2 -O0") + +if(WIN32) + add_definitions(-D_WIN32_WINNT=0x0600) # Windows vista + add_definitions(-DWINVER=0x0600) + add_definitions(-DUNICODE -D_UNICODE) + add_definitions(-DMINGW_HAS_SECURE_API) # for _s functions +endif(WIN32) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${HARDENING_FLAGS}") + +# Cmake does not correctly identify gcc windres when cross compiling +# making this line neccessary to set the correct flags for it. +# See: http://public.kitware.com/Bug/view.php?id=11773 +SET(CMAKE_RC_COMPILE_OBJECT + "<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -Ocoff <SOURCE> <OBJECT>") + +#add_subdirectory(img) +### Include the actual source directories +add_subdirectory(src)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/INSTALL Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,68 @@ +/** @file INSTALL +@brief Installation Instructions +******************************* + +For Debian based GNU / Linux +============================ +Tested development platform: Ubuntu 14.4 amd64. + +Build dependencies are: + build-essential cmake libqt5core5a qttools5-dev-tools qt5-default \ + qtbase-dev qtbase5-dev-tools qttools5-dev inkscape + + +This document expects the following setup for build and installation. +It is recommended to set a custom installation prefix to avoid root +privileges. + + export CUSTOM_PREFIX=<Prefix of your choice (default /usr)> + mkdir -p $CUSTOM_PREFIX/bin + export PATH=$CUSTOM_PREFIX/bin:$PATH + +Building the Software: + cd <PATH_TO_REPO> + mkdir build-native + cd build-native + cmake .. -DCMAKE_PREFIX_PATH=$CUSTOM_PREFIX + +For Microsoft Windows +===================== +The Windows variant should be cross compiled from a Debian based GNU/Linux +system. The minimum requirement is Debian stable. + +Tested development platform is Ubuntu 14.4 + +Dependencies on the Host system: + + apt-get install git autoconf automake bash bison bzip2 \ + cmake flex gettext git g++ intltool \ + libffi-dev libtool libltdl-dev libssl-dev \ + libxml-parser-perl make openssl patch perl \ + pkg-config scons sed unzip curl xz-utils autopoint \ + gperf + +Build the windows binaries: + + MXEPATH=$CUSTOM_PREFIX/win + git clone https://github.com/Intevation/mxe.git $MXEPATH + cd $MXEPATH + git checkout replay-it + echo "MXE_TARGETS := i686-w64-mingw32.static" > settings.mk + make qtbase + +Add CMAKE_STRIP to the toolchain file: + + echo "set(CMAKE_STRIP $MXEPATH/usr/bin/i686-w64-mingw32.static-strip)" >> \ + "$MXEPATH/usr/i686-w64-mingw32.static/share/cmake/mxe-conf.cmake" + +Compile the software: + + cd repo + mkdir build-windows + cd build-windows + MXETARGET=$MXEPATH/usr/i686-w64-mingw32.static/ + cmake .. \ + -DCMAKE_PREFIX_PATH="$MXETARGET/qt5;$MXETARGET;" \ + -DCMAKE_TOOLCHAIN_FILE="$MXETARGET/share/cmake/mxe-conf.cmake" \ + -DCMAKE_VERBOSE_MAKEFILE=True +*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake/HGVersion.cmake Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,57 @@ +# Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik +# Software engineering by Intevation GmbH +# +# This file is Free Software under the GNU GPL (v>=2) +# and comes with ABSOLUTELY NO WARRANTY! +# See LICENSE.txt for details. + +# This makes some variables available to generate a nice version number for +# hg managed repositories. +# It sets HG_REVISION_TAG to the value of the latest tag +# HG_REVISION_DIST to the differences between the tag and the current tip +# HG_REVISION_ID to the actual revision +# based on code found in the lemon graph library https://lemon.cs.elte.hu +# HG_REVISON to a nice combination of those. +find_package(Hg) +if (HG_FOUND) + EXECUTE_PROCESS( + COMMAND + hg log -r. --template "{latesttag}" + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE HG_REVISION_TAG + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + EXECUTE_PROCESS( + COMMAND + hg log -r. --template "{latesttagdistance}" + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE HG_REVISION_DIST + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + EXECUTE_PROCESS( + COMMAND + hg log -r. --template "{node|short}" + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE HG_REVISION_ID + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + IF(HG_REVISION_TAG STREQUAL "") + SET(HG_REVISION_ID "hg-tip") + ELSE() + IF(HG_REVISION_TAG STREQUAL "null") + SET(HG_REVISION_TAG "trunk") + ELSEIF(HG_REVISION_TAG MATCHES "^r") + STRING(SUBSTRING ${HG_REVISION_TAG} 1 -1 HG_REVISION_TAG) + ENDIF() + IF(HG_REVISION_DIST STREQUAL "0") + SET(HG_REVISION ${HG_REVISION_TAG}) + ELSE() + SET(HG_REVISION + "${HG_REVISION_TAG}+${HG_REVISION_DIST}-${HG_REVISION_ID}") + ENDIF() + ENDIF() +ENDIF()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake/SvgToPng.cmake Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,29 @@ +macro(svg_to_png + file_from + file_to + dpi + size + list_to_add) + +# remove ../'s +get_filename_component(_file_from ${CMAKE_CURRENT_SOURCE_DIR}/${file_from} REALPATH) +get_filename_component(_file_to ${CMAKE_CURRENT_SOURCE_DIR}/${file_to} REALPATH) + +list(APPEND ${list_to_add} ${_file_to}) + +find_program(INKSCAPE_EXE inkscape) +mark_as_advanced(INKSCAPE_EXE) + +if(INKSCAPE_EXE) + add_custom_command( + OUTPUT ${_file_to} + COMMAND ${INKSCAPE_EXE} ${_file_from} --export-width=${size} --export-height=${size} --export-dpi=${dpi} --without-gui --export-png=${_file_to} + DEPENDS ${_file_from} ${INKSCAPE_EXE} + ) +else() + message(WARNING "Inkscape not found, could not re-generate ${_file_to} from ${_file_from}!") +endif() + +unset(_file_from) +unset(_file_to) +endmacro()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/CMakeLists.txt Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,92 @@ +# Copyright (C) 2014 by Intevation GmbH +# +# This file is Free Software under the GNU GPL (v>=2) +# and comes with ABSOLUTELY NO WARRANTY! +# See LICENSE.txt for details. + +include_directories(${Qt5Widgets_INCLUDE_DIRS}) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +add_definitions(${Qt5Widgets_DEFINITIONS}) + +set(APPLICATION_SRC + main.cpp + mainwindow.cpp + strhelp.c + util_win.c + util_linux.c +) + +find_package(Qt5LinguistTools) + +if(UNIX) + # See: https://bugreports.qt-project.org/browse/QTBUG-35918 + # XCB_EXTRA_LIBS should be gotten automatically. + # The following list is taken from the .pri file + get_target_property(_loc Qt5::Widgets LOCATION) + get_filename_component(_qtpath ${_loc} PATH) + + set(XCB_EXTRA_LIBS + -L${_qtpath} + -lQt5DBus -lQt5Gui -lQt5Core -lQt5PlatformSupport + -lX11 -lX11-xcb -lxcb + -lXrender -lSM -lICE -ldbus-1 + -lm -ldl -lrt -lpthread ) + +elseif(WIN32) + set (_add_executable_params WIN32) + + get_target_property(_loc Qt5::Widgets LOCATION) + get_filename_component(_qtpath ${_loc} PATH) + set(WINDOWS_EXTRA_LIBS + -L${_qtpath} + -lwinspool -lshlwapi + -lQt5PlatformSupport -lQt5Gui -lcomdlg32 -loleaut32 -limm32 -lwinmm + -lglu32 -lopengl32 -lgdi32 -lQt5Core -lole32 -lmstask -luuid -lws2_32 + -ladvapi32 -lshell32 -luser32 -lkernel32 -lpcre16 -lz) + + set(EXTRA_STATIC_LIBS Qt5::QWindowsIntegrationPlugin ${WINDOWS_EXTRA_LIBS}) +endif() + +set(QT_RESOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/fonts.qrc + # ${CMAKE_SOURCE_DIR}/img/icons.qrc +) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") +qt5_add_resources(APPLICATION_SRC ${QT_RESOURCES}) + +if(Qt5LinguistTools_FOUND) + + set(FILES_TO_TRANSLATE + ${APPLICATION_SRC} + ) + + # Include translation as a resource + # This works in the source directory to enable the rcc dependencies to be found + # and it also updates the currently available localization. + configure_file(l10n/l10n.qrc.in l10n.qrc) + qt5_add_resources(APPLICATION_SRC ${CMAKE_CURRENT_BINARY_DIR}/l10n.qrc) + qt5_create_translation(TRANSLATION_SRC ${FILES_TO_TRANSLATE} + ${CMAKE_CURRENT_SOURCE_DIR}/l10n/main_de_DE.ts) +endif() + +add_executable(${PROJECT_NAME} + ${_add_executable_params} + # ${IMG_SRC} + ${APPLICATION_SRC} + ${TRANSLATION_SRC} + # ${CMAKE_SOURCE_DIR}/img/icon.rc + ) + + +target_link_libraries(${PROJECT_NAME} + Qt5::Widgets + ${EXTRA_STATIC_LIBS}) + +if (WIN32) + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-municode") +endif(WIN32) + +install(TARGETS ${PROJECT_NAME} DESTINATION bin)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/constants.h Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,56 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H +/* Copyright (C) 2014 by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + +/** @file Common definitions for this project. + * + * This file can be included to pull in common + * definitions in the application. */ + +/**@def The version of the software package. */ +#ifndef VERSION +#define VERSION "0.0.1" +#endif + +/**@def The user visible application name. */ +#ifndef APPNAME +#define APPNAME "undefined" +#endif + +/**@def The user visible organization behind this. */ +#ifndef ORGANIZATION +#define ORGANIZATION "Intevation GmbH" +#endif + +/**@def Short command line description. */ +#define DESCRIPTION "A tool to replay recorded user sessions." + +/**@def Short copyright notice to show users. */ +#define COPYRIGHT "Copyright (C) 2015 Intevation GmbH \n\n" \ + "This file is Free Software under the GNU GPL (v>=2)\n" \ + "and comes with ABSOLUTELY NO WARRANTY!\n" + +/**@def the config key for the last selected root folder. */ +#define ROOT_FOLDER_KEY "RootFolder" + +/**@def the config key for the root folder info pattern. */ +#define ROOT_FOLDER_PATTERN_KEY "RootFolderPattern" + +/**@def the default value for the root folder pattern */ +#define DEFAULT_ROOT_PATTERN "Datum_Fachnummr_Batch-Nr." + +/**@def the config key for the last selected subfolder. */ +#define SUB_FOLDER_KEY "SubFolder" + +/**@def the config key for the sub folder info pattern. */ +#define SUB_FOLDER_PATTERN_KEY "SubFolderPattern" + +/**@def the default value for the root folder pattern */ +#define SUB_FOLDER_PATTERN "IP-Addr_Nethz-Login" + +#endif // CONSTANTS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fonts.qrc Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/fonts"> + <file alias="DejaVuSans.ttf">fonts/DejaVuSans.ttf</file> +</qresource> +</RCC>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/l10n/l10n.qrc.in Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/l10n"> + <file alias="main_de_DE.qm">@CMAKE_CURRENT_BINARY_DIR@/main_de_DE.qm</file> +</qresource> +</RCC>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/l10n/main_de_DE.ts Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="de_DE"> +<context> + <name>MainWindow</name> + <message> + <location filename="../mainwindow.cpp" line="50"/> + <source>Error!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../mainwindow.cpp" line="112"/> + <source>Failed to access directory: '%1'</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>main</name> + <message> + <location filename="../main.cpp" line="145"/> + <source>The folder containing the data to replay.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../main.cpp" line="147"/> + <source>Print debug output.</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.cpp Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,172 @@ +/* Copyright (C) 2014 by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + +/** @file Main entry point for the application. + * + * This file is the wrapper around the qt application. + * Does command line parsing and preparation of the QApplication. + */ +#include "constants.h" + +#include "mainwindow.h" + +#include "strhelp.h" +#include "util.h" + +#include <QApplication> +#include <QCommandLineParser> +#include <QtPlugin> +#include <QDebug> +#include <QTranslator> +#include <QSettings> +#include <QFontDatabase> +#include <QSplashScreen> +#include <QTimer> + +#ifdef Q_OS_WIN + + #include <windows.h> + #include <shlobj.h> + + Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) +#else +/* this is only necessary if we build statically for GNU/Linux */ +// Q_IMPORT_PLUGIN(QXcbIntegrationPlugin) +#endif + +#ifdef IS_TAG_BUILD +bool g_debug = false; +#else +bool g_debug = true; +#endif + +QtMessageHandler g_default_msg_handler = NULL; + +void filterDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + if (!g_debug && type == QtDebugMsg) { + return; + } + + if (g_default_msg_handler) { + (*g_default_msg_handler)(type, context, msg); + } +} + +int realMain(int argc, char **argv); + +#if defined(WIN32) && defined(UNICODE) + +/** @brief Unicode entry point. + * + * Converts arguments to UTF-8 and executes the real + * entry point realMain. + */ +int wmain(int argc, wchar_t **argv, wchar_t **envp) +{ + char **utf8args = NULL; + + utf8args = (char**) xmalloc0 ((argc + 1) * sizeof(char*)); + + for (int i = 0; i < argc; i++) { + utf8args[i] = wchar_to_utf8(argv[i], wcslen(argv[i])); + if (utf8args[i] == NULL) { + printf ("Fatal: could not convert arguments to UTF-8.\n"); + exit(-1); + } + } + int ret = realMain(argc, utf8args); + strv_free(utf8args); + + return ret; +} +#else +int main(int argc, char **argv) +{ + return realMain(argc, argv); +} +#endif + +/** @brief The real entry point to the application. + * + * @param [in] argc the count of the arguments. + * @param [in] argv On GNU/Linux this function expects argv to be in the + * native system encoding. On Windows the arguments + * shall be UTF-8 + * + * @returns 0 on success an error code otherwise. */ +int realMain(int argc, char **argv) +{ + /* QApplication setup */ + QApplication app (argc, argv); + QApplication::setQuitOnLastWindowClosed(true); + QApplication::setOrganizationName(QString::fromLatin1(ORGANIZATION)); + QApplication::setApplicationName(QString::fromLatin1(APPNAME)); + QApplication::setApplicationVersion(QString::fromLatin1(VERSION)); + QSettings::setDefaultFormat(QSettings::IniFormat); + + /* Setup translations */ + QTranslator translator; + if (QLocale::system().name() == "C") { + /* Useful for testing / development as the primary target is german */ + translator.load(":/l10n/main_de_DE"); + } else { + translator.load(":/l10n/main_" + QLocale::system().name()); + } + app.installTranslator(&translator); + + /* Install static fonts */ + + /* The putenv here works around a bug in qt (#29192). Qt thinks it is a fatal + * error if the font directory does not exist. Will be fixed in Qt 5.4 */ + char * inst_dir = get_install_dir(); + if (inst_dir) { + qputenv("QT_QPA_FONTDIR", inst_dir); + xfree(inst_dir); + } + int fontId = QFontDatabase::addApplicationFont(":/fonts/DejaVuSans.ttf"); + if (fontId != -1) + { + QFont font("DejaVuSans"); + font.setPointSize(9); + app.setFont(font); + } + + /* Parse the command line */ + QCommandLineParser parser; + parser.setApplicationDescription(QObject::tr(DESCRIPTION) + "\n" + + QObject::tr(COPYRIGHT)); + parser.addHelpOption(); + + parser.addPositionalArgument("folder", QCoreApplication::translate("main", "The folder containing the data to replay.")); + QCommandLineOption debugOpt(QStringList() << "debug", + QCoreApplication::translate("main", "Print debug output.")); + parser.addOption(debugOpt); + + parser.process(app); + +#ifdef IS_TAG_BUILD + g_debug = parser.isSet(debugOpt); +#else + g_debug = true; +#endif + g_default_msg_handler = qInstallMessageHandler(filterDebugOutput); + + + /* Initialize the main window */ + MainWindow mainWin; + + const QStringList args = parser.positionalArguments(); + if (args.isEmpty() || args.size() > 1) { + parser.showHelp(1); + } + mainWin.setFolder(args.first()); + + mainWin.show(); + + return app.exec(); /* Go event loop */ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mainwindow.cpp Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,117 @@ +/* Copyright (C) 2014 by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + +/** @file See mainwindow.h */ +#include "mainwindow.h" + +#include "constants.h" + +#include <QDebug> +#include <QDialog> +#include <QWidget> +#include <QHBoxLayout> +#include <QLabel> +#include <QPushButton> +#include <QDir> +#include <QFileDialog> +#include <QMessageBox> +#include <QApplication> +#include <QDragEnterEvent> +#include <QDragLeaveEvent> +#include <QDropEvent> +#include <QDragMoveEvent> +#include <QMimeData> +#include <QStandardPaths> +#include <QStyle> +#include <QStatusBar> + +MainWindow::MainWindow() : + mHasValidFolder(false) +{ + setStatusBar(new QStatusBar()); + + setupGUI(); + readSettings(); + setAcceptDrops(true); + //QIcon windowIcon = QIcon(":/icon-64.png"); + //setWindowIcon(windowIcon); + +} + +void MainWindow::setupGUI() +{ +} + +void MainWindow::showErrorMessage(const QString& errMsg) { + QMessageBox::warning(this, tr("Error!"), errMsg); + statusBar()->showMessage(errMsg); +} + +void MainWindow::closeEvent(QCloseEvent *event) { + mSettings.setValue("geometry", saveGeometry()); + mSettings.setValue("windowState", saveState()); + QMainWindow::closeEvent(event); +} + +void MainWindow::readSettings() { + restoreGeometry(mSettings.value("geometry").toByteArray()); + restoreState(mSettings.value("windowState").toByteArray()); +} + +void MainWindow::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasUrls()) { + foreach (const QUrl & url, event->mimeData()->urls()) { + if (url.isLocalFile()) { + event->acceptProposedAction(); + return; + } + } + } +} + +void MainWindow::dragMoveEvent(QDragMoveEvent *event) +{ + if (event->mimeData()->hasUrls()) { + foreach (const QUrl & url, event->mimeData()->urls()) { + if (url.isLocalFile()) { + event->acceptProposedAction(); + return; + } + } + } +} + +void MainWindow::dropEvent(QDropEvent *event) +{ + const QMimeData *mimeData = event->mimeData(); + + if (mimeData->hasUrls()) { + foreach (const QUrl & url, mimeData->urls()) { + if (!url.isLocalFile()) { + qDebug() << "Ignoring drop of " << url; + continue; + } + } + } +} + +void MainWindow::dragLeaveEvent(QDragLeaveEvent *event) +{ + event->accept(); +} + +void MainWindow::setFolder(const QString& folder) +{ + QFileInfo fi(folder); + if (!fi.isDir() || !fi.isReadable()) { + showErrorMessage(tr("Failed to access directory: '%1'").arg(folder)); + } + QDir dir = QDir(folder); + + // TODO; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mainwindow.h Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,58 @@ +/* Copyright (C) 2014 by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + + +/** @file The Main UI class. + * + * Parent class of all dialogs and graphical user interaction. + */ +#include <QMainWindow> +#include <QSettings> + +class QPushButton; +class QDropEvent; +class QDragLeaveEvent; +class QDragMoveEvent; +class QDragEnterEvent; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + +protected: + /** @brief UI setup */ + void setupGUI(); + + /** @brief Cleanup and save the current state */ + virtual void closeEvent(QCloseEvent *event); + + /** @brief Restores the last window state */ + void readSettings(); + + /* The drag drop actions */ + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dragLeaveEvent(QDragLeaveEvent *event); + void dropEvent(QDropEvent *event); + +public slots: + /** @brief set an absolute folder to read a metadata.csv from. */ + void setFolder(const QString &folder); + +protected slots: + /** @brief Show an error dialog to the user. */ + void showErrorMessage(const QString& errMsg); + +private: + QSettings mSettings; + + bool mHasValidFolder; + QString mCurFolder; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/strhelp.c Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,276 @@ +/* Copyright (C) 2014 by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ +/* Needed to get asprintf */ +#define _GNU_SOURCE 1 + +/** @file See strhelp.h for documentation. */ + +#include <ctype.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#ifdef WIN32 +#include <windows.h> +#endif + +static void +out_of_core(void) +{ + fputs("\nfatal: out of memory\n", stderr); + exit(2); +} + +void * +xmalloc( size_t n ) +{ + void *p = malloc( n ); + if( !p ) + out_of_core(); + return p; +} + +void * +xmalloc0( size_t n ) +{ + void *p = malloc( n ); + if( !p ) + out_of_core(); + memset (p, 0, n); + return p; +} + +void * +xrealloc( void *a, size_t n ) +{ + void *p = realloc( a, n ); + if( !p ) + out_of_core(); + return p; +} + +char * +xstrndup( const char *string, const size_t len ) +{ + char *p = xmalloc( len + 1 ); + memcpy( p, string, len ); + p[len] = '\0'; + return p; +} + +unsigned int +strv_length (char **str_array) +{ + unsigned int i = 0; + + if (!str_array) + return 0; + + while (str_array[i]) + ++i; + + return i; +} + +void strv_append (char ***pArray, const char *string, const size_t len) +{ + unsigned int old_len = 0; + + if (!*pArray) + { + *pArray = xmalloc(2 * sizeof(char*)); + (*pArray)[0] = xstrndup(string, len); + (*pArray)[1] = NULL; + return; + } + old_len = strv_length(*pArray); + *pArray = xrealloc(*pArray, sizeof(char**) * (old_len + 2)); + + (*pArray)[old_len] = xstrndup(string, len); + (*pArray)[old_len + 1] = NULL; +} + +void +str_append_str(char **pDst, size_t *dst_len, const char *appendage, const size_t len) +{ + if (!appendage) + return; + + if (!(*pDst)) + { + *pDst = xstrndup(appendage, len); + *dst_len = len; + } + else + { + size_t new_size = (*dst_len) + len + 1; + char *p_old = *pDst; + *pDst = xmalloc(new_size); + strncpy(*pDst, p_old, *dst_len); + strncpy(*pDst + *dst_len, appendage, len); + *dst_len = new_size - 1; + (*pDst)[*dst_len] = '\0'; + free (p_old); + } +} + +void +strv_free (char **str_array) +{ + if (str_array) + { + int i; + + for (i = 0; str_array[i] != NULL; i++) + free (str_array[i]); + + free (str_array); + } +} + +bool +str_equal (char *s1, char *s2) +{ + size_t l1 = strlen(s1); + size_t l2 = strlen(s2); + if ((l1 == l2) && + (strcmp(s1, s2) == 0)) + return true; + else + return false; +} + +bool +str_starts_with (char *s1, char *s2) +{ + size_t l2 = strlen(s2); + if (strncmp(s1, s2, l2) == 0) + return true; + else + return false; +} + +void +str_trim (char **s) +{ + size_t i; + if (*s != NULL) + { + while (isspace(**s)) + (*s)++; + i = strlen(*s); + while (isspace((*s)[--i])) + (*s)[i] = '\0'; + } +} + +void +xfree (void *p) +{ + if (p) + free (p); +} + +int +xasprintf (char **strp, const char *fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = vasprintf(strp, fmt, ap); + va_end(ap); + + if (ret == -1) + out_of_core(); + + return ret; +} + +#ifdef WIN32 +/* Adapted from GPGOL rev. e512053 */ +char * +wchar_to_utf8 (const wchar_t *string, size_t len) +{ + int n, ilen; + char *result; + + ilen = (int) len; + if (ilen < 0) + return NULL; + + /* Note, that CP_UTF8 is not defined in Windows versions earlier + than NT.*/ + n = WideCharToMultiByte (CP_UTF8, 0, string, ilen, NULL, 0, NULL, NULL); + if (n < 0) + return NULL; + + result = xmalloc ((size_t)n+1); + n = WideCharToMultiByte (CP_UTF8, 0, string, ilen, result, n, NULL, NULL); + if (n < 0) + { + xfree (result); + return NULL; + } + result[n] = 0; + return result; +} + +/* Adapted from GPGOL rev. e512053 */ +wchar_t * +utf8_to_wchar (const char *string, size_t len) +{ + int n, ilen; + wchar_t *result; + + ilen = (int) len; + if (ilen < 0) + return NULL; + + n = MultiByteToWideChar (CP_UTF8, 0, string, ilen, NULL, 0); + if (n < 0 || n + 1 < 0) + return NULL; + + result = xmalloc ((size_t)(n+1) * sizeof *result); + n = MultiByteToWideChar (CP_UTF8, 0, string, ilen, result, n); + if (n < 0) + { + xfree (result); + return NULL; + } + result[n] = 0; + return result; +} + +wchar_t +*acp_to_wchar (const char *string, size_t len) +{ + int n, ilen; + wchar_t *result; + + ilen = (int) len; + if (ilen < 0) + return NULL; + + n = MultiByteToWideChar (CP_ACP, 0, string, ilen, NULL, 0); + if (n < 0 || n + 1 < 0) + return NULL; + + result = xmalloc ((size_t)(n+1) * sizeof *result); + n = MultiByteToWideChar (CP_ACP, 0, string, ilen, result, n); + if (n < 0) + { + xfree (result); + return NULL; + } + result[n] = 0; + return result; +} +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/strhelp.h Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,172 @@ +/* Copyright (C) 2014 by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ +#ifndef STRHELP_H +#define STRHELP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdbool.h> +#include <stddef.h> + +/** + * @file strhelp.h + * @brief Helper functions for c strings and memory management + * @details strhelp contains terminating memory allocation functions and + * some conveniance functions to work with c strings or arrays of c + * strings. + */ + +/** @def To avoid that a compiler optimizes certain memset calls away */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +/** @def To avoid that a compiler optimizes certain memset calls away */ +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + + +void *xmalloc( size_t n ); +/** @brief like malloc but initalizes the values with 0 */ +void *xmalloc0( size_t n ); +void *xrealloc( void *a, size_t n ); +void *xcalloc( size_t n, size_t m ); +char *xstrndup( const char *string, const size_t len ); +void xfree ( void *p ); + +/** + * @brief Terminating variant of asprintf + * + * This function behaves exactly like asprintf(3) but will terminate + * when an error occures (usally that means that memoy allocation + * failed). + */ +int xasprintf (char **strp, const char *fmt, ...); + +/** + * @brief Returns the length of the given %NULL-terminated + * string array str_array. + * @param[in] str_array a %NULL-terminated array of strings + * @returns length of str_array. + */ +unsigned int strv_length (char **str_array); + +/** + * @brief append a string to a NULL terminated array of strings. + * + * @param[in,out] pArray pointer to the NULL terminated list of string pointers. + * @param[in] string pointer to the string to append to the list. + * @param[in] len length of the string to append to the list + */ +void strv_append (char ***pArray, const char *string, const size_t len); + +/** + * @brief append a string to another string. + * + * @param[in,out] pDst pointer to the string to be extended. + * @param[in,out] dst_len length of the dst string. Will be modified. + * @param[in] appendage pointer to the string to append. + * @param[in] len length of the string to append. + */ +void str_append_str (char **pDst, size_t *dst_len, const char *appendage, + const size_t len); + +/** + * @brief Frees the given %NULL-terminated string array. + * @param[in,out] str_array a %NULL-terminated array of strings + */ +void strv_free (char **str_array); + +/** + * @brief Checks whether two strings exactly match + * @param[in] s1 the first string + * @param[in] s2 the second string + * @returns true if s1 and s2 are equal + */ +bool str_equal (char *s1, char *s2); + +/** + * @brief Checks whether s2 exactly matches the beginning of s1. + * @param[in] s1 the string who's beginning is searched + * @param[in] s2 the string which is searched for + * @returns true if s1 starts with s2, false otherwise + */ +bool str_starts_with (char *s1, char *s2); + +/** + * @brief Trims all white space from the start and end of string. + * @details the start of the string is trimmed by setting *s to the + * first non white space character. The end is trimmed by setting the + * first character after the last non white space character to \0. + * @param[in,out] s ponter to the string to strip + */ +bool str_trim (char **s); + +/** @brief decode base64 encoded data + * + * The memory allocated for dest needs to be free'd by the + * caller. + * + * _Input warning:_ + * If the input contains invalid base64 characters an error + * is returned. + * + * If the input is invalid base64 but consists of valid + * base64 characters _no error_ is returned and dst contains + * the valid input up to the error. + * + * @param [out] dst Pointer to the destination. Needs to be NULL + * @param [out] dst_size Size allocated for the destination. + * @param [in] src Pointer to the base64 encoded data. + * @param [in] src_size Size of the encoded data. + * + * @returns 0 on success a polarssl error or -1 otherwise + */ +int str_base64_decode(char **dst, size_t *dst_size, char *src, + size_t src_size); + +#ifdef WIN32 + +/** @brief convert a utf8 string to utf16 wchar + * + * @param[in] string utf8 string. Must be at least len characters long. + * @param[in] len number of characters to be converted. + * + * @returns pointer to a newly allocated wchar array. NULL on error. + * + **/ +wchar_t *utf8_to_wchar (const char *string, size_t len); + +/** @brief convert a local 8 bit (acp) string to utf16 wchar + * + * @param[in] string acp string. Must be at least len characters long. + * @param[in] len number of characters to be converted. + * + * @returns pointer to a newly allocated wchar array. NULL on error. + * + **/ +wchar_t *acp_to_wchar (const char *string, size_t len); + +/** @brief convert a utf16 string to utf8 + * + * @param[in] string utf16 string. Must be at least len characters long. + * @param[in] len number of characters to be converted. + * + * @returns pointer to a newly allocated char array. NULL on error. + * + **/ +char *wchar_to_utf8 (const wchar_t *string, size_t len); +#endif + +#ifdef __cplusplus +} +#endif + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/util.h Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,54 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ +#ifndef COMMON_UTIL_H +#define COMMON_UTIL_H +/* @file util.h + * @brief The usual useful stuff that fit nowhere else + */ +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Get the directory in which the current process resides in + * + * Look up the directory in which the current process is placed. + * If the path is longer then MAX_PATH NULL is returned. + * + * Returns a utf-8 encoded string that has to be freed by the caller + * on linux the path is returned as is including the last /. + * + * @returns The directory of the current process + */ +char * get_install_dir(); + +#ifndef WIN32 +/**@def Some value to use as equivalent as MAX_PATH on windows */ +#define MAX_PATH_LINUX 4000 + +/**@brief Get the directory in which the process proc resides in + * + * Look up the directory in which the process proc is placed. + * If the path is longer then MAX_PATH NULL is returned. + * + * Returns a utf-8 encoded string that has to be freed by the caller + * on linux the path is returned as is including the last /. + * + * @param[in] A process id or special name from the proc file system. + * + * @returns The directory of the process + */ +char * get_proc_install_dir(const char *proc); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // COMMON_UTIL_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/util_linux.c Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,70 @@ +#ifndef WIN32 +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + +/**@file Linux implementation of functions declared in util.h */ + +#include "util.h" +#include "string.h" +#include "strhelp.h" +#include "unistd.h" +#include <sys/types.h> +#include <pwd.h> + +char * +get_proc_install_dir(const char *proc) +{ + char *retval = NULL, + *procpath = NULL, + *p = NULL, + buf[MAX_PATH_LINUX]; + ssize_t ret; + size_t path_len = 0; + + if (!proc) + { + return NULL; + } + + xasprintf(&procpath, "/proc/%s/exe", proc); + + ret = readlink (procpath, buf, MAX_PATH_LINUX); + xfree(procpath); + procpath = NULL; + + if (ret <= 0) + { + return NULL; + } + + buf[ret] = '\0'; + + /* cut off the filename */ + p = strrchr (buf, '/'); + if (p == NULL) + { + return NULL; + } + *(p + 1) = '\0'; + + path_len = strlen (buf); + retval = xmalloc (path_len + 1); + strncpy (retval, buf, path_len); + retval[path_len] = '\0'; + + return retval; +} + +char * +get_install_dir() +{ + return get_proc_install_dir("self"); +} + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/util_win.c Mon Mar 23 12:41:52 2015 +0100 @@ -0,0 +1,49 @@ +#ifdef WIN32 +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + +/**@file Linux implementation of functions declared in util.h */ + +#include "util.h" +#include "strhelp.h" + +#include <windows.h> + +char * +get_install_dir() +{ + wchar_t wPath[MAX_PATH]; + char *utf8path = NULL; + char *dirsep = NULL; + + if (!GetModuleFileNameW (NULL, wPath, MAX_PATH - 1)) + { + return NULL; + } + + /* wPath might not be 0 terminated */ + wPath[MAX_PATH - 1] = '\0'; + + utf8path = wchar_to_utf8 (wPath, wcsnlen(wPath, MAX_PATH)); + + if (utf8path == NULL) + { + return NULL; + } + + /* Cut away the executable name */ + dirsep = strrchr(utf8path, '\\'); + if (dirsep == NULL) + { + return NULL; + } + *dirsep = '\0'; + return utf8path; +} +#endif +