Compare commits
14 Commits
v2.0.1
..
6.0_alpha3
| Author | SHA1 | Date | |
|---|---|---|---|
| 10db33e21e | |||
| 78cb2bc641 | |||
| 0c67ad480c | |||
| 141bff5dd3 | |||
| ae8f851b06 | |||
| 65d3f78a14 | |||
| f2fbc7463b | |||
| 91626a9c87 | |||
| 858a70fe82 | |||
| 3200be221c | |||
| 452059cb18 | |||
| c84d96043e | |||
| 3179f447ce | |||
| 9c0c6480e3 |
@@ -1,43 +0,0 @@
|
||||
[Buildset]
|
||||
Number of Builditems=1
|
||||
|
||||
[Buildset][Builditem0]
|
||||
Itemname=KMess
|
||||
Itempath=./
|
||||
Projectname=KMess
|
||||
|
||||
[CMake]
|
||||
BuildDirs=./build
|
||||
CMakeDir=/usr/share/cmake/Modules
|
||||
Current CMake binary=cmake
|
||||
CurrentBuildDir=./build
|
||||
CurrentInstallDir=
|
||||
ProjectRootRelative=./
|
||||
|
||||
[Chat Window debug-Run Options]
|
||||
Arguments=--runtest chatwindow
|
||||
Executable=./build/src/kmess
|
||||
Working Directory=./build/src/
|
||||
|
||||
[Contact List debug-Run Options]
|
||||
Arguments=--runtest contactlist
|
||||
Executable=./build/src/kmess
|
||||
Working Directory=./build/src/
|
||||
|
||||
[Debug-Run Options]
|
||||
Executable=./build/src/kmess
|
||||
|
||||
[MakeBuilder]
|
||||
Abort on First Error=false
|
||||
Number Of Jobs=3
|
||||
Run Multiple Jobs=true
|
||||
|
||||
[Project]
|
||||
VersionControlSupport=kdevsubversion
|
||||
|
||||
[Run Options]
|
||||
Run Targets=Chat Window debug,Contact List debug,Debug
|
||||
|
||||
[Veritas]
|
||||
executables=
|
||||
framework=QTest
|
||||
@@ -28,7 +28,7 @@
|
||||
Mauricio Rother <mauricio@digicomm.com.br>
|
||||
Leonel Freire <leonelfreire@gmail.com>
|
||||
Sergio Rafael Lemke <bedi.com@gmail.com>
|
||||
Maurício Arozi Moraes
|
||||
Morris Arozi Moraes
|
||||
|
||||
Catalan:
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
Jaap Woldringh <jjh.woldringh@planet.nl>
|
||||
Elve <elve@savage-elve.net>
|
||||
Sander Pientka <cumulus0007@gmail.com>
|
||||
Heimen Stoffels <djmusic121@gmail.com>
|
||||
Heimen Stoffels <vistausss@gmail.com>
|
||||
|
||||
Estonian:
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
Lauri Võsandi <v6sa@hotmail.com>
|
||||
Mihkel Tõnnov <mihhkel@gmail.com>
|
||||
Rivo Laks <rivolaks@hot.ee>
|
||||
Timo Tambet <ttambet@gmail.com>
|
||||
|
||||
Finnish:
|
||||
|
||||
@@ -82,6 +83,12 @@
|
||||
Andrea Blankenstijn <darkan9el@gmail.com>
|
||||
Barthe Guillaume <gu_barthe@yahoo.fr>
|
||||
Scias <shining.scias@gmail.com>
|
||||
Grégory Bellier <gregory.bellier@gmail.com>
|
||||
Anthony Rey <gnuk@mailoo.org>
|
||||
|
||||
Galician:
|
||||
|
||||
Indalecio Freiría Santos <ifreiria@gmail.com>
|
||||
|
||||
German:
|
||||
|
||||
@@ -108,7 +115,7 @@
|
||||
|
||||
Japanese:
|
||||
|
||||
Daniel E. Moctezuma <shinsen27@gmail.com>
|
||||
Daniel E. Moctezuma <dmoctezuma@kmess.org>
|
||||
|
||||
Korean:
|
||||
|
||||
@@ -118,6 +125,14 @@
|
||||
|
||||
Øyvind Sæther <oyvind@sather.tk>
|
||||
|
||||
Portuguese:
|
||||
|
||||
Bruno Almeida <bruno.r.almeida@gmail.com>
|
||||
|
||||
Russian:
|
||||
|
||||
Dmitriy Simbiriatin <slpiv@mail.ru>
|
||||
|
||||
Serbian:
|
||||
|
||||
Zoran Milovanović <provalisam@gmail.com>
|
||||
@@ -229,6 +244,17 @@
|
||||
- Emoticon preview in settings page
|
||||
- Clickable contact properties dialog text
|
||||
|
||||
Marco Mentasti <marcomentasti@gmail.com>
|
||||
- Internationalization fixes
|
||||
- Drag'n'drop of images into display pictures
|
||||
|
||||
Francesco Nwokeka
|
||||
- Now Listening toggle button above the contact list.
|
||||
|
||||
Timo Tambet <ttambet@gmail.com>
|
||||
- Contact Changed and Group Changed notifications.
|
||||
- Contact added user dialog tabbing
|
||||
|
||||
KMerlin <http://kmerlin.olsd.de/>
|
||||
- Inspiration and assorted code
|
||||
|
||||
|
||||
+85
-236
@@ -1,251 +1,100 @@
|
||||
PROJECT( kmess )
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(kmess VERSION 6.0.0 LANGUAGES C CXX)
|
||||
|
||||
#### System checks ####
|
||||
find_package(ECM REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_MODULE_PATH}
|
||||
${ECM_MODULE_PATH}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
# To add checks, see in one or more of these paths
|
||||
# /usr/share/cmake/Modules
|
||||
# /usr/share/kde4/apps/cmake/modules
|
||||
# /usr/share/apps/cmake
|
||||
set(BUILD_WITH_QT6 ON CACHE BOOL "Build against Qt 6" FORCE)
|
||||
set(QT_DEFAULT_MAJOR_VERSION 6)
|
||||
|
||||
# Check for cmake, same as minimum for KDE 4.0.0
|
||||
CMAKE_MINIMUM_REQUIRED( VERSION 2.4.5 )
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||
|
||||
# Check for KDE 4
|
||||
FIND_PACKAGE( KDE4 REQUIRED )
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Core5Compat DBus Gui Multimedia Network Test WebEngineWidgets Widgets Xml)
|
||||
find_package(KF6 REQUIRED COMPONENTS
|
||||
Codecs
|
||||
Completion
|
||||
Config
|
||||
ConfigWidgets
|
||||
CoreAddons
|
||||
Crash
|
||||
IdleTime
|
||||
I18n
|
||||
IconThemes
|
||||
KIO
|
||||
Notifications
|
||||
NotifyConfig
|
||||
Parts
|
||||
Service
|
||||
Solid
|
||||
StatusNotifierItem
|
||||
TextWidgets
|
||||
WidgetsAddons
|
||||
WindowSystem
|
||||
Wallet
|
||||
XmlGui
|
||||
)
|
||||
|
||||
# Check for libxml2
|
||||
FIND_PACKAGE( LibXml2 )
|
||||
MACRO_LOG_FEATURE( LIBXML2_FOUND "LibXML2" "Libraries used to develop XML-aware applications" "http://www.xmlsoft.org/" TRUE ""
|
||||
" Required for the chat styles system.
|
||||
* You will need this package and the matching development package: for example, 'kmess' and 'kmess-dev' or 'kmess-devel'.
|
||||
* Usually the package names for this library are:
|
||||
on Ubuntu: 'libxml2' and 'libxml2-dev'
|
||||
on openSUSE: 'libxml2' and 'libxml2-devel'
|
||||
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
|
||||
find_package(LibXml2 REQUIRED)
|
||||
find_package(LibXslt REQUIRED)
|
||||
find_package(GCrypt REQUIRED)
|
||||
|
||||
# Check for libxslt
|
||||
FIND_PACKAGE( LibXslt )
|
||||
MACRO_LOG_FEATURE( LIBXSLT_FOUND "LibXSLT" "A library to transform XML into other formats" "http://www.xmlsoft.org/XSLT" TRUE ""
|
||||
" Required for the chat styles system.
|
||||
* You will need this package and the matching development package: for example, 'kmess' and 'kmess-dev' or 'kmess-devel'.
|
||||
* Usually the package names for this library are:
|
||||
on Ubuntu: 'libxslt' and 'libxslt-dev'
|
||||
on openSUSE: 'libxslt' and 'libxslt-devel'
|
||||
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
|
||||
set(ISFQT_IS_BUNDLED TRUE)
|
||||
set(USE_BUNDLED_LIBRARIES ISFQT)
|
||||
add_subdirectory(contrib/isf-qt)
|
||||
|
||||
# Check for qca2
|
||||
FIND_PACKAGE( QCA2 )
|
||||
MACRO_LOG_FEATURE( QCA2_FOUND "QCA 2" "A cryptographic library written in Qt to access various encryption methods" "http://delta.affinix.com/qca/" TRUE ""
|
||||
" Required for the Windows Live Messenger login process.
|
||||
* You will need this package and the matching development package: for example, 'kmess' and 'kmess-dev' or 'kmess-devel'.
|
||||
* Usually the package names for this library are:
|
||||
on Ubuntu: 'libqca2', 'libqca2-dev' and 'libqca2-plugin-ossl'
|
||||
on openSUSE: 'libqca2' and 'libqca2-devel'
|
||||
on Fedora: 'qca2' and 'qca2-devel'
|
||||
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
|
||||
option(KMESS_DISABLE_LIKEBACK "Disable the old LikeBack feedback UI" ON)
|
||||
if(KMESS_DISABLE_LIKEBACK)
|
||||
set(KMESS_DISABLE_LIKEBACK 1)
|
||||
else()
|
||||
set(KMESS_DISABLE_LIKEBACK 0)
|
||||
endif()
|
||||
|
||||
# As far as I know, it is impossible to find out if the required QCA plugin for OpenSSL is installed:
|
||||
# so we need to ask QCA itself it it's got such a plugin. Pretty darned unportable stuff.
|
||||
IF( QCA2_FOUND )
|
||||
IF( UNIX )
|
||||
EXECUTE_PROCESS( COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check-qca2-ossl.sh OUTPUT_VARIABLE HAS_QCA2_OSSL_PLUGIN )
|
||||
IF( HAS_QCA2_OSSL_PLUGIN EQUAL 1 )
|
||||
SET( QCA2_OSSL_PLUGIN_FOUND TRUE )
|
||||
ELSE( HAS_QCA2_OSSL_PLUGIN EQUAL 1 )
|
||||
SET( QCA2_OSSL_PLUGIN_FOUND FALSE )
|
||||
ENDIF( HAS_QCA2_OSSL_PLUGIN EQUAL 1 )
|
||||
MACRO_LOG_FEATURE( QCA2_OSSL_PLUGIN_FOUND "QCA 2 - OpenSSL Plugin" "OpenSSL interaction library for QCA2" "http://delta.affinix.com/qca/" TRUE ""
|
||||
" Required for the Windows Live Messenger login process.
|
||||
* This package should have been installed along QCA2: if you have QCA2 installed
|
||||
but still see this message, your distribution probably packages it separately.
|
||||
Ubuntu does this, the package name is 'libqca2-plugin-ossl'.
|
||||
* Please refer to the KMess forum for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
|
||||
ELSE( UNIX )
|
||||
# TODO: Find another *portable* way to detect the OSSL plugin.
|
||||
MESSAGE( STATUS "NOTE: The qca2 OpenSSL can't be detected on this platform yet. Make sure you have it installed." )
|
||||
ENDIF( UNIX )
|
||||
ENDIF( QCA2_FOUND )
|
||||
set(KMESS_VERSION "6.0_alpha3")
|
||||
set(KMESS_ENABLE_DEBUG_OUTPUT 0)
|
||||
set(KMESS_BUILT_DEBUGFULL FALSE)
|
||||
set(HAVE_LIBISFQT 1)
|
||||
set(HAVE_NEW_TRAY 1)
|
||||
|
||||
# Check for XScreenSaver extension
|
||||
OPTION( WANT_XSCREENSAVER "Build with X11 screensaver auto-away support" ON )
|
||||
IF( WANT_XSCREENSAVER )
|
||||
MACRO_BOOL_TO_01( X11_Xscreensaver_FOUND HAVE_XSCREENSAVER )
|
||||
MACRO_OPTIONAL_FIND_PACKAGE(X11)
|
||||
IF( X11_FOUND )
|
||||
MACRO_LOG_FEATURE( X11_Xscreensaver_FOUND "XScreenSaver" "X11 extension used to check idle state" "" FALSE ""
|
||||
" Required for the auto-away feature.
|
||||
* Usually the package names for this library are:
|
||||
on Ubuntu: 'libxss-dev'
|
||||
on openSUSE: 'xorg-x11-libs'
|
||||
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
|
||||
ELSE( X11_FOUND )
|
||||
MESSAGE( STATUS "NOTE: The auto-away feature is not supported on this platform yet." )
|
||||
ENDIF( X11_FOUND )
|
||||
ENDIF( WANT_XSCREENSAVER )
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
# Check for libkonq
|
||||
# QUIET is to fix compiling on systems like Debian Lenny, which don't have FindLibKonq.cmake
|
||||
# (for an optional feature, we don't want that to be fatal)
|
||||
MACRO_OPTIONAL_FIND_PACKAGE( LibKonq QUIET )
|
||||
MACRO_LOG_FEATURE( LIBKONQ_FOUND "LibKonq" "Integration with Konqueror context menu" "http://www.kde.org/" FALSE ""
|
||||
" Optional context menu integration with Konqueror.
|
||||
* You will need this package and the matching development package: for example, 'kmess' and 'kmess-dev' or 'kmess-devel'.
|
||||
* Usually the package names for this library are:
|
||||
on Ubuntu: 'libkonq5' and 'libkonq5-dev'
|
||||
on openSUSE: 'libkonq5' and 'libkonq-devel'
|
||||
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
|
||||
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050F00 -DQT_NO_URL_CAST_FROM_STRING)
|
||||
|
||||
# Compatibility variables kept for old subdirectory install rules while the
|
||||
# source tree is being ported away from KDE4-era CMake.
|
||||
set(BIN_INSTALL_DIR ${KDE_INSTALL_BINDIR})
|
||||
set(CONFIG_INSTALL_DIR ${KDE_INSTALL_CONFDIR})
|
||||
set(DATA_INSTALL_DIR ${KDE_INSTALL_DATADIR})
|
||||
set(HTML_INSTALL_DIR ${KDE_INSTALL_DOCBUNDLEDIR})
|
||||
set(ICON_INSTALL_DIR ${KDE_INSTALL_ICONDIR})
|
||||
set(LOCALE_INSTALL_DIR ${KDE_INSTALL_LOCALEDIR})
|
||||
set(PLUGIN_INSTALL_DIR ${KDE_INSTALL_PLUGINDIR})
|
||||
set(SERVICES_INSTALL_DIR ${KDE_INSTALL_KSERVICESDIR})
|
||||
set(SHARE_INSTALL_PREFIX ${KDE_INSTALL_DATADIR})
|
||||
set(SOUND_INSTALL_DIR ${KDE_INSTALL_SOUNDDIR})
|
||||
set(XDG_APPS_INSTALL_DIR ${KDE_INSTALL_APPDIR})
|
||||
|
||||
# Check for libisf-qt
|
||||
MACRO_OPTIONAL_FIND_PACKAGE( IsfQt QUIET )
|
||||
MACRO_LOG_FEATURE( ISFQT_FOUND "LibISF-Qt" "Library to manage Microsoft's Mobile Ink" "http://www.kmess.org/" FALSE ""
|
||||
" Support to send handwriting messages in a format compatible with Windows Live Messenger.
|
||||
In absence of an installed isf-qt version, the bundled version will be compiled.")
|
||||
MACRO_BOOL_TO_01( ISFQT_FOUND HAVE_LIBISFQT ) # For config-kmess.h.in
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/config-kmess.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/config-kmess.h)
|
||||
|
||||
# Display the dependency collection results
|
||||
MACRO_DISPLAY_FEATURE_LOG()
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${LIBXML2_INCLUDE_DIR}
|
||||
${LIBXSLT_INCLUDE_DIR}
|
||||
${GCRYPT_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
||||
|
||||
#### Configure build ####
|
||||
|
||||
INCLUDE( MacroLibrary )
|
||||
INCLUDE( KDE4Defaults )
|
||||
|
||||
IF( NOT ISFQT_FOUND )
|
||||
# isf-qt is not installed on the system.
|
||||
# use the bundled version.
|
||||
SET( ISFQT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/isf-qt/include )
|
||||
SET( ISFQT_LIBRARIES isf-qt )
|
||||
|
||||
SET( USE_BUNDLED_LIBRARIES ${USE_BUNDLED_LIBRARIES} ISFQT )
|
||||
SET( HAVE_LIBISFQT 1 )
|
||||
SET( ISFQT_FOUND TRUE )
|
||||
ENDIF( NOT ISFQT_FOUND )
|
||||
|
||||
ADD_DEFINITIONS( ${QT_DEFINITIONS} ${KDE4_DEFINITIONS} )
|
||||
|
||||
INCLUDE_DIRECTORIES( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} ${LIBXML2_INCLUDE_DIR} )
|
||||
|
||||
|
||||
#### Define the app version number ####
|
||||
|
||||
# Switch between the following two commands to force using a predefined version number
|
||||
# EXECUTE_PROCESS( COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cmake/get-svn-version.sh OUTPUT_VARIABLE KMESS_VERSION )
|
||||
SET( KMESS_VERSION "2.0.1" )
|
||||
|
||||
|
||||
#### Define compiler flags ####
|
||||
|
||||
# Tune the debug build with even more flags
|
||||
# also see FindKDE4Internal.cmake for more defaults
|
||||
IF( CMAKE_COMPILER_IS_GNUCXX )
|
||||
# skipped: -ansi -pendantic -Wfatal-errors -Wold-style-cast -Wconversion
|
||||
SET( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -Wall" )
|
||||
SET( CMAKE_CXX_FLAGS_DEBUGFULL "-O0 -g3 -fno-inline -Wall -Woverloaded-virtual -Wsign-compare -Wundef" )
|
||||
# the -fvisibility option makes symbols also visible to the KDE backtrace dumper, but
|
||||
# the MinGW gcc doesn't seem to understand it well, so only add it if we're not on win32
|
||||
IF( NOT WIN32 )
|
||||
SET( CMAKE_CXX_FLAGS_DEBUGFULL "${CMAKE_CXX_FLAGS_DEBUGFULL} -fvisibility=default" )
|
||||
ENDIF( NOT WIN32 )
|
||||
ENDIF( CMAKE_COMPILER_IS_GNUCXX )
|
||||
|
||||
|
||||
# Define the default build type
|
||||
# Possible values:
|
||||
# - none
|
||||
# - release
|
||||
# - debug
|
||||
# - debugfull (even fewer optimisations)
|
||||
# - relwithdebinfo (release with debug info)
|
||||
# - minsizerel (minsize release)
|
||||
# Uncomment the next line to always force building in full debug mode
|
||||
# SET( CMAKE_BUILD_TYPE debugfull )
|
||||
|
||||
# Enable the KMess debug output when compiling a debug build
|
||||
IF( CMAKE_BUILD_TYPE STREQUAL debugfull OR KMESS_DEBUG_OUTPUT EQUAL 1 )
|
||||
SET( KMESS_ENABLE_DEBUG_OUTPUT "1" )
|
||||
ELSE( CMAKE_BUILD_TYPE STREQUAL debugfull OR KMESS_DEBUG_OUTPUT EQUAL 1 )
|
||||
SET( KMESS_ENABLE_DEBUG_OUTPUT "0" )
|
||||
ENDIF( CMAKE_BUILD_TYPE STREQUAL debugfull OR KMESS_DEBUG_OUTPUT EQUAL 1 )
|
||||
|
||||
|
||||
# Change symbol visibility, to obtain clearer KDE backtraces
|
||||
SET( __KDE_HAVE_GCC_VISIBILITY 0 )
|
||||
|
||||
# Disable LikeBack if not needed
|
||||
IF( KMESS_DISABLE_LIKEBACK EQUAL 1 )
|
||||
SET( KMESS_DISABLE_LIKEBACK "1" )
|
||||
ELSE( KMESS_DISABLE_LIKEBACK EQUAL 1 )
|
||||
SET( KMESS_DISABLE_LIKEBACK "0" )
|
||||
ENDIF( KMESS_DISABLE_LIKEBACK EQUAL 1 )
|
||||
|
||||
# Set a default installation path
|
||||
IF( NOT CMAKE_INSTALL_PREFIX )
|
||||
SET( CMAKE_INSTALL_PREFIX "/usr" )
|
||||
ENDIF( NOT CMAKE_INSTALL_PREFIX )
|
||||
|
||||
IF( CMAKE_USE_CPACK EQUAL 1 )
|
||||
MESSAGE( STATUS "Enabling the CPack package target..." )
|
||||
# source: http://www.vtk.org/Wiki/CMake:Packaging_With_CPack
|
||||
INCLUDE( InstallRequiredSystemLibraries )
|
||||
# the installer will be named ${PACKAGENAME}-{VERSIONMAJOR}.{VERSIONMINOR}.{VERSIONPATCH}-win32.exe.
|
||||
# the installer will say "Welcome to the ${INSTALL_DIRECTORY} Setup Wizard and install to ${INSTALL_DIRECTORY} too, and
|
||||
# put the program in start menu under the ${INSTALL_DIRECTORY} name.
|
||||
# it will ask if ${PACKAGENAME} should be put in PATH.
|
||||
SET( CPACK_PACKAGE_NAME "KMess" )
|
||||
SET( CPACK_PACKAGE_DESCRIPTION_SUMMARY "KMess (package description)" )
|
||||
SET( CPACK_PACKAGE_VENDOR "The KMess team" )
|
||||
SET( CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README" )
|
||||
SET( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING" )
|
||||
SET( CPACK_PACKAGE_VERSION_MAJOR "1" )
|
||||
SET( CPACK_PACKAGE_VERSION_MINOR "0" )
|
||||
SET( CPACK_PACKAGE_VERSION_PATCH "0" )
|
||||
SET( CPACK_PACKAGE_INSTALL_DIRECTORY "KMess" )
|
||||
IF( WIN32 AND NOT UNIX )
|
||||
# There is a bug in NSI that does not handle full unix paths properly. Make
|
||||
# sure there is at least one set of four (4) backslashes.
|
||||
SET( CPACK_GENERATOR "NSIS" )
|
||||
SET( CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/data/icons\\\\hi32-app-kmess.png" )
|
||||
SET( CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\kmess.exe" )
|
||||
SET( CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} KMess (display name)" )
|
||||
SET( CPACK_NSIS_HELP_LINK "http:\\\\\\\\kmess.org" )
|
||||
SET( CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\kmess.org" )
|
||||
SET( CPACK_NSIS_CONTACT "project@kmess.org" )
|
||||
SET( CPACK_NSIS_MODIFY_PATH ON )
|
||||
ELSE( WIN32 AND NOT UNIX )
|
||||
SET( CPACK_STRIP_FILES "bin/kmess" )
|
||||
SET( CPACK_SOURCE_STRIP_FILES "" )
|
||||
ENDIF( WIN32 AND NOT UNIX )
|
||||
|
||||
SET( CPACK_PACKAGE_EXECUTABLES "kmess" "KMess" )
|
||||
INCLUDE( CPack )
|
||||
ENDIF( CMAKE_USE_CPACK EQUAL 1 )
|
||||
|
||||
#### Other settings ####
|
||||
|
||||
# Generate config-kmess.h
|
||||
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/config-kmess.h.in ${CMAKE_CURRENT_BINARY_DIR}/config-kmess.h )
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
|
||||
# continue in directories
|
||||
ADD_SUBDIRECTORY( po )
|
||||
ADD_SUBDIRECTORY( data )
|
||||
ADD_SUBDIRECTORY( doc )
|
||||
ADD_SUBDIRECTORY( src )
|
||||
|
||||
IF( LIBKONQ_FOUND )
|
||||
ADD_SUBDIRECTORY( src/utils/kmess-send )
|
||||
ENDIF( LIBKONQ_FOUND )
|
||||
|
||||
IF( USE_BUNDLED_LIBRARIES MATCHES "ISFQT" )
|
||||
ADD_SUBDIRECTORY( contrib/isf-qt )
|
||||
ENDIF( )
|
||||
|
||||
|
||||
# Also add the tests if compiling in development mode
|
||||
IF( CMAKE_BUILD_TYPE STREQUAL debugfull AND KMESS_DEBUG_OUTPUT EQUAL 1 )
|
||||
ADD_SUBDIRECTORY( tests )
|
||||
ENDIF( CMAKE_BUILD_TYPE STREQUAL debugfull AND KMESS_DEBUG_OUTPUT EQUAL 1 )
|
||||
add_subdirectory(po)
|
||||
add_subdirectory(data)
|
||||
add_subdirectory(src)
|
||||
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -1,3 +1,476 @@
|
||||
--- 2.0.6.2 released ---
|
||||
|
||||
2011-11-26 (Dmoctezuma)
|
||||
* Follow Location redirects, MS seems to have moved some accounts
|
||||
to other servers. (patch by Lekensteyn)
|
||||
|
||||
2011-04-12 (Sjors)
|
||||
* Apply a patch by Francesco Nwokeka, fixing a part of #480 by moving
|
||||
file transfer settings into its own tab in the settings screen.
|
||||
* Include Phonon headers correctly.
|
||||
|
||||
2011-04-10 (Ruben)
|
||||
* Fixed XML for DBus interface
|
||||
|
||||
2011-04-03 (Dmoctezuma)
|
||||
* Updated email address.
|
||||
|
||||
2011-03-14 (Dmoctezuma)
|
||||
* Updated Japanese translation.
|
||||
|
||||
2011-02-27 (Dmoctezuma)
|
||||
* Updated Japanese translation.
|
||||
|
||||
2011-02-25 (Adam)
|
||||
* Fix bug where KMess would fail to build on relwithdebinfo builds when
|
||||
--enable-debug-output was set
|
||||
|
||||
--- 2.0.6.1 released ---
|
||||
|
||||
2011-02-16 (Adam)
|
||||
* Fix yet another login bug caused because our initial profile data no
|
||||
longer includes a language preference.
|
||||
|
||||
--- 2.0.6 released ---
|
||||
|
||||
2011-01-13 (Adam)
|
||||
* Fix bug where KMess couldn't login due to badly formed URL commands.
|
||||
|
||||
2011-01-08 (Valerio)
|
||||
* Fixed crash when taking any action in the Contact Added User dialog.
|
||||
Also removed an unnecessary signal-bouncing slot.
|
||||
* Fixed a dangling pointer issue when the Contact Added User dialog was
|
||||
shown, closed and shown again.
|
||||
|
||||
2011-01-05 (Adam)
|
||||
* Add new widget, FaderWidget, which smoothly fades between the initial view
|
||||
and the contact list. Disable by setting NoFadeEffect to true under the
|
||||
MainWindow section of kmessrc.
|
||||
|
||||
2011-01-02 (Pano)
|
||||
* Merged an updated Japanese translation by Daniel E. Moctezuma.
|
||||
* Merged an updated Spanish translation by Daniel E. Moctezuma.
|
||||
* Merged an updated German translation.
|
||||
|
||||
2010-12-24 (Adam)
|
||||
* Fix retrieval of roaming display picture.
|
||||
|
||||
2010-12-23 (Adam)
|
||||
* Fix a problem where roaming service profile data was invalid.
|
||||
|
||||
2010-12-13 (Valerio)
|
||||
* Fixed "Visit Link" context-menu icon in chat. Thanks to IRC's agostino for the
|
||||
heads-up.
|
||||
|
||||
2010-11-16 (Adam)
|
||||
* (Finally) merged in a modified patch by Timo Tambet that groups all
|
||||
"contact added user" windows as tabs under a single dialog.
|
||||
|
||||
--- 2.0.5 released ---
|
||||
|
||||
2010-10-23 (Valerio)
|
||||
* Added new chats to the log records, no need to logout to see the chat logs of
|
||||
the current session anymore.
|
||||
* Made the HTTP connection timer fix from yesterday to compile with Qt < 4.7.
|
||||
* Fixed building with certain compiler configurations.
|
||||
|
||||
2010-10-22 (Valerio)
|
||||
* Show user's display picture in chat by default.
|
||||
* Fixed HTTP connection timers, now midnight and clock skews don't cause any
|
||||
more the HTTP rate limiter to fail.
|
||||
|
||||
2010-10-16 (Valerio)
|
||||
* Integrated Chat History with the Chat Window:
|
||||
- added a menu item and toolbar action, showing a menu containing the current
|
||||
tab's contacts;
|
||||
- added a context menu entry in the Contacts Panel.
|
||||
* Removed some unused code in ContactFrame.
|
||||
* Fixed logging in with long passwords (17+ characters). The Live servers don't
|
||||
accept those, hehehe.
|
||||
|
||||
2010-10-16 (Adam)
|
||||
* Fix the parsing of offline IM messages.
|
||||
|
||||
2010-09-19 (Adam)
|
||||
* Fix a signal issue in MsnNotificationConnection, thanks Timo Tambet
|
||||
|
||||
2010-09-10 (Pano)
|
||||
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
|
||||
|
||||
2010-09-03 (Adam)
|
||||
* Fix a crash caused when the contacts widget was deleted twice in a chat window.
|
||||
|
||||
2010-09-02 (Sjors)
|
||||
* Add <html> tag to status notification messages so HTML is stripped correctly
|
||||
by knotify.
|
||||
|
||||
2010-08-13 (Pano)
|
||||
* Merged an updated Estonian translation by Timo Tambet.
|
||||
|
||||
2010-08-13 (Pano)
|
||||
* Merged an updated Hungarian translation by József Makay.
|
||||
|
||||
2010-08-11 (Adam)
|
||||
* Merge modified patch by Timo Tambet that gives notifications for address
|
||||
book changes (contact and group changes).
|
||||
|
||||
2010-08-05 (Adam)
|
||||
* Bump version number to 2.0.5dev
|
||||
|
||||
2010-08-05 (Sjors)
|
||||
* Made the SOAP request waiter its own object instead of a QTimer::singleShot
|
||||
because now it can be stopped if logging in fails, fixing a crash.
|
||||
|
||||
2010-08-04 (Pano)
|
||||
* Merged an updated French translation by Anthony Rey.
|
||||
|
||||
--- 2.0.4 released ---
|
||||
|
||||
2010-07-25 (Adam)
|
||||
* Fix ticket #524, thanks to Timo Tambet
|
||||
|
||||
2010-07-24 (Adam)
|
||||
* Properly handle non-messenger Hotmail contacts that appear on our address book.
|
||||
They need to be marked as Messenger users once we add them to our contact list.
|
||||
|
||||
2010-07-23 (Adam)
|
||||
* Add get-git-version.sh script to return the HEAD revision KMess was built with.
|
||||
Removed get-svn-version.sh accordingly.
|
||||
* When adding a contact, the contact type should be "Regular" AFAIK.
|
||||
* Add AddressBookService::removePending to remove a handle from the Pending list.
|
||||
* AddressBookService::getMembershipListUpdate now calls the correct method when
|
||||
deleting a membership.
|
||||
|
||||
2010-07-22 (Valerio)
|
||||
* Fixed the conditions to enable the "Save chat" and "Clear chat" options in the chat view's context menu.
|
||||
|
||||
2010-07-21 (Valerio)
|
||||
* Fixed contact frame tooltips, there were HTML entities exposed.
|
||||
|
||||
2010-07-20 (Pano)
|
||||
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
|
||||
|
||||
2010-07-17 (Adam)
|
||||
* Improve the handling of contacts that are on the address book and
|
||||
the pending list at the same time (shouldn't happen, but it does).
|
||||
* If a user is already on the friend list, don't allow the "add" option
|
||||
to be chosen in ContactAddedUserDialog.
|
||||
* Index all contacts by lower case handle to avoid any casing issues on retrieval.
|
||||
|
||||
2010-07-17 (Adam)
|
||||
* Attempt to solve some of the memory issues on KDE 4.5.
|
||||
|
||||
2010-07-12 (Adam)
|
||||
* Fix contact list background issues on KDE 4.5
|
||||
|
||||
2010-07-10 (Pano)
|
||||
* Merged an updated Japanese translation by Daniel E. Moctezuma.
|
||||
* Merged an updated Brazilian Portuguese translation by Morris Arozi Moraes.
|
||||
|
||||
2010-07-06 (Pano)
|
||||
* Merged an updated French translation by Grégory Bellier.
|
||||
* Merged an updated German translation.
|
||||
|
||||
2010-07-06 (Valerio)
|
||||
* Fixed sending messages only containing whitespace.
|
||||
|
||||
2010-07-05 (Valerio)
|
||||
* Fixed pressing Enter to send a drawing worked even when nothing was in the drawing.
|
||||
|
||||
2010-07-04 (Valerio)
|
||||
* Fixed the ability to drag'n'drop into the message editor a received Ink drawing, and an issue with
|
||||
the Ink editor button when doing so.
|
||||
|
||||
2010-06-29 (Valerio)
|
||||
* Added a class to autonomously manage the chat logs retrieval.
|
||||
* Rewritten the Chat History dialog, now using a calendar to list dates with available chat logs.
|
||||
|
||||
2010-06-27 (Pano)
|
||||
* Merged an updated Traditional Chinese translation by the Tryneeds-Chinese Translation Platform.
|
||||
|
||||
2010-06-27 (Valerio)
|
||||
* Made immutable the display picture size in the contacts dock, to avoid weird picture resizes.
|
||||
* Made the chat history box to respect the "Show the emails of contacts instead of the friendly name" option.
|
||||
* Merged patch by dah_, changing the contact list to be sorted by status, then alphabetically.
|
||||
|
||||
2010-06-27 (Adam)
|
||||
* Add a check to ABService to prevent it recognising memberships for
|
||||
non-passport members. Otherwise when we try to manipulate the memberships
|
||||
for non-passport members we'll get errors since we're not handling them
|
||||
correctly.
|
||||
* Only pop up the "Contact Added User" dialog if a user is on the Pending list.
|
||||
* Fix comments in kmess.notifyrc
|
||||
|
||||
2010-06-26 (Valerio)
|
||||
* Fixed wrong URL when retrieving a display picture from the server.
|
||||
* Changed X11 libraries inclusion to fix building KMess from Fedora 13.
|
||||
|
||||
2010-06-24 (Pano)
|
||||
* Merged an updated Dutch translation by Heimen Stoffels.
|
||||
|
||||
2010-06-20 (Adam)
|
||||
* Fix a i18n bug in the system tray code.
|
||||
|
||||
2010-06-19 (Valerio)
|
||||
* Added support for a new ISF-Qt feature, PNG fortification. This allows users
|
||||
to drag and drop their and their contacts' drawings into the message editor
|
||||
to be edited.
|
||||
|
||||
2010-06-19 (Adam)
|
||||
* Backported the new KDE4 system tray spec. Remains optional for people who
|
||||
are using KDE < 4.3.
|
||||
|
||||
2010-06-13 (Sjors)
|
||||
* Workarounded a documented limitation in KDE4_ADD_APP_ICON() to show the
|
||||
KMess icon correctly.
|
||||
|
||||
2010-06-13 (Pano)
|
||||
* Merged an updated Japanese translation by Daniel E. Moctezuma.
|
||||
|
||||
2010-06-07 (Sjors) (noknotify branch)
|
||||
* Fixed a crash because QSystemTrayIcon was constructed statically before
|
||||
main().
|
||||
* Taught MacNotification class how to play sounds.
|
||||
* Made MacNotification class take some predefined actions on receiving
|
||||
certain events.
|
||||
|
||||
2010-06-03 (Sjors) (noknotify branch)
|
||||
* Added MacNotification class, which currently makes the KMess icon in the
|
||||
Dock 'jump' when its method is called.
|
||||
* Made the NotificationManager use MacNotification instead when doing
|
||||
notifications on the Mac.
|
||||
* Added support to MacNotification class to display Growl messages through
|
||||
QSystemTrayIcon.
|
||||
* Added support to MacNotification for stripping HTML off messages, so they
|
||||
display correctly in Growl.
|
||||
|
||||
2010-05-31 (Adam)
|
||||
* Fix bug in chatwindow.ui: use the global include for IsfInkCanvas.
|
||||
|
||||
2010-05-29 (Pano)
|
||||
* Merged an updated Japanese translation by Daniel E. Moctezuma.
|
||||
|
||||
2010-05-25 (Pano)
|
||||
* Merged an updated Catalan translation by Adrià Arrufat.
|
||||
|
||||
2010-05-13 (Valerio)
|
||||
* Fixed bug which made login to fail when the roaming service gives us a changed display
|
||||
picture before setting the initial status.
|
||||
|
||||
2010-05-08 (Pano)
|
||||
* Merged an updated Dutch translation by Heimen Stoffels.
|
||||
|
||||
2010-05-08 (sifcenter)
|
||||
* Fixed bug on show listening music when the user is busy (maybe also with other states): the bit operation doesn't work
|
||||
if the flags (STATUS_*) have more "1" bits set.
|
||||
|
||||
2010-05-03 (Pano)
|
||||
* Merged an updated Japanese translation by Daniel E. Moctezuma.
|
||||
|
||||
2010-04-25 (Pano)
|
||||
* Merged an updated Japanese translation by Daniel E. Moctezuma.
|
||||
|
||||
2010-04-15 (Pano)
|
||||
* Merged an updated German translation.
|
||||
|
||||
2010-04-02 (Pano)
|
||||
* Merged an updated Dutch translation by Heimen Stoffels.
|
||||
|
||||
2010-04-01 (Pano)
|
||||
* Merged an updated Japanese translation by Daniel E. Moctezuma.
|
||||
|
||||
2010-03-30 (Adam)
|
||||
* Add Francesco Nwokeka to the credits dialog for the Now Playing toggle button.
|
||||
* Workaround a Qt 4.6.1/4.6.2 bug which was causing multiple copies of a single DP to appear in the "set previous
|
||||
display picture" dialog and the contact properties dialog.
|
||||
|
||||
2010-03-28 (Adam)
|
||||
* Bug fix on MPRIS querying - the Identity method is located on the root interface, not the /Player interface.
|
||||
* Reduce the number of debug messages coming out of NowListeningClient. Emits a debug message only when the song changes.
|
||||
* Remove "contact does not have you on their contact list" text from the tool tips.
|
||||
|
||||
2010-03-27 (Adam)
|
||||
* Merge a modified patch by z3r0 from the boards; adds a toggle button for "now listening" to the contact list.
|
||||
* Display the currently playing song above the CL even while appearing offline.
|
||||
* Make the size of the CL DP depend on whether or not music is playing.
|
||||
* Adjust font size of now listening label to match personal message.
|
||||
|
||||
2010-03-17 (Adam)
|
||||
* Fix bug where account properties were not properly updated in some cases.
|
||||
* Fix bug where "Log in Automatically" was not obeyed and saved if it was unchecked after being enabled.
|
||||
* When removing a contact that is already blocked, do not add them to the allow list.
|
||||
|
||||
2010-03-16 (Pano)
|
||||
* Added a Galician translation by Indalecio Freiría Santos.
|
||||
|
||||
2010-03-13 (Adam)
|
||||
* Fix bug where the status was set to "Idle" upon waking up from sleep.
|
||||
* Fix bug where IDL status was kept after disconnection.
|
||||
|
||||
--- 2.0.3 released ---
|
||||
|
||||
2010-03-09 (Pano)
|
||||
* Merged a Russian translation by Dmitriy Simbiriatin.
|
||||
|
||||
2010-03-05 (Pano)
|
||||
* Merged an updated Japanese translation by Daniel E. Moctezuma.
|
||||
* Merged an updated Slovak translation by Rastislav Krupanský.
|
||||
|
||||
2010-03-02 (Pano)
|
||||
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
|
||||
|
||||
2010-03-01 (Pano)
|
||||
* Merged an updated Spanish translation by Mauricio Muñoz Lucero.
|
||||
* Merged an updated Turkish translation by Uğur Çetin.
|
||||
* Merged an updated Portuguese translation by Bruno Almeida.
|
||||
* Merged an updated Estonian translation by Rivo Laks.
|
||||
|
||||
2010-02-28 (Pano)
|
||||
* Merged an updated Greek translation by Dimitrios Glentadakis.
|
||||
|
||||
2010-02-27 (Pano)
|
||||
* Merged an updated German translation.
|
||||
* Merged an updated Catalan translation by Adrià Arrufat.
|
||||
* Merged an updated Brazilian Portuguese translation by Morris Arozi Moraes.
|
||||
* Merged an updated Dutch translation by Heimen Stoffels.
|
||||
|
||||
2010-02-26 (Pano)
|
||||
* Merged an updated French translation by Grégory Bellier.
|
||||
|
||||
2010-02-25 (Pano)
|
||||
* Merged an updated Hungarian translation by Pauli Henrik.
|
||||
|
||||
2010-02-22 (Pano)
|
||||
* Added a Portuguese translation by Bruno Almeida.
|
||||
|
||||
2010-02-21 (Adam)
|
||||
* Bug fix: ink editor was greyed out when changing tabs.
|
||||
|
||||
2010-02-20 (Ruben)
|
||||
* Added DBus methods to get and set a personal message.
|
||||
|
||||
2010-02-20 (Adam)
|
||||
* Backport: fix "contact added user" dialog appearing on next logon after deleting a contact.
|
||||
|
||||
2010-02-19 (Adam)
|
||||
* Disable the reverse list colouring of the CL until we sort out the updating of membership lists.
|
||||
|
||||
2010-02-18 (Adam)
|
||||
* Re-enable the password edit field in AccountSettingsDialog.
|
||||
* Format times in text log files according to KLocale.
|
||||
|
||||
2010-02-16 (Adam)
|
||||
* Fix a bug where the window size was not saved/reloaded properly on chat window close. See the comments
|
||||
in chatwindow.cpp, line 1395 however.
|
||||
|
||||
2010-01-13 (Adam)
|
||||
* Backport: properly update UI when choosing to connect with a different account whilst connection is in progress.
|
||||
|
||||
2010-01-29 (Ruben)
|
||||
* Trunk backport: Added workaround where "last seen" and/or "last message" are in the year 2106.
|
||||
|
||||
2010-01-28 (Pano)
|
||||
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
|
||||
* Merged an updated Dutch translation by Sjors Gielen.
|
||||
|
||||
2010-01-24 (Adam)
|
||||
* New feature: if proxy connection fails, remove proxy details and try again.
|
||||
|
||||
2010-01-24 (Pano)
|
||||
* Added a Russian translation by Dmitriy Simbiriatin.
|
||||
|
||||
2010-01-21 (Ruben)
|
||||
* Improved layout flexibility of the contact properties dialog. (Trunk backport)
|
||||
|
||||
2010-01-20 (Pano)
|
||||
* Merged an updated Brazilian Portuguese translation by Morris Arozi Moraes.
|
||||
|
||||
2010-01-19 (Adam)
|
||||
* Bump copyright years.
|
||||
* Bug fix: correctly parse MSN color information in chat messages.
|
||||
* Bump version to 2.0.3dev.
|
||||
|
||||
2010-01-17 (Adam)
|
||||
* Bug fix: friendly names weren't shown in Ink error messages.
|
||||
* Bug fix: Ink validation failed if there were trailing \r\n characters; trim them out first.
|
||||
* Bug fix: fixed long standing crash that occurred with InvitedContacts and restarted chats.
|
||||
Reported by Ralesk.
|
||||
|
||||
2010-01-16 (Pano)
|
||||
* Merged an updated Greek translation by Dimitrios Glentadakis.
|
||||
|
||||
2010-01-15 (Ruben)
|
||||
* Merged improved patch by Mamadou Gueye, to show email count in systray tooltip.
|
||||
|
||||
2010-01-09 (Pano)
|
||||
* Updated message catalogs (POT and PO files)
|
||||
|
||||
2010-01-08 (sifcenter)
|
||||
* Use the SOAP reply into QDocDocument to indent and print it.
|
||||
* Added a small tooltip for the image in contact properties dialog.
|
||||
|
||||
2010-01-08 (Valerio)
|
||||
* Improved the sizes of the friendly name and personal message labels on the
|
||||
Contact List.
|
||||
* Added a workaround to a KDE bug, requiring the spell checker to be set twice
|
||||
when switching between tabs.
|
||||
|
||||
2010-01-06 (Pano)
|
||||
* Merged an updated French translation by Grégory Bellier.
|
||||
|
||||
2010-01-02 (Valerio)
|
||||
* Merged patch by Mentos, fixing emoticon encoding issues in chat logs.
|
||||
* Merged patch by Mentos, fixing a bug when setting a custom display picture
|
||||
to a contact.
|
||||
* Merged patch by Mentos, which enables dragging and dropping of images
|
||||
into display picture frames.
|
||||
* Fixed issue with empty personal messages on login showing an empty message
|
||||
instead of the default message.
|
||||
|
||||
2009-12-31 (Valerio)
|
||||
* Replaced the contact list friendlyname and PM labels with new labels
|
||||
editable inline by clicking.
|
||||
|
||||
2009-12-29 (Valerio)
|
||||
* Removed code to change the size of the displayed picture in chat.
|
||||
* Merged patch by Mentos, fixing emoticon encoding issues.
|
||||
* Merged patch by ipereira, adding translator details in the pot files.
|
||||
|
||||
2009-12-23 (Adam)
|
||||
* After discussion with Sjors reverted QtWebKit commit. Will be moved into a branch
|
||||
where it can be stabilised before being moved back into trunk or 2.0.x.
|
||||
|
||||
2009-12-23 (Sjors)
|
||||
* Replaced QCA with GCrypt. This makes Mac and Windows builds much, much
|
||||
easier and removes the support hell QCA used to be, because it required
|
||||
OpenSSL plugins and that stuff.
|
||||
|
||||
2009-12-19 (Sjors)
|
||||
* Removed KHTML in favor of QtWebKit. This will help us make Qt-only builds for Windows and Mac.
|
||||
* Also removed KUrl in favor of QUrl, since they are almost the same anyway.
|
||||
|
||||
2009-12-15 (Valerio)
|
||||
* Fixed a meaningless error dialog when logging in with accounts which have
|
||||
added the Messenger official email address to the contact list.
|
||||
|
||||
2009-12-08 (Valerio)
|
||||
* Fixed a crash which occurred when trying to login with the wrong password.
|
||||
|
||||
2009-12-05 (Adam)
|
||||
* Fix a crash bug that can occur when we receive a CHG earlier than we should.
|
||||
|
||||
--- 2.0.2 released ---
|
||||
|
||||
2009-12-04 (Pano)
|
||||
* Merged an updated Japanese translation by Daniel E. Moctezuma.
|
||||
|
||||
2009-12-03 (Sjors)
|
||||
* Fixed a bug introduced just before 2.0.1 release, making it impossible to
|
||||
log in twice in the same KMess run.
|
||||
|
||||
2009-12-02 (Pano)
|
||||
* Merged an updated Brazilian Portuguese translation by Maurício Arozi Moraes.
|
||||
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
|
||||
|
||||
--- 2.0.1 released ---
|
||||
|
||||
@@ -69,7 +542,7 @@
|
||||
|
||||
2009-11-02 (Adam)
|
||||
* Ensure the height of items in the contact list is sufficient to fully
|
||||
display the contact name and PSM (strings got cut off when people used large
|
||||
display the contact name and PSM (strings got cut off when people used large
|
||||
KDE font sizes).
|
||||
* Increase the notification unlock timeout to 10 seconds after the last ILN.
|
||||
* Allow the download/upload buttons in the transfer window to expand to show their
|
||||
@@ -106,14 +579,14 @@
|
||||
* Store display name on roaming service but do not use it for display (in line with WLM).
|
||||
* Remove duplicate "Show Statusbar" from the list of shortcuts.
|
||||
* Fix updating of display picture with the roaming service.
|
||||
* Change keystrokes for scrolling in chat message view - pgdn/pgup = scroll, alt+pgdn/pgup = fast scroll.
|
||||
* Change keystrokes for scrolling in chat message view - pgdn/pgup = scroll, alt+pgdn/pgup = fast scroll.
|
||||
Fixes a clash with the text editor which caused the view to scroll when shift+pg selecting text in the editor.
|
||||
|
||||
2009-10-22 (Adam)
|
||||
* Fix build error introduced in r5567. My bad.
|
||||
* Fix a crash bug that was introduced with a previous fix. Previous fix has been reverted pending better solution.
|
||||
* Improve fix for KDE bug #209960.
|
||||
* Stop writing bad "last seen date" and "last message date" values when saving contact list.
|
||||
* Stop writing bad "last seen date" and "last message date" values when saving contact list.
|
||||
|
||||
2009-10-21 (Adam)
|
||||
* Cache last display names of contacts; works around an issue where the AddressBook service
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = KMess
|
||||
PROJECT_NUMBER = 2.0.1
|
||||
PROJECT_NUMBER = 2.0.6.2
|
||||
OUTPUT_DIRECTORY = ./apidocs
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
KMess Feature list
|
||||
========================
|
||||
- 2.0.3 -
|
||||
Setting your friendly name and personal message by clicking on their labels in the contact list.
|
||||
A display of the unread email count in the system tray tooltip.
|
||||
Ability to change personal message using DBus.
|
||||
|
||||
- 2.0.2 -
|
||||
Enabled drag-and-drop of images into display picture frames.
|
||||
|
||||
- 2.0.1 -
|
||||
Synchronization of friendly names, personal messages and display pictures with Messenger.
|
||||
Support to send screenshots by dragging and dropping them to a chat.
|
||||
@@ -103,4 +111,4 @@ Chats can be configured to show timestamps when contacts send messages.
|
||||
A "compact" chat format can be used to remove extraneous line breaks and reduce the size of the chat.
|
||||
The chat window caption in the taskbar alternates between lower and upper case to inform the user of a received message when the window is not on top.
|
||||
Internationalization support, with translations in: English, Dutch, German, Italian, Portuguese, Spanish, Turkish, Chinese, French, Catalan, Arabic, Korean, Norsk, Thai, Danish, and Estonian
|
||||
There is now a method, though not absolute, to tell if a contact is blocking you. If a chat is started with a contact that appears offline, you will be informed if the contact is offline or online and blocking you.
|
||||
There is now a method, though not absolute, to tell if a contact is blocking you. If a chat is started with a contact that appears offline, you will be informed if the contact is offline or online and blocking you.
|
||||
|
||||
@@ -1,8 +1,125 @@
|
||||
Changes between KMess Git and 2.0.6.2:
|
||||
--------------------------------------
|
||||
|
||||
- None yet
|
||||
|
||||
Changes between KMess 2.0.6.2 and 2.0.6.1:
|
||||
------------------------------------------
|
||||
|
||||
- Follow redirects, fixing connection issue. Thanks to Lekensteyn.
|
||||
- Moved file transfer settings into own tab.
|
||||
- updated Japanese translation by Daniel E. Moctezuma.
|
||||
|
||||
Changes between KMess 2.0.6.1 and 2.0.6:
|
||||
----------------------------------------
|
||||
|
||||
- fix bug where KMess couldn't login due to missing language preference information.
|
||||
|
||||
Changes between KMess 2.0.6 and 2.0.5:
|
||||
--------------------------------------
|
||||
|
||||
- fix bug where KMess couldn't login due to badly formed URL commands.
|
||||
- fixed crash when taking any action in the Contact Added User dialog.
|
||||
- fixed a possible crash when using the Contact Added User dialog.
|
||||
- Added a fading effect when switching between the initial view and the contact list.
|
||||
- fixed retrieval of display pictures from online MSN storage.
|
||||
- fixed a problem where roaming service profile data was invalid.
|
||||
- fixed "Visit Link" context-menu icon in chat. Thanks to IRC's agostino.
|
||||
- improved Contact Added User dialog with tabs. Thanks ti Timo Tambet.
|
||||
- updated Japanese translation by Daniel E. Moctezuma.
|
||||
- updated Spanish translation by Daniel E. Moctezuma.
|
||||
- updated German translation.
|
||||
|
||||
|
||||
Changes between KMess 2.0.5 and 2.0.4:
|
||||
--------------------------------------
|
||||
|
||||
- added Chat History integration with the Chat Window, with a menu item, toolbar
|
||||
action, and a context menu item.
|
||||
- added KDE notifications for contact and group changes (Patch by Timo Tambet).
|
||||
- fixed a crash due to changes by Microsoft in how Offline Messages are sent.
|
||||
- fixed a possible crash during login.
|
||||
- fixed a crash when closing a chat window.
|
||||
- fixed logging in with long passwords (17+ characters). MSN cuts them to 16, hehehe.
|
||||
- removed all HTML from KDE notifications to fix weird text cutting problems.
|
||||
- updated French translation by Anthony Rey.
|
||||
- updated Estonian translation by Timo Tambet.
|
||||
- updated Hungarian translation by József Makay.
|
||||
- updated Traditional Chinese translation by Yen-chou Chen.
|
||||
|
||||
Changes between KMess 2.0.4 and 2.0.3:
|
||||
--------------------------------------
|
||||
|
||||
- added a tip text on the contact list's search bar (Patch by Timo Tambet).
|
||||
- added support for a new ISF-Qt feature, PNG fortification, allowing to drag
|
||||
and drop handwriting drawings into the message editor to be edited.
|
||||
- added support for notifications on the Mac.
|
||||
- added a toggle button for Now Listening to the contact list (Patch by Francesco Nwokeka).
|
||||
- added Galician translation by Indalecio Freiría Santos.
|
||||
- fixed invalid characters in contact frame tooltips.
|
||||
- fixed "Contact Added User" dialog pop-ups, appearing for already added contacts.
|
||||
- fixed the application icon resolution.
|
||||
- fixed log in failure, due to a mismanaged remote display picture reception.
|
||||
- fixed URL when retrieving display pictures from MSN.
|
||||
- fixed saving account properties.
|
||||
- fixed removal and blocking of contacts.
|
||||
- fixed saving the automatic login option.
|
||||
- fixed status changing bugs when disconnecting or waking up from sleep.
|
||||
- improved compatibility with KDE 4.5.
|
||||
- improved the Chat History dialog, now using a calendar to list dates with available chat logs.
|
||||
- improved contact list sorting, now done by status, then alphabetically (Patch by dah_ at the boards).
|
||||
- improved management of unknown contacts.
|
||||
- improved widget sizes and behavior on the contact list.
|
||||
- updated the system tray widget to the new KDE 4.3+ one.
|
||||
- updated Japanese translation by Daniel E. Moctezuma.
|
||||
- updated Dutch translation by Heimen Stoffels.
|
||||
- updated German translation by Panagiotis Papadopoulos.
|
||||
- updated Catalan translation by Adrià Arrufat.
|
||||
- updated Traditional Chinese translation by the Tryneeds-Chinese Translation Platform.
|
||||
- updated French translation by Grégory Bellier.
|
||||
- updated Brazilian Portuguese translation by Morris Arozi Moraes.
|
||||
- updated Traditional Chinese translation by Yen-chou Chen.
|
||||
|
||||
Changes between KMess 2.0.3 and 2.0.2:
|
||||
--------------------------------------
|
||||
- added ability to drag-and-drop images into display picture frames.
|
||||
- added setting friendly name and personal message by clicking on their labels in the contact list.
|
||||
- added Russian translation by Dmitriy Simbiriatin.
|
||||
- added Portuguese translation by Bruno Almeida.
|
||||
- added showing unread email count in the system tray tooltip.
|
||||
- added setting personal message using DBus.
|
||||
- fixed crash when logging in with the wrong password.
|
||||
- fixed bug causing the "Contact Added User" dialog to appear after deleting contacts.
|
||||
- fixed bug causing the chat window size to not be saved under KDE 4.4.
|
||||
- improved performance when drawing complex ink messages.
|
||||
- improved proxy support.
|
||||
- updated French translation by Grégory Bellier.
|
||||
- updated Catalan translation by Adrià Arrufat.
|
||||
- updated German translation by Panagiotis Papadopoulos.
|
||||
- updated Greek translation by Dimitrios Glentadakis.
|
||||
- updated Brazilian Portuguese translation by Morris Arozi Moraes.
|
||||
- updated Traditional Chinese translation by Yen-chou Chen.
|
||||
- updated Dutch translation by Sjors Gielen.
|
||||
- updated Dutch translation by Heimen Stoffels.
|
||||
- updated Hungarian translation by Pauli Henrik.
|
||||
- updated Spanish translation by Mauricio Muñoz Lucero.
|
||||
- updated Turkish translation by Uğur Çetin.
|
||||
- updated Estonian translation by Rivo Laks.
|
||||
- updated Traditional Chinese translation by Yen-chou Chen.
|
||||
- updated Japanese translation by Daniel E. Moctezuma.
|
||||
- updated Slovak translation by Rastislav Krupanský.
|
||||
|
||||
Changes between KMess 2.0.2 and 2.0.1:
|
||||
--------------------------------------
|
||||
- fixed a bug that was introduced just before the release of KMess 2.0.1,
|
||||
making it impossible to login twice in the same KMess session.
|
||||
- updated Japanese translation by Daniel E. Moctezuma.
|
||||
- updated Brazilian Portuguese translation by Maurício Arozi Moraes.
|
||||
|
||||
Changes between KMess 2.0.1 and 2.0:
|
||||
--------------------------------------
|
||||
- added a "Log in automatically" checkbox to the initial view (patch by Camille Begue).
|
||||
- added ability to open the chat history dialog when not connected
|
||||
(patch by Camille Begue).
|
||||
- added ability to open the chat history dialog when not connected (patch by Camille Begue).
|
||||
- added Test Server support.
|
||||
- added shortcut checking of added/edited emoticons for invalid characters.
|
||||
- added usage of smooth pixmap scaling for display pictures in the contact list.
|
||||
@@ -40,7 +157,7 @@ Changes between KMess 2.0.1 and 2.0:
|
||||
- updated Brazilian Portuguese translation by Maurício Arozi Moraes.
|
||||
- updated Catalan translation by Adrià Arrufat.
|
||||
- updated Dutch translation by Sjors Gielen.
|
||||
- updated Estonian translation by Lauri Võsandi, Mihkel Tõnnov and Rivo Laks.
|
||||
- updated Estonian translation by Lauri Võsandi, Mihkel Tõnnov and Rivo Laks.
|
||||
- updated Finnish translation by Marko Mäkilä.
|
||||
- updated French translation by Émeric Dupont.
|
||||
- updated German translation by Panagiotis Papadopoulos.
|
||||
|
||||
@@ -63,6 +63,17 @@ To build a TGZ package for Slackware, run:
|
||||
|
||||
|
||||
|
||||
Licensing
|
||||
=========
|
||||
|
||||
We provide along with KMess some Oxygen icons which are usually bundled with Kopete.
|
||||
They are released under LGPL 3.0 (see http://www.oxygen-icons.org/).
|
||||
See COPYING_ICONS for full license text.
|
||||
|
||||
The remainder of KMess is released under the GPL2+ . See COPYING for full license text.
|
||||
|
||||
|
||||
|
||||
More Information
|
||||
================
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,82 @@
|
||||
# - Try to find GCrypt
|
||||
# Once done this will define
|
||||
#
|
||||
# GCRYPT_FOUND - system has GCrypt
|
||||
# GCRYPT_INCLUDE_DIRS - the GCrypt include directory
|
||||
# GCRYPT_LIBRARIES - Link these to use GCrypt
|
||||
# GCRYPT_DEFINITIONS - Compiler switches required for using GCrypt
|
||||
#
|
||||
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
# Imported into KMess, monday october 19, 2009 by Sjors
|
||||
# reference URL:
|
||||
# http://dev.libssh.org/export/27d25752e93c19d3e6584915bd64b72e43f3afc0/ \
|
||||
# cmake/Modules/FindGCrypt.cmake
|
||||
#
|
||||
|
||||
|
||||
if (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(GCRYPT_FOUND TRUE)
|
||||
else (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
|
||||
find_path(GCRYPT_INCLUDE_DIR
|
||||
NAMES
|
||||
gcrypt.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR)
|
||||
|
||||
find_library(GCRYPT_LIBRARY
|
||||
NAMES
|
||||
gcrypt
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(GCRYPT_LIBRARY)
|
||||
|
||||
if (GCRYPT_LIBRARY)
|
||||
set(GCRYPT_FOUND TRUE CACHE INTERNAL "Wether the gcrypt library has been found" FORCE)
|
||||
endif (GCRYPT_LIBRARY)
|
||||
|
||||
set(GCRYPT_INCLUDE_DIRS
|
||||
${GCRYPT_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (GCRYPT_FOUND)
|
||||
set(GCRYPT_LIBRARIES
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GCRYPT_LIBRARY}
|
||||
)
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
if (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
|
||||
set(GCRYPT_FOUND TRUE)
|
||||
endif (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
|
||||
|
||||
if (GCRYPT_FOUND)
|
||||
if (NOT GCrypt_FIND_QUIETLY)
|
||||
message(STATUS "Found GCrypt: ${GCRYPT_LIBRARIES}")
|
||||
endif (NOT GCrypt_FIND_QUIETLY)
|
||||
else (GCRYPT_FOUND)
|
||||
if (GCrypt_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find GCrypt")
|
||||
endif (GCrypt_FIND_REQUIRED)
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
|
||||
|
||||
endif (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
|
||||
Executable → Regular
@@ -11,6 +11,9 @@
|
||||
/* Define if debug output should be enabled */
|
||||
#define KMESS_DEBUG ${KMESS_ENABLE_DEBUG_OUTPUT}
|
||||
|
||||
/* Define what the build type of KMess is */
|
||||
#cmakedefine KMESS_BUILT_DEBUGFULL ${KMESS_BUILD_DEBUGFULL}
|
||||
|
||||
/* Define the fallback prefix */
|
||||
#define KMESS_PREFIX "${CMAKE_INSTALL_PREFIX}"
|
||||
|
||||
@@ -22,3 +25,6 @@
|
||||
|
||||
/* Define whether Ink support is enabled */
|
||||
#define KMESS_ENABLE_INK ${HAVE_LIBISFQT}
|
||||
|
||||
/* Define whether we have the new system tray */
|
||||
#cmakedefine HAVE_NEW_TRAY
|
||||
|
||||
Executable → Regular
+8
-7
@@ -7,22 +7,23 @@ appver="`egrep 'SET.*KMESS_VERSION' CMakeLists.txt | sed -e 's/.*"\([^"]*\)".*/\
|
||||
date="`date +%Y%m%d`"
|
||||
|
||||
# Make sure we have the right repository
|
||||
if [ ! -f kmess.kdevelop ]; then
|
||||
/bin/echo -n "svn (unknown)"
|
||||
if [ ! -f kmess.kdev4 ]; then
|
||||
/bin/echo -n "git (unknown)"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Display normal version if subversion is not installed
|
||||
if [ ! -x `which svnversion 2>/dev/null` ]; then
|
||||
# Display normal version if git is not installed
|
||||
if [ ! -x `which git 2>/dev/null` ]; then
|
||||
/bin/echo -n "$appver"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Display subversion version if this is a working copy
|
||||
svnver=`LANG=C svnversion`
|
||||
gitname=`LANG=C git describe --all HEAD 2>/dev/null | sed -e 's:^heads/::g'`
|
||||
gitver=`LANG=C git rev-parse --short HEAD 2>/dev/null`
|
||||
|
||||
# see if this is not a repository.
|
||||
if [ "$svnver" = "exported" ]; then
|
||||
if [ -z "$gitver" ]; then
|
||||
if [ -z "$KMESS_VER" ]; then
|
||||
/bin/echo -n "$appver";
|
||||
else
|
||||
@@ -32,4 +33,4 @@ if [ "$svnver" = "exported" ]; then
|
||||
fi
|
||||
|
||||
# display subversion version and date
|
||||
/bin/echo -n "$appver-svn (`svnversion` >= $date)"
|
||||
/bin/echo -n "$appver-git ($gitname@$gitver >= $date)"
|
||||
@@ -54,7 +54,7 @@ DEBUG=0
|
||||
# Globals
|
||||
cd `dirname $0`
|
||||
SRC_DIR="$PWD"
|
||||
KMESS_VER="`./cmake/get-svn-version.sh`"
|
||||
KMESS_VER="`./cmake/get-git-version.sh`"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
# Build files and dirs
|
||||
build*
|
||||
|
||||
# KDevelop and other IDE-specific project files
|
||||
*.kdev*
|
||||
@@ -1,29 +1,44 @@
|
||||
PROJECT( isf-qt )
|
||||
CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )
|
||||
CMAKE_MINIMUM_REQUIRED( VERSION 3.16 )
|
||||
PROJECT( isf-qt LANGUAGES CXX )
|
||||
|
||||
|
||||
#### Main switches ####
|
||||
|
||||
# Define the default build type
|
||||
# Possible values:
|
||||
# - none
|
||||
# - release
|
||||
# - debug
|
||||
# - debugfull (even fewer optimisations)
|
||||
# - relwithdebinfo (release with debug info)
|
||||
# - minsizerel (minimum size release)
|
||||
# Uncomment the next line to force building in full debug mode
|
||||
SET( CMAKE_BUILD_TYPE debugfull )
|
||||
# Bundled mode: you can add Isf-Qt as a subdirectory
|
||||
# of your CMake-based prjoect easily. Just use:
|
||||
# SET( USE_BUNDLED_LIBRARIES ISFQT )
|
||||
# and Isf-Qt will be built and statically linked in your
|
||||
# application, without installing anything
|
||||
IF( ISFQT_IS_BUNDLED OR USE_BUNDLED_LIBRARIES MATCHES "ISFQT" )
|
||||
SET( ISFQT_IS_BUNDLED TRUE )
|
||||
MESSAGE( "-- Will build Isf-Qt in bundled mode." )
|
||||
ELSE()
|
||||
SET( ISFQT_IS_BUNDLED FALSE )
|
||||
ENDIF()
|
||||
|
||||
# Only set the build type if we're not being bundled: if we are, we'll
|
||||
# use the build type specified by the parent project
|
||||
IF( NOT ISFQT_IS_BUNDLED )
|
||||
|
||||
# Define the default build type
|
||||
# Possible values:
|
||||
# - none
|
||||
# - release
|
||||
# - debug
|
||||
# - debugfull (even fewer optimisations)
|
||||
# - relwithdebinfo (release with debug info)
|
||||
# - minsizerel (minimum size release)
|
||||
# Uncomment the next line to force building in full debug mode
|
||||
SET( CMAKE_BUILD_TYPE debugfull )
|
||||
ENDIF()
|
||||
|
||||
# Define the library version number
|
||||
SET( ISFQT_VERSION "0.9" )
|
||||
SET( ISFQT_VERSION "1.0dev" )
|
||||
|
||||
|
||||
#### Inclusions ####
|
||||
|
||||
FIND_PACKAGE( Qt4 REQUIRED )
|
||||
|
||||
ENABLE_TESTING()
|
||||
FIND_PACKAGE( Qt6 REQUIRED COMPONENTS Core Core5Compat Gui Widgets )
|
||||
|
||||
OPTION( WANT_GIF "Enable support for reading and writing Fortified-GIF images" ON )
|
||||
IF( WANT_GIF )
|
||||
@@ -68,13 +83,27 @@ IF( CMAKE_COMPILER_IS_GNUCXX )
|
||||
"-O0 -g3 -fno-inline -Wall -Woverloaded-virtual -Wsign-compare -Wundef -fvisibility=default" )
|
||||
ENDIF( CMAKE_COMPILER_IS_GNUCXX )
|
||||
|
||||
IF( NOT ISFQT_DEBUG_OUTPUT STREQUAL "1" AND NOT ISFQT_DEBUG_OUTPUT STREQUAL "0" )
|
||||
IF( CMAKE_BUILD_TYPE MATCHES debug )
|
||||
SET( ISFQT_DEBUG_OUTPUT 1 )
|
||||
ELSE()
|
||||
SET( ISFQT_DEBUG_OUTPUT 0 )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
||||
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} src include )
|
||||
|
||||
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/isfqtconfig.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/isfqtconfig.h )
|
||||
|
||||
ADD_SUBDIRECTORY( src )
|
||||
ADD_SUBDIRECTORY( tests )
|
||||
|
||||
IF( NOT ISFQT_IS_BUNDLED )
|
||||
ENABLE_TESTING()
|
||||
ADD_SUBDIRECTORY( tests )
|
||||
ENDIF()
|
||||
|
||||
|
||||
#### Project CMake configuration files creation ####
|
||||
@@ -87,14 +116,14 @@ SET( LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib"
|
||||
SET( SHARED_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share"
|
||||
CACHE STRING "Directory where the shared data will be installed" )
|
||||
|
||||
# Prepare the IsfQtConfig.cmake file, which allows other projects to find us
|
||||
# Prepare thej IsfQtConfig.cmake file, which allows other projects to find us
|
||||
CONFIGURE_FILE( cmake/IsfQtConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/IsfQtConfig.cmake" @ONLY )
|
||||
|
||||
|
||||
#### Installation ####
|
||||
|
||||
# Do not install the resources if we're bundling it in KMess
|
||||
IF( NOT USE_BUNDLED_LIBRARIES MATCHES "ISFQT" )
|
||||
# Do not install the resources if we're bundling it into an application
|
||||
IF( NOT ISFQT_IS_BUNDLED )
|
||||
INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/IsfQtConfig.cmake
|
||||
DESTINATION ${LIB_INSTALL_DIR}/isfqt )
|
||||
INSTALL( FILES cmake/FindIsfQt.cmake
|
||||
|
||||
@@ -1,3 +1,40 @@
|
||||
2010-07-23 (Valerio)
|
||||
* Fixed the copy constructor in Stroke, it was not copying all the necessary properties.
|
||||
* Fixed some compiler warnings.
|
||||
* Improved bundled compilation mode.
|
||||
|
||||
2010-07-22 (Valerio)
|
||||
* Improved the InkEdit text - added a checkbox to show the usage of Canvas::isEmpty() and a label
|
||||
to show usage of the Canvas::inkChanged() signal.
|
||||
* Fixed inkChanged() signal emission in Canvas: it was emitted too early, when the drawing was not
|
||||
updated yet: slots connected to inkChanged() could then call isEmpty() and get a true return value,
|
||||
even if the drawing wasn't empty.
|
||||
|
||||
2010-06-27 (Adam)
|
||||
* Use Q_ASSERT_X instead of qWarning where appropriate.
|
||||
|
||||
2010-06-19 (Valerio)
|
||||
* Changed the default behavior of InkCanvas::pixmap(), now paints on a transparent
|
||||
background, instead of a white one.
|
||||
|
||||
2010-06-19 (Valerio)
|
||||
* Added support for PNG fortification. Like GIF fortification, this feature allows to
|
||||
write a PNG containing the full ISF drawing inside itself. Of course, it's now also
|
||||
possible to read a PNG containing ISF data and retrieve the actual drawing.
|
||||
|
||||
2010-03-20 (Adam)
|
||||
* Slight optimisation to painting - we no longer draw the background color, Qt does it for us.
|
||||
Also, only render the parts of the buffer that have changed.
|
||||
|
||||
2010-03-13 (Adam)
|
||||
* Add a bezier curve smoothing algorithm. Strokes with the FitToCurve flag set are
|
||||
rendered with an approximate bezier curve. Gives much smoother looking strokes.
|
||||
|
||||
2010-02-21 (Adam)
|
||||
* Optimise the painting of strokes. Cache logic added to IsfQtDrawing and only
|
||||
strokes that have been added are painted. Also, no longer do a full bounding rect
|
||||
recalculation when a stroke is added.
|
||||
|
||||
2009-10-03 (Adam)
|
||||
* Remove unused HIMETRIC conversion methods.
|
||||
|
||||
|
||||
+20
-3
@@ -5,9 +5,16 @@ About LibISF-Qt:
|
||||
LibISF-Qt is a Qt4 library made to encode and decode Microsoft's
|
||||
Ink Serialized Format (ISF) files.
|
||||
|
||||
Q. What the hell is this?
|
||||
A. It's a library, written in C++/Qt4, to read and write ISF
|
||||
image files.
|
||||
Q. What is ISF?
|
||||
A. Ink Serialized Format is an open specification initially
|
||||
made by Microsoft, and then freed up with their "Open
|
||||
Specification Promise" initiative. ISF is a file format
|
||||
made to store handwriting very efficiently: an ISF file
|
||||
with a somewhat complex handwritten drawing takes less than
|
||||
1000 bytes. ISF supports metrics to adapt drawings to
|
||||
different form factors, bezier smoothing of drawn strokes,
|
||||
coloring, stroke size varying by pen pressure, linking
|
||||
in static data, and more.
|
||||
|
||||
Q. How does this library differ from aMSN's or Emesene's?
|
||||
A. It's written with Qt, which makes it easily portable on
|
||||
@@ -42,6 +49,16 @@ If everything went right again, install it:
|
||||
$ make install
|
||||
Aaand now you're set. :)
|
||||
|
||||
LibISF-Qt natively supports being bundled into other applications.
|
||||
Bundling means that the library does not get installed system-wide
|
||||
along with your application, but instead it gets statically linked
|
||||
into the application.
|
||||
The idea is that you copy the Isf-Qt source tree (with an SVN export
|
||||
or a Git submodule) into your project's tree, and then set up your
|
||||
CMake listfile to add this library as a subdirectory:
|
||||
> SET( ISFQT_IS_BUNDLED TRUE )
|
||||
> ADD_SUBDIRECTORY( contrib/isf-qt )
|
||||
And again, you're done!
|
||||
|
||||
|
||||
Documentation:
|
||||
|
||||
+2
-1
@@ -14,7 +14,7 @@ OUTSTANDING
|
||||
- Read and write user-defined custom tags
|
||||
- Interpret, use and write pressure information
|
||||
- Associating text recognized by OCR to the drawn strokes
|
||||
- Modify strokes
|
||||
- Alter stroke points
|
||||
|
||||
DONE
|
||||
----
|
||||
@@ -38,4 +38,5 @@ DONE
|
||||
- Add new strokes to an IsfDrawing
|
||||
- Stroke attributes: width, colour, pressure
|
||||
- Export IsfDrawing to raw-isf, isf-base64 and fortified-gif
|
||||
- Export IsfDrawing to PNG
|
||||
- Delete strokes
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#define ISFQT_VERSION "${ISFQT_VERSION}"
|
||||
|
||||
// Define if debug output should be enabled
|
||||
#define ISFQT_DEBUG ${ISFQT_DEBUG_OUTPUT}
|
||||
#if ${ISFQT_DEBUG_OUTPUT}
|
||||
#define ISFQT_DEBUG
|
||||
#endif
|
||||
|
||||
// Define if fortified-GIF support is enabled
|
||||
#define ISFQT_GIF_ENABLED ${GIF_ENABLED}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "isfqtstroke.h"
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef ISFQT_QMATRIX_COMPAT_H
|
||||
#define ISFQT_QMATRIX_COMPAT_H
|
||||
|
||||
#include <QTransform>
|
||||
|
||||
using QMatrix = QTransform;
|
||||
|
||||
#endif
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -42,7 +40,7 @@ namespace Isf
|
||||
* @class InkCanvas
|
||||
* @brief This is a control designed for the drawing and display of Ink.
|
||||
*
|
||||
* InkCanvas is used for drawing and displaying Ink. The currently displayed Ink drawing can be retrieved
|
||||
* InkCanvas is used for drawing and displaying Ink. The currently displayed Ink drawing can be retrieved
|
||||
* or set using the drawing() and setDrawing() methods.
|
||||
*
|
||||
* To set the properties of the current pen, use the setPenColor(), setPenSize() and setPenType() methods.
|
||||
@@ -51,7 +49,7 @@ namespace Isf
|
||||
* Example:
|
||||
*
|
||||
* \code
|
||||
* InkCanvas *canvas = new Isf::InkCanvas( this );
|
||||
* InkCanvas* canvas = new Isf::InkCanvas( this );
|
||||
* canvas->setPenColor( Qt::blue );
|
||||
* canvas->setPenSize( 10 );
|
||||
*
|
||||
@@ -62,7 +60,7 @@ namespace Isf
|
||||
* // now an eraser will be used and strokes can be erased individually.
|
||||
* \endcode
|
||||
*
|
||||
* To return the currently displayed Ink as a QImage, use image(). To return the raw ISF data, suitable
|
||||
* To return the currently displayed Ink as a QImage, use image(). To return the raw ISF data, suitable
|
||||
* for saving to disk or sending over a network, use bytes().
|
||||
*
|
||||
* To write the ISF data directly to a QIODevice, such as a file, use the save() method.
|
||||
@@ -94,37 +92,37 @@ namespace Isf
|
||||
};
|
||||
|
||||
public: // public constructors
|
||||
InkCanvas( QWidget *parent = 0 );
|
||||
~InkCanvas();
|
||||
InkCanvas( QWidget* = 0 );
|
||||
~InkCanvas();
|
||||
|
||||
public: // public methods
|
||||
QByteArray bytes();
|
||||
Isf::Drawing *drawing();
|
||||
Isf::Drawing* drawing();
|
||||
QImage image();
|
||||
bool isEmpty();
|
||||
QColor penColor();
|
||||
int penSize();
|
||||
PenType penType();
|
||||
void save( QIODevice &device, bool base64 = false );
|
||||
void setDrawing( Isf::Drawing *drawing );
|
||||
virtual QSize sizeHint() const;
|
||||
void save( QIODevice&, bool = false );
|
||||
void setDrawing( Isf::Drawing* );
|
||||
QSize sizeHint() const override;
|
||||
|
||||
public slots:
|
||||
void clear();
|
||||
void setCanvasColor( QColor newColor );
|
||||
void setPenColor( QColor newColor );
|
||||
void setPenSize( int pixels );
|
||||
void setPenType( PenType type );
|
||||
void setCanvasColor( QColor );
|
||||
void setPenColor( QColor );
|
||||
void setPenSize( int );
|
||||
void setPenType( PenType );
|
||||
|
||||
protected: // protected methods
|
||||
void mousePressEvent( QMouseEvent *event );
|
||||
void mouseMoveEvent( QMouseEvent *event );
|
||||
void mouseReleaseEvent( QMouseEvent *event );
|
||||
void paintEvent( QPaintEvent *event );
|
||||
void resizeEvent( QResizeEvent *event );
|
||||
void mousePressEvent( QMouseEvent* ) override;
|
||||
void mouseMoveEvent( QMouseEvent* ) override;
|
||||
void mouseReleaseEvent( QMouseEvent* ) override;
|
||||
void paintEvent( QPaintEvent* ) override;
|
||||
void resizeEvent( QResizeEvent* ) override;
|
||||
|
||||
private: // private methods
|
||||
void drawLineTo( const QPoint &endPoint );
|
||||
void drawLineTo( const QPoint& );
|
||||
void clearBuffer();
|
||||
void updateCursor();
|
||||
|
||||
@@ -140,7 +138,7 @@ namespace Isf
|
||||
/// It's true if the erase brush was selected
|
||||
bool erasingImage_;
|
||||
/// Current drawing being manipulated
|
||||
Isf::Drawing *drawing_;
|
||||
Isf::Drawing* drawing_;
|
||||
/// Initial drawing, can be overridden with drawing_
|
||||
Isf::Drawing initialDrawing_;
|
||||
/// Last point where the mouse pointer was released
|
||||
@@ -152,7 +150,7 @@ namespace Isf
|
||||
/// Pen type
|
||||
PenType penType_;
|
||||
/// The current stroke being drawn
|
||||
Isf::Stroke *currentStroke_;
|
||||
Isf::Stroke* currentStroke_;
|
||||
/// The pixmap buffer where in progress strokes are drawn
|
||||
QPixmap bufferPixmap_;
|
||||
/// Cache pixmap so the Ink isn't redrawn on every mouse move
|
||||
@@ -161,7 +159,7 @@ namespace Isf
|
||||
bool drawingDirty_;
|
||||
|
||||
signals:
|
||||
/// Emitted when the ink representation is modified (stroke drawn,
|
||||
/// Emitted when the ink representation is modified (stroke drawn,
|
||||
/// stroke deleted, current drawing changed).
|
||||
void inkChanged();
|
||||
};
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -41,6 +39,7 @@ namespace Isf
|
||||
{
|
||||
// Forward declarations
|
||||
class Drawing;
|
||||
class StreamData;
|
||||
|
||||
|
||||
|
||||
@@ -137,8 +136,8 @@ namespace Isf
|
||||
, IsHighlighter = 0x0100 ///< This stroke is an highlighter stroke
|
||||
, IsRectangle = 0x0200 ///< Meaning unknown
|
||||
};
|
||||
Q_DECLARE_FLAGS( StrokeFlags, StrokeFlag )
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( StrokeFlags )
|
||||
Q_DECLARE_FLAGS( StrokeFlags, StrokeFlag );
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( StrokeFlags );
|
||||
|
||||
|
||||
|
||||
@@ -183,6 +182,14 @@ namespace Isf
|
||||
, resolution( vResolution )
|
||||
{
|
||||
}
|
||||
/// Quick comparison operator
|
||||
bool operator ==( const Metric& other )
|
||||
{
|
||||
return min == other.min
|
||||
&& max == other.max
|
||||
&& units == other.units
|
||||
&& resolution == other.resolution;
|
||||
}
|
||||
|
||||
/// Minimum value
|
||||
qint64 min;
|
||||
@@ -232,52 +239,6 @@ namespace Isf
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Drawing attributes for points.
|
||||
*/
|
||||
struct AttributeSet
|
||||
{
|
||||
/// Constructor
|
||||
AttributeSet()
|
||||
: color( Qt::black )
|
||||
, flags( 0x10 ) // Meaning unknown
|
||||
, penSize( 8.f, 8.f ) // Default pen is 8.0 pixels wide
|
||||
{
|
||||
}
|
||||
|
||||
/// The stroke color, optionally with alpha channel
|
||||
QColor color;
|
||||
/// Mask of StrokeFlags, @see StrokeFlags
|
||||
StrokeFlags flags;
|
||||
/// Dimensions of the pencil in pixels
|
||||
QSizeF penSize;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Drawing attributes for strokes.
|
||||
*/
|
||||
struct StrokeInfo
|
||||
{
|
||||
/// Constructor
|
||||
StrokeInfo()
|
||||
: hasPressureData( false )
|
||||
, hasXData( true )
|
||||
, hasYData( true )
|
||||
{
|
||||
}
|
||||
|
||||
/// Whether the stroke contains pressure info or not
|
||||
bool hasPressureData;
|
||||
/// Whether the stroke contains X coordinates or not
|
||||
bool hasXData;
|
||||
/// Whether the stroke contains Y coordinates or not
|
||||
bool hasYData;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A single point within a stroke.
|
||||
*/
|
||||
@@ -290,17 +251,23 @@ namespace Isf
|
||||
{
|
||||
}
|
||||
/// Constructor with point only
|
||||
Point( const QPoint &point )
|
||||
Point( const QPoint& point )
|
||||
: position( point )
|
||||
, pressureLevel( 0 )
|
||||
{
|
||||
}
|
||||
/// Constructor with point and pressure
|
||||
Point( const QPoint &point, const qint64 pressure )
|
||||
Point( const QPoint& point, const qint64 pressure )
|
||||
: position( point )
|
||||
, pressureLevel( pressure )
|
||||
{
|
||||
}
|
||||
/// Quick comparison operator
|
||||
bool operator ==( const Point& other )
|
||||
{
|
||||
return position == other.position
|
||||
&& pressureLevel == other.pressureLevel;
|
||||
}
|
||||
|
||||
/// coordinates
|
||||
QPoint position;
|
||||
@@ -311,32 +278,9 @@ namespace Isf
|
||||
|
||||
|
||||
/**
|
||||
* A pen stroke.
|
||||
* A list of Point items.
|
||||
*/
|
||||
struct Stroke
|
||||
{
|
||||
/// Constructor
|
||||
Stroke()
|
||||
: attributes( 0 )
|
||||
, info( 0 )
|
||||
, metrics( 0 )
|
||||
, transform( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
/// Bounding rectangle of this stroke
|
||||
QRect boundingRect;
|
||||
/// Link to the attributes of this stroke's points, if any
|
||||
AttributeSet *attributes;
|
||||
/// Link to this stroke's attributes, if any
|
||||
StrokeInfo *info;
|
||||
/// Link to this stroke's metrics, if any
|
||||
Metrics *metrics;
|
||||
/// List of points
|
||||
QList<Point> points;
|
||||
/// Link to this stroke's transformation, if any
|
||||
QMatrix *transform;
|
||||
};
|
||||
typedef QList<Point> PointList;
|
||||
|
||||
|
||||
|
||||
@@ -359,12 +303,16 @@ namespace Isf
|
||||
|
||||
public: // Public static methods
|
||||
|
||||
static Drawing &reader( const QByteArray &isfData, bool decodeFromBase64 = false );
|
||||
static Drawing &readerGif( const QByteArray &gifRawBytes, bool decodeFromBase64 = false );
|
||||
static Drawing &reader( const QByteArray&, bool = false );
|
||||
static Drawing &readerGif( const QByteArray&, bool = false );
|
||||
static Drawing &readerPng( const QByteArray&, bool = false );
|
||||
static bool supportsGif();
|
||||
static QByteArray writer( const Drawing &drawing, bool encodeToBase64 = false );
|
||||
static QByteArray writerGif( const Drawing &drawing, bool encodeToBase64 = false );
|
||||
static QByteArray writer( const Drawing&, bool = false );
|
||||
static QByteArray writerGif( const Drawing&, bool = false );
|
||||
static QByteArray writerPng( const Drawing&, bool = false );
|
||||
|
||||
private: // Private static properties
|
||||
static StreamData* streamData_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -27,16 +25,20 @@
|
||||
#define ISFQTDRAWING_H
|
||||
|
||||
#include <IsfQt>
|
||||
#include <IsfQtStroke>
|
||||
|
||||
#include <QMap>
|
||||
#include <QMatrix>
|
||||
#include <QPaintDevice>
|
||||
#include <QUuid>
|
||||
#include <QPixmap>
|
||||
|
||||
|
||||
// Forward declarations
|
||||
class QByteArray;
|
||||
|
||||
class AttributeSet;
|
||||
|
||||
|
||||
|
||||
namespace Isf
|
||||
@@ -64,58 +66,45 @@ namespace Isf
|
||||
|
||||
public: // public constructors
|
||||
Drawing();
|
||||
Drawing( const Drawing &other );
|
||||
Drawing( const Drawing& );
|
||||
~Drawing();
|
||||
|
||||
public: // public state retrieval methods
|
||||
AttributeSet *attributeSet( quint32 index );
|
||||
const QList<AttributeSet*> attributeSets();
|
||||
QRect boundingRect();
|
||||
QRect boundingRect() const;
|
||||
void clear();
|
||||
IsfError error() const;
|
||||
qint32 indexOfStroke( const Stroke* ) const;
|
||||
bool isEmpty() const;
|
||||
bool isNull() const;
|
||||
QPixmap pixmap( const QColor backgroundColor = Qt::white );
|
||||
QSize size();
|
||||
Stroke *stroke( quint32 index );
|
||||
Stroke *strokeAtPoint( const QPoint &point );
|
||||
QPixmap pixmap( const QColor = Qt::transparent );
|
||||
void setBoundingRect( QRect );
|
||||
QSize size() const;
|
||||
Stroke* stroke( quint32 );
|
||||
Stroke* strokeAtPoint( const QPoint& );
|
||||
const QList<Stroke*> strokes();
|
||||
QMatrix *transform( quint32 index );
|
||||
const QList<QMatrix*> transforms();
|
||||
|
||||
public: // public manipulation methods
|
||||
qint32 addAttributeSet( AttributeSet *newAttributeSet );
|
||||
qint32 addStroke( Stroke *newStroke );
|
||||
qint32 addTransform( QMatrix *newTransform );
|
||||
bool deleteAttributeSet( quint32 index );
|
||||
bool deleteStroke( quint32 index );
|
||||
bool deleteStroke( Stroke *stroke ) ;
|
||||
bool deleteTransform( quint32 index );
|
||||
bool setCurrentAttributeSet( AttributeSet *attributeSet );
|
||||
bool setCurrentTransform( QMatrix *transform );
|
||||
qint32 addStroke( Stroke* );
|
||||
qint32 addStroke( PointList = PointList() );
|
||||
bool deleteStroke( quint32 );
|
||||
bool deleteStroke( Stroke* );
|
||||
|
||||
private:
|
||||
void updateBoundingRect();
|
||||
|
||||
private: // Private properties
|
||||
/// List of attributes of the points in the drawing
|
||||
QList<AttributeSet*> attributeSets_;
|
||||
/// Bounding rectangle of the drawing
|
||||
QRect boundingRect_;
|
||||
/// Cached bounding rectangle
|
||||
QRect cacheRect_;
|
||||
/// The cached pixmap
|
||||
QPixmap cachePixmap_;
|
||||
/// Virtual drawing canvas dimensions
|
||||
QRect canvas_;
|
||||
/// Link to the currently used metric data
|
||||
Metrics *currentMetrics_;
|
||||
/// Link to the currently used point info data
|
||||
AttributeSet *currentAttributeSet_;
|
||||
/// Link to the currently used stroke info data
|
||||
StrokeInfo *currentStrokeInfo_;
|
||||
/// Link to the currently used transformation
|
||||
QMatrix *currentTransform_;
|
||||
/// Link to the default metric data
|
||||
Metrics defaultMetrics_;
|
||||
/// Link to the default point info data
|
||||
AttributeSet defaultAttributeSet_;
|
||||
/// Link to the default stroke info data
|
||||
StrokeInfo defaultStrokeInfo_;
|
||||
/// Link to the default transformation
|
||||
QMatrix defaultTransform_;
|
||||
/// A list of strokes that need to be repainted.
|
||||
QList<Stroke*> changedStrokes_;
|
||||
/// Is the drawing dirty? i.e, requires repainting?
|
||||
bool dirty_;
|
||||
/// Last parsing error (if there is one)
|
||||
IsfError error_;
|
||||
/// List of registered GUIDs
|
||||
@@ -130,16 +119,8 @@ namespace Isf
|
||||
quint64 maxGuid_;
|
||||
/// Maximum thickness of the strokes
|
||||
QSizeF maxPenSize_;
|
||||
/// List of metrics used in the drawing
|
||||
QList<Metrics*> metrics_;
|
||||
/// Pixel size of the drawing
|
||||
QSize size_;
|
||||
/// List of information about the drawing's strokes
|
||||
QList<StrokeInfo*> strokeInfo_;
|
||||
/// List of strokes composing this drawing
|
||||
QList<Stroke*> strokes_;
|
||||
/// Transformation matrices
|
||||
QList<QMatrix*> transforms_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2010 by Valerio Pilo *
|
||||
* valerio@kmess.org *
|
||||
* *
|
||||
* Copyright (C) 2010 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef ISFQTSTROKE_H
|
||||
#define ISFQTSTROKE_H
|
||||
|
||||
#include <IsfQt>
|
||||
|
||||
#include <QColor>
|
||||
#include <QList>
|
||||
#include <QMatrix>
|
||||
#include <QRect>
|
||||
#include <QSizeF>
|
||||
|
||||
|
||||
// Forward declarations
|
||||
class QPainterPath;
|
||||
|
||||
|
||||
|
||||
namespace Isf
|
||||
{
|
||||
|
||||
|
||||
|
||||
// Forward declarations
|
||||
class AttributeSet;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A pen stroke.
|
||||
*/
|
||||
class Stroke
|
||||
{
|
||||
public:
|
||||
Stroke();
|
||||
Stroke( const Stroke& );
|
||||
~Stroke();
|
||||
|
||||
void addPoint( Point );
|
||||
void addPoints( PointList );
|
||||
QRect boundingRect() const;
|
||||
QColor color() const;
|
||||
void finalize();
|
||||
StrokeFlags flags() const;
|
||||
bool hasPressureData() const;
|
||||
Metrics* metrics();
|
||||
QPainterPath painterPath();
|
||||
QSizeF penSize() const;
|
||||
PointList& points();
|
||||
void setColor( QColor );
|
||||
void setFlag( StrokeFlag, bool = true );
|
||||
void setFlags( StrokeFlags );
|
||||
void setMetrics( Metrics* );
|
||||
void setPenSize( QSizeF );
|
||||
void setTransform( QMatrix* );
|
||||
QMatrix* transform();
|
||||
|
||||
private:
|
||||
void bezierCalculateControlPoints();
|
||||
void bezierGetFirstControlPoints( double[], double*, int );
|
||||
|
||||
private:
|
||||
/// Bezier data
|
||||
QList<QPointF> bezierControlPoints1_;
|
||||
QList<QPointF> bezierControlPoints2_;
|
||||
QList<QPointF> bezierKnots_;
|
||||
/// Bounding rectangle of this stroke
|
||||
QRect boundingRect_;
|
||||
/// The stroke color, optionally with alpha channel
|
||||
QColor color_;
|
||||
/// Whether the stroke data needs to be analyzed or not
|
||||
bool finalized_;
|
||||
/// Mask of StrokeFlags, @see StrokeFlags
|
||||
StrokeFlags flags_;
|
||||
/// Whether the stroke contains pressure information or not
|
||||
bool hasPressureData_;
|
||||
/// Link to this stroke's metrics, if any
|
||||
Metrics* metrics_;
|
||||
/// Dimensions of the pencil in pixels
|
||||
QSizeF penSize_;
|
||||
/// List of points
|
||||
PointList points_;
|
||||
/// Link to this stroke's transformation, if any
|
||||
QMatrix* transform_;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}; // namespace Isf
|
||||
|
||||
|
||||
|
||||
#endif // ISFQTSTROKE_H
|
||||
@@ -14,20 +14,25 @@ SET( ISFQT_SOURCES
|
||||
tagswriter.cpp
|
||||
isfqt.cpp
|
||||
isfinkcanvas.cpp
|
||||
isfqtstroke.cpp
|
||||
)
|
||||
|
||||
SET( ISFQT_PUBLIC_HEADERS
|
||||
../include/isfqt.h
|
||||
../include/isfqtdrawing.h
|
||||
../include/isfinkcanvas.h
|
||||
../include/IsfQt
|
||||
../include/isfqtstroke.h
|
||||
../include/IsfQtDrawing
|
||||
../include/IsfInkCanvas
|
||||
../include/IsfQtStroke
|
||||
../include/IsfQt
|
||||
)
|
||||
|
||||
SET( ISFQT_LIBS
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
Qt6::Core
|
||||
Qt6::Core5Compat
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
SET( ISFQT_RCCS
|
||||
@@ -42,17 +47,17 @@ ENDIF( GIF_FOUND )
|
||||
|
||||
#### Compilation ####
|
||||
|
||||
QT4_WRAP_CPP( MOC_SRCS ../include/isfinkcanvas.h )
|
||||
QT6_WRAP_CPP( MOC_SRCS ../include/isfinkcanvas.h )
|
||||
|
||||
QT4_ADD_RESOURCES( ISFQT_RCC_SRCS ${ISFQT_RCCS} )
|
||||
QT6_ADD_RESOURCES( ISFQT_RCC_SRCS ${ISFQT_RCCS} )
|
||||
|
||||
INCLUDE_DIRECTORIES( ${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
|
||||
# Do not install the library if we're bundling it in KMess
|
||||
IF( NOT USE_BUNDLED_LIBRARIES MATCHES "ISFQT" )
|
||||
ADD_LIBRARY( isf-qt SHARED ${ISFQT_SOURCES} ${MOC_SRCS} ${ISFQT_RCC_SRCS} )
|
||||
ELSE()
|
||||
# Do not install the library if we're bundling it into an application
|
||||
IF( ISFQT_IS_BUNDLED )
|
||||
ADD_LIBRARY( isf-qt STATIC ${ISFQT_SOURCES} ${MOC_SRCS} ${ISFQT_RCC_SRCS} )
|
||||
ELSE()
|
||||
ADD_LIBRARY( isf-qt SHARED ${ISFQT_SOURCES} ${MOC_SRCS} ${ISFQT_RCC_SRCS} )
|
||||
ENDIF()
|
||||
|
||||
TARGET_LINK_LIBRARIES( isf-qt ${ISFQT_LIBS} )
|
||||
@@ -64,7 +69,7 @@ SET_TARGET_PROPERTIES( isf-qt PROPERTIES
|
||||
#### Installation ####
|
||||
|
||||
# Do not install the library if we're bundling it in KMess
|
||||
IF( NOT USE_BUNDLED_LIBRARIES MATCHES "ISFQT" )
|
||||
IF( NOT ISFQT_IS_BUNDLED )
|
||||
INSTALL( TARGETS isf-qt LIBRARY
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" )
|
||||
INSTALL( FILES ${ISFQT_PUBLIC_HEADERS}
|
||||
|
||||
@@ -36,7 +36,7 @@ using namespace Isf::Compress;
|
||||
* @param data Data to analyze
|
||||
* @return Block size
|
||||
*/
|
||||
quint8 BitPackingAlgorithm::blockSize( const QList<qint64> &data )
|
||||
quint8 BitPackingAlgorithm::blockSize( const QList<qint64>& data )
|
||||
{
|
||||
quint8 blockSize = 0;
|
||||
qint64 num;
|
||||
@@ -78,7 +78,7 @@ quint8 BitPackingAlgorithm::blockSize( const QList<qint64> &data )
|
||||
* @param source List of values to compress
|
||||
* @return bool
|
||||
*/
|
||||
bool BitPackingAlgorithm::deflate( QByteArray &encodedData, quint8 blockSize, const QList<qint64> &source )
|
||||
bool BitPackingAlgorithm::deflate( QByteArray& encodedData, quint8 blockSize, const QList<qint64>& source )
|
||||
{
|
||||
if( blockSize > 64 )
|
||||
{
|
||||
@@ -158,7 +158,7 @@ bool BitPackingAlgorithm::deflate( QByteArray &encodedData, quint8 blockSize, co
|
||||
* @param decodedData List where to place decompressed values
|
||||
* @return bool
|
||||
*/
|
||||
bool BitPackingAlgorithm::inflate( DataSource &source, quint64 length, quint8 blockSize, QList<qint64> &decodedData )
|
||||
bool BitPackingAlgorithm::inflate( DataSource* source, quint64 length, quint8 blockSize, QList<qint64>& decodedData )
|
||||
{
|
||||
if( blockSize > 64 )
|
||||
{
|
||||
@@ -166,7 +166,7 @@ bool BitPackingAlgorithm::inflate( DataSource &source, quint64 length, quint8 bl
|
||||
blockSize = 64; // Fuck it :P
|
||||
}
|
||||
|
||||
if( source.atEnd() )
|
||||
if( source->atEnd() )
|
||||
{
|
||||
qWarning() << "Cannot inflate: no more bits available!";
|
||||
return true;
|
||||
@@ -178,7 +178,7 @@ bool BitPackingAlgorithm::inflate( DataSource &source, quint64 length, quint8 bl
|
||||
|
||||
while( index++ < length )
|
||||
{
|
||||
value = source.getBits( blockSize );
|
||||
value = source->getBits( blockSize );
|
||||
|
||||
// If the mask matches, the sign bit is set, so ORing value and mask will
|
||||
// set all leftmost bits to 1, making it a real 64bit signed integer
|
||||
|
||||
@@ -32,9 +32,9 @@ namespace Isf
|
||||
namespace BitPackingAlgorithm
|
||||
{
|
||||
|
||||
quint8 blockSize( const QList<qint64> &data );
|
||||
bool deflate( QByteArray &encodedData, quint8 blockSize, const QList<qint64> &source );
|
||||
bool inflate( DataSource &source, quint64 length, quint8 blockSize, QList<qint64> &decodedData );
|
||||
quint8 blockSize( const QList<qint64>& data );
|
||||
bool deflate( QByteArray& encodedData, quint8 blockSize, const QList<qint64>& source );
|
||||
bool inflate( DataSource* source, quint64 length, quint8 blockSize, QList<qint64>& decodedData );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ using namespace Isf::Compress;
|
||||
* @param data Data to analyze
|
||||
* @return Index value
|
||||
*/
|
||||
quint8 BitPackingByteAlgorithm::index( const QList<qint64> &data )
|
||||
quint8 BitPackingByteAlgorithm::index( const QList<qint64>& data )
|
||||
{
|
||||
Q_UNUSED( data );
|
||||
|
||||
@@ -78,7 +78,7 @@ quint8 BitPackingByteAlgorithm::index( const QList<qint64> &data )
|
||||
* @param source List of values to compress
|
||||
* @return bool
|
||||
*/
|
||||
bool BitPackingByteAlgorithm::deflate( QByteArray &encodedData, quint8 index, const QList<qint64> &source )
|
||||
bool BitPackingByteAlgorithm::deflate( QByteArray& encodedData, quint8 index, const QList<qint64>& source )
|
||||
{
|
||||
Q_UNUSED( encodedData );
|
||||
Q_UNUSED( index );
|
||||
@@ -163,7 +163,7 @@ bool BitPackingByteAlgorithm::deflate( QByteArray &encodedData, quint8 index, co
|
||||
* @param decodedData List where to place decompressed values
|
||||
* @return bool
|
||||
*/
|
||||
bool BitPackingByteAlgorithm::inflate( DataSource &source, quint64 length, quint8 index, QList<qint64> &decodedData )
|
||||
bool BitPackingByteAlgorithm::inflate( DataSource* source, quint64 length, quint8 index, QList<qint64>& decodedData )
|
||||
{
|
||||
if( index > 24 )
|
||||
{
|
||||
@@ -171,7 +171,7 @@ bool BitPackingByteAlgorithm::inflate( DataSource &source, quint64 length, quint
|
||||
index = 24; // Fuck it :P
|
||||
}
|
||||
|
||||
if( source.atEnd() )
|
||||
if( source->atEnd() )
|
||||
{
|
||||
qWarning() << "Cannot inflate: no more bits available!";
|
||||
return true;
|
||||
@@ -185,7 +185,7 @@ bool BitPackingByteAlgorithm::inflate( DataSource &source, quint64 length, quint
|
||||
quint64 pos = 0;
|
||||
while( pos++ < count )
|
||||
{
|
||||
quint8 byte = source.getBits( cBits, &ok );
|
||||
quint8 byte = source->getBits( cBits, &ok );
|
||||
|
||||
if( ! ok )
|
||||
{
|
||||
|
||||
@@ -32,9 +32,9 @@ namespace Isf
|
||||
namespace BitPackingByteAlgorithm
|
||||
{
|
||||
|
||||
quint8 index( const QList<qint64> &data );
|
||||
bool deflate( QByteArray &encodedData, quint8 index, const QList<qint64> &source );
|
||||
bool inflate( DataSource &source, quint64 length, quint8 index, QList<qint64> &decodedData );
|
||||
quint8 index( const QList<qint64>& data );
|
||||
bool deflate( QByteArray& encodedData, quint8 index, const QList<qint64>& source );
|
||||
bool inflate( DataSource* source, quint64 length, quint8 index, QList<qint64>& decodedData );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ using namespace Isf::Compress;
|
||||
* @param data Data to transform - the list will be modified.
|
||||
* @return bool
|
||||
*/
|
||||
bool Delta::transform( QList<qint64> &data )
|
||||
bool Delta::transform( QList<qint64>& data )
|
||||
{
|
||||
qint64 currentDelta = 0;
|
||||
qint64 previousDelta = 0;
|
||||
@@ -57,7 +57,7 @@ bool Delta::transform( QList<qint64> &data )
|
||||
* @param data Data to transform - the list will be modified.
|
||||
* @return bool
|
||||
*/
|
||||
bool Delta::inverseTransform( QList<qint64> &data )
|
||||
bool Delta::inverseTransform( QList<qint64>& data )
|
||||
{
|
||||
qint64 currentDelta = 0;
|
||||
qint64 previousDelta = 0;
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace Isf
|
||||
namespace Delta
|
||||
{
|
||||
|
||||
bool transform( QList<qint64> &data );
|
||||
bool inverseTransform( QList<qint64> &data );
|
||||
bool transform( QList<qint64>& data );
|
||||
bool inverseTransform( QList<qint64>& data );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ const int huffmanBases_[HUFFMAN_BASES_NUM][HUFFMAN_BASE_SIZE] =
|
||||
* @param data Data to analyze
|
||||
* @return index value
|
||||
*/
|
||||
quint8 HuffmanAlgorithm::index( const QList<qint64> &data )
|
||||
quint8 HuffmanAlgorithm::index( const QList<qint64>& data )
|
||||
{
|
||||
quint8 index = 0;
|
||||
|
||||
@@ -88,14 +88,14 @@ quint8 HuffmanAlgorithm::index( const QList<qint64> &data )
|
||||
* @param source List of values to compress
|
||||
* @return bool
|
||||
*/
|
||||
bool HuffmanAlgorithm::deflate( QByteArray &encodedData, quint8 index, const QList<qint64> &source )
|
||||
bool HuffmanAlgorithm::deflate( QByteArray& encodedData, quint8 index, const QList<qint64>& source )
|
||||
{
|
||||
DataSource output( encodedData );
|
||||
output.skipToNextByte();
|
||||
|
||||
foreach( quint64 value, source )
|
||||
{
|
||||
if( ! deflateValue( output, index, value ) )
|
||||
if( ! deflateValue( &output, index, value ) )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Deflating failure for value:" << value;
|
||||
@@ -121,7 +121,7 @@ bool HuffmanAlgorithm::deflate( QByteArray &encodedData, quint8 index, const QLi
|
||||
* @param value Value to compress
|
||||
* @return bool
|
||||
*/
|
||||
bool HuffmanAlgorithm::deflateValue( DataSource &output, quint8 index, qint64 value )
|
||||
bool HuffmanAlgorithm::deflateValue( DataSource* output, quint8 index, qint64 value )
|
||||
{
|
||||
qint64 temp = value;
|
||||
quint8 requiredBits = 0;
|
||||
@@ -182,8 +182,8 @@ bool HuffmanAlgorithm::deflateValue( DataSource &output, quint8 index, qint64 va
|
||||
}
|
||||
|
||||
// Add the bits to the data source
|
||||
output.append( bits );
|
||||
output.append( valueBits );
|
||||
output->append( bits );
|
||||
output->append( valueBits );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -199,7 +199,7 @@ bool HuffmanAlgorithm::deflateValue( DataSource &output, quint8 index, qint64 va
|
||||
* @param decodedData List where to place decompressed values
|
||||
* @return bool
|
||||
*/
|
||||
bool HuffmanAlgorithm::inflate( DataSource &source, quint64 length, quint8 index, QList<qint64> &decodedData )
|
||||
bool HuffmanAlgorithm::inflate( DataSource* source, quint64 length, quint8 index, QList<qint64>& decodedData )
|
||||
{
|
||||
QVector<int> huffmanBases;
|
||||
QVector<int> bitAmounts( HUFFMAN_BASE_SIZE );
|
||||
@@ -238,7 +238,7 @@ bool HuffmanAlgorithm::inflate( DataSource &source, quint64 length, quint8 index
|
||||
|
||||
while( (uint)decodedData.length() < length )
|
||||
{
|
||||
bit = source.getBit();
|
||||
bit = source->getBit();
|
||||
|
||||
if( bit )
|
||||
{
|
||||
@@ -252,7 +252,7 @@ bool HuffmanAlgorithm::inflate( DataSource &source, quint64 length, quint8 index
|
||||
}
|
||||
else if( count < (uint)bitAmounts.size() )
|
||||
{
|
||||
quint64 offset = source.getBits( bitAmounts[ count ] );
|
||||
quint64 offset = source->getBits( bitAmounts[ count ] );
|
||||
bool sign = offset & 0x1;
|
||||
offset /= 2;
|
||||
value = huffmanBases[ count ] + offset;
|
||||
|
||||
@@ -32,13 +32,13 @@ namespace Isf
|
||||
namespace HuffmanAlgorithm
|
||||
{
|
||||
|
||||
bool deflate( QByteArray &encodedData, quint8 index, const QList<qint64> &source );
|
||||
bool inflate( DataSource &source, quint64 length, quint8 index, QList<qint64> &decodedData );
|
||||
quint8 index( const QList<qint64> &data );
|
||||
bool deflate( QByteArray& encodedData, quint8 index, const QList<qint64>& source );
|
||||
bool inflate( DataSource* source, quint64 length, quint8 index, QList<qint64>& decodedData );
|
||||
quint8 index( const QList<qint64>& data );
|
||||
|
||||
// Internal use methods
|
||||
|
||||
bool deflateValue( DataSource &output, quint8 index, qint64 value );
|
||||
bool deflateValue( DataSource* output, quint8 index, qint64 value );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@ using namespace Isf;
|
||||
* @param decodedData List where to store the decoded values
|
||||
* @return bool
|
||||
*/
|
||||
bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint64> &decodedData )
|
||||
bool Compress::inflatePacketData( DataSource* source, quint64 length, QList<qint64>& decodedData )
|
||||
{
|
||||
if( source.atEnd() )
|
||||
if( source->atEnd() )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qWarning() << "Source was at end!";
|
||||
@@ -52,8 +52,8 @@ bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result;
|
||||
uchar byte = source.getByte();
|
||||
bool result = false;
|
||||
uchar byte = source->getByte();
|
||||
qint16 algorithm = ( byte & AlgorithmMask );
|
||||
quint8 algorithmData = 0;
|
||||
|
||||
@@ -68,7 +68,7 @@ bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint
|
||||
* We need an ISF stream with such a characteristic to be sure.
|
||||
*/
|
||||
qWarning() << "Unknown decompression method!";
|
||||
qDebug() << "[Information - type: best, byte:" << QString::number( source.getByte(), 16 ) << "hex]";
|
||||
qDebug() << "[Information - type: best, byte:" << QString::number( source->getByte(), 16 ) << "hex]";
|
||||
return false;
|
||||
}
|
||||
// Use the "default compression" algorithm, which is Huffman
|
||||
@@ -137,15 +137,15 @@ bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint
|
||||
qDebug() << "[Information - type: unknown, byte:" << QString::number( byte, 16 ) << "hex]";
|
||||
|
||||
// Go back to the previous read position
|
||||
source.seekRelative( -1 );
|
||||
source->seekRelative( -1 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Discard any partially read bytes
|
||||
if( ! source.atEnd() )
|
||||
if( ! source->atEnd() )
|
||||
{
|
||||
source.skipToNextByte();
|
||||
source->skipToNextByte();
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -163,7 +163,7 @@ bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint
|
||||
* @param source List of values to compress
|
||||
* @return bool
|
||||
*/
|
||||
bool Compress::deflatePacketData( QByteArray &encodedData, const QList<qint64> &source )
|
||||
bool Compress::deflatePacketData( QByteArray& encodedData, const QList<qint64>& source )
|
||||
{
|
||||
bool result;
|
||||
|
||||
@@ -244,9 +244,9 @@ bool Compress::deflatePacketData( QByteArray &encodedData, const QList<qint64> &
|
||||
* @param decodedData List where to store the decoded values
|
||||
* @return bool
|
||||
*/
|
||||
bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qint64> &decodedData )
|
||||
bool Compress::inflatePropertyData( DataSource* source, quint64 length, QList<qint64>& decodedData )
|
||||
{
|
||||
if( source.atEnd() )
|
||||
if( source->atEnd() )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qWarning() << "Source was at end!";
|
||||
@@ -255,7 +255,7 @@ bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qi
|
||||
}
|
||||
|
||||
bool result;
|
||||
quint8 byte = source.getByte();
|
||||
quint8 byte = source->getByte();
|
||||
qint16 algorithm = ( byte & AlgorithmMask );
|
||||
quint8 algorithmData = 0;
|
||||
|
||||
@@ -270,7 +270,7 @@ bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qi
|
||||
* We need an ISF stream with such a characteristic to be sure.
|
||||
*/
|
||||
qWarning() << "Unknown decompression method!";
|
||||
qDebug() << "[Information - type: default, byte:" << QString::number( source.getByte(), 16 ) << "hex]";
|
||||
qDebug() << "[Information - type: default, byte:" << QString::number( source->getByte(), 16 ) << "hex]";
|
||||
return false;
|
||||
}
|
||||
// Use the "best compression" algorithm, which is Huffman
|
||||
@@ -379,15 +379,15 @@ bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qi
|
||||
qDebug() << "[Information - type: unknown, byte:" << QString::number( byte, 16 ) << "hex]";
|
||||
|
||||
// Go back to the previous read position
|
||||
source.seekRelative( -1 );
|
||||
source->seekRelative( -1 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Discard any partially read bytes
|
||||
if( ! source.atEnd() )
|
||||
if( ! source->atEnd() )
|
||||
{
|
||||
source.skipToNextByte();
|
||||
source->skipToNextByte();
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -406,7 +406,7 @@ bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qi
|
||||
* @param source List of values to compress
|
||||
* @return bool
|
||||
*/
|
||||
bool Compress::deflatePropertyData( QByteArray &encodedData, const QList<qint64> &source )
|
||||
bool Compress::deflatePropertyData( QByteArray& encodedData, const QList<qint64>& source )
|
||||
{
|
||||
Q_UNUSED( encodedData );
|
||||
Q_UNUSED( source );
|
||||
|
||||
@@ -112,11 +112,11 @@ namespace Isf
|
||||
};
|
||||
|
||||
|
||||
bool inflatePacketData( DataSource &source, quint64 length, QList<qint64> &decodedData );
|
||||
bool deflatePacketData( QByteArray &destination, const QList<qint64> &decodedData );
|
||||
bool inflatePacketData( DataSource* source, quint64 length, QList<qint64>& decodedData );
|
||||
bool deflatePacketData( QByteArray& destination, const QList<qint64>& decodedData );
|
||||
|
||||
bool inflatePropertyData( DataSource &source, quint64 length, QList<qint64> &decodedData );
|
||||
bool deflatePropertyData( QByteArray &destination, const QList<qint64> &decodedData );
|
||||
bool inflatePropertyData( DataSource* source, quint64 length, QList<qint64>& decodedData );
|
||||
bool deflatePropertyData( QByteArray& destination, const QList<qint64>& decodedData );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -29,7 +27,7 @@
|
||||
|
||||
|
||||
using namespace Isf;
|
||||
using namespace Compress;
|
||||
using namespace Isf::Compress;
|
||||
|
||||
|
||||
|
||||
@@ -51,7 +49,7 @@ DataSource::DataSource()
|
||||
*
|
||||
* @param data Byte array to copy and use as data source
|
||||
*/
|
||||
DataSource::DataSource( const QByteArray &data )
|
||||
DataSource::DataSource( const QByteArray& data )
|
||||
: currentBitIndex_( 8 )
|
||||
{
|
||||
buffer_.setData( data );
|
||||
@@ -109,7 +107,7 @@ void DataSource::append( char byte )
|
||||
*
|
||||
* @param constBits The list of bits to append
|
||||
*/
|
||||
void DataSource::append( const QBitArray &constBits )
|
||||
void DataSource::append( const QBitArray& constBits )
|
||||
{
|
||||
if( constBits.size() == 0 )
|
||||
{
|
||||
@@ -202,7 +200,7 @@ void DataSource::append( const QBitArray &constBits )
|
||||
*
|
||||
* @param bytes The bytes to append
|
||||
*/
|
||||
void DataSource::append( const QByteArray &bytes )
|
||||
void DataSource::append( const QByteArray& bytes )
|
||||
{
|
||||
bool wasEmpty = ( buffer_.size() == 0 );
|
||||
|
||||
@@ -274,7 +272,7 @@ void DataSource::clear()
|
||||
*
|
||||
* @return byte array
|
||||
*/
|
||||
const QByteArray &DataSource::data() const
|
||||
const QByteArray& DataSource::data() const
|
||||
{
|
||||
return buffer_.data();
|
||||
}
|
||||
@@ -328,7 +326,7 @@ quint8 DataSource::getBitIndex()
|
||||
* @param ok If set, it will contain whether the call was successful or not.
|
||||
* @return bool
|
||||
*/
|
||||
bool DataSource::getBit( bool *ok )
|
||||
bool DataSource::getBit( bool* ok )
|
||||
{
|
||||
if( currentBitIndex_ >= 8 )
|
||||
{
|
||||
@@ -367,7 +365,7 @@ bool DataSource::getBit( bool *ok )
|
||||
* @param ok If set, it will contain whether the call was successful or not.
|
||||
* @return quint64 with the set of read bits
|
||||
*/
|
||||
quint64 DataSource::getBits( quint8 amount, bool *ok )
|
||||
quint64 DataSource::getBits( quint8 amount, bool* ok )
|
||||
{
|
||||
if( amount > 64 )
|
||||
{
|
||||
@@ -436,7 +434,7 @@ quint64 DataSource::getBits( quint8 amount, bool *ok )
|
||||
* @param ok If set, it will contain whether the call was successful or not.
|
||||
* @return char
|
||||
*/
|
||||
char DataSource::getByte( bool *ok )
|
||||
char DataSource::getByte( bool* ok )
|
||||
{
|
||||
bool gotBitOk;
|
||||
quint8 pos = 0;
|
||||
@@ -480,7 +478,7 @@ char DataSource::getByte( bool *ok )
|
||||
* @param ok If set, it will contain whether the call was successful or not.
|
||||
* @return byte array of read bytes
|
||||
*/
|
||||
QByteArray DataSource::getBytes( quint8 amount, bool *ok )
|
||||
QByteArray DataSource::getBytes( quint8 amount, bool* ok )
|
||||
{
|
||||
QByteArray bytes;
|
||||
bool gotByteOk;
|
||||
@@ -600,7 +598,7 @@ void DataSource::prepend( char byte )
|
||||
*
|
||||
* @param bytes Bytes to add
|
||||
*/
|
||||
void DataSource::prepend( const QByteArray &bytes )
|
||||
void DataSource::prepend( const QByteArray& bytes )
|
||||
{
|
||||
buffer_.buffer().prepend( bytes );
|
||||
|
||||
@@ -663,7 +661,7 @@ void DataSource::seekRelative( int pos )
|
||||
*
|
||||
* @param data New array to copy and use as the data source
|
||||
*/
|
||||
void DataSource::setData( const QByteArray &data )
|
||||
void DataSource::setData( const QByteArray& data )
|
||||
{
|
||||
buffer_.close();
|
||||
buffer_.setData( data );
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -49,30 +47,30 @@ namespace Isf
|
||||
|
||||
public: // Public constructors
|
||||
DataSource();
|
||||
DataSource( const QByteArray &data );
|
||||
DataSource( const QByteArray& data );
|
||||
~DataSource();
|
||||
|
||||
public: // Public status retrieval methods
|
||||
bool atEnd( bool considerBits = false ) const;
|
||||
const QByteArray &data() const;
|
||||
const QByteArray& data() const;
|
||||
qint64 pos() const;
|
||||
qint64 size() const;
|
||||
|
||||
public: // Public data manipulation methods
|
||||
void append( char byte );
|
||||
void append( const QBitArray &bits );
|
||||
void append( const QByteArray &bytes );
|
||||
void append( const QBitArray& bits );
|
||||
void append( const QByteArray& bytes );
|
||||
void clear();
|
||||
void flush();
|
||||
bool getBit( bool *ok = 0 );
|
||||
quint64 getBits( quint8 amount, bool *ok = 0 );
|
||||
bool getBit( bool* ok = 0 );
|
||||
quint64 getBits( quint8 amount, bool* ok = 0 );
|
||||
quint8 getBitIndex();
|
||||
char getByte( bool *ok = 0 );
|
||||
QByteArray getBytes( quint8 amount, bool *ok = 0 );
|
||||
char getByte( bool* ok = 0 );
|
||||
QByteArray getBytes( quint8 amount, bool* ok = 0 );
|
||||
void prepend( char byte );
|
||||
void prepend( const QByteArray &bytes );
|
||||
void prepend( const QByteArray& bytes );
|
||||
void reset();
|
||||
void setData( const QByteArray &data );
|
||||
void setData( const QByteArray& data );
|
||||
void seekRelative( int pos );
|
||||
void skipToNextByte();
|
||||
void skipToPrevByte();
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -40,7 +38,7 @@ using namespace Isf;
|
||||
* @param source Data Source where to read bytes from
|
||||
* @return quint64
|
||||
*/
|
||||
quint64 Compress::decodeUInt( DataSource &source )
|
||||
quint64 Compress::decodeUInt( DataSource* source )
|
||||
{
|
||||
quint8 byte; // Current byte
|
||||
quint8 flag; // Used to find out if there are more bytes to convert
|
||||
@@ -49,7 +47,7 @@ quint64 Compress::decodeUInt( DataSource &source )
|
||||
|
||||
do
|
||||
{
|
||||
byte = source.getByte();
|
||||
byte = source->getByte();
|
||||
flag = byte & 0x80;
|
||||
value |= (byte & 0x7F) << count;
|
||||
count += 7;
|
||||
@@ -67,7 +65,7 @@ quint64 Compress::decodeUInt( DataSource &source )
|
||||
* @param source Data Source where to read bytes from
|
||||
* @return qint64
|
||||
*/
|
||||
qint64 Compress::decodeInt( DataSource &source )
|
||||
qint64 Compress::decodeInt( DataSource* source )
|
||||
{
|
||||
bool isNegative = false;
|
||||
qint64 value = decodeUInt( source );
|
||||
@@ -98,7 +96,7 @@ qint64 Compress::decodeInt( DataSource &source )
|
||||
* @param source Data Source where to read bytes from
|
||||
* @return float
|
||||
*/
|
||||
float Compress::decodeFloat( DataSource &source )
|
||||
float Compress::decodeFloat( DataSource* source )
|
||||
{
|
||||
qint8 index;
|
||||
|
||||
@@ -113,14 +111,14 @@ float Compress::decodeFloat( DataSource &source )
|
||||
index = 3;
|
||||
do
|
||||
{
|
||||
data.bytes[ index-- ] = source.getByte();
|
||||
data.bytes[ index-- ] = source->getByte();
|
||||
}
|
||||
while( index >= 0 );
|
||||
#else
|
||||
index = 0;
|
||||
do
|
||||
{
|
||||
data.bytes[ index++ ] = source.getByte();
|
||||
data.bytes[ index++ ] = source->getByte();
|
||||
}
|
||||
while( index <= 3 );
|
||||
#endif
|
||||
@@ -170,17 +168,17 @@ QByteArray Compress::encodeUInt( quint64 value )
|
||||
* @param prepend False (default value) to append the encoded value to the existing data
|
||||
* True to prepend the new value to the existing data
|
||||
*/
|
||||
void Compress::encodeUInt( DataSource &source, quint64 value, bool prepend )
|
||||
void Compress::encodeUInt( DataSource* source, quint64 value, bool prepend )
|
||||
{
|
||||
QByteArray result( encodeUInt( value ) );
|
||||
|
||||
if( prepend )
|
||||
{
|
||||
source.prepend( result );
|
||||
source->prepend( result );
|
||||
}
|
||||
else
|
||||
{
|
||||
source.append( result );
|
||||
source->append( result );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,17 +224,17 @@ QByteArray Compress::encodeInt( qint64 value )
|
||||
* @param prepend False (default value) to append the encoded value to the existing data
|
||||
* True to prepend the new value to the existing data
|
||||
*/
|
||||
void Compress::encodeInt( DataSource &source, qint64 value, bool prepend )
|
||||
void Compress::encodeInt( DataSource* source, qint64 value, bool prepend )
|
||||
{
|
||||
QByteArray result( encodeInt( value ) );
|
||||
|
||||
if( prepend )
|
||||
{
|
||||
source.prepend( result );
|
||||
source->prepend( result );
|
||||
}
|
||||
else
|
||||
{
|
||||
source.append( result );
|
||||
source->append( result );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,17 +289,17 @@ QByteArray Compress::encodeFloat( float value )
|
||||
* @param prepend False (default value) to append the encoded value to the existing data
|
||||
* True to prepend the new value to the existing data
|
||||
*/
|
||||
void Compress::encodeFloat( DataSource &source, float value, bool prepend )
|
||||
void Compress::encodeFloat( DataSource* source, float value, bool prepend )
|
||||
{
|
||||
QByteArray result( encodeFloat( value ) );
|
||||
|
||||
if( prepend )
|
||||
{
|
||||
source.prepend( result );
|
||||
source->prepend( result );
|
||||
}
|
||||
else
|
||||
{
|
||||
source.append( result );
|
||||
source->append( result );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -37,18 +35,18 @@ namespace Isf
|
||||
namespace Compress
|
||||
{
|
||||
|
||||
quint64 decodeUInt( DataSource &source );
|
||||
qint64 decodeInt( DataSource &source );
|
||||
float decodeFloat( DataSource &source );
|
||||
quint64 decodeUInt( DataSource* source );
|
||||
qint64 decodeInt( DataSource* source );
|
||||
float decodeFloat( DataSource* source );
|
||||
|
||||
QByteArray encodeUInt( quint64 value );
|
||||
void encodeUInt( DataSource &source, quint64 value, bool prepend = false );
|
||||
void encodeUInt( DataSource* source, quint64 value, bool prepend = false );
|
||||
|
||||
QByteArray encodeInt( qint64 value );
|
||||
void encodeInt( DataSource &source, qint64 value, bool prepend = false );
|
||||
void encodeInt( DataSource* source, qint64 value, bool prepend = false );
|
||||
|
||||
QByteArray encodeFloat( float value );
|
||||
void encodeFloat( DataSource &source, float value, bool prepend = false );
|
||||
void encodeFloat( DataSource* source, float value, bool prepend = false );
|
||||
|
||||
quint8 getMultiByteSize( quint64 value );
|
||||
quint8 getMultiByteSize( qint64 value );
|
||||
|
||||
@@ -28,18 +28,18 @@
|
||||
|
||||
|
||||
// Internal helper function to read GIF data from a byte array
|
||||
int GifReadFromByteArray( GifFileType *gif, GifByteType* bytes, int size )
|
||||
int GifReadFromByteArray( GifFileType* gif, GifByteType* bytes, int size )
|
||||
{
|
||||
QBuffer *buffer = (QBuffer*) gif->UserData;
|
||||
QBuffer* buffer = (QBuffer*) gif->UserData;
|
||||
return buffer->read( (char*)bytes, size );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Internal helper function to write GIF data into a byte array
|
||||
int GifWriteToByteArray( GifFileType *gif, const GifByteType* bytes, int size )
|
||||
int GifWriteToByteArray( GifFileType* gif, const GifByteType* bytes, int size )
|
||||
{
|
||||
QBuffer *buffer = (QBuffer*) gif->UserData;
|
||||
QBuffer* buffer = (QBuffer*) gif->UserData;
|
||||
return buffer->write( (char*)bytes, size );
|
||||
}
|
||||
|
||||
|
||||
+220
-276
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -43,7 +41,7 @@ using namespace Isf;
|
||||
*
|
||||
* @param parent The parent widget.
|
||||
*/
|
||||
InkCanvas:: InkCanvas( QWidget *parent )
|
||||
InkCanvas:: InkCanvas( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, erasingImage_( false )
|
||||
, drawing_( 0 )
|
||||
@@ -59,6 +57,10 @@ InkCanvas:: InkCanvas( QWidget *parent )
|
||||
setPenColor( Qt::black );
|
||||
setPenSize( 4 );
|
||||
|
||||
setAttribute( Qt::WA_StaticContents, true ); // only give us paint events for the parts of us that become visible on resize.
|
||||
|
||||
setAutoFillBackground( true );
|
||||
|
||||
clear();
|
||||
|
||||
// prepare the buffer
|
||||
@@ -69,8 +71,6 @@ InkCanvas:: InkCanvas( QWidget *parent )
|
||||
|
||||
// start with a drawing pen by default.
|
||||
setPenType( DrawingPen );
|
||||
|
||||
setAttribute( Qt::WA_StaticContents );
|
||||
}
|
||||
|
||||
|
||||
@@ -90,62 +90,13 @@ InkCanvas::~InkCanvas()
|
||||
|
||||
|
||||
/**
|
||||
* Creates a QCursor displayed when the mouse pointer moves over the widget.
|
||||
* Returns the drawing's ISF representation.
|
||||
*
|
||||
* The cursor becomes a point, drawn with the current stroke colour and pen size.
|
||||
* @return A QByteArray filled with ISF data.
|
||||
*/
|
||||
void InkCanvas::updateCursor()
|
||||
QByteArray InkCanvas::bytes()
|
||||
{
|
||||
if ( cursorPixmap_.isNull() )
|
||||
{
|
||||
cursorPixmap_ = QPixmap( QSize( 32, 32 ) );
|
||||
}
|
||||
|
||||
if ( penType_ == EraserPen )
|
||||
{
|
||||
cursorPixmap_ = QPixmap( ":pics/draw-eraser.png" );
|
||||
cursor_ = QCursor( cursorPixmap_, 0, cursorPixmap_.height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
cursorPixmap_.fill( Qt::transparent );
|
||||
|
||||
QPainter painter( &cursorPixmap_ );
|
||||
|
||||
painter.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true );
|
||||
painter.setPen( QPen( color_, penSize_, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin ) );
|
||||
|
||||
// now draw a point.
|
||||
painter.drawPoint( QPoint( cursorPixmap_.size().width() / 2, cursorPixmap_.size().height() / 2 ) );
|
||||
|
||||
cursor_ = QCursor( cursorPixmap_ );
|
||||
}
|
||||
|
||||
// create our cursor.
|
||||
setCursor( cursor_ );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the suggested size for the canvas.
|
||||
*
|
||||
* The actual size hint will depend on the size of the drawing on the canvas. By default,
|
||||
* the size hint is 300x300 pixels.
|
||||
*/
|
||||
QSize InkCanvas::sizeHint() const
|
||||
{
|
||||
if ( drawing_->isNull() )
|
||||
{
|
||||
return QSize( 300, 300 );
|
||||
}
|
||||
else
|
||||
{
|
||||
QRect boundingRect = drawing_->boundingRect();
|
||||
boundingRect.setTopLeft( QPoint( 0, 0 ) );
|
||||
return boundingRect.size();
|
||||
}
|
||||
return Isf::Stream::writer( *drawing_ );
|
||||
}
|
||||
|
||||
|
||||
@@ -174,58 +125,47 @@ void InkCanvas::clear()
|
||||
|
||||
|
||||
/**
|
||||
* Change the color of the pen used to draw on the Ink canvas.
|
||||
* Clear the internal pixmap buffer.
|
||||
*
|
||||
* @param newColor The new color for the pen.
|
||||
* The buffer used to quickly render on the widget painting area
|
||||
* the new and old strokes: every new stroke is saved here.
|
||||
* This allows to avoid repainting all strokes at every paint event.
|
||||
*/
|
||||
void InkCanvas::setPenColor( QColor newColor )
|
||||
void InkCanvas::clearBuffer()
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Setting new pen color:" << newColor.name();
|
||||
#endif
|
||||
|
||||
color_ = newColor;
|
||||
|
||||
updateCursor();
|
||||
bufferPixmap_ = QPixmap( size() );
|
||||
bufferPixmap_.fill( Qt::transparent );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change the size of the pen. This value is in pixels.
|
||||
* Retrieve the Isf::Drawing instance that the canvas is currently manipulating.
|
||||
*
|
||||
* @param pixels The size of the pen, in pixels
|
||||
* Beware: if you have not set your own Isf::Drawing instance via setDrawing(), you must not delete
|
||||
* the object that this method returns. In this case this method returns a pointer to an internal
|
||||
* Isf::Drawing instance that must not be deleted. If you have previously used setDrawing() then you
|
||||
* are free to do whatever you like with this pointer.
|
||||
*
|
||||
* \code
|
||||
* InkCanvas* canvas = new InkCanvas( this );
|
||||
*
|
||||
* Isf::Drawing* drawing = canvas->drawing();
|
||||
* delete drawing; // bad! deleting an object internal to InkCanvas.
|
||||
*
|
||||
* canvas->setDrawing( existingIsfDrawingInstance );
|
||||
*
|
||||
* drawing = canvas->drawing();
|
||||
* delete drawing; // good - drawing points to existingIsfDrawingInstance.
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* @see setDrawing()
|
||||
* @return The current Isf::Drawing instance.
|
||||
*/
|
||||
void InkCanvas::setPenSize( int pixels )
|
||||
Isf::Drawing* InkCanvas::drawing()
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Setting new pen size:" << pixels;
|
||||
#endif
|
||||
penSize_ = pixels;
|
||||
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change the pen type.
|
||||
*
|
||||
* Currently, only PenType::EraserPen and PenType::DrawingPen are supported. See the PenType
|
||||
* enum for more information.
|
||||
*
|
||||
* @see PenType
|
||||
* @param type The new pen type
|
||||
*/
|
||||
void InkCanvas::setPenType( PenType type )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Setting new pen type:" << type;
|
||||
#endif
|
||||
|
||||
penType_ = type;
|
||||
|
||||
updateCursor();
|
||||
return drawing_;
|
||||
}
|
||||
|
||||
|
||||
@@ -239,16 +179,12 @@ void InkCanvas::setPenType( PenType type )
|
||||
* @see mousePressEvent()
|
||||
* @param endPoint Final point of the line
|
||||
*/
|
||||
void InkCanvas::drawLineTo( const QPoint &endPoint )
|
||||
void InkCanvas::drawLineTo( const QPoint& endPoint )
|
||||
{
|
||||
if( drawing_ == 0 )
|
||||
{
|
||||
qWarning() << "Uninitialized usage of InkCanvas!";
|
||||
return;
|
||||
}
|
||||
Q_ASSERT_X( drawing_, "drawLineTo", "Drawing is null" );
|
||||
|
||||
// draw the "in progress" strokes on the buffer.
|
||||
QPainter painter( &(bufferPixmap_) );
|
||||
QPainter painter( &bufferPixmap_ );
|
||||
painter.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true );
|
||||
|
||||
QColor color = color_;
|
||||
@@ -282,6 +218,18 @@ void InkCanvas::drawLineTo( const QPoint &endPoint )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Renders the ink drawing to a QImage and returns it.
|
||||
*
|
||||
* @return A QImage containing the rendered Ink.
|
||||
*/
|
||||
QImage InkCanvas::image()
|
||||
{
|
||||
return drawing_->pixmap( Qt::white ).toImage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get whether the drawing is empty (i.e., contains no strokes).
|
||||
*
|
||||
@@ -306,13 +254,9 @@ bool InkCanvas::isEmpty()
|
||||
* @see mouseReleaseEvent()
|
||||
* @param event The mouse button press event
|
||||
*/
|
||||
void InkCanvas::mousePressEvent( QMouseEvent *event )
|
||||
void InkCanvas::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
if( drawing_ == 0 )
|
||||
{
|
||||
qWarning() << "Uninitialized usage of InkCanvas!";
|
||||
return;
|
||||
}
|
||||
Q_ASSERT_X( drawing_, "mousePressEvent", "Drawing is null" );
|
||||
|
||||
if( event->button() != Qt::LeftButton )
|
||||
{
|
||||
@@ -325,7 +269,7 @@ void InkCanvas::mousePressEvent( QMouseEvent *event )
|
||||
{
|
||||
// is there a stroke here?
|
||||
QPoint point = event->pos();
|
||||
Stroke *s = drawing_->strokeAtPoint( point );
|
||||
Stroke* s = drawing_->strokeAtPoint( point );
|
||||
if ( s != 0 )
|
||||
{
|
||||
drawing_->deleteStroke( s );
|
||||
@@ -338,47 +282,19 @@ void InkCanvas::mousePressEvent( QMouseEvent *event )
|
||||
|
||||
lastPoint_ = event->pos();
|
||||
|
||||
// Search if there already is an attributes set compatible with the current one
|
||||
Isf::AttributeSet *reusableAttributeSet = 0;
|
||||
foreach( Isf::AttributeSet *set, drawing_->attributeSets() )
|
||||
{
|
||||
if( abs( (qreal)penSize_ - set->penSize.width() ) < 1.0f
|
||||
&& color_ == set->color )
|
||||
{
|
||||
reusableAttributeSet = set;
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Found an usable ISF attribute set";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If none is found, create a new one
|
||||
if( ! reusableAttributeSet )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Creating new attribute set";
|
||||
#endif
|
||||
reusableAttributeSet = new Isf::AttributeSet;
|
||||
reusableAttributeSet->color = color_;
|
||||
reusableAttributeSet->penSize.setWidth ( (qreal)penSize_ );
|
||||
reusableAttributeSet->penSize.setHeight( (qreal)penSize_ );
|
||||
|
||||
drawing_->addAttributeSet( reusableAttributeSet );
|
||||
}
|
||||
|
||||
// Use it for the next strokes
|
||||
drawing_->setCurrentAttributeSet( reusableAttributeSet );
|
||||
|
||||
// If there already is a stroke, add it
|
||||
if( currentStroke_ )
|
||||
{
|
||||
currentStroke_->finalize();
|
||||
drawing_->addStroke( currentStroke_ );
|
||||
currentStroke_ = 0;
|
||||
}
|
||||
|
||||
currentStroke_ = new Isf::Stroke;
|
||||
currentStroke_->points.append( Isf::Point( lastPoint_ ) );
|
||||
currentStroke_ = new Isf::Stroke();
|
||||
currentStroke_->addPoint( lastPoint_ );
|
||||
currentStroke_->setColor( color_ );
|
||||
currentStroke_->setPenSize( QSizeF( (qreal)penSize_, (qreal)penSize_ ) );
|
||||
currentStroke_->setFlag( FitToCurve, true );
|
||||
|
||||
// Draw the initial point
|
||||
drawLineTo( lastPoint_ );
|
||||
@@ -390,7 +306,7 @@ void InkCanvas::mousePressEvent( QMouseEvent *event )
|
||||
* Continue drawing the current stroke.
|
||||
*
|
||||
* As the cursor moves across the canvas we continue drawing the stroke started in
|
||||
* mousePressEvent(). A line is drawn between the last point and the current point
|
||||
* mousePressEvent(). A line is drawn between the last point and the current point
|
||||
* as given by QMouseEvent::pos().
|
||||
*
|
||||
* Once the mouse button is released, drawing ends.
|
||||
@@ -399,18 +315,20 @@ void InkCanvas::mousePressEvent( QMouseEvent *event )
|
||||
* @see mouseReleaseEvent()
|
||||
* @param event The mouse move event
|
||||
*/
|
||||
void InkCanvas::mouseMoveEvent( QMouseEvent *event )
|
||||
void InkCanvas::mouseMoveEvent( QMouseEvent* event )
|
||||
{
|
||||
if( ! ( event->buttons() & Qt::LeftButton ) || ! scribbling_ )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Q_ASSERT_X( drawing_, "mouseMoveEvent", "Drawing is null" );
|
||||
|
||||
if ( penType_ == EraserPen )
|
||||
{
|
||||
// is there a stroke here?
|
||||
QPoint point = event->pos();
|
||||
Stroke *s = drawing_->strokeAtPoint( point );
|
||||
Stroke* s = drawing_->strokeAtPoint( point );
|
||||
if ( s != 0 )
|
||||
{
|
||||
drawing_->deleteStroke( s );
|
||||
@@ -421,12 +339,6 @@ void InkCanvas::mouseMoveEvent( QMouseEvent *event )
|
||||
return;
|
||||
}
|
||||
|
||||
if( drawing_ == 0 )
|
||||
{
|
||||
qWarning() << "Uninitialized usage of InkCanvas!";
|
||||
return;
|
||||
}
|
||||
|
||||
QPoint position( event->pos() );
|
||||
|
||||
// Don't add duplicate points. Mainly useful when drawing dots.
|
||||
@@ -437,16 +349,10 @@ void InkCanvas::mouseMoveEvent( QMouseEvent *event )
|
||||
|
||||
drawLineTo( position );
|
||||
|
||||
if( currentStroke_ == 0 )
|
||||
{
|
||||
#ifdef KMESSDEBUG_INKEDIT_GENERAL
|
||||
qWarning() << "The stroke isn't ready!";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
Q_ASSERT_X( currentStroke_, "mouseMoveEvent", "currentStroke_ is null" );
|
||||
|
||||
// Add the new point to the stroke
|
||||
currentStroke_->points.append( Isf::Point( lastPoint_ ) );
|
||||
currentStroke_->addPoint( lastPoint_ );
|
||||
}
|
||||
|
||||
|
||||
@@ -460,13 +366,9 @@ void InkCanvas::mouseMoveEvent( QMouseEvent *event )
|
||||
* @see mouseMoveEvent()
|
||||
* @param event The mouse release event
|
||||
*/
|
||||
void InkCanvas::mouseReleaseEvent( QMouseEvent *event )
|
||||
void InkCanvas::mouseReleaseEvent( QMouseEvent* event )
|
||||
{
|
||||
if( drawing_ == 0 )
|
||||
{
|
||||
qWarning() << "Uninitialized usage of InkCanvas!";
|
||||
return;
|
||||
}
|
||||
Q_ASSERT_X( drawing_, "mouseReleaseEvent", "Drawing is null" );
|
||||
|
||||
if( event->button() != Qt::LeftButton || ! scribbling_ )
|
||||
{
|
||||
@@ -486,16 +388,7 @@ void InkCanvas::mouseReleaseEvent( QMouseEvent *event )
|
||||
drawLineTo( position );
|
||||
}
|
||||
|
||||
scribbling_ = false;
|
||||
emit inkChanged();
|
||||
|
||||
if( ! currentStroke_ )
|
||||
{
|
||||
#ifdef KMESSDEBUG_INKEDIT_GENERAL
|
||||
qWarning() << "The stroke isn't ready!";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
Q_ASSERT_X( currentStroke_, "mouseReleaseEvent", "currentStroke_ is null" );
|
||||
|
||||
#ifdef KMESSDEBUG_INKEDIT_GENERAL
|
||||
qDebug() << "Finishing up stroke";
|
||||
@@ -504,9 +397,10 @@ void InkCanvas::mouseReleaseEvent( QMouseEvent *event )
|
||||
// Don't add duplicate points. Mainly useful when drawing dots.
|
||||
if( lastPoint_ != position )
|
||||
{
|
||||
currentStroke_->points.append( Isf::Point( lastPoint_ ) );
|
||||
currentStroke_->addPoint( lastPoint_ );
|
||||
}
|
||||
|
||||
currentStroke_->finalize();
|
||||
drawing_->addStroke( currentStroke_ );
|
||||
|
||||
currentStroke_ = 0;
|
||||
@@ -515,21 +409,12 @@ void InkCanvas::mouseReleaseEvent( QMouseEvent *event )
|
||||
|
||||
// clear the buffer.
|
||||
clearBuffer();
|
||||
}
|
||||
|
||||
// update
|
||||
update();
|
||||
|
||||
|
||||
/**
|
||||
* Clear the internal pixmap buffer.
|
||||
*
|
||||
* The buffer used to quickly render on the widget painting area
|
||||
* the new and old strokes: every new stroke is saved here.
|
||||
* This allows to avoid repainting all strokes at every paint event.
|
||||
*/
|
||||
void InkCanvas::clearBuffer()
|
||||
{
|
||||
bufferPixmap_ = QPixmap( size() );
|
||||
bufferPixmap_.fill( Qt::transparent );
|
||||
scribbling_ = false;
|
||||
emit inkChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -539,28 +424,19 @@ void InkCanvas::clearBuffer()
|
||||
*
|
||||
* For performance reasons an internal buffer is used to ensure that
|
||||
* the entire Ink drawing is not re-rendered on each paintEvent call.
|
||||
* This buffer is invalidated only when a stroke is added or removed, the
|
||||
* This buffer is invalidated only when a stroke is added or removed, the
|
||||
* drawing is changed or the canvas cleared.
|
||||
*
|
||||
*
|
||||
* @param event The paint event from Qt.
|
||||
*/
|
||||
void InkCanvas::paintEvent( QPaintEvent *event )
|
||||
void InkCanvas::paintEvent( QPaintEvent* event )
|
||||
{
|
||||
Q_UNUSED( event );
|
||||
|
||||
QPainter painter( this );
|
||||
|
||||
painter.save();
|
||||
painter.setBrush( QBrush( canvasColor_ ) );
|
||||
painter.drawRect( QRect(-1, -1, width() + 1 , height() + 1 ) );
|
||||
painter.restore();
|
||||
|
||||
if( drawing_ == 0 )
|
||||
{
|
||||
qWarning() << "Uninitialized usage of InkCanvas!";
|
||||
return;
|
||||
}
|
||||
Q_ASSERT_X( drawing_, "paintEvent", "Drawing is null" );
|
||||
|
||||
// draw the ISF first, then the buffer over the top.
|
||||
// buffer has a transparent background.
|
||||
@@ -583,42 +459,13 @@ void InkCanvas::paintEvent( QPaintEvent *event )
|
||||
painter.drawPixmap( boundingRect.topLeft(), isfPixmap );
|
||||
|
||||
// draw the buffer from 0,0.
|
||||
painter.drawPixmap( QPoint(0, 0), bufferPixmap_ );
|
||||
painter.drawPixmap( event->rect(), bufferPixmap_, event->rect() );
|
||||
|
||||
QWidget::paintEvent( event );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The widget has changed size, re-draw everything.
|
||||
*
|
||||
* @param event The resizing event.
|
||||
*/
|
||||
void InkCanvas::resizeEvent( QResizeEvent *event )
|
||||
{
|
||||
// need to resize the buffer pixmap.
|
||||
clearBuffer();
|
||||
|
||||
update();
|
||||
|
||||
QWidget::resizeEvent( event );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Renders the ink drawing to a QImage and returns it.
|
||||
*
|
||||
* @return A QImage containing the rendered Ink.
|
||||
*/
|
||||
QImage InkCanvas::image()
|
||||
{
|
||||
return drawing_->pixmap().toImage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the current pen color.
|
||||
*
|
||||
@@ -659,32 +506,18 @@ InkCanvas::PenType InkCanvas::penType()
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the Isf::Drawing instance that the canvas is currently manipulating.
|
||||
* The widget has changed size, re-draw everything.
|
||||
*
|
||||
* Beware: if you have not set your own Isf::Drawing instance via setDrawing(), you must not delete
|
||||
* the object that this method returns. In this case this method returns a pointer to an internal
|
||||
* Isf::Drawing instance that must not be deleted. If you have previously used setDrawing() then you
|
||||
* are free to do whatever you like with this pointer.
|
||||
*
|
||||
* \code
|
||||
* InkCanvas *canvas = new InkCanvas( this );
|
||||
*
|
||||
* Isf::Drawing *drawing = canvas->drawing();
|
||||
* delete drawing; // bad! deleting an object internal to InkCanvas.
|
||||
*
|
||||
* canvas->setDrawing( existingIsfDrawingInstance );
|
||||
*
|
||||
* drawing = canvas->drawing();
|
||||
* delete drawing; // good - drawing points to existingIsfDrawingInstance.
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* @see setDrawing()
|
||||
* @return The current Isf::Drawing instance.
|
||||
* @param event The resizing event.
|
||||
*/
|
||||
Isf::Drawing *InkCanvas::drawing()
|
||||
void InkCanvas::resizeEvent( QResizeEvent* event )
|
||||
{
|
||||
return drawing_;
|
||||
// need to resize the buffer pixmap.
|
||||
clearBuffer();
|
||||
|
||||
update();
|
||||
|
||||
QWidget::resizeEvent( event );
|
||||
}
|
||||
|
||||
|
||||
@@ -692,8 +525,8 @@ Isf::Drawing *InkCanvas::drawing()
|
||||
/**
|
||||
* Save the current ISF drawing to a QIODevice.
|
||||
*
|
||||
* If the base64 param is True, then the drawing will be written base64-encoded.
|
||||
* This is helpful for transmission over mediums which are not binary-friendly.
|
||||
* If the base64 param is true, then the drawing will be written base64-encoded.
|
||||
* This is helpful for transmission over binary-unfriendly media.
|
||||
*
|
||||
* @param dev The QIODevice to save to.
|
||||
* @param base64 If true, the drawing is written encoded with base64.
|
||||
@@ -706,18 +539,6 @@ void InkCanvas::save( QIODevice &dev, bool base64 )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the drawing's ISF representation.
|
||||
*
|
||||
* @return A QByteArray filled with ISF data.
|
||||
*/
|
||||
QByteArray InkCanvas::bytes()
|
||||
{
|
||||
return Isf::Stream::writer( *drawing_ );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the canvas colour (i.e., the background colour of the InkCanvas control)
|
||||
*
|
||||
@@ -731,6 +552,10 @@ void InkCanvas::setCanvasColor( QColor newColor )
|
||||
qDebug() << "Setting new canvas color:" << newColor.name();
|
||||
#endif
|
||||
canvasColor_ = newColor;
|
||||
|
||||
QPalette p = palette();
|
||||
p.setColor( QPalette::Window, newColor );
|
||||
setPalette( p );
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -740,11 +565,11 @@ void InkCanvas::setCanvasColor( QColor newColor )
|
||||
* Changes the currently displayed Ink to the one supplied.
|
||||
*
|
||||
* Note: InkCanvas does not take ownership of Isf::Drawing instances supplied here.
|
||||
* You are still responsible for ensuring they are deleted appropriately.
|
||||
* You are still responsible of ensuring they are deleted appropriately.
|
||||
*
|
||||
* @param drawing The new Ink drawing to display.
|
||||
*/
|
||||
void InkCanvas::setDrawing( Isf::Drawing *drawing )
|
||||
void InkCanvas::setDrawing( Isf::Drawing* drawing )
|
||||
{
|
||||
drawing_ = drawing;
|
||||
|
||||
@@ -757,7 +582,126 @@ void InkCanvas::setDrawing( Isf::Drawing *drawing )
|
||||
|
||||
drawingDirty_ = true;
|
||||
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change the color of the pen used to draw on the Ink canvas.
|
||||
*
|
||||
* @param newColor The new color for the pen.
|
||||
*/
|
||||
void InkCanvas::setPenColor( QColor newColor )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Setting new pen color:" << newColor.name();
|
||||
#endif
|
||||
|
||||
color_ = newColor;
|
||||
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change the size of the pen. This value is in pixels.
|
||||
*
|
||||
* @param pixels The size of the pen, in pixels
|
||||
*/
|
||||
void InkCanvas::setPenSize( int pixels )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Setting new pen size:" << pixels;
|
||||
#endif
|
||||
penSize_ = pixels;
|
||||
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change the pen type.
|
||||
*
|
||||
* Currently, only PenType::EraserPen and PenType::DrawingPen are supported. See the PenType
|
||||
* enum for more information.
|
||||
*
|
||||
* @see PenType
|
||||
* @param type The new pen type
|
||||
*/
|
||||
void InkCanvas::setPenType( PenType type )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Setting new pen type:" << type;
|
||||
#endif
|
||||
|
||||
penType_ = type;
|
||||
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the suggested size for the canvas.
|
||||
*
|
||||
* The actual size hint will depend on the size of the drawing on the canvas. By default,
|
||||
* the size hint is 300x300 pixels.
|
||||
*/
|
||||
QSize InkCanvas::sizeHint() const
|
||||
{
|
||||
if ( drawing_->isNull() )
|
||||
{
|
||||
return QSize( 300, 300 );
|
||||
}
|
||||
else
|
||||
{
|
||||
QRect boundingRect = drawing_->boundingRect();
|
||||
boundingRect.setTopLeft( QPoint( 0, 0 ) );
|
||||
return boundingRect.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a QCursor displayed when the mouse pointer moves over the widget.
|
||||
*
|
||||
* The cursor becomes a point, drawn with the current stroke colour and pen size.
|
||||
*/
|
||||
void InkCanvas::updateCursor()
|
||||
{
|
||||
if ( cursorPixmap_.isNull() )
|
||||
{
|
||||
cursorPixmap_ = QPixmap( QSize( 32, 32 ) );
|
||||
}
|
||||
|
||||
if ( penType_ == EraserPen )
|
||||
{
|
||||
cursorPixmap_ = QPixmap( ":pics/draw-eraser.png" );
|
||||
cursor_ = QCursor( cursorPixmap_, 0, cursorPixmap_.height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
cursorPixmap_.fill( Qt::transparent );
|
||||
|
||||
QPainter painter( &cursorPixmap_ );
|
||||
|
||||
painter.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true );
|
||||
painter.setPen( QPen( color_, penSize_, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin ) );
|
||||
|
||||
// now draw a point.
|
||||
painter.drawPoint( QPoint( cursorPixmap_.size().width() / 2, cursorPixmap_.size().height() / 2 ) );
|
||||
|
||||
cursor_ = QCursor( cursorPixmap_ );
|
||||
}
|
||||
|
||||
// create our cursor.
|
||||
setCursor( cursor_ );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -44,6 +42,12 @@
|
||||
|
||||
namespace Isf
|
||||
{
|
||||
// Forward declarations
|
||||
class Stroke;
|
||||
namespace Compress
|
||||
{
|
||||
class DataSource;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -114,6 +118,104 @@ namespace Isf
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Drawing attributes for points.
|
||||
*/
|
||||
struct AttributeSet
|
||||
{
|
||||
/// Constructor
|
||||
AttributeSet()
|
||||
: color( Qt::black )
|
||||
, flags( 0x10 ) // Meaning unknown
|
||||
, penSize( 8.f, 8.f ) // Default pen is 8.0 pixels wide
|
||||
{
|
||||
}
|
||||
/// Quick comparison operator
|
||||
bool operator ==( const AttributeSet& other ) const
|
||||
{
|
||||
return color == other.color
|
||||
&& flags == other.flags
|
||||
&& penSize == other.penSize;
|
||||
}
|
||||
/// Quick comparison operator
|
||||
bool operator !=( const AttributeSet& other ) const
|
||||
{
|
||||
return color != other.color
|
||||
|| flags != other.flags
|
||||
|| penSize != other.penSize;
|
||||
}
|
||||
|
||||
/// The stroke color, optionally with alpha channel
|
||||
QColor color;
|
||||
/// Mask of StrokeFlags, @see StrokeFlags
|
||||
StrokeFlags flags;
|
||||
/// Dimensions of the pencil in pixels
|
||||
QSizeF penSize;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Drawing attributes for strokes.
|
||||
*/
|
||||
struct StrokeInfo
|
||||
{
|
||||
/// Constructor
|
||||
StrokeInfo()
|
||||
: hasPressureData( false )
|
||||
, hasXData( true )
|
||||
, hasYData( true )
|
||||
{
|
||||
}
|
||||
|
||||
/// Whether the stroke contains pressure info or not
|
||||
bool hasPressureData;
|
||||
/// Whether the stroke contains X coordinates or not
|
||||
bool hasXData;
|
||||
/// Whether the stroke contains Y coordinates or not
|
||||
bool hasYData;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal parser data
|
||||
*/
|
||||
struct StreamData
|
||||
{
|
||||
StreamData()
|
||||
: currentAttributeSetIndex( 0 )
|
||||
, currentMetricsIndex( 0 )
|
||||
, currentStrokeInfoIndex( 0 )
|
||||
, currentTransformsIndex( 0 )
|
||||
, dataSource( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
/// List of attributes of the points in the drawing
|
||||
QList<AttributeSet> attributeSets;
|
||||
/// Drawing's bounding rectangle
|
||||
QRect boundingRect;
|
||||
/// Current attribute set
|
||||
quint64 currentAttributeSetIndex;
|
||||
/// Current metrics set
|
||||
quint64 currentMetricsIndex;
|
||||
/// Current stroke info
|
||||
quint64 currentStrokeInfoIndex;
|
||||
/// Current transform
|
||||
quint64 currentTransformsIndex;
|
||||
/// Raw bytes source used to read and write streams
|
||||
Compress::DataSource* dataSource;
|
||||
/// List of metrics used in the drawing
|
||||
QList<Metrics*> metrics;
|
||||
/// List of stroke info
|
||||
QList<StrokeInfo*> strokeInfos;
|
||||
/// Transformation matrices
|
||||
QList<QMatrix*> transforms;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+203
-394
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -48,6 +46,10 @@ using namespace Compress;
|
||||
#define SUPPORTED_ISF_VERSION 0
|
||||
|
||||
|
||||
// Initialization of static properties
|
||||
StreamData* Stream::streamData_( 0 );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a raw ISF data stream into a drawing.
|
||||
@@ -59,23 +61,26 @@ using namespace Compress;
|
||||
* need to be decoded first
|
||||
* @return an Isf::Drawing, with null contents on error
|
||||
*/
|
||||
Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
|
||||
Drawing& Stream::reader( const QByteArray& rawData, bool decodeFromBase64 )
|
||||
{
|
||||
// Create a new drawing on the heap to ensure it will keep
|
||||
// living after this method returns
|
||||
Drawing *drawing = new Drawing;
|
||||
DataSource isfData( decodeFromBase64
|
||||
? QByteArray::fromBase64( rawData )
|
||||
: rawData );
|
||||
int size = isfData.size();
|
||||
|
||||
if( size == 0 )
|
||||
{
|
||||
return *drawing;
|
||||
}
|
||||
Drawing* drawing = new Drawing();
|
||||
|
||||
ParserState state = ISF_PARSER_START;
|
||||
|
||||
streamData_ = new StreamData();
|
||||
streamData_->dataSource = new DataSource( decodeFromBase64
|
||||
? QByteArray::fromBase64( rawData )
|
||||
: rawData );
|
||||
|
||||
int size = streamData_->dataSource->size();
|
||||
if( size == 0 )
|
||||
{
|
||||
state = ISF_PARSER_FINISH;
|
||||
drawing->error_ = ISF_ERROR_BAD_STREAMSIZE;
|
||||
}
|
||||
|
||||
while( state != ISF_PARSER_FINISH )
|
||||
{
|
||||
switch( state )
|
||||
@@ -83,7 +88,7 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
|
||||
case ISF_PARSER_START:
|
||||
{
|
||||
// step 1: read ISF version.
|
||||
quint8 version = decodeUInt( isfData );
|
||||
quint8 version = decodeUInt( streamData_->dataSource );
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Version:" << version;
|
||||
#endif
|
||||
@@ -106,13 +111,13 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
|
||||
{
|
||||
// read ISF stream size.
|
||||
// check it matches the length of the data array.
|
||||
quint64 streamSize = decodeUInt( isfData );
|
||||
quint64 streamSize = decodeUInt( streamData_->dataSource );
|
||||
|
||||
if ( streamSize != (quint64)( isfData.size() - isfData.pos() ) )
|
||||
if ( streamSize != (quint64)( streamData_->dataSource->size() - streamData_->dataSource->pos() ) )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "Invalid stream size" << streamSize
|
||||
<< ", expected" << ( isfData.size() - isfData.pos() );
|
||||
<< ", expected" << ( streamData_->dataSource->size() - streamData_->dataSource->pos() );
|
||||
#endif
|
||||
// streamsize is bad.
|
||||
drawing->error_ = ISF_ERROR_BAD_STREAMSIZE;
|
||||
@@ -126,12 +131,6 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
|
||||
// Validate the drawing
|
||||
drawing->isNull_ = false;
|
||||
|
||||
// Fill up the default properties
|
||||
drawing->currentMetrics_ = &drawing->defaultMetrics_;
|
||||
drawing->currentAttributeSet_ = &drawing->defaultAttributeSet_;
|
||||
drawing->currentStrokeInfo_ = &drawing->defaultStrokeInfo_;
|
||||
drawing->currentTransform_ = &drawing->defaultTransform_;
|
||||
|
||||
// start looking for ISF tags.
|
||||
state = ISF_PARSER_TAG;
|
||||
}
|
||||
@@ -139,331 +138,16 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
|
||||
break;
|
||||
}
|
||||
|
||||
// ******************
|
||||
// This is the key point of the state machine. This will continually loop looking for ISF
|
||||
// tags and farming off to the appropriate method.
|
||||
// *******************
|
||||
case ISF_PARSER_TAG:
|
||||
{
|
||||
if( isfData.atEnd() )
|
||||
if( streamData_->dataSource->atEnd() )
|
||||
{
|
||||
state = ISF_PARSER_FINISH;
|
||||
break;
|
||||
}
|
||||
|
||||
QString place( "0x" + QString::number( isfData.pos(), 16 ).toUpper() );
|
||||
quint64 tagIndex = decodeUInt( isfData );
|
||||
|
||||
switch( tagIndex )
|
||||
{
|
||||
case TAG_INK_SPACE_RECT:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_INK_SPACE_RECT";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseInkSpaceRectangle( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_GUID_TABLE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_GUID_TABLE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseGuidTable( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_DRAW_ATTRS_TABLE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_DRAW_ATTRS_TABLE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseAttributeTable( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_DRAW_ATTRS_BLOCK:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_DRAW_ATTRS_BLOCK";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseAttributeBlock( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_STROKE_DESC_TABLE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_STROKE_DESC_TABLE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseStrokeDescTable( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_STROKE_DESC_BLOCK:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_STROKE_DESC_BLOCK";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseStrokeDescBlock( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_BUTTONS:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_BUTTONS";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_BUTTONS" );
|
||||
break;
|
||||
|
||||
case TAG_NO_X:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_NO_X";
|
||||
#endif
|
||||
drawing->error_ = ISF_ERROR_NONE;
|
||||
|
||||
drawing->hasXData_ = false;
|
||||
break;
|
||||
|
||||
case TAG_NO_Y:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_NO_Y";
|
||||
#endif
|
||||
drawing->hasYData_ = false;
|
||||
break;
|
||||
|
||||
case TAG_DIDX:
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_DIDX";
|
||||
#endif
|
||||
|
||||
quint64 value = decodeUInt( isfData );
|
||||
|
||||
if( value < (uint)drawing->attributeSets_.count() )
|
||||
{
|
||||
drawing->currentAttributeSet_ = drawing->attributeSets_[ value ];
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Next strokes will use drawing attributes #" << value;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qWarning() << "Invalid drawing attribute ID!";
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TAG_STROKE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_STROKE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseStroke( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_STROKE_PROPERTY_LIST:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_STROKE_PROPERTY_LIST";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_STROKE_PROPERTY_LIST" );
|
||||
break;
|
||||
|
||||
case TAG_POINT_PROPERTY:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_POINT_PROPERTY";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_POINT_PROPERTY" );
|
||||
break;
|
||||
|
||||
case TAG_SIDX:
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_SIDX";
|
||||
#endif
|
||||
|
||||
quint64 value = decodeUInt( isfData );
|
||||
|
||||
if( value < (uint)drawing->strokeInfo_.count() )
|
||||
{
|
||||
drawing->currentStrokeInfo_ = drawing->strokeInfo_[ value ];
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Next strokes will use stroke info #" << value;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qWarning() << "Invalid stroke ID!";
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TAG_COMPRESSION_HEADER:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_COMPRESSION_HEADER";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_COMPRESSION_HEADER" );
|
||||
break;
|
||||
|
||||
case TAG_TRANSFORM_TABLE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_TABLE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseTransformationTable( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_TRANSFORM:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
|
||||
break;
|
||||
|
||||
case TAG_TRANSFORM_ISOTROPIC_SCALE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_ISOTROPIC_SCALE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
|
||||
break;
|
||||
|
||||
case TAG_TRANSFORM_ANISOTROPIC_SCALE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_ANISOTROPIC_SCALE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
|
||||
break;
|
||||
|
||||
case TAG_TRANSFORM_ROTATE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_ROTATE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
|
||||
break;
|
||||
|
||||
case TAG_TRANSFORM_TRANSLATE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_TRANSLATE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
|
||||
break;
|
||||
|
||||
case TAG_TRANSFORM_SCALE_AND_TRANSLATE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_SCALE_AND_TRANSLATE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
|
||||
break;
|
||||
|
||||
case TAG_TRANSFORM_QUAD:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_QUAD";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
|
||||
break;
|
||||
|
||||
case TAG_TIDX:
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_TIDX";
|
||||
#endif
|
||||
|
||||
quint64 value = decodeUInt( isfData );
|
||||
|
||||
if( value < (uint)drawing->transforms_.count() )
|
||||
{
|
||||
drawing->currentTransform_ = drawing->transforms_[ value ];
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Next strokes will use transform #" << value;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qWarning() << "Invalid transform ID!";
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TAG_METRIC_TABLE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_METRIC_TABLE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseMetricTable( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_METRIC_BLOCK:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_METRIC_BLOCK";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseMetricBlock( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_MIDX:
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_MIDX";
|
||||
#endif
|
||||
|
||||
quint64 value = decodeUInt( isfData );
|
||||
|
||||
if( value < (uint)drawing->metrics_.count() )
|
||||
{
|
||||
drawing->currentMetrics_ = drawing->metrics_[ value ];
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Next strokes will use metrics #" << value;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qWarning() << "Invalid metrics ID!";
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TAG_MANTISSA:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_MANTISSA";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_MANTISSA" );
|
||||
break;
|
||||
|
||||
case TAG_PERSISTENT_FORMAT:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_PERSISTENT_FORMAT";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parsePersistentFormat( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_HIMETRIC_SIZE:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_HIMETRIC_SIZE";
|
||||
#endif
|
||||
drawing->error_ = TagsParser::parseHiMetricSize( isfData, *drawing );
|
||||
break;
|
||||
|
||||
case TAG_STROKE_IDS:
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_STROKE_IDS";
|
||||
#endif
|
||||
|
||||
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_STROKE_IDS" );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
// If the tagIndex is known from the GUID table, show it differently
|
||||
if( drawing->maxGuid_ > 0
|
||||
&& tagIndex >= DEFAULT_TAGS_NUMBER && tagIndex <= drawing->maxGuid_ )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Got tag (@" << place << "): TAG_CUSTOM:" << tagIndex;
|
||||
#endif
|
||||
TagsParser::parseCustomTag( isfData, *drawing, tagIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
TagsParser::parseUnsupported( isfData, "Unknown " + QString::number( tagIndex ) );
|
||||
}
|
||||
break;
|
||||
|
||||
} // End of tagIndex switch
|
||||
// Read the next tag from the stream
|
||||
drawing->error_ = TagsParser::nextTag( streamData_, drawing );
|
||||
|
||||
if( drawing->error_ != ISF_ERROR_NONE )
|
||||
{
|
||||
@@ -489,8 +173,12 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
|
||||
qDebug();
|
||||
#endif
|
||||
|
||||
delete streamData_->dataSource;
|
||||
|
||||
if( drawing->error_ != ISF_ERROR_NONE )
|
||||
{
|
||||
delete streamData_;
|
||||
streamData_ = 0;
|
||||
return *drawing;
|
||||
}
|
||||
|
||||
@@ -498,15 +186,17 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
|
||||
|
||||
// Adjust the bounding rectangle to include the strokes borders
|
||||
QSize penSize( drawing->maxPenSize_.toSize() );
|
||||
drawing->boundingRect_.adjust( -penSize.width() - 1, -penSize.height() - 1,
|
||||
+penSize.width() + 1, +penSize.height() + 1 );
|
||||
|
||||
streamData_->boundingRect.adjust( -penSize.width() - 1, -penSize.height() - 1,
|
||||
+penSize.width() + 1, +penSize.height() + 1 );
|
||||
drawing->setBoundingRect( streamData_->boundingRect );
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Drawing bounding rectangle:" << drawing->boundingRect_;
|
||||
qDebug() << "Drawing bounding rectangle:" << drawing->boundingRect();
|
||||
qDebug() << "Maximum thickness:" << drawing->maxPenSize_;
|
||||
#endif
|
||||
|
||||
delete streamData_;
|
||||
streamData_ = 0;
|
||||
return *drawing;
|
||||
}
|
||||
|
||||
@@ -528,7 +218,7 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
|
||||
* need to be decoded first
|
||||
* @return an Isf::Drawing, with null contents on error
|
||||
*/
|
||||
Drawing &Stream::readerGif( const QByteArray &gifRawBytes, bool decodeFromBase64 )
|
||||
Drawing& Stream::readerGif( const QByteArray& gifRawBytes, bool decodeFromBase64 )
|
||||
{
|
||||
QByteArray isfData;
|
||||
|
||||
@@ -549,7 +239,7 @@ Drawing &Stream::readerGif( const QByteArray &gifRawBytes, bool decodeFromBase64
|
||||
gifData.open( QIODevice::ReadOnly );
|
||||
|
||||
// Open the gif file
|
||||
GifFileType *gifImage = DGifOpen( (void*)&gifData, GifReadFromByteArray );
|
||||
GifFileType* gifImage = DGifOpen( (void*)&gifData, GifReadFromByteArray );
|
||||
if( gifImage != 0 )
|
||||
{
|
||||
DGifGetComment( gifImage, data?? );
|
||||
@@ -622,6 +312,51 @@ Drawing &Stream::readerGif( const QByteArray &gifRawBytes, bool decodeFromBase64
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a Fortified-PNG image into a drawing.
|
||||
*
|
||||
* If the PNG image or the ISF data within it are invalid, or if the PNG did not
|
||||
* have any ISF stream within, then a null Drawing is returned.
|
||||
*
|
||||
* @param gifRawBytes Source byte array with a Fortified PNG image
|
||||
* @param decodeFromBase64 True if the bytes are in the Base64 format and
|
||||
* need to be decoded first
|
||||
* @return an Isf::Drawing, with null contents on error
|
||||
*/
|
||||
Drawing& Stream::readerPng( const QByteArray& pngRawBytes, bool decodeFromBase64 )
|
||||
{
|
||||
QByteArray isfData;
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Reading a PNG-Fortified file";
|
||||
#endif
|
||||
|
||||
QByteArray pngBytes( decodeFromBase64
|
||||
? QByteArray::fromBase64( pngRawBytes )
|
||||
: pngRawBytes );
|
||||
|
||||
QImage imageData( QImage::fromData( pngBytes, "PNG" ) );
|
||||
if( ! imageData.isNull() )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "Picture data is valid: checking for the ISF data tag...";
|
||||
#endif
|
||||
isfData = imageData.text( "application/x-ms-ink" ).toLatin1();
|
||||
|
||||
if( ! isfData.isEmpty() )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "ISF data found! Decoding from Base64 and parsing it...";
|
||||
#endif
|
||||
isfData = QByteArray::fromBase64( isfData );
|
||||
}
|
||||
}
|
||||
|
||||
return reader( isfData );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return whether the library was built with Fortified GIF support or not.
|
||||
*
|
||||
@@ -644,9 +379,9 @@ bool Stream::supportsGif()
|
||||
* encoded with Base64 or not
|
||||
* @return Byte array with an ISF data stream
|
||||
*/
|
||||
QByteArray Stream::writer( const Drawing &drawing, bool encodeToBase64 )
|
||||
QByteArray Stream::writer( const Drawing& drawing, bool encodeToBase64 )
|
||||
{
|
||||
if( &drawing == 0 || drawing.isNull() || drawing.error() != ISF_ERROR_NONE )
|
||||
if( drawing.isNull() || drawing.error() != ISF_ERROR_NONE )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qDebug() << "The drawing was not valid!";
|
||||
@@ -654,41 +389,51 @@ QByteArray Stream::writer( const Drawing &drawing, bool encodeToBase64 )
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
DataSource isfData;
|
||||
streamData_ = new StreamData();
|
||||
streamData_->dataSource = new DataSource();
|
||||
DataSource* dataSource = streamData_->dataSource;
|
||||
|
||||
// Add the initial data
|
||||
TagsWriter::prepare( streamData_, &drawing );
|
||||
|
||||
// Write the persistent format tag
|
||||
TagsWriter::addPersistentFormat( isfData, drawing );
|
||||
TagsWriter::addPersistentFormat( streamData_, &drawing );
|
||||
|
||||
// Write the drawing size
|
||||
TagsWriter::addHiMetricSize( isfData, drawing );
|
||||
TagsWriter::addHiMetricSize( streamData_, &drawing );
|
||||
|
||||
// Write the attributes
|
||||
TagsWriter::addAttributeTable( isfData, drawing );
|
||||
TagsWriter::addAttributeTable( streamData_, &drawing );
|
||||
|
||||
// Write the metrics
|
||||
TagsWriter::addMetricsTable( isfData, drawing );
|
||||
TagsWriter::addMetricsTable( streamData_, &drawing );
|
||||
|
||||
// Write the transforms
|
||||
TagsWriter::addTransformationTable( isfData, drawing );
|
||||
TagsWriter::addTransformationTable( streamData_, &drawing );
|
||||
|
||||
// Write the strokes
|
||||
TagsWriter::addStrokes( isfData, drawing );
|
||||
TagsWriter::addStrokes( streamData_, &drawing );
|
||||
|
||||
// Write the stream size (at the start of the stream)
|
||||
encodeUInt( isfData, isfData.size(), true/*prepend*/ );
|
||||
encodeUInt( dataSource, dataSource->size(), true/*prepend*/ );
|
||||
|
||||
// Write the version number (at the start of the stream)
|
||||
encodeUInt( isfData, SUPPORTED_ISF_VERSION, true/*prepend*/ );
|
||||
encodeUInt( dataSource, SUPPORTED_ISF_VERSION, true/*prepend*/ );
|
||||
|
||||
QByteArray data( dataSource->data() );
|
||||
|
||||
delete streamData_->dataSource;
|
||||
delete streamData_;
|
||||
streamData_ = 0;
|
||||
|
||||
// Convert to Base64 if needed
|
||||
if( encodeToBase64 )
|
||||
{
|
||||
return isfData.data().toBase64();
|
||||
return data.toBase64();
|
||||
}
|
||||
else
|
||||
{
|
||||
return isfData.data();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,13 +448,16 @@ QByteArray Stream::writer( const Drawing &drawing, bool encodeToBase64 )
|
||||
* withous GIF support. Use Stream::supportsGif() to verify whether
|
||||
* GIF was compiled in or not.
|
||||
*
|
||||
* The Fortified-GIF format is nothing more than a GIF image with the original
|
||||
* ISF drawing added as a GIF Comment field.
|
||||
*
|
||||
* @see supportsGif()
|
||||
* @param drawing Source drawing
|
||||
* @param encodeToBase64 Whether the converted ISF stream should be
|
||||
* @param encodeToBase64 Whether the converted GIF should be
|
||||
* encoded with Base64 or not
|
||||
* @return Byte array with an ISF data stream
|
||||
* @return Byte array with a GIF data stream (optionally encoded with Base64)
|
||||
*/
|
||||
QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
|
||||
QByteArray Stream::writerGif( const Drawing& drawing, bool encodeToBase64 )
|
||||
{
|
||||
QByteArray imageBytes;
|
||||
|
||||
@@ -730,18 +478,20 @@ QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
|
||||
|
||||
// Initialise the gif variables
|
||||
QBuffer gifData;
|
||||
GifFileType *gifImage = NULL;
|
||||
ColorMapObject *cmap = NULL;
|
||||
int height = isfImage.height();
|
||||
int width = isfImage.width();
|
||||
int numColors = 0;
|
||||
bool gifError = true;
|
||||
GifFileType* gifImage = NULL;
|
||||
ColorMapObject* cmap = NULL;
|
||||
int height = isfImage.height();
|
||||
int width = isfImage.width();
|
||||
int colorCount = 0;
|
||||
int numColors = 0;
|
||||
int gifErrorCode = 0;
|
||||
bool gifError = true;
|
||||
|
||||
// Convert the image to GIF using libgif
|
||||
|
||||
// Open the gif file
|
||||
gifData.open( QIODevice::WriteOnly );
|
||||
gifImage = EGifOpen( (void*)&gifData, GifWriteToByteArray );
|
||||
gifImage = EGifOpen( (void*)&gifData, GifWriteToByteArray, &gifErrorCode );
|
||||
if( gifImage == 0 )
|
||||
{
|
||||
qWarning() << "Couldn't initialize gif library!";
|
||||
@@ -749,21 +499,22 @@ QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
|
||||
}
|
||||
|
||||
// Create the color map
|
||||
numColors = ( isfImage.numColors() << 2 );
|
||||
if( numColors > 256 )
|
||||
colorCount = isfImage.colorCount();
|
||||
numColors = 2;
|
||||
while( numColors < colorCount && numColors < 256 )
|
||||
{
|
||||
numColors = 256;
|
||||
numColors <<= 1;
|
||||
}
|
||||
|
||||
cmap = MakeMapObject( numColors, NULL );
|
||||
if( cmap == 0 && isfImage.numColors() > 1 )
|
||||
cmap = GifMakeMapObject( numColors, NULL );
|
||||
if( cmap == 0 && colorCount > 1 )
|
||||
{
|
||||
qWarning() << "Couldn't create map object for gif conversion (colors:" << isfImage.numColors() << ")!";
|
||||
qWarning() << "Couldn't create map object for gif conversion (colors:" << colorCount << ")!";
|
||||
goto writeError;
|
||||
}
|
||||
|
||||
// Fill in the color map with the colors in the image color table
|
||||
for( int i = 0; i < isfImage.numColors(); ++i )
|
||||
for( int i = 0; i < colorCount && i < numColors; ++i )
|
||||
{
|
||||
const QRgb &color( isfImage.color( i ) );
|
||||
cmap->Colors[i].Red = qRed ( color );
|
||||
@@ -795,7 +546,7 @@ QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
|
||||
// Write every scanline
|
||||
for( int line = 0; line < height; ++line )
|
||||
{
|
||||
if( EGifPutLine( gifImage, isfImage.scanLine( line ), width ) == GIF_ERROR )
|
||||
if( EGifPutLine( gifImage, reinterpret_cast<GifPixelType*>( isfImage.scanLine( line ) ), width ) == GIF_ERROR )
|
||||
{
|
||||
qWarning() << "EGifPutLine failed at scanline" << line
|
||||
<< "(height:" << isfImage.height()
|
||||
@@ -828,9 +579,15 @@ QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
|
||||
else
|
||||
{
|
||||
// Write the extension
|
||||
if( EGifPutExtensionFirst( gifImage, COMMENT_EXT_FUNC_CODE, MAX_GIF_BYTE, isfData.left( MAX_GIF_BYTE ).data() ) == GIF_ERROR )
|
||||
if( EGifPutExtensionLeader( gifImage, COMMENT_EXT_FUNC_CODE ) == GIF_ERROR )
|
||||
{
|
||||
qWarning() << "EGifPutExtensionFirst failed!";
|
||||
qWarning() << "EGifPutExtensionLeader failed!";
|
||||
goto writeError;
|
||||
}
|
||||
|
||||
if( EGifPutExtensionBlock( gifImage, MAX_GIF_BYTE, isfData.left( MAX_GIF_BYTE ).constData() ) == GIF_ERROR )
|
||||
{
|
||||
qWarning() << "EGifPutExtensionBlock failed!";
|
||||
goto writeError;
|
||||
}
|
||||
|
||||
@@ -842,9 +599,9 @@ QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
|
||||
// Write all the full data blocks
|
||||
while( length >= MAX_GIF_BYTE )
|
||||
{
|
||||
if( EGifPutExtensionNext( gifImage, 0, MAX_GIF_BYTE, isfData.mid( pos, MAX_GIF_BYTE ).data() ) == GIF_ERROR )
|
||||
if( EGifPutExtensionBlock( gifImage, MAX_GIF_BYTE, isfData.mid( pos, MAX_GIF_BYTE ).constData() ) == GIF_ERROR )
|
||||
{
|
||||
qWarning() << "EGifPutExtensionNext failed!";
|
||||
qWarning() << "EGifPutExtensionBlock failed!";
|
||||
goto writeError;
|
||||
}
|
||||
|
||||
@@ -855,19 +612,17 @@ QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
|
||||
// Write the last block
|
||||
if( length > 0 )
|
||||
{
|
||||
if( EGifPutExtensionLast( gifImage, 0, length, isfData.mid( pos, MAX_GIF_BYTE ).data() ) == GIF_ERROR )
|
||||
if( EGifPutExtensionBlock( gifImage, length, isfData.mid( pos, MAX_GIF_BYTE ).constData() ) == GIF_ERROR )
|
||||
{
|
||||
qWarning() << "EGifPutExtensionLast (n) failed!";
|
||||
qWarning() << "EGifPutExtensionBlock (tail) failed!";
|
||||
goto writeError;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if( EGifPutExtensionTrailer( gifImage ) == GIF_ERROR )
|
||||
{
|
||||
if( EGifPutExtensionLast( gifImage, 0, 0, 0 ) == GIF_ERROR )
|
||||
{
|
||||
qWarning() << "EGifPutExtensionLast (0) failed!";
|
||||
goto writeError;
|
||||
}
|
||||
qWarning() << "EGifPutExtensionTrailer failed!";
|
||||
goto writeError;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -875,13 +630,19 @@ QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
|
||||
|
||||
writeError:
|
||||
// Clean up the GIF converter etc
|
||||
EGifCloseFile( gifImage );
|
||||
FreeMapObject( cmap );
|
||||
if( gifImage != 0 && EGifCloseFile( gifImage, &gifErrorCode ) == GIF_ERROR )
|
||||
{
|
||||
gifError = true;
|
||||
}
|
||||
if( cmap != 0 )
|
||||
{
|
||||
GifFreeMapObject( cmap );
|
||||
}
|
||||
gifData.close();
|
||||
|
||||
if( gifError )
|
||||
{
|
||||
qWarning() << "GIF error code:" << GifLastError();
|
||||
qWarning() << "GIF error code:" << gifErrorCode << GifErrorString( gifErrorCode );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -908,3 +669,51 @@ writeError:
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a drawing into a Fortified-PNG image.
|
||||
*
|
||||
* The resulting byte array will be empty if the drawing is not valid.
|
||||
*
|
||||
* The Fortified-PNG format is nothing more than a PNG image with the original
|
||||
* ISF drawing added as a PNG text field.
|
||||
*
|
||||
* @param drawing Source drawing
|
||||
* @param encodeToBase64 Whether the converted ISF stream should be
|
||||
* encoded with Base64 or not
|
||||
* @return Byte array with a PNG data stream (optionally encoded with Base64)
|
||||
*/
|
||||
QByteArray Stream::writerPng( const Drawing& drawing, bool encodeToBase64 )
|
||||
{
|
||||
Drawing source( drawing );
|
||||
|
||||
// Get the ISF data stream
|
||||
QByteArray isfData( writer( source ) );
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "PNG-Fortifying an ISF stream of size" << isfData.size();
|
||||
#endif
|
||||
|
||||
// Get the actual image
|
||||
QImage isfImage( source.pixmap().toImage() );
|
||||
|
||||
// Add to it the Base64 version of the ISF drawing, as a comment and in Base64 form
|
||||
// (that's because the PNG text fields are only meant to hold text)
|
||||
isfImage.setText( "application/x-ms-ink", isfData.toBase64() );
|
||||
|
||||
// Save it as a PNG image
|
||||
QBuffer imageBytes;
|
||||
imageBytes.open( QIODevice::WriteOnly );
|
||||
isfImage.save( &imageBytes, "PNG" );
|
||||
imageBytes.close();
|
||||
|
||||
// Convert to Base64 if needed
|
||||
if( encodeToBase64 )
|
||||
{
|
||||
return imageBytes.data().toBase64();
|
||||
}
|
||||
else
|
||||
{
|
||||
return imageBytes.data();
|
||||
}
|
||||
}
|
||||
|
||||
+256
-496
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,516 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2010 by Valerio Pilo *
|
||||
* valerio@kmess.org *
|
||||
* *
|
||||
* Copyright (C) 2010 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "isfqtstroke.h"
|
||||
|
||||
#include "isfqt-internal.h"
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QVector>
|
||||
|
||||
|
||||
using namespace Isf;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Stroke::Stroke()
|
||||
: finalized_( true )
|
||||
, metrics_( 0 )
|
||||
, transform_( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*
|
||||
* @param other The object to clone
|
||||
*/
|
||||
Stroke::Stroke( const Stroke& other )
|
||||
{
|
||||
bezierControlPoints1_ = other.bezierControlPoints1_;
|
||||
bezierControlPoints2_ = other.bezierControlPoints2_;
|
||||
bezierKnots_ = other.bezierKnots_;
|
||||
|
||||
boundingRect_ = other.boundingRect_;
|
||||
color_ = other.color_;
|
||||
finalized_ = other.finalized_;
|
||||
flags_ = other.flags_;
|
||||
hasPressureData_ = other.hasPressureData_;
|
||||
metrics_ = other.metrics_;
|
||||
penSize_ = other.penSize_;
|
||||
points_ = other.points_;
|
||||
transform_ = other.transform_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
Stroke::~Stroke()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Stroke::addPoint( Point point )
|
||||
{
|
||||
// Avoid splitting up the logic
|
||||
addPoints( PointList() << point );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Stroke::addPoints( PointList points )
|
||||
{
|
||||
points_.append( points );
|
||||
|
||||
// Hunt for pressure info
|
||||
if( ! hasPressureData_ )
|
||||
{
|
||||
foreach( Point point, points )
|
||||
{
|
||||
if( point.pressureLevel != 0 )
|
||||
{
|
||||
hasPressureData_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finalized_ = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Given a series of known (knot) points, knots, calculates the control points (c1, c2) to approximate a series of
|
||||
* bezier curves passing smoothly through the knot points.
|
||||
*/
|
||||
void Stroke::bezierCalculateControlPoints()
|
||||
{
|
||||
// bezierKnots_.clear();
|
||||
// bezierControlPoints1_.clear();
|
||||
// bezierControlPoints2_.clear();
|
||||
|
||||
int numPoints = points_.size();
|
||||
|
||||
// For a better curve, don't pass through all of points:
|
||||
// skip about 70% of them
|
||||
int toSkip = 0.70 * numPoints;
|
||||
int step = numPoints / ( numPoints - toSkip );
|
||||
step = ( step < 1 ) ? 1 : step; // Sanity check
|
||||
|
||||
for( int i = 0; i < numPoints; i += step )
|
||||
{
|
||||
bezierKnots_.append( points_.at(i).position );
|
||||
}
|
||||
|
||||
// always pass through the last point.
|
||||
bezierKnots_.append( points_.last().position );
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if( bezierKnots_.size() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int n = bezierKnots_.size() - 1;
|
||||
if( n < 1 )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG
|
||||
qWarning() << "Require at least two knot points to generate Bezier control points; ignoring.";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// special case: Bezier curve should be a straight line.
|
||||
if( n == 1 )
|
||||
{
|
||||
QPointF cp1, cp2;
|
||||
QPointF k1 = bezierKnots_.at(0); // knot point 1
|
||||
QPointF k2 = bezierKnots_.at(1); // knot point 2
|
||||
|
||||
cp1.setX( ( 2 * k1.x() + k2.x() ) / 3.0 );
|
||||
cp1.setY( ( 2 * k1.y() + k2.y() ) / 3.0 );
|
||||
|
||||
cp2.setX( ( 2 * cp1.x() - k1.x() ) );
|
||||
cp2.setY( ( 2 * cp1.y() - k1.y() ) );
|
||||
|
||||
bezierControlPoints1_.append( cp1 );
|
||||
bezierControlPoints2_.append( cp2 );
|
||||
|
||||
return; // done!
|
||||
}
|
||||
|
||||
// right hand side vector.
|
||||
QVector<double> rhs( n );
|
||||
|
||||
// set RHS x values
|
||||
for( int i = 1; i < n-1; i++ )
|
||||
{
|
||||
rhs[i] = 4 * bezierKnots_[i].x() + 2 * bezierKnots_[i+1].x();
|
||||
}
|
||||
|
||||
rhs[0] = bezierKnots_[0].x() + 2 * bezierKnots_[1].x();
|
||||
rhs[n-1] = ( 8 * bezierKnots_[n-1].x() + bezierKnots_[n].x() ) / 2.0;
|
||||
|
||||
// get the first ctl points x values.
|
||||
QVector<double> x( n );
|
||||
bezierGetFirstControlPoints( rhs.data(), x.data(), n );
|
||||
|
||||
|
||||
// now set RHS y-values.
|
||||
for(int i = 1; i < n-1; i++ )
|
||||
{
|
||||
rhs[i] = 4 * bezierKnots_[i].y() + 2 * bezierKnots_[i+1].y();
|
||||
}
|
||||
|
||||
rhs[0] = bezierKnots_[0].y() + 2 * bezierKnots_[1].y();
|
||||
rhs[n-1] = ( 8 * bezierKnots_[n-1].y() + bezierKnots_[n].y() ) / 2.0;
|
||||
|
||||
QVector<double> y( n );
|
||||
bezierGetFirstControlPoints( rhs.data(), y.data(), n );
|
||||
|
||||
// now fill the output QList.
|
||||
for( int i = 0; i < n; i++ )
|
||||
{
|
||||
QPointF cp1( x[i], y[i] );
|
||||
QPointF cp2;
|
||||
|
||||
// second ctl point
|
||||
if ( i < n-1 )
|
||||
{
|
||||
cp2 = QPointF( 2 * bezierKnots_[i+1].x() - x[i+1],
|
||||
2 * bezierKnots_[i+1].y() - y[i+1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
cp2 = QPointF( ( bezierKnots_[n].x() + x[n-1] ) / 2,
|
||||
( bezierKnots_[n].y() + y[n-1] ) / 2 );
|
||||
}
|
||||
|
||||
bezierControlPoints1_.append( cp1 );
|
||||
bezierControlPoints2_.append( cp2 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Solves the system for the first control points.
|
||||
void Stroke::bezierGetFirstControlPoints( double rhs[], double* xOut, int n )
|
||||
{
|
||||
double* x = xOut; // solution vector.
|
||||
QVector<double> tmp( n ); // temp workspace.
|
||||
|
||||
double b = 2.0;
|
||||
x[0] = rhs[0] / b;
|
||||
for( int i = 1; i < n; i++ ) // decomposition and forward substitution
|
||||
{
|
||||
tmp[i] = 1 / b;
|
||||
b = ( i < n - 1 ? 4.0 : 3.5 ) - tmp[i];
|
||||
x[i] = (rhs[i] - x[i-1]) / b;
|
||||
}
|
||||
|
||||
for( int i = 1; i < n; i++ )
|
||||
{
|
||||
x[n-i-1] -= tmp[n-i] * x[n-i]; // back substitution.
|
||||
}
|
||||
|
||||
// results are in xOut.
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the rectangle which contains this stroke.
|
||||
*
|
||||
* @return Rectangle
|
||||
*/
|
||||
QRect Stroke::boundingRect() const
|
||||
{
|
||||
return boundingRect_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QColor Stroke::color() const
|
||||
{
|
||||
return color_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply the changes to the stroke.
|
||||
*
|
||||
* Calculating the stroke bounds is complex, so a lazy approach was
|
||||
* chosen instead of recalculating them for every added point.
|
||||
*/
|
||||
void Stroke::finalize()
|
||||
{
|
||||
if( finalized_ )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// A polygon is used to determine the stroke's bounding rect
|
||||
quint64 numPoints = points_.count();
|
||||
QPolygon polygon( numPoints );
|
||||
for( quint64 index = 0; index < numPoints; ++index )
|
||||
{
|
||||
polygon.setPoint( index, points_.at( index ).position );
|
||||
}
|
||||
|
||||
// Transform the bounding rect with the current transformation
|
||||
if( transform_ )
|
||||
{
|
||||
polygon = transform_->map( polygon );
|
||||
}
|
||||
|
||||
// Set the bounding rectangle, expanded it to also accommodate pen size
|
||||
float halfPenSize = penSize_.width() / 2;
|
||||
boundingRect_ = polygon.boundingRect().adjusted( -( halfPenSize ), -( halfPenSize ),
|
||||
halfPenSize, halfPenSize );
|
||||
|
||||
// Finally, pre-calculate the stroke paths
|
||||
painterPath();
|
||||
|
||||
finalized_ = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the stroke drawing flags.
|
||||
*
|
||||
* @return Stroke flags
|
||||
*/
|
||||
StrokeFlags Stroke::flags() const
|
||||
{
|
||||
return flags_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get whether the stroke contains pressure information.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool Stroke::hasPressureData() const
|
||||
{
|
||||
return hasPressureData_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the stroke metrics.
|
||||
*
|
||||
* @return Metrics*
|
||||
*/
|
||||
Metrics* Stroke::metrics()
|
||||
{
|
||||
return metrics_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a painter path to draw this stroke.
|
||||
*
|
||||
* The path is adjusted according to the drawing flags.
|
||||
* Given a list of knot points, generates a QPainterPath that describes the stroke.
|
||||
*
|
||||
* If the FitToCurve flag is present, the stroke path is generated using bezier curves
|
||||
* to approximate the stroke, giving a much smoother appearance.
|
||||
*
|
||||
* @see calculateControlPoints()
|
||||
* @return QPainterPath
|
||||
*/
|
||||
QPainterPath Stroke::painterPath()
|
||||
{
|
||||
int numPoints = points_.size();
|
||||
|
||||
if( numPoints == 0 )
|
||||
{
|
||||
return QPainterPath();
|
||||
}
|
||||
|
||||
QPointF startPos( points_.first().position );
|
||||
|
||||
QPainterPath path( startPos );
|
||||
|
||||
if( ( flags_ & FitToCurve ) == false )
|
||||
{
|
||||
foreach( Point point, points_ )
|
||||
{
|
||||
path.lineTo( point.position );
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// don't calculate control points if they've
|
||||
// already been calculated.
|
||||
if( bezierKnots_.isEmpty() )
|
||||
{
|
||||
bezierCalculateControlPoints();
|
||||
}
|
||||
|
||||
for( int i = 0; i < bezierControlPoints1_.size(); i++ )
|
||||
{
|
||||
// draw the bezier curve!
|
||||
path.cubicTo( bezierControlPoints1_[ i ], bezierControlPoints2_[ i ], bezierKnots_[ i + 1 ] );
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the current pen size
|
||||
*
|
||||
* @return QSizeF of the stroke pen
|
||||
*/
|
||||
QSizeF Stroke::penSize() const
|
||||
{
|
||||
return penSize_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the list of points
|
||||
*
|
||||
* @return List of stroke points
|
||||
*/
|
||||
PointList& Stroke::points()
|
||||
{
|
||||
return points_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change pen color
|
||||
*
|
||||
* @param newColor new pen color
|
||||
*/
|
||||
void Stroke::setColor( QColor newColor )
|
||||
{
|
||||
color_ = newColor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change a flag
|
||||
*
|
||||
* @param flag The flag to alter
|
||||
* @param set If true, the flag will be set. If false, it will be unset.
|
||||
*/
|
||||
void Stroke::setFlag( StrokeFlag flag, bool set )
|
||||
{
|
||||
if( set )
|
||||
{
|
||||
flags_ |= flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags_ ^= flag;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change stroke flags all at once.
|
||||
*
|
||||
* @param newFlags Flags bitfield
|
||||
*/
|
||||
void Stroke::setFlags( StrokeFlags newFlags )
|
||||
{
|
||||
flags_ = newFlags;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the current pen size
|
||||
*
|
||||
* @param newMetrics The new metrics object
|
||||
*/
|
||||
void Stroke::setMetrics( Metrics* newMetrics )
|
||||
{
|
||||
metrics_ = newMetrics;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the current pen size
|
||||
*
|
||||
* @return QSizeF of the stroke pen
|
||||
*/
|
||||
void Stroke::setPenSize( QSizeF newSize )
|
||||
{
|
||||
penSize_ = newSize;
|
||||
|
||||
// The bounding box changes with pen size
|
||||
finalized_ = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply a transformation to the stroke.
|
||||
*
|
||||
* The stroke doesn't take ownership of the transformation.
|
||||
*
|
||||
* @param newTransform Transformation to apply
|
||||
*/
|
||||
void Stroke::setTransform( QMatrix* newTransform )
|
||||
{
|
||||
transform_ = newTransform;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the stroke transformation, if any
|
||||
*
|
||||
* @return QMatrix, possibly null
|
||||
*/
|
||||
QMatrix* Stroke::transform()
|
||||
{
|
||||
return transform_;
|
||||
}
|
||||
+606
-232
File diff suppressed because it is too large
Load Diff
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -39,11 +37,7 @@ namespace Isf
|
||||
|
||||
|
||||
// Forward declarations
|
||||
namespace Compress
|
||||
{
|
||||
class DataSource;
|
||||
}
|
||||
using Compress::DataSource;
|
||||
class StreamData;
|
||||
class Drawing;
|
||||
|
||||
|
||||
@@ -57,27 +51,29 @@ namespace Isf
|
||||
{
|
||||
|
||||
public: // Static public methods
|
||||
static IsfError parseCustomTag( DataSource &source, Drawing &drawing, quint64 tagIndex );
|
||||
static IsfError parseGuidTable( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseHiMetricSize( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseInkSpaceRectangle( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseAttributeBlock( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseAttributeTable( DataSource &source, Drawing &drawing );
|
||||
static IsfError parsePersistentFormat( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseMetricBlock( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseMetricTable( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseTransformation( DataSource &source, Drawing &drawing, quint64 transformType );
|
||||
static IsfError parseTransformationTable( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseStroke( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseStrokeDescBlock( DataSource &source, Drawing &drawing );
|
||||
static IsfError parseStrokeDescTable( DataSource &source, Drawing &drawing );
|
||||
static IsfError nextTag( StreamData* streamData, Drawing* drawing );
|
||||
|
||||
static IsfError parseCustomTag( StreamData* streamData, Drawing* drawing, quint64 tagIndex );
|
||||
static IsfError parseGuidTable( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseHiMetricSize( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseInkSpaceRectangle( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseAttributeBlock( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseAttributeTable( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parsePersistentFormat( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseMetricBlock( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseMetricTable( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseTransformation( StreamData* streamData, Drawing* drawing, quint64 transformType );
|
||||
static IsfError parseTransformationTable( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseStroke( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseStrokeDescBlock( StreamData* streamData, Drawing* drawing );
|
||||
static IsfError parseStrokeDescTable( StreamData* streamData, Drawing* drawing );
|
||||
|
||||
public: // Static public debugging methods
|
||||
static IsfError parseUnsupported( DataSource &source, const QString &tagName );
|
||||
static IsfError parseUnsupported( StreamData* streamData, const QString& tagName );
|
||||
|
||||
private: // Static private debugging methods
|
||||
static QByteArray analyzePayload( DataSource &source, const QString &tagName );
|
||||
static QByteArray analyzePayload( DataSource &source, const quint64 payloadSize, const QString &message = QString() );
|
||||
static QByteArray analyzePayload( StreamData* streamData, const QString& tagName );
|
||||
static QByteArray analyzePayload( StreamData* streamData, const quint64 payloadSize, const QString& message = QString() );
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -46,7 +44,7 @@ using namespace Isf::Compress;
|
||||
* @param drawing Drawing from which to obtain the data to write
|
||||
* @return IsfError
|
||||
*/
|
||||
IsfError TagsWriter::addPersistentFormat( DataSource &source, const Drawing &drawing )
|
||||
IsfError TagsWriter::addPersistentFormat( StreamData* streamData, const Drawing* drawing )
|
||||
{
|
||||
Q_UNUSED( drawing );
|
||||
|
||||
@@ -57,7 +55,7 @@ IsfError TagsWriter::addPersistentFormat( DataSource &source, const Drawing &dra
|
||||
tagContents.prepend( encodeUInt( tagContents.size() ) );
|
||||
tagContents.prepend( encodeUInt( TAG_PERSISTENT_FORMAT ) );
|
||||
|
||||
source.append( tagContents );
|
||||
streamData->dataSource->append( tagContents );
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Persistent Format version";
|
||||
@@ -75,19 +73,20 @@ IsfError TagsWriter::addPersistentFormat( DataSource &source, const Drawing &dra
|
||||
* @param drawing Drawing from which to obtain the data to write
|
||||
* @return IsfError
|
||||
*/
|
||||
IsfError TagsWriter::addHiMetricSize( DataSource &source, const Drawing &drawing )
|
||||
IsfError TagsWriter::addHiMetricSize( StreamData* streamData, const Drawing* drawing )
|
||||
{
|
||||
QByteArray tagContents;
|
||||
|
||||
tagContents.append( encodeInt( drawing.size_.width () ) );
|
||||
tagContents.append( encodeInt( drawing.size_.height() ) );
|
||||
QPoint size( drawing->boundingRect().bottomRight() );
|
||||
tagContents.append( encodeInt( size.x() ) );
|
||||
tagContents.append( encodeInt( size.y() ) );
|
||||
|
||||
encodeUInt( source, TAG_HIMETRIC_SIZE );
|
||||
encodeUInt( source, tagContents.size() );
|
||||
source.append( tagContents );
|
||||
encodeUInt( streamData->dataSource, TAG_HIMETRIC_SIZE );
|
||||
encodeUInt( streamData->dataSource, tagContents.size() );
|
||||
streamData->dataSource->append( tagContents );
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Added drawing dimensions:" << drawing.size_;
|
||||
qDebug() << "- Added drawing dimensions:" << size;
|
||||
#endif
|
||||
|
||||
return ISF_ERROR_NONE;
|
||||
@@ -105,68 +104,85 @@ IsfError TagsWriter::addHiMetricSize( DataSource &source, const Drawing &drawing
|
||||
* @param drawing Drawing from which to obtain the data to write
|
||||
* @return IsfError
|
||||
*/
|
||||
IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawing )
|
||||
IsfError TagsWriter::addAttributeTable( StreamData* streamData, const Drawing* drawing )
|
||||
{
|
||||
Q_UNUSED( drawing );
|
||||
|
||||
QByteArray blockData;
|
||||
QByteArray tagContents;
|
||||
AttributeSet defaultAttributeSet;
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Adding" << drawing.attributeSets_.count() << "attributes...";
|
||||
quint8 counter = 0;
|
||||
#endif
|
||||
|
||||
foreach( const AttributeSet *info, drawing.attributeSets_ )
|
||||
// Add default attributes if the drawing didn't contain any
|
||||
if( streamData->attributeSets.isEmpty() )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Adding a default attribute set...";
|
||||
#endif
|
||||
AttributeSet set;
|
||||
streamData->attributeSets.append( set );
|
||||
}
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
else
|
||||
{
|
||||
qDebug() << "- Adding" << streamData->attributeSets.count() << "attributes...";
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach( const AttributeSet set, streamData->attributeSets )
|
||||
{
|
||||
// Add the color to the attribute block
|
||||
if( info->color != defaultAttributeSet.color )
|
||||
if( set.color != defaultAttributeSet.color )
|
||||
{
|
||||
blockData.append( encodeUInt( GUID_COLORREF ) );
|
||||
|
||||
// Prepare the color value, it needs to be stored in BGR format,
|
||||
// in the 24 least significant bits
|
||||
quint64 value = ( info->color.blue () << 16 )
|
||||
| ( info->color.green() << 8 )
|
||||
| ( info->color.red () << 0 );
|
||||
quint64 value = ( set.color.blue () << 16 )
|
||||
| ( set.color.green() << 8 )
|
||||
| ( set.color.red () << 0 );
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << " - Color:" << info->color.name();
|
||||
qDebug() << " - Color:" << set.color.name();
|
||||
#endif
|
||||
blockData.append( encodeUInt( value ) );
|
||||
|
||||
// Add the transparency if needed
|
||||
if( info->color.alpha() < 255 )
|
||||
if( set.color.alpha() < 255 )
|
||||
{
|
||||
blockData.append( encodeUInt( GUID_TRANSPARENCY ) );
|
||||
blockData.append( encodeUInt( info->color.alpha() ) );
|
||||
blockData.append( encodeUInt( set.color.alpha() ) );
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << " - Alpha:" << info->color.alpha();
|
||||
qDebug() << " - Alpha:" << set.color.alpha();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Add the pen size
|
||||
if( info->penSize != defaultAttributeSet.penSize )
|
||||
if( set.penSize != defaultAttributeSet.penSize )
|
||||
{
|
||||
blockData.append( encodeUInt( GUID_PEN_WIDTH ) );
|
||||
blockData.append( encodeUInt( info->penSize.width() * HiMetricToPixel ) );
|
||||
blockData.append( encodeUInt( set.penSize.width() * HiMetricToPixel ) );
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << " - Pen width:" << ( info->penSize.width() * HiMetricToPixel );
|
||||
qDebug() << " - Pen width:" << ( set.penSize.width() * HiMetricToPixel );
|
||||
#endif
|
||||
if( info->penSize.width() != info->penSize.height() )
|
||||
if( set.penSize.width() != set.penSize.height() )
|
||||
{
|
||||
blockData.append( encodeUInt( GUID_PEN_HEIGHT ) );
|
||||
blockData.append( encodeUInt( info->penSize.height() * HiMetricToPixel ) );
|
||||
blockData.append( encodeUInt( set.penSize.height() * HiMetricToPixel ) );
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << " - Pen height:" << ( info->penSize.height() * HiMetricToPixel );
|
||||
qDebug() << " - Pen height:" << ( set.penSize.height() * HiMetricToPixel );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Add the other drawing flags
|
||||
if( info->flags != defaultAttributeSet.flags )
|
||||
if( set.flags != defaultAttributeSet.flags )
|
||||
{
|
||||
StrokeFlags flags = info->flags;
|
||||
StrokeFlags flags = set.flags;
|
||||
if( flags & IsRectangle )
|
||||
{
|
||||
blockData.append( encodeUInt( GUID_PEN_TIP ) );
|
||||
@@ -185,9 +201,6 @@ IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawi
|
||||
}
|
||||
*/
|
||||
|
||||
// Add FitToCurve too for now, as a test
|
||||
flags |= FitToCurve;
|
||||
|
||||
// Copy the other flags as they are
|
||||
blockData.append( encodeUInt( GUID_DRAWING_FLAGS ) );
|
||||
blockData.append( encodeUInt( flags ) );
|
||||
@@ -207,7 +220,7 @@ IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawi
|
||||
#endif
|
||||
}
|
||||
|
||||
if( drawing.attributeSets_.count() > 1 )
|
||||
if( streamData->attributeSets.count() > 1 )
|
||||
{
|
||||
tagContents.prepend( encodeUInt( tagContents.size() ) );
|
||||
tagContents.prepend( encodeUInt( TAG_DRAW_ATTRS_TABLE ) );
|
||||
@@ -217,7 +230,7 @@ IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawi
|
||||
tagContents.prepend( encodeUInt( TAG_DRAW_ATTRS_BLOCK ) );
|
||||
}
|
||||
|
||||
source.append( tagContents );
|
||||
streamData->dataSource->append( tagContents );
|
||||
|
||||
return ISF_ERROR_NONE;
|
||||
}
|
||||
@@ -234,27 +247,29 @@ IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawi
|
||||
* @param drawing Drawing from which to obtain the data to write
|
||||
* @return IsfError
|
||||
*/
|
||||
IsfError TagsWriter::addMetricsTable( DataSource &source, const Drawing &drawing )
|
||||
IsfError TagsWriter::addMetricsTable( StreamData* streamData, const Drawing* drawing )
|
||||
{
|
||||
Q_UNUSED( drawing );
|
||||
|
||||
QByteArray metricData;
|
||||
QByteArray metricBlockData;
|
||||
QByteArray tagData;
|
||||
Metrics defaultMetrics;
|
||||
Metric *defaultMetric;
|
||||
Metric* defaultMetric;
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Adding" << drawing.metrics_.count() << "metrics...";
|
||||
qDebug() << "- Adding" << streamData->metrics.count() << "metrics...";
|
||||
quint8 counter = 0;
|
||||
#endif
|
||||
|
||||
foreach( const Metrics *metrics, drawing.metrics_ )
|
||||
foreach( const Metrics* metrics, streamData->metrics )
|
||||
{
|
||||
QMapIterator<int,Metric> it( metrics->items );
|
||||
while( it.hasNext() )
|
||||
{
|
||||
it.next();
|
||||
const quint64 &property = it.key ();
|
||||
const Metric &metric = it.value();
|
||||
const quint64& property = it.key ();
|
||||
const Metric& metric = it.value();
|
||||
|
||||
// Skip metrics which are set to the default
|
||||
defaultMetric = &defaultMetrics.items[ property ];
|
||||
@@ -293,17 +308,17 @@ IsfError TagsWriter::addMetricsTable( DataSource &source, const Drawing &drawing
|
||||
#endif
|
||||
}
|
||||
|
||||
if( drawing.metrics_.count() > 1 )
|
||||
if( streamData->metrics.count() > 1 )
|
||||
{
|
||||
tagData.prepend( encodeUInt( TAG_METRIC_TABLE ) );
|
||||
}
|
||||
else if ( drawing.metrics_.count() == 1 )
|
||||
else if ( streamData->metrics.count() == 1 )
|
||||
{
|
||||
tagData.prepend( encodeUInt( TAG_METRIC_BLOCK ) );
|
||||
}
|
||||
// else: don't do anything.
|
||||
|
||||
source.append( tagData );
|
||||
streamData->dataSource->append( tagData );
|
||||
|
||||
return ISF_ERROR_NONE;
|
||||
}
|
||||
@@ -320,8 +335,10 @@ IsfError TagsWriter::addMetricsTable( DataSource &source, const Drawing &drawing
|
||||
* @param drawing Drawing from which to obtain the data to write
|
||||
* @return IsfError
|
||||
*/
|
||||
IsfError TagsWriter::addTransformationTable( DataSource &source, const Drawing &drawing )
|
||||
IsfError TagsWriter::addTransformationTable( StreamData* streamData, const Drawing* drawing )
|
||||
{
|
||||
Q_UNUSED( drawing );
|
||||
|
||||
QByteArray blockData;
|
||||
QByteArray tagContents;
|
||||
quint64 transformTag;
|
||||
@@ -337,11 +354,11 @@ IsfError TagsWriter::addTransformationTable( DataSource &source, const Drawing &
|
||||
*/
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Adding" << drawing.transforms_.count() << "transformations...";
|
||||
qDebug() << "- Adding" << streamData->transforms.count() << "transformations...";
|
||||
quint8 counter = 0;
|
||||
#endif
|
||||
|
||||
foreach( const QMatrix *trans, drawing.transforms_ )
|
||||
foreach( const QMatrix* trans, streamData->transforms )
|
||||
{
|
||||
/*
|
||||
* All transforms are written backwards because they're stored my most
|
||||
@@ -443,24 +460,27 @@ IsfError TagsWriter::addTransformationTable( DataSource &source, const Drawing &
|
||||
}
|
||||
|
||||
|
||||
if ( drawing.transforms_.size() == 0 )
|
||||
if ( streamData->transforms.size() == 0 )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Added default transformation";
|
||||
#endif
|
||||
|
||||
// write the default transform.
|
||||
const QMatrix *transform = &drawing.defaultTransform_;
|
||||
// Write the default transform
|
||||
QMatrix defaultTransform;
|
||||
defaultTransform.scale( 1.f, 1.f );
|
||||
defaultTransform.translate( .0f, .0f );
|
||||
|
||||
tagContents.append( TAG_TRANSFORM_ISOTROPIC_SCALE );
|
||||
tagContents.append( encodeFloat( transform->m11() * HiMetricToPixel ) );
|
||||
tagContents.append( encodeFloat( defaultTransform.m11() * HiMetricToPixel ) );
|
||||
}
|
||||
else if ( drawing.transforms_.size() > 1 )
|
||||
else if ( streamData->transforms.size() > 1 )
|
||||
{
|
||||
tagContents.prepend( encodeUInt( tagContents.size() ) );
|
||||
tagContents.prepend( encodeUInt( TAG_TRANSFORM_TABLE ) );
|
||||
}
|
||||
|
||||
source.append( tagContents );
|
||||
streamData->dataSource->append( tagContents );
|
||||
|
||||
return ISF_ERROR_NONE;
|
||||
}
|
||||
@@ -474,76 +494,75 @@ IsfError TagsWriter::addTransformationTable( DataSource &source, const Drawing &
|
||||
* @param drawing Drawing from which to obtain the data to write
|
||||
* @return IsfError
|
||||
*/
|
||||
IsfError TagsWriter::addStrokes( DataSource &source, const Drawing &drawing )
|
||||
IsfError TagsWriter::addStrokes( StreamData* streamData, const Drawing* drawing )
|
||||
{
|
||||
QByteArray blockData;
|
||||
QByteArray tagContents;
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Adding" << drawing.strokes_.count() << "strokes...";
|
||||
qDebug() << "- Adding" << drawing->strokes_.count() << "strokes...";
|
||||
quint8 counter = 0;
|
||||
#endif
|
||||
|
||||
// Last set of attibutes applied to a stroke
|
||||
Metrics *currentMetrics = 0;
|
||||
AttributeSet *currentAttributeSet = 0;
|
||||
QMatrix *currentTransform = 0;
|
||||
AttributeSet currentAttributeSet;
|
||||
const Metrics* currentMetrics = 0;
|
||||
const QMatrix* currentTransform = 0;
|
||||
|
||||
foreach( const Stroke *stroke, drawing.strokes_ )
|
||||
foreach( Stroke* stroke, drawing->strokes_ )
|
||||
{
|
||||
// There is more than one set of metrics, assign each stroke to its own
|
||||
if( drawing.metrics_.count() > 1 )
|
||||
if( streamData->metrics.count() > 1 )
|
||||
{
|
||||
// Make sure that the first strokes use the first metrics list (write a MIDX only
|
||||
// when needed)
|
||||
if( currentMetrics == 0 )
|
||||
{
|
||||
currentMetrics = drawing.metrics_.first();
|
||||
currentMetrics = streamData->metrics.first();
|
||||
}
|
||||
|
||||
// Only write a MIDX if this stroke needs different metrics than the last stroke
|
||||
if( currentMetrics != stroke->metrics && stroke->metrics != 0 )
|
||||
Metrics* metrics = stroke->metrics();
|
||||
if( metrics && currentMetrics != metrics )
|
||||
{
|
||||
currentMetrics = stroke->metrics;
|
||||
currentMetrics = metrics;
|
||||
blockData.append( encodeUInt( TAG_MIDX ) );
|
||||
blockData.append( encodeUInt( drawing.metrics_.indexOf( stroke->metrics ) ) );
|
||||
blockData.append( encodeUInt( streamData->metrics.indexOf( metrics ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
// There is more than one set of attributes, assign each stroke to its own
|
||||
if( drawing.attributeSets_.count() > 1 )
|
||||
if( streamData->attributeSets.count() > 1 )
|
||||
{
|
||||
// Make sure that the first strokes use the first attribute set (write a DIDX only
|
||||
// when needed)
|
||||
if( currentAttributeSet == 0 )
|
||||
{
|
||||
currentAttributeSet = drawing.attributeSets_.first();
|
||||
}
|
||||
|
||||
// Only write a DIDX if this stroke needs a different attribute set than the last stroke
|
||||
if( currentAttributeSet != stroke->attributes && stroke->attributes != 0 )
|
||||
if( currentAttributeSet.color != stroke->color()
|
||||
|| currentAttributeSet.flags != stroke->flags()
|
||||
|| currentAttributeSet.penSize != stroke->penSize() )
|
||||
{
|
||||
currentAttributeSet = stroke->attributes;
|
||||
currentAttributeSet.color = stroke->color();
|
||||
currentAttributeSet.flags = stroke->flags();
|
||||
currentAttributeSet.penSize = stroke->penSize();
|
||||
|
||||
blockData.append( encodeUInt( TAG_DIDX ) );
|
||||
blockData.append( encodeUInt( drawing.attributeSets_.indexOf( stroke->attributes ) ) );
|
||||
blockData.append( encodeUInt( streamData->attributeSets.indexOf( currentAttributeSet ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that the first strokes use the first transform (write a TIDX only
|
||||
// when needed)
|
||||
if ( drawing.transforms_.count() > 0 )
|
||||
if ( streamData->transforms.count() > 0 )
|
||||
{
|
||||
if( currentTransform == 0 )
|
||||
{
|
||||
currentTransform = drawing.transforms_.first();
|
||||
currentTransform = streamData->transforms.first();
|
||||
}
|
||||
|
||||
// Only write a TIDX if this stroke needs a different transform than the last stroke
|
||||
if( currentTransform != stroke->transform && stroke->transform != 0 )
|
||||
if( currentTransform != stroke->transform() && stroke->transform() != 0 )
|
||||
{
|
||||
currentTransform = stroke->transform;
|
||||
currentTransform = stroke->transform();
|
||||
blockData.append( encodeUInt( TAG_TIDX ) );
|
||||
blockData.append( encodeUInt( drawing.transforms_.indexOf( stroke->transform ) ) );
|
||||
blockData.append( encodeUInt( streamData->transforms.indexOf( stroke->transform() ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,7 +576,7 @@ IsfError TagsWriter::addStrokes( DataSource &source, const Drawing &drawing )
|
||||
// Write this stroke in the stream
|
||||
|
||||
QList<qint64> xPoints, yPoints;
|
||||
foreach( const Point &point, stroke->points )
|
||||
foreach( const Point& point, stroke->points() )
|
||||
{
|
||||
xPoints.append( point.position.x() );
|
||||
yPoints.append( point.position.y() );
|
||||
@@ -568,7 +587,7 @@ IsfError TagsWriter::addStrokes( DataSource &source, const Drawing &drawing )
|
||||
|
||||
// The stroke is made by tag, then payload size, then number of points, then
|
||||
// the compressed points data
|
||||
blockData.prepend( encodeUInt( stroke->points.count() ) );
|
||||
blockData.prepend( encodeUInt( stroke->points().count() ) );
|
||||
blockData.prepend( encodeUInt( blockData.size() ) );
|
||||
blockData.prepend( encodeUInt( TAG_STROKE ) );
|
||||
|
||||
@@ -580,7 +599,80 @@ IsfError TagsWriter::addStrokes( DataSource &source, const Drawing &drawing )
|
||||
#endif
|
||||
}
|
||||
|
||||
source.append( tagContents );
|
||||
streamData->dataSource->append( tagContents );
|
||||
|
||||
return ISF_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the stream data for writing.
|
||||
*
|
||||
* @param source Data Source where to write bytes to
|
||||
* @param drawing Drawing from which to obtain the data to write
|
||||
* @return IsfError
|
||||
*/
|
||||
IsfError TagsWriter::prepare( StreamData* streamData, const Drawing* drawing )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Optimizing data...";
|
||||
#endif
|
||||
|
||||
streamData->attributeSets.clear();
|
||||
streamData->metrics.clear();
|
||||
streamData->transforms.clear();
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << " - " << drawing->strokes_.count() << "strokes to optimize";
|
||||
#endif
|
||||
|
||||
// Prepare the list of attributes
|
||||
foreach( Stroke* stroke, drawing->strokes_ )
|
||||
{
|
||||
AttributeSet set;
|
||||
set.color = stroke->color();
|
||||
set.flags = stroke->flags();
|
||||
set.penSize = stroke->penSize();
|
||||
|
||||
Metrics* metrics = stroke->metrics();
|
||||
QMatrix* transform = stroke->transform();
|
||||
|
||||
if( ! streamData->attributeSets.contains( set ) )
|
||||
{
|
||||
streamData->attributeSets.append( set );
|
||||
}
|
||||
if( metrics && ! streamData->metrics.contains( metrics ) )
|
||||
{
|
||||
streamData->metrics.append( metrics );
|
||||
}
|
||||
if( transform && ! streamData->transforms.contains( transform ) )
|
||||
{
|
||||
streamData->transforms.append( transform );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
int count = 0;
|
||||
#endif
|
||||
|
||||
// Add default elements if the drawing didn't contain any
|
||||
if( streamData->attributeSets.isEmpty() )
|
||||
{
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << " - Added " << count << "default elements";
|
||||
#endif
|
||||
AttributeSet set;
|
||||
streamData->attributeSets.append( set );
|
||||
}
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << " - Added " << count << "default elements";
|
||||
#endif
|
||||
|
||||
#ifdef ISFQT_DEBUG_VERBOSE
|
||||
qDebug() << "- Optimization phase complete";
|
||||
#endif
|
||||
|
||||
return ISF_ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* *
|
||||
* Copyright (C) 2009 by Adam Goossens *
|
||||
* adam@kmess.org *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation; either version 2.1 of the *
|
||||
@@ -52,13 +50,13 @@ namespace Isf
|
||||
class TagsWriter
|
||||
{
|
||||
public: // Static public methods
|
||||
static IsfError addPersistentFormat( DataSource &source, const Drawing &drawing );
|
||||
static IsfError addHiMetricSize( DataSource &source, const Drawing &drawing );
|
||||
static IsfError addAttributeTable( DataSource &source, const Drawing &drawing );
|
||||
static IsfError addMetricsTable( DataSource &source, const Drawing &drawing );
|
||||
static IsfError addTransformationTable( DataSource &source, const Drawing &drawing );
|
||||
static IsfError addStrokes( DataSource &source, const Drawing &drawing );
|
||||
|
||||
static IsfError addPersistentFormat( StreamData* streamData, const Drawing* drawing );
|
||||
static IsfError addHiMetricSize( StreamData* streamData, const Drawing* drawing );
|
||||
static IsfError addAttributeTable( StreamData* streamData, const Drawing* drawing );
|
||||
static IsfError addMetricsTable( StreamData* streamData, const Drawing* drawing );
|
||||
static IsfError addTransformationTable( StreamData* streamData, const Drawing* drawing );
|
||||
static IsfError addStrokes( StreamData* streamData, const Drawing* drawing );
|
||||
static IsfError prepare( StreamData* streamData, const Drawing* drawing );
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ MACRO( add_multiple_tests )
|
||||
QT4_AUTOMOC( test_${test}.cpp )
|
||||
ADD_EXECUTABLE( test_${test} test_${test}.cpp )
|
||||
ADD_TEST( libisf-${test} test_${test} )
|
||||
TARGET_LINK_LIBRARIES( test_${test} ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} isf-qt )
|
||||
TARGET_LINK_LIBRARIES( test_${test} ${QT_QTTEST_LIBRARY} ${QT_QTGUI_LIBRARY} isf-qt )
|
||||
ENDFOREACH( test )
|
||||
ENDMACRO( add_multiple_tests )
|
||||
|
||||
@@ -15,6 +15,7 @@ ADD_MULTIPLE_TESTS(
|
||||
isfdrawing
|
||||
multibyte_coding
|
||||
algorithms
|
||||
png_fortification
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ class TestDecode : public QMainWindow, private Ui::TestDecode
|
||||
|
||||
// read some test raw ISF data from a file on the filesystem and
|
||||
// return it as a QByteArray.
|
||||
QByteArray readTestIsfData( const QString &filename )
|
||||
QByteArray readTestIsfData( const QString& filename )
|
||||
{
|
||||
QFile file( filename );
|
||||
if ( !file.exists() )
|
||||
@@ -154,7 +154,7 @@ class TestDecode : public QMainWindow, private Ui::TestDecode
|
||||
|
||||
// read some test raw ISF data from a file on the filesystem and
|
||||
// return it as a QByteArray.
|
||||
void saveTestIsfData( const QByteArray &data )
|
||||
void saveTestIsfData( const QByteArray& data )
|
||||
{
|
||||
static int number = 1;
|
||||
QString fileName( "test" + QString::number( number ) + "." );
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <QDataStream>
|
||||
#include <QTextStream>
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
|
||||
#include <IsfInkCanvas>
|
||||
|
||||
@@ -46,22 +47,24 @@ TestInkEdit::TestInkEdit()
|
||||
connect( cmdSave_, SIGNAL(clicked()), this, SLOT( saveInk() ) );
|
||||
connect( cmdLoad_, SIGNAL(clicked()), this, SLOT( loadInk() ) );
|
||||
connect( cmdClear_, SIGNAL(clicked()), this, SLOT( clearInk() ) );
|
||||
|
||||
|
||||
connect( cmdStrokeColor_, SIGNAL(clicked()), this, SLOT( chooseColor() ) );
|
||||
connect( cmdCanvasColor_, SIGNAL(clicked()), this, SLOT( chooseColor() ) );
|
||||
|
||||
|
||||
connect( editor_, SIGNAL(inkChanged()), this, SLOT( inkChanged() ) );
|
||||
|
||||
QButtonGroup *grp = new QButtonGroup( this );
|
||||
grp->addButton( rbDrawing_ );
|
||||
grp->addButton( rbEraser_ );
|
||||
|
||||
|
||||
connect( grp, SIGNAL( buttonClicked( QAbstractButton * ) ), this, SLOT( penTypeChanged( QAbstractButton * ) ) );
|
||||
|
||||
|
||||
connect( spinWidth_, SIGNAL( valueChanged( int ) ), editor_, SLOT( setPenSize( int ) ) );
|
||||
|
||||
editor_->setPenSize( spinWidth_->value() );
|
||||
/*
|
||||
setWindowTitle("Ink Edit Test");
|
||||
|
||||
|
||||
editor_ = new Isf::InkEdit();
|
||||
editor_->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
|
||||
|
||||
@@ -72,29 +75,29 @@ TestInkEdit::TestInkEdit()
|
||||
cmdSave_ = new QPushButton();
|
||||
cmdSave_->setText( "Save Ink" );
|
||||
connect( cmdSave_, SIGNAL(clicked()), this, SLOT( saveInk() ) );
|
||||
|
||||
|
||||
cmdLoad_ = new QPushButton();
|
||||
cmdLoad_->setText( "Load Ink" );
|
||||
connect( cmdLoad_, SIGNAL(clicked()), this, SLOT( loadInk() ) );
|
||||
|
||||
|
||||
QPushButton *cmdClear_ = new QPushButton();
|
||||
cmdClear_->setText( "Clear Ink" );
|
||||
connect( cmdClear_, SIGNAL(clicked()), this, SLOT( clearInk() ) );
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout();
|
||||
QHBoxLayout *strokeBtnLayout = new QHBoxLayout();
|
||||
|
||||
|
||||
layout->addWidget( sayLabel_ );
|
||||
|
||||
layout->addWidget( editor_ );
|
||||
|
||||
|
||||
QHBoxLayout *ctlBtnLayout = new QHBoxLayout();
|
||||
ctlBtnLayout->addWidget(cmdSave_);
|
||||
ctlBtnLayout->addWidget(cmdLoad_);
|
||||
ctlBtnLayout->addWidget(cmdClear_);
|
||||
|
||||
layout->addLayout( ctlBtnLayout );
|
||||
|
||||
|
||||
setLayout( layout );
|
||||
*/
|
||||
}
|
||||
@@ -135,7 +138,7 @@ void TestInkEdit::saveInk()
|
||||
{
|
||||
QString filter;
|
||||
QString saveFile = QFileDialog::getSaveFileName( this, "Save Ink", QString(), "Raw ISF (*.isf);;base64-encoded ISF (*.isf64)", &filter );
|
||||
if ( saveFile != QString() )
|
||||
if ( saveFile != QString() )
|
||||
{
|
||||
QFile file(saveFile);
|
||||
file.open(QIODevice::WriteOnly);
|
||||
@@ -148,18 +151,18 @@ void TestInkEdit::saveInk()
|
||||
{
|
||||
editor_->save( file );
|
||||
}
|
||||
|
||||
|
||||
file.close();
|
||||
|
||||
|
||||
QMessageBox::information(0, "Save complete", "Saved to " + saveFile );
|
||||
}
|
||||
}
|
||||
|
||||
void TestInkEdit::loadInk()
|
||||
void TestInkEdit::loadInk()
|
||||
{
|
||||
QString filter;
|
||||
QString filename = QFileDialog::getOpenFileName( this, "Open Ink", QString(), "Raw ISF (*.isf);;base64-encoded ISF (*.isf64)", &filter );
|
||||
if ( ! filename.isEmpty() )
|
||||
if ( ! filename.isEmpty() )
|
||||
{
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
@@ -170,7 +173,7 @@ void TestInkEdit::loadInk()
|
||||
|
||||
// got some ink.
|
||||
Isf::Drawing *drawing = &Isf::Stream::reader(data);
|
||||
|
||||
|
||||
editor_->setDrawing( drawing );
|
||||
|
||||
editor_->updateGeometry();
|
||||
@@ -182,12 +185,20 @@ void TestInkEdit::clearInk()
|
||||
editor_->clear();
|
||||
}
|
||||
|
||||
void TestInkEdit::inkChanged()
|
||||
{
|
||||
emptyDrawingCheckbox_->setChecked( editor_->isEmpty() );
|
||||
|
||||
statusLabel_->setText( "Drawing changed!" );
|
||||
QTimer::singleShot( 3000, statusLabel_, SLOT(clear()) );
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
QApplication app( argc, argv );
|
||||
|
||||
TestInkEdit edit;
|
||||
edit.show();
|
||||
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
@@ -40,19 +40,20 @@
|
||||
class TestInkEdit : public QWidget, public Ui::TestInkEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
TestInkEdit();
|
||||
~TestInkEdit();
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
void saveInk();
|
||||
void loadInk();
|
||||
void clearInk();
|
||||
void penTypeChanged( QAbstractButton *button );
|
||||
void chooseColor();
|
||||
void inkChanged();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -130,6 +130,9 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="text">
|
||||
<string>Drawing</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -142,6 +145,19 @@ p, li { white-space: pre-wrap; }
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="emptyDrawingCheckbox_">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Is empty?</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
@@ -161,6 +177,9 @@ p, li { white-space: pre-wrap; }
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="statusLabel_"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
@@ -46,7 +46,3 @@ void TestAlgorithms::testDataSource()
|
||||
|
||||
|
||||
QTEST_MAIN(TestAlgorithms)
|
||||
|
||||
|
||||
|
||||
#include "test_algorithms.moc"
|
||||
|
||||
@@ -116,7 +116,7 @@ void TestIsfDrawing::createDrawing()
|
||||
|
||||
// read some test raw ISF data from a file on the filesystem and
|
||||
// return it as a QByteArray.
|
||||
void TestIsfDrawing::readTestIsfData( const QString &filename, QByteArray &byteArray )
|
||||
void TestIsfDrawing::readTestIsfData( const QString& filename, QByteArray& byteArray )
|
||||
{
|
||||
QFile file( filename );
|
||||
QVERIFY( file.exists() );
|
||||
@@ -132,7 +132,3 @@ void TestIsfDrawing::readTestIsfData( const QString &filename, QByteArray &byteA
|
||||
|
||||
|
||||
QTEST_MAIN(TestIsfDrawing)
|
||||
|
||||
|
||||
|
||||
#include "test_isfdrawing.moc"
|
||||
|
||||
@@ -23,7 +23,7 @@ class TestIsfDrawing : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestIsfDrawing();
|
||||
void readTestIsfData( const QString &filename, QByteArray &byteArray );
|
||||
void readTestIsfData( const QString& filename, QByteArray& byteArray );
|
||||
|
||||
private slots:
|
||||
void emptyConstructor_NullDrawing();
|
||||
|
||||
@@ -138,7 +138,7 @@ void TestMultibyteCoding::unsignedDecode()
|
||||
data.append( Q_UINT64_C(0x7D) ); // decimal 125
|
||||
data.reset(); // To re-read the appended bytes
|
||||
|
||||
result = Isf::Compress::decodeUInt( data );
|
||||
result = Isf::Compress::decodeUInt( &data );
|
||||
|
||||
QVERIFY(result == Q_UINT64_C(0x7D) );
|
||||
|
||||
@@ -150,7 +150,7 @@ void TestMultibyteCoding::unsignedDecode()
|
||||
data.append( Q_UINT64_C(0x01) );
|
||||
data.reset(); // To re-read the appended bytes
|
||||
|
||||
result = Isf::Compress::decodeUInt( data );
|
||||
result = Isf::Compress::decodeUInt( &data );
|
||||
QVERIFY( result == Q_UINT64_C(0x80) );
|
||||
|
||||
data.clear();
|
||||
@@ -162,7 +162,7 @@ void TestMultibyteCoding::unsignedDecode()
|
||||
data.append( Q_UINT64_C(0x03) );
|
||||
data.reset(); // To re-read the appended bytes
|
||||
|
||||
result = Isf::Compress::decodeUInt( data );
|
||||
result = Isf::Compress::decodeUInt( &data );
|
||||
QVERIFY( result == Q_UINT64_C(0xFFFF) );
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ void TestMultibyteCoding::signedDecode()
|
||||
data.append( (char)((0x0A << 1) | 0x01) );
|
||||
data.reset(); // To re-read the appended byte
|
||||
|
||||
result = Isf::Compress::decodeInt( data );
|
||||
result = Isf::Compress::decodeInt( &data );
|
||||
QVERIFY( result == Q_INT64_C(-10) );
|
||||
|
||||
data.clear();
|
||||
@@ -200,7 +200,7 @@ void TestMultibyteCoding::signedDecode()
|
||||
data.append( Q_INT64_C(0x01) );
|
||||
data.reset(); // To re-read the appended byte
|
||||
|
||||
result = Isf::Compress::decodeInt( data );
|
||||
result = Isf::Compress::decodeInt( &data );
|
||||
QVERIFY( result == Q_INT64_C(-64) );
|
||||
|
||||
data.clear();
|
||||
@@ -211,7 +211,7 @@ void TestMultibyteCoding::signedDecode()
|
||||
data.append( Q_INT64_C(0x01) );
|
||||
data.reset(); // To re-read the appended byte
|
||||
|
||||
result = Isf::Compress::decodeInt( data );
|
||||
result = Isf::Compress::decodeInt( &data );
|
||||
QVERIFY( result == Q_INT64_C(100) );
|
||||
|
||||
data.clear();
|
||||
@@ -222,7 +222,7 @@ void TestMultibyteCoding::signedDecode()
|
||||
data.append( Q_INT64_C(0x07) );
|
||||
data.reset(); // To re-read the appended byte
|
||||
|
||||
result = Isf::Compress::decodeInt( data );
|
||||
result = Isf::Compress::decodeInt( &data );
|
||||
QVERIFY( result == Q_INT64_C(-500) );
|
||||
}
|
||||
|
||||
@@ -254,14 +254,10 @@ void TestMultibyteCoding::floatDecode()
|
||||
data.append( Q_INT64_C(0xC1) );
|
||||
data.reset(); // To re-read the appended bytes
|
||||
|
||||
result = Isf::Compress::decodeFloat( data );
|
||||
result = Isf::Compress::decodeFloat( &data );
|
||||
QVERIFY( result == -12.345678901f );
|
||||
}
|
||||
|
||||
|
||||
|
||||
QTEST_MAIN(TestMultibyteCoding)
|
||||
|
||||
|
||||
|
||||
#include "test_multibyte_coding.moc"
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.*/
|
||||
|
||||
#include "test_png_fortification.h"
|
||||
|
||||
#include <IsfQtDrawing>
|
||||
|
||||
#include "isfqt-internal.h"
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <QPixmap>
|
||||
|
||||
|
||||
using namespace Isf;
|
||||
using namespace Isf::Compress;
|
||||
|
||||
|
||||
|
||||
|
||||
void TestPngFortification::testEncode()
|
||||
{
|
||||
QPixmap pix( QSize( 135, 114 ) );
|
||||
pix.fill( Qt::transparent );
|
||||
qDebug() << "pix size:" << pix.size();
|
||||
|
||||
qDebug() << "#################### ENCODER TEST ####################";
|
||||
|
||||
QFile file( "../../tests/test2.isf" );
|
||||
QVERIFY( file.exists() );
|
||||
|
||||
// read file into qbytearray.
|
||||
QVERIFY( file.open( QIODevice::ReadOnly ) );
|
||||
|
||||
Drawing drawing = Stream::reader( file.readAll(), false );
|
||||
|
||||
QVERIFY( ! drawing.isNull() );
|
||||
|
||||
QByteArray byteArray( Stream::writerPng( drawing, false ) );
|
||||
|
||||
QVERIFY( ! byteArray.isEmpty() );
|
||||
|
||||
QImage img = QImage::fromData( byteArray, "PNG" );
|
||||
|
||||
QVERIFY( ! img.isNull() );
|
||||
qDebug() << "Image size:" << img.size();
|
||||
|
||||
QVERIFY( tempFile.open() );
|
||||
|
||||
tempFile.write( byteArray );
|
||||
tempFile.close();
|
||||
}
|
||||
|
||||
|
||||
void TestPngFortification::testDecode()
|
||||
{
|
||||
qDebug() << "#################### DECODER TEST ####################";
|
||||
|
||||
QVERIFY( tempFile.exists() );
|
||||
|
||||
// read file and convert to qbytearray.
|
||||
QVERIFY( tempFile.open() );
|
||||
|
||||
QByteArray byteArray( tempFile.readAll() );
|
||||
|
||||
Drawing drawing = Stream::readerPng( byteArray, false );
|
||||
|
||||
QVERIFY( ! drawing.isNull() );
|
||||
|
||||
qDebug() << "Drawing size:" << drawing.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
QTEST_MAIN(TestPngFortification)
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.*/
|
||||
|
||||
#ifndef TESTPNG_FORTIFICATION_H
|
||||
#define TESTPNG_FORTIFICATION_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QTemporaryFile>
|
||||
|
||||
|
||||
|
||||
class TestPngFortification : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void testEncode();
|
||||
void testDecode();
|
||||
|
||||
private:
|
||||
|
||||
QTemporaryFile tempFile;
|
||||
};
|
||||
|
||||
#endif // TESTPNG_FORTIFICATION_H
|
||||
+3
-2
@@ -6,5 +6,6 @@ ADD_SUBDIRECTORY( emoticons )
|
||||
ADD_SUBDIRECTORY( chatstyles )
|
||||
|
||||
INSTALL( FILES kmesschatstyles.knsrc DESTINATION ${CONFIG_INSTALL_DIR} )
|
||||
INSTALL( FILES kmess.notifyrc DESTINATION ${DATA_INSTALL_DIR}/kmess )
|
||||
INSTALL( FILES kmess.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} )
|
||||
INSTALL( FILES kmess.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR} )
|
||||
INSTALL( FILES kmess.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}
|
||||
RENAME org.kmess.kmess.desktop )
|
||||
|
||||
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES Classic-compact.xsl Classic-compact.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Classic-compact/ )
|
||||
install(
|
||||
FILES
|
||||
Classic-compact.xsl
|
||||
Classic-compact.css
|
||||
DESTINATION
|
||||
${DATA_INSTALL_DIR}/kmess/styles/Classic-compact/
|
||||
)
|
||||
|
||||
|
||||
@@ -67,6 +67,19 @@ div.conversation
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Style overrides for chat history messages
|
||||
*/
|
||||
.history {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.history * {
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Remaining markup is done inline in the .xsl file.
|
||||
|
||||
@@ -27,6 +27,36 @@
|
||||
omit-xml-declaration="yes"
|
||||
encoding="utf-8" />
|
||||
|
||||
|
||||
<!--
|
||||
Template for the chat history
|
||||
-->
|
||||
<xsl:template match="history">
|
||||
<div class="history">
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Template for conversation headers
|
||||
-->
|
||||
<xsl:template match="header">
|
||||
<div class="{body/@dir}">
|
||||
<div style="margin:2em;padding:.5em;border:1px solid #dce6ff;font-size:larger;color:purple;text-align:center;" dir="{body/@dir}">
|
||||
<div class="conversationLabel" dir="{body/@dir}">
|
||||
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
|
||||
</div>
|
||||
<div class="conversationDate" dir="{body/@dir}">
|
||||
<xsl:value-of select="date"/>
|
||||
<xsl:text>   </xsl:text>
|
||||
<xsl:value-of select="time"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Normal chat message.
|
||||
This is used to process individual chat messages.
|
||||
|
||||
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES Classic.xsl Classic.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Classic/ )
|
||||
install(
|
||||
FILES
|
||||
Classic.xsl
|
||||
Classic.css
|
||||
DESTINATION
|
||||
${DATA_INSTALL_DIR}/kmess/styles/Classic/
|
||||
)
|
||||
|
||||
|
||||
@@ -67,6 +67,19 @@ div.conversation
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Style overrides for chat history messages
|
||||
*/
|
||||
.history {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.history * {
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remaining markup is done inline in the .xsl file.
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,36 @@
|
||||
indent="no"
|
||||
omit-xml-declaration="yes" />
|
||||
|
||||
|
||||
<!--
|
||||
Template for the chat history
|
||||
-->
|
||||
<xsl:template match="history">
|
||||
<div class="history">
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
Template for conversation headers
|
||||
-->
|
||||
<xsl:template match="header">
|
||||
<div class="{body/@dir}">
|
||||
<div style="margin:2em;padding:.5em;border:1px solid #dce6ff;font-size:larger;color:purple;text-align:center;" dir="{body/@dir}">
|
||||
<div class="conversationLabel" dir="{body/@dir}">
|
||||
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
|
||||
</div>
|
||||
<div class="conversationDate" dir="{body/@dir}">
|
||||
<xsl:value-of select="date"/>
|
||||
<xsl:text>   </xsl:text>
|
||||
<xsl:value-of select="time"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Normal chat message.
|
||||
This is used to process individual chat messages.
|
||||
|
||||
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES Colourful-Enclosed.xsl Colourful-Enclosed.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Colourful-Enclosed/ )
|
||||
install(
|
||||
FILES
|
||||
Colourful-Enclosed.xsl
|
||||
Colourful-Enclosed.css
|
||||
DESTINATION
|
||||
${DATA_INSTALL_DIR}/kmess/styles/Colourful-Enclosed/
|
||||
)
|
||||
|
||||
|
||||
@@ -214,3 +214,16 @@ div.conversation
|
||||
color: purple;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Style overrides for chat history messages
|
||||
*/
|
||||
.history {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.history * {
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
<xsl:param name="csspath" select="'Colourful-Enclosed.css'" />
|
||||
|
||||
|
||||
<!--
|
||||
Template for the chat history
|
||||
-->
|
||||
<xsl:template match="history">
|
||||
<div class="history">
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Template for the page body
|
||||
-->
|
||||
@@ -68,6 +78,24 @@
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for conversation headers
|
||||
-->
|
||||
<xsl:template match="header">
|
||||
<div class="{body/@dir}">
|
||||
<div class="conversation" dir="{body/@dir}">
|
||||
<div class="conversationLabel" dir="{body/@dir}">
|
||||
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
|
||||
</div>
|
||||
<div class="conversationDate" dir="{body/@dir}">
|
||||
<xsl:value-of select="date"/>
|
||||
<xsl:text>   </xsl:text>
|
||||
<xsl:value-of select="time"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Template for normal messages
|
||||
|
||||
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES Dim.xsl Dim.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Dim/ )
|
||||
install(
|
||||
FILES
|
||||
Dim.xsl
|
||||
Dim.css
|
||||
DESTINATION
|
||||
${DATA_INSTALL_DIR}/kmess/styles/Dim/
|
||||
)
|
||||
|
||||
|
||||
@@ -200,3 +200,18 @@ div.conversation
|
||||
margin-bottom: 1em;
|
||||
color: purple;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Style overrides for chat history messages
|
||||
*/
|
||||
.history {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.history * {
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
<xsl:param name="csspath" select="'Dim.css'" />
|
||||
|
||||
|
||||
<!--
|
||||
Template for the chat history
|
||||
-->
|
||||
<xsl:template match="history">
|
||||
<div class="history">
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Template for the page body
|
||||
-->
|
||||
@@ -68,6 +78,24 @@
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for conversation headers
|
||||
-->
|
||||
<xsl:template match="header">
|
||||
<div class="{body/@dir}">
|
||||
<div class="conversation" dir="{body/@dir}">
|
||||
<div class="conversationLabel" dir="{body/@dir}">
|
||||
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
|
||||
</div>
|
||||
<div class="conversationDate" dir="{body/@dir}">
|
||||
<xsl:value-of select="date"/>
|
||||
<xsl:text>   </xsl:text>
|
||||
<xsl:value-of select="time"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for normal messages
|
||||
-->
|
||||
|
||||
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES Efficient.xsl Efficient.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Efficient/ )
|
||||
install(
|
||||
FILES
|
||||
Efficient.xsl
|
||||
Efficient.css
|
||||
DESTINATION
|
||||
${DATA_INSTALL_DIR}/kmess/styles/Efficient/
|
||||
)
|
||||
|
||||
|
||||
@@ -271,3 +271,19 @@ div.conversation
|
||||
font-size: larger;
|
||||
color: purple;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Style overrides for chat history messages
|
||||
*/
|
||||
.history {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.history * {
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
<xsl:param name="csspath" select="'Efficient.css'" />
|
||||
|
||||
|
||||
<!--
|
||||
Template for the chat history
|
||||
-->
|
||||
<xsl:template match="history">
|
||||
<div class="history">
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Template for the page body
|
||||
-->
|
||||
@@ -68,6 +78,24 @@
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for conversation headers
|
||||
-->
|
||||
<xsl:template match="header">
|
||||
<div class="{body/@dir}">
|
||||
<div class="conversation" dir="{body/@dir}">
|
||||
<div class="conversationLabel" dir="{body/@dir}">
|
||||
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
|
||||
</div>
|
||||
<div class="conversationDate" dir="{body/@dir}">
|
||||
<xsl:value-of select="date"/>
|
||||
<xsl:text>   </xsl:text>
|
||||
<xsl:value-of select="time"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for normal messages
|
||||
-->
|
||||
|
||||
@@ -4,5 +4,17 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES Fresh-dark.xsl Fresh-dark.css bg_gravatar.gif bg_gravatar_rtl.gif buddy_icon.png DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Fresh-dark/ )
|
||||
|
||||
install(
|
||||
FILES
|
||||
Fresh-dark.xsl
|
||||
Fresh-dark.css
|
||||
bg_gravatar.gif
|
||||
bg_gravatar_rtl.gif
|
||||
bg_gravatar_gray.gif
|
||||
bg_gravatar_gray_rtl.gif
|
||||
buddy_icon.png
|
||||
DESTINATION
|
||||
${DATA_INSTALL_DIR}/kmess/styles/Fresh-dark/
|
||||
)
|
||||
|
||||
|
||||
@@ -300,3 +300,28 @@ div.conversation
|
||||
font-size: larger;
|
||||
color: #bb0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Style overrides for chat history messages
|
||||
*/
|
||||
.history {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.history * {
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.history .avatar
|
||||
{
|
||||
background-image: url("bg_gravatar_gray.gif");
|
||||
}
|
||||
|
||||
.history .rtl .avatar
|
||||
{
|
||||
background-image: url("bg_gravatar_gray_rtl.gif");
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,16 @@
|
||||
<xsl:param name="csspath" select="'Fresh-dark.css'" />
|
||||
|
||||
|
||||
<!--
|
||||
Template for the chat history
|
||||
-->
|
||||
<xsl:template match="history">
|
||||
<div class="history">
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Template for the page body
|
||||
-->
|
||||
@@ -69,6 +79,24 @@
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for conversation headers
|
||||
-->
|
||||
<xsl:template match="header">
|
||||
<div class="{body/@dir}">
|
||||
<div class="conversation" dir="{body/@dir}">
|
||||
<div class="conversationLabel" dir="{body/@dir}">
|
||||
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
|
||||
</div>
|
||||
<div class="conversationDate" dir="{body/@dir}">
|
||||
<xsl:value-of select="date"/>
|
||||
<xsl:text>   </xsl:text>
|
||||
<xsl:value-of select="time"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for normal messages
|
||||
-->
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
@@ -4,5 +4,16 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES Fresh.xsl Fresh.css bg_gravatar.gif bg_gravatar_rtl.gif buddy_icon.png DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Fresh/ )
|
||||
install(
|
||||
FILES
|
||||
Fresh.xsl
|
||||
Fresh.css
|
||||
bg_gravatar.gif
|
||||
bg_gravatar_rtl.gif
|
||||
bg_gravatar_gray.gif
|
||||
bg_gravatar_gray_rtl.gif
|
||||
buddy_icon.png
|
||||
DESTINATION
|
||||
${DATA_INSTALL_DIR}/kmess/styles/Fresh/
|
||||
)
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ dl, dt, dd
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* general message layout and colors.
|
||||
*/
|
||||
@@ -300,3 +299,27 @@ div.conversation
|
||||
color: purple;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Style overrides for chat history messages
|
||||
*/
|
||||
.history {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.history * {
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.history .avatar
|
||||
{
|
||||
background-image: url("bg_gravatar_gray.gif");
|
||||
}
|
||||
|
||||
.history .rtl .avatar
|
||||
{
|
||||
background-image: url("bg_gravatar_gray_rtl.gif");
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
<xsl:param name="csspath" select="'Fresh.css'" />
|
||||
|
||||
|
||||
<!--
|
||||
Template for the chat history
|
||||
-->
|
||||
<xsl:template match="history">
|
||||
<div class="history">
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Template for the page body
|
||||
-->
|
||||
@@ -68,6 +78,24 @@
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for conversation headers
|
||||
-->
|
||||
<xsl:template match="header">
|
||||
<div class="{body/@dir}">
|
||||
<div class="conversation" dir="{body/@dir}">
|
||||
<div class="conversationLabel" dir="{body/@dir}">
|
||||
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
|
||||
</div>
|
||||
<div class="conversationDate" dir="{body/@dir}">
|
||||
<xsl:value-of select="date"/>
|
||||
<xsl:text>   </xsl:text>
|
||||
<xsl:value-of select="time"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for normal messages
|
||||
-->
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -4,21 +4,22 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
|
||||
########### install files ###############
|
||||
|
||||
set(kmess_pure_FILES
|
||||
Pure.css
|
||||
Pure.xsl
|
||||
arrow0.png
|
||||
arrow1.png
|
||||
clock.png
|
||||
contact.png
|
||||
corner-bl.png
|
||||
corner-br.png
|
||||
corner-tl.png
|
||||
corner-tr.png
|
||||
important.png
|
||||
myself.png
|
||||
system.png
|
||||
)
|
||||
|
||||
install( FILES ${kmess_pure_FILES} DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Pure/ )
|
||||
install(
|
||||
FILES
|
||||
Pure.css
|
||||
Pure.xsl
|
||||
arrow0.png
|
||||
arrow1.png
|
||||
clock.png
|
||||
contact.png
|
||||
corner-bl.png
|
||||
corner-br.png
|
||||
corner-tl.png
|
||||
corner-tr.png
|
||||
important.png
|
||||
myself.png
|
||||
system.png
|
||||
DESTINATION
|
||||
${DATA_INSTALL_DIR}/kmess/styles/Pure/
|
||||
)
|
||||
|
||||
|
||||
@@ -338,3 +338,19 @@ div.conversation
|
||||
font-size: larger;
|
||||
color: purple;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Style overrides for chat history messages
|
||||
*/
|
||||
.history {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.history * {
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
<xsl:param name="csspath" select="'Pure.css'" />
|
||||
|
||||
|
||||
<!--
|
||||
Template for the chat history
|
||||
-->
|
||||
<xsl:template match="history">
|
||||
<div class="history">
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Template for the page body
|
||||
-->
|
||||
@@ -68,6 +78,24 @@
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Template for conversation headers
|
||||
-->
|
||||
<xsl:template match="header">
|
||||
<div class="{body/@dir}">
|
||||
<div class="conversation" dir="{body/@dir}">
|
||||
<div class="conversationLabel" dir="{body/@dir}">
|
||||
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
|
||||
</div>
|
||||
<div class="conversationDate" dir="{body/@dir}">
|
||||
<xsl:value-of select="date"/>
|
||||
<xsl:text>   </xsl:text>
|
||||
<xsl:value-of select="time"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Template for normal messages
|
||||
|
||||
Executable → Regular
Executable → Regular
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user