Compare commits

..

14 Commits

Author SHA1 Message Date
Mario Fetka 9fd7e99274 Bump version to 6.0 alpha5 2026-07-06 13:58:09 +02:00
Mario Fetka bf567146d8 Clean up KF6 chat window warnings 2026-07-06 13:51:57 +02:00
Mario Fetka 3bade98d2f Harden address book updates for Escargot 2026-07-06 13:38:43 +02:00
Mario Fetka bd03359d79 Bump version to 6.0 alpha4 2026-07-06 13:21:16 +02:00
Mario Fetka 89b4218853 Handle missing Escargot profile URL 2026-07-06 13:14:56 +02:00
Mario Fetka f9f479588f Fix Escargot privacy mode mapping 2026-07-06 12:40:45 +02:00
Mario Fetka 40e81af6c6 Keep Escargot login alive without storage profile 2026-07-06 11:48:10 +02:00
Mario Fetka 10db33e21e Bump version to 6.0 alpha3 2026-07-06 09:46:58 +02:00
Mario Fetka 78cb2bc641 Port isf-qt to giflib 5 and clean build warnings 2026-07-06 09:37:59 +02:00
Mario Fetka 0c67ad480c Point roaming storage at Escargot service host 2026-07-06 08:05:06 +02:00
Mario Fetka 141bff5dd3 Bump version to 6.0 alpha2 2026-07-06 07:42:20 +02:00
Mario Fetka ae8f851b06 Fix KF6 runtime integration warnings 2026-07-06 07:37:58 +02:00
Mario Fetka 65d3f78a14 Fix contact list model teardown crash 2026-07-06 07:29:12 +02:00
Mario Fetka f2fbc7463b Port KMess to KF6 and Qt6 2026-07-06 07:16:41 +02:00
257 changed files with 3846 additions and 3685 deletions
+85 -257
View File
@@ -1,272 +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 )
INCLUDE( KDE4Defaults )
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
)
# Make sure the rest still works
IF( NOT KDE4_FOUND )
# The macro's MACRO_LOG_FEATURE, MACRO_OPTIONAL_FIND_PACKAGE, MACRO_BOOL_TO_01
# are part of the KDE cmake modules, so these can't be used now.
find_package(LibXml2 REQUIRED)
find_package(LibXslt REQUIRED)
find_package(GCrypt REQUIRED)
MESSAGE( FATAL_ERROR "\n"
" The KDE Development Platform was not found.\n"
" \n"
" You will need this package and the matching development package.\n"
" Usually the package names for this library are:\n"
" on Debian and Ubuntu: 'kdebase-runtime' and 'kdelibs5-dev'\n"
" on openSUSE: 'kdebase4-runtime' and 'libkde4-devel'\n"
" \n"
" Please refer to the KMess board for more info,\n"
" and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
ENDIF( NOT KDE4_FOUND )
set(ISFQT_IS_BUNDLED TRUE)
set(USE_BUNDLED_LIBRARIES ISFQT)
add_subdirectory(contrib/isf-qt)
# 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, 'libxml2' and 'libxml2-dev' or 'libxml2-devel'.
* Usually the package names for this library are:
on Debian and 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" )
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()
# 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.
* Usually the package names for this library are:
on Debian and Ubuntu: 'libxslt' and 'libxslt1-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(KMESS_VERSION "6.0_alpha5")
set(KMESS_ENABLE_DEBUG_OUTPUT 0)
set(KMESS_BUILT_DEBUGFULL FALSE)
set(HAVE_LIBISFQT 1)
set(HAVE_NEW_TRAY 1)
# Add cmake directory to the MODULE_PATH, so cmake can find GCrypt
SET( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} $ENV{CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake )
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 GCrypt
FIND_PACKAGE( GCrypt )
IF( NOT GCRYPT_FOUND )
MACRO_LOG_FEATURE( GCRYPT_FOUND "GCrypt" "A library to encrypt messages with various cyphers" "http://www.gnupg.org/" TRUE ""
"It is required for the Live Messenger login process.
* Usually the package names for this library are:
on Debian and Ubuntu: 'libgcrypt' and 'libgcrypt11-dev'
on openSUSE: 'libgcrypt' and 'libgcrypt-devel'
on Fedora: 'gcrypt' and 'gcrypt-devel'
* Please refer to the KMess board for more info,
and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
ELSE()
MESSAGE( STATUS "Looking for GCrypt - found" )
ENDIF()
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050F00 -DQT_NO_URL_CAST_FROM_STRING)
# 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 Debian and 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 )
# 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 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 ""
"This is an optional feature.
* Usually the package names for this library are:
on Debian and 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" )
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/config-kmess.h.in
${CMAKE_CURRENT_BINARY_DIR}/config-kmess.h)
# 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
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${LIBXML2_INCLUDE_DIR}
${LIBXSLT_INCLUDE_DIR}
${GCRYPT_INCLUDE_DIRS}
)
# Check for KNotificationItem. KDE 4.3.1 and later have it integrated in kdelibs/experimental.
# It will be available by default in 4.4.
IF( ${KDE_VERSION} VERSION_LESS 4.3.70 ) # KDE trunk has a higher version number than this.
MACRO_OPTIONAL_FIND_PACKAGE(LibKNotificationItem-1)
MACRO_LOG_FEATURE( LIBKNOTIFICATIONITEM-1_FOUND "LibKNotificationItem-1" "The experimental new KDE systray library" "http://www.kde.org" FALSE ""
"LibKNotificationItem-1 is the experimental new KDE systray library. It will be included
by default in KDE 4.4 and is available for use in KDE 4.3.1 and above." )
MACRO_BOOL_TO_01( LIBKNOTIFICATIONITEM-1_FOUND HAVE_NEW_TRAY )
ELSE()
SET( HAVE_NEW_TRAY 1 )
ENDIF()
# Display the dependency collection results
MACRO_DISPLAY_FEATURE_LOG()
#### 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-git-version.sh OUTPUT_VARIABLE KMESS_VERSION )
SET( KMESS_VERSION "2.0.6.2" )
#### 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 )
IF( CMAKE_BUILD_TYPE STREQUAL debugfull )
SET( KMESS_BUILT_DEBUGFULL TRUE )
ELSE( CMAKE_BUILD_TYPE STREQUAL debugfull )
SET( KMESS_BUILT_DEBUGFULL FALSE )
ENDIF( CMAKE_BUILD_TYPE STREQUAL debugfull )
# 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)
+3 -4
View File
@@ -1,5 +1,5 @@
PROJECT( isf-qt )
CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )
CMAKE_MINIMUM_REQUIRED( VERSION 3.16 )
PROJECT( isf-qt LANGUAGES CXX )
#### Main switches ####
@@ -38,7 +38,7 @@ SET( ISFQT_VERSION "1.0dev" )
#### Inclusions ####
FIND_PACKAGE( Qt4 REQUIRED )
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 )
@@ -129,4 +129,3 @@ IF( NOT ISFQT_IS_BUNDLED )
INSTALL( FILES cmake/FindIsfQt.cmake
DESTINATION ${CMAKE_ROOT}/Modules )
ENDIF()
+8
View File
@@ -0,0 +1,8 @@
#ifndef ISFQT_QMATRIX_COMPAT_H
#define ISFQT_QMATRIX_COMPAT_H
#include <QTransform>
using QMatrix = QTransform;
#endif
+6 -6
View File
@@ -105,7 +105,7 @@ namespace Isf
PenType penType();
void save( QIODevice&, bool = false );
void setDrawing( Isf::Drawing* );
virtual QSize sizeHint() const;
QSize sizeHint() const override;
public slots:
void clear();
@@ -115,11 +115,11 @@ namespace Isf
void setPenType( PenType );
protected: // protected methods
void mousePressEvent( QMouseEvent* );
void mouseMoveEvent( QMouseEvent* );
void mouseReleaseEvent( QMouseEvent* );
void paintEvent( QPaintEvent* );
void resizeEvent( QResizeEvent* );
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& );
+7 -5
View File
@@ -29,8 +29,10 @@ SET( ISFQT_PUBLIC_HEADERS
)
SET( ISFQT_LIBS
${QT_QTCORE_LIBRARY}
${QT_QTGUI_LIBRARY}
Qt6::Core
Qt6::Core5Compat
Qt6::Gui
Qt6::Widgets
)
SET( ISFQT_RCCS
@@ -45,11 +47,11 @@ 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 into an application
IF( ISFQT_IS_BUNDLED )
+2 -2
View File
@@ -131,14 +131,14 @@ namespace Isf
{
}
/// Quick comparison operator
bool operator ==( const AttributeSet& other )
bool operator ==( const AttributeSet& other ) const
{
return color == other.color
&& flags == other.flags
&& penSize == other.penSize;
}
/// Quick comparison operator
bool operator !=( const AttributeSet& other )
bool operator !=( const AttributeSet& other ) const
{
return color != other.color
|| flags != other.flags
+45 -34
View File
@@ -341,7 +341,7 @@ Drawing& Stream::readerPng( const QByteArray& pngRawBytes, bool decodeFromBase64
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Picture data is valid: checking for the ISF data tag...";
#endif
isfData = imageData.text( "application/x-ms-ink" ).toAscii();
isfData = imageData.text( "application/x-ms-ink" ).toLatin1();
if( ! isfData.isEmpty() )
{
@@ -381,7 +381,7 @@ bool Stream::supportsGif()
*/
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!";
@@ -478,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!";
@@ -497,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 );
@@ -543,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()
@@ -576,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;
}
@@ -590,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;
}
@@ -603,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;
}
}
@@ -623,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
{
@@ -704,5 +717,3 @@ QByteArray Stream::writerPng( const Drawing& drawing, bool encodeToBase64 )
return imageBytes.data();
}
}
+1 -1
View File
@@ -30,6 +30,7 @@
#include <IsfQtDrawing>
#include <QPainter>
#include <QPainterPath>
#include <QPixmap>
#include <cmath>
@@ -726,4 +727,3 @@ void Drawing::updateBoundingRect()
#endif
}
+7 -8
View File
@@ -26,6 +26,7 @@
#include "isfqt-internal.h"
#include <QPainterPath>
#include <QVector>
using namespace Isf;
@@ -169,7 +170,7 @@ void Stroke::bezierCalculateControlPoints()
}
// right hand side vector.
double rhs[n];
QVector<double> rhs( n );
// set RHS x values
for( int i = 1; i < n-1; i++ )
@@ -181,8 +182,8 @@ void Stroke::bezierCalculateControlPoints()
rhs[n-1] = ( 8 * bezierKnots_[n-1].x() + bezierKnots_[n].x() ) / 2.0;
// get the first ctl points x values.
double x[n];
bezierGetFirstControlPoints( rhs, x, n );
QVector<double> x( n );
bezierGetFirstControlPoints( rhs.data(), x.data(), n );
// now set RHS y-values.
@@ -194,8 +195,8 @@ void Stroke::bezierCalculateControlPoints()
rhs[0] = bezierKnots_[0].y() + 2 * bezierKnots_[1].y();
rhs[n-1] = ( 8 * bezierKnots_[n-1].y() + bezierKnots_[n].y() ) / 2.0;
double y[n];
bezierGetFirstControlPoints( rhs, y, n );
QVector<double> y( n );
bezierGetFirstControlPoints( rhs.data(), y.data(), n );
// now fill the output QList.
for( int i = 0; i < n; i++ )
@@ -226,7 +227,7 @@ void Stroke::bezierCalculateControlPoints()
void Stroke::bezierGetFirstControlPoints( double rhs[], double* xOut, int n )
{
double* x = xOut; // solution vector.
double tmp[n]; // temp workspace.
QVector<double> tmp( n ); // temp workspace.
double b = 2.0;
x[0] = rhs[0] / b;
@@ -513,5 +514,3 @@ QMatrix* Stroke::transform()
{
return transform_;
}
+5 -7
View File
@@ -406,7 +406,7 @@ IsfError TagsParser::parseUnsupported( StreamData* streamData, const QString& ta
*/
IsfError TagsParser::parseCustomTag( StreamData* streamData, Drawing* drawing, quint64 tagIndex )
{
quint64 tag = tagIndex - FIRST_CUSTOM_TAG_ID;
quint64 tag = tagIndex - static_cast<quint64>( FIRST_CUSTOM_TAG_ID );
// Find if we have this tag registered in the GUID table
if( tag >= (quint64)drawing->guids_.count() )
@@ -427,8 +427,8 @@ IsfError TagsParser::parseCustomTag( StreamData* streamData, Drawing* drawing, q
// String values
if(
guid == "{96E9B229-B657-DA4F-BFFD-F54DBA4C35F9}" // Unknown meaning, name?
|| guid == "{7C8E448A-390F-D94C-BB52-71FDA3221674}" // Unknown meaning, surname?
guid == QUuid( "{96E9B229-B657-DA4F-BFFD-F54DBA4C35F9}" ) // Unknown meaning, name?
|| guid == QUuid( "{7C8E448A-390F-D94C-BB52-71FDA3221674}" ) // Unknown meaning, surname?
)
{
// TODO: WTF is the first char for? Its value is always "0x08"
@@ -438,7 +438,7 @@ IsfError TagsParser::parseCustomTag( StreamData* streamData, Drawing* drawing, q
foreach( quint64 item, data )
{
string.append( (quint8)item );
string.append( QChar( static_cast<quint8>( item ) ) );
}
#ifdef ISFQT_DEBUG
@@ -1136,7 +1136,7 @@ IsfError TagsParser::parseTransformation( StreamData* streamData, Drawing* drawi
float dx = Compress::decodeFloat( dataSource );
float dy = Compress::decodeFloat( dataSource );
transform->setMatrix( scaleX, scaleY, shearX, shearY, dx, dy );
transform->setMatrix( scaleX, shearX, 0, shearY, scaleY, 0, dx, dy, 1 );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Transformation details - "
@@ -1611,5 +1611,3 @@ QByteArray TagsParser::analyzePayload( StreamData* streamData, const quint64 pay
return result;
}
-4
View File
@@ -46,7 +46,3 @@ void TestAlgorithms::testDataSource()
QTEST_MAIN(TestAlgorithms)
#include "test_algorithms.moc"
-4
View File
@@ -132,7 +132,3 @@ void TestIsfDrawing::readTestIsfData( const QString& filename, QByteArray& byteA
QTEST_MAIN(TestIsfDrawing)
#include "test_isfdrawing.moc"
@@ -261,7 +261,3 @@ void TestMultibyteCoding::floatDecode()
QTEST_MAIN(TestMultibyteCoding)
#include "test_multibyte_coding.moc"
@@ -84,7 +84,3 @@ void TestPngFortification::testDecode()
QTEST_MAIN(TestPngFortification)
#include "test_png_fortification.moc"
+3 -2
View File
@@ -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 )
+11 -9
View File
@@ -1,14 +1,16 @@
KDE4_INSTALL_ICONS( ${ICON_INSTALL_DIR} )
SET( KMESS_ICON_INSTALL_DIR ${DATA_INSTALL_DIR}/kmess/icons/hicolor/16x16 )
# If Likeback is enabled, install the needed icons
IF( NOT ${KMESS_DISABLE_LIKEBACK} EQUAL 1 )
INSTALL( FILES likeback_bug.png DESTINATION ${KMESS_ICON_INSTALL_DIR}/actions )
INSTALL( FILES likeback_dislike.png DESTINATION ${KMESS_ICON_INSTALL_DIR}/actions )
INSTALL( FILES likeback_feature.png DESTINATION ${KMESS_ICON_INSTALL_DIR}/actions )
INSTALL( FILES likeback_like.png DESTINATION ${KMESS_ICON_INSTALL_DIR}/actions )
INSTALL( FILES likeback_bug.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/16x16/actions )
INSTALL( FILES likeback_dislike.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/16x16/actions )
INSTALL( FILES likeback_feature.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/16x16/actions )
INSTALL( FILES likeback_like.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/16x16/actions )
ENDIF( NOT ${KMESS_DISABLE_LIKEBACK} EQUAL 1 )
INSTALL( FILES kmess-shadow.png DESTINATION ${KMESS_ICON_INSTALL_DIR}/apps )
INSTALL( FILES hi16-app-kmess.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/16x16/apps RENAME kmess.png )
INSTALL( FILES hi22-app-kmess.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/22x22/apps RENAME kmess.png )
INSTALL( FILES hi32-app-kmess.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/32x32/apps RENAME kmess.png )
INSTALL( FILES hi48-app-kmess.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/48x48/apps RENAME kmess.png )
INSTALL( FILES hi64-app-kmess.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/64x64/apps RENAME kmess.png )
INSTALL( FILES hi128-app-kmess.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/128x128/apps RENAME kmess.png )
INSTALL( FILES kmess-shadow.png DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/256x256/apps )
+5 -5
View File
@@ -1,14 +1,15 @@
[Desktop Entry]
Name=KMess
Exec=kmess -caption "%c" %i
Exec=kmess
Icon=kmess
Type=Application
DocPath=kmess/index.html
Terminal=0
Terminal=false
Categories=Qt;KDE;Network;InstantMessaging;
StartupWMClass=kmess
Comment=Live Messenger Client for KDE
Comment[de]=Live-Messenger-Klon für KDE 4
Comment[nl]=MSN Messenger Kloon voor KDE 4
Comment[de]=Live-Messenger-Client für KDE
Comment[nl]=Live Messenger-client voor KDE
GenericName=Live Messenger Client
GenericName[af]=Irc Kliënt
GenericName[ar]=عميل MSN
@@ -67,4 +68,3 @@ GenericName[xx]=xxMSN Clientxx
GenericName[zh_CN]=MSN
GenericName[zh_TW]=MSN
GenericName[zu]=Umthengi we MSN
+2 -4
View File
@@ -1,5 +1,3 @@
include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
add_subdirectory( en )
# Documentation still uses the old KDE4 handbook macro. It will be ported
# once the application target itself configures and compiles with KF6.
+5 -2
View File
@@ -16,9 +16,12 @@ ELSE( NOT GETTEXT_MSGFMT_EXECUTABLE )
FOREACH( _poFile ${PO_FILES} )
GET_FILENAME_COMPONENT( _lang ${_poFile} NAME_WE )
SET( _gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo )
ADD_CUSTOM_COMMAND( TARGET translations
ADD_CUSTOM_COMMAND( OUTPUT ${_gmoFile}
COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} --check -o ${_gmoFile} ${_poFile}
DEPENDS ${_poFile})
DEPENDS ${_poFile}
VERBATIM )
ADD_CUSTOM_TARGET( translation_${_lang} DEPENDS ${_gmoFile} )
ADD_DEPENDENCIES( translations translation_${_lang} )
INSTALL( FILES ${_gmoFile} DESTINATION ${LOCALE_INSTALL_DIR}/${_lang}/LC_MESSAGES/ RENAME ${catalogname}.mo )
ENDFOREACH( _poFile ${PO_FILES} )
+1 -1
View File
@@ -10,7 +10,7 @@ msgstr ""
"PO-Revision-Date: 2011-02-08 00:53+0100\n"
"Last-Translator: Adrià Arrufat <swiftscythe@gmail.com>\n"
"Language-Team: American English <kde-i18n-doc@kde.org>\n"
"Language: \n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+1 -1
View File
@@ -17,7 +17,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Language: et\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 1.1\n"
+1 -1
View File
@@ -15,7 +15,7 @@ msgstr ""
"PO-Revision-Date: 2009-11-07 17:26+0200\n"
"Last-Translator: \n"
"Language-Team: American English <kde-i18n-doc@kde.org>\n"
"Language: \n"
"Language: fi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+1 -1
View File
@@ -21,7 +21,7 @@ msgstr ""
"PO-Revision-Date: 2011-01-12 05:48+0100\n"
"Last-Translator: Scias <shining.scias@gmail.com>\n"
"Language-Team: French <kde-i18n-doc@kde.org>\n"
"Language: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+1 -1
View File
@@ -10,7 +10,7 @@ msgstr ""
"PO-Revision-Date: 2010-03-11 09:10+0100\n"
"Last-Translator: Indalecio Freiría Santos <ifreiria@gmail.com>\n"
"Language-Team: Galego <proxecto@trasno.net>\n"
"Language: \n"
"Language: gl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+1 -1
View File
@@ -15,7 +15,7 @@ msgstr ""
"PO-Revision-Date: 2009-07-24 21:20+0200\n"
"Last-Translator: Ralesk <ralesk@drangolin.net>\n"
"Language-Team: <NONE>\n"
"Language: \n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+1 -1
View File
@@ -21,7 +21,7 @@ msgstr ""
"PO-Revision-Date: 2011-02-09 11:08+0100\n"
"Last-Translator: Heimen Stoffels <vistausss@gmail.com>\n"
"Language-Team: Dutch <kde-i18n-doc@kde.org>\n"
"Language: \n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+1 -1
View File
@@ -16,7 +16,7 @@ msgstr ""
"PO-Revision-Date: 2010-07-09 20:07-0300\n"
"Last-Translator: Morris\n"
"Language-Team: American English <>\n"
"Language: \n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+1 -1
View File
@@ -15,7 +15,7 @@ msgstr ""
"PO-Revision-Date: 2009-11-18 19:28+0100\n"
"Last-Translator: Panagiotis Papadopoulos <pano_90@gmx.net>\n"
"Language-Team: en_US <kde-i18n-doc@kde.org>\n"
"Language: \n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+1
View File
@@ -13,6 +13,7 @@ msgstr ""
"PO-Revision-Date: 2010-09-10 08:34+0800\n"
"Last-Translator: Yen-chou Chen <yenchou.mse90@nctu.edu.tw>\n"
"Language-Team: Chinese Traditional <zh-l10n@linux.org.tw>\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+44 -45
View File
@@ -1,5 +1,5 @@
INCLUDE_DIRECTORIES( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} ${GCRYPT_INCLUDE_DIRS} )
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${GCRYPT_INCLUDE_DIRS})
########### next target ###############
@@ -151,18 +151,43 @@ SET(kmess_UI_FILES
)
SET(kmess_LIBS
${KDE4_KDECORE_LIBS}
${KDE4_KDEUI_LIBS}
${KDE4_KIO_LIBS}
${KDE4_KHTML_LIBS}
${KDE4_KNOTIFYCONFIG_LIBS}
${KDE4_KNEWSTUFF2_LIBS}
${KDE4_PHONON_LIBS}
${KDE4_SOLID_LIBS}
Qt6::Core
Qt6::Core5Compat
Qt6::DBus
Qt6::Gui
Qt6::Multimedia
Qt6::Network
Qt6::Test
Qt6::WebEngineWidgets
Qt6::Widgets
Qt6::Xml
isf-qt
KF6::ConfigCore
KF6::ConfigGui
KF6::ConfigWidgets
KF6::Codecs
KF6::Completion
KF6::CoreAddons
KF6::Crash
KF6::IdleTime
KF6::I18n
KF6::IconThemes
KF6::KIOCore
KF6::KIOWidgets
KF6::Notifications
KF6::NotifyConfig
KF6::Parts
KF6::Service
KF6::Solid
KF6::StatusNotifierItem
KF6::TextWidgets
KF6::WidgetsAddons
KF6::WindowSystem
KF6::Wallet
KF6::XmlGui
${LIBXML2_LIBRARIES}
${LIBXSLT_LIBRARIES}
${GCRYPT_LIBRARIES}
${QT_QTTEST_LIBRARY}
)
IF( ${GIF_FOUND} )
@@ -170,10 +195,7 @@ IF( ${GIF_FOUND} )
SET( kmess_LIBS ${kmess_LIBS} ${GIF_LIBRARIES} )
ENDIF( ${GIF_FOUND} )
IF( ISFQT_FOUND )
INCLUDE_DIRECTORIES( ${ISFQT_INCLUDE_DIR} )
SET( kmess_LIBS ${kmess_LIBS} ${ISFQT_LIBRARIES} )
ENDIF( ISFQT_FOUND )
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/contrib/isf-qt/include )
# If LikeBack is enabled, compile it
IF( NOT ${KMESS_DISABLE_LIKEBACK} EQUAL 1 )
@@ -192,16 +214,8 @@ if(APPLE)
set(kmess_SOURCES ${kmess_SOURCES} notification/macnotification.cpp)
endif(APPLE)
#new system tray spec - optional
IF( HAVE_NEW_TRAY )
SET( kmess_SOURCES ${kmess_SOURCES}
notification/newsystemtraywidget.cpp )
INCLUDE_DIRECTORIES( ${KNOTIFICATIONITEM_INCLUDE_DIR} )
SET( kmess_LIBS ${kmess_LIBS} ${KNOTIFICATIONITEM_LIBRARIES} )
ELSE()
SET( kmess_SOURCES ${kmess_SOURCES}
notification/systemtraywidget.cpp )
ENDIF()
SET( kmess_SOURCES ${kmess_SOURCES}
notification/newsystemtraywidget.cpp )
# If we're compiling in debug mode:
IF( ${KMESS_ENABLE_DEBUG_OUTPUT} EQUAL 1 )
@@ -218,33 +232,18 @@ IF( ${KMESS_ENABLE_DEBUG_OUTPUT} EQUAL 1 )
ENDIF( CMAKE_BUILD_TYPE STREQUAL debugfull )
ENDIF( ${KMESS_ENABLE_DEBUG_OUTPUT} EQUAL 1 )
# Add XScreensaver library for away-idle detection.
IF( X11_Xscreensaver_FOUND )
SET(kmess_LIBS ${kmess_LIBS} ${X11_Xscreensaver_LIB} ${X11_LIBRARIES} )
ENDIF( X11_Xscreensaver_FOUND )
IF( ${KDE_VERSION} VERSION_LESS 4.4.0 )
# Set our KDE debug number to be the default
add_definitions( -DKDE_DEFAULT_DEBUG_AREA=5130 )
ENDIF()
# Define the app icon for Windows / Mac OS
SET( kmess_SRCS )
KDE4_ADD_APP_ICON( kmess_SRCS ../data/icons/hi*-app-kmess.png )
SET( kmess_SOURCES ${kmess_SOURCES} ${kmess_SRCS} )
# Create a DBus adapter from XML file
QT4_ADD_DBUS_ADAPTOR( kmess_SOURCES utils/kmessdbus.xml utils/kmessdbus.h KMessDBus )
qt_add_dbus_adaptor( kmess_DBUS_SRCS utils/kmessdbus.xml utils/kmessdbus.h KMessDBus )
# Define all files
KDE4_ADD_UI_FILES( kmess_SOURCES ${kmess_UI_FILES} )
KDE4_ADD_EXECUTABLE( kmess ${kmess_SOURCES} )
qt_wrap_ui( kmess_UI_SRCS ${kmess_UI_FILES} )
add_executable( kmess ${kmess_SOURCES} ${kmess_UI_SRCS} ${kmess_DBUS_SRCS} )
target_include_directories( kmess PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} )
# Link to final executable
TARGET_LINK_LIBRARIES( kmess ${kmess_LIBS} )
INSTALL( TARGETS kmess DESTINATION ${BIN_INSTALL_DIR})
INSTALL( FILES chat/chatwindowui.rc DESTINATION ${DATA_INSTALL_DIR}/kmess )
INSTALL( FILES kmessinterfaceui.rc DESTINATION ${DATA_INSTALL_DIR}/kmess )
INSTALL( FILES chat/chatwindowui.rc DESTINATION ${KDE_INSTALL_KXMLGUIDIR}/kmess )
INSTALL( FILES kmessinterfaceui.rc DESTINATION ${KDE_INSTALL_KXMLGUIDIR}/kmess )
+27 -11
View File
@@ -19,17 +19,17 @@
#include "contact/msnobject.h"
#include "utils/kmessconfig.h"
#include "utils/kmessshared.h"
#include "accountsmanager.h"
#include "kmessdebug.h"
#include <QDir>
#include <QRegExp>
#include <QRegularExpression>
#include <KConfigGroup>
#include <KGlobal>
#include <KLocale>
#include <KStandardDirs>
#include <KLocalizedString>
#ifdef KMESSDEBUG_ACCOUNT
@@ -54,7 +54,7 @@ Account::Account()
friendlyName_( i18n("Your name"), false ), // Do not parse this name, CurrentAccount is not ready when initializing
guestAccount_(true),
groupFollowupMessages_(true),
handle_( i18n("you@hotmail.com") ),
handle_( i18n("you@escargot.chat") ),
hideNotificationsWhenBusy_(true),
idleTime_(5),
initialStatus_(STATUS_ONLINE),
@@ -649,7 +649,7 @@ int Account::getListPictureSize() const
// Return the path to the current display picture
const QString Account::getPicturePath( bool fallBack ) const
{
static QString defaultPicture( KGlobal::dirs()->findResource( "data", "kmess/pics/kmesspic.png" ) );
static QString defaultPicture( KMessShared::findResource( "data", "kmess/pics/kmesspic.png" ) );
// Return the picture path if the user has selected to show it; else return an empty string
if( ! showPicture_ )
@@ -726,7 +726,27 @@ bool Account::isGuestAccount() const
// Validate a contact email
bool Account::isValidEmail( QString email )
{
return email.contains( QRegExp( "^[A-Z0-9._%\\-]+@(?:[A-Z0-9\\-]+\\.)+[A-Z]{2,4}$", Qt::CaseInsensitive ) );
static const QRegularExpression emailPattern(
"^[A-Z0-9._%\\-]+@(?:[A-Z0-9\\-]+\\.)+[A-Z]{2,}$",
QRegularExpression::CaseInsensitiveOption );
return emailPattern.match( email ).hasMatch();
}
// Validate a Messenger handle
bool Account::isValidHandle( QString handle )
{
handle = handle.trimmed();
if( isValidEmail( handle ) )
{
return true;
}
static const QRegularExpression escargotNamePattern(
"^[A-Z0-9._%\\-]{1,64}$",
QRegularExpression::CaseInsensitiveOption );
return escargotNamePattern.match( handle ).hasMatch();
}
@@ -828,7 +848,7 @@ void Account::readProperties( const QString &handle )
// This default is "Fresh" as of 1.5 final, to improve the first impression a user gets.
// The previous "Default" theme has been renamed to "Classic".
// This code also makes the migration from 1.5-pre2 to 1.5 (and beyond) easier.
if( KGlobal::dirs()->findResource( "data", "kmess/styles/" + chatStyle_ + '/' + chatStyle_ + ".xsl" ).isEmpty() )
if( KMessShared::findResource( "data", "kmess/styles/" + chatStyle_ + '/' + chatStyle_ + ".xsl" ).isEmpty() )
{
#ifdef KMESSDEBUG_ACCOUNT_DIRTY
kmDebug() << "Auto-corrected chat & setting, setting 'dirty' to true.";
@@ -1787,7 +1807,3 @@ void Account::updateMsnObject()
emit changedMsnObject();
}
}
#include "account.moc"
+2
View File
@@ -285,6 +285,8 @@ class Account : public QObject
public: // Static public members
// Validate a contact email
static bool isValidEmail( QString email );
// Validate a Messenger handle. Escargot/NINA can also use plain usernames.
static bool isValidHandle( QString handle );
protected: // Protected methods
// Update the email-supported state (protected method)
+4 -9
View File
@@ -24,17 +24,14 @@
// The constructor
AccountAction::AccountAction(Account *account, QWidget *parent )
: KAction(parent),
: QAction(parent),
account_(account)
{
setObjectName( "AccountAction[" + account->getHandle() + ']' );
// The idea is to have an action that sends the account when its
// normal "activated" signal is sent.
// Then connect this action's regular "activated" signal to the action's
// slotActivated slot, which will then emit an "activated(account)"
// signal.
connect( this, SIGNAL( activated() ),
// QAction emits triggered(); this class keeps the old activated(account)
// signal for callers that want the associated Account object.
connect( this, SIGNAL( triggered() ),
this, SLOT ( slotActivated() ) );
// Initialize the text by calling update.
@@ -67,5 +64,3 @@ void AccountAction::updateText()
setText( account_->getHandle() );
}
#include "accountaction.moc"
+4 -3
View File
@@ -18,7 +18,8 @@
#ifndef ACCOUNTACTION_H
#define ACCOUNTACTION_H
#include <KAction>
#include <QAction>
#include <QWidget>
// Forward declarations
@@ -33,7 +34,7 @@ class Account;
* @author Mike K. Bennett
* @ingroup Root
*/
class AccountAction : public KAction
class AccountAction : public QAction
{
Q_OBJECT
@@ -48,7 +49,7 @@ class AccountAction : public KAction
void updateText();
protected slots:
//Inherit from KAction...
//Inherit from QAction...
void slotActivated();
private: // Private attributes
+8 -12
View File
@@ -26,7 +26,7 @@
#include <QDir>
#include <KConfig>
#include <KLocale>
#include <KLocalizedString>
#include <KMessageBox>
@@ -177,7 +177,7 @@ void AccountsManager::deleteAccount( Account *account )
emit accountDeleted( account );
QString handle( account->getHandle() );
KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
KMessApplication *kmessApp = static_cast<KMessApplication *>(QApplication::instance());
if( kmessApp->getContactListWindow()->isConnected()
&& CurrentAccount::instance()->getHandle() == handle )
@@ -261,7 +261,7 @@ void AccountsManager::initializePasswordManager( bool block )
}
// Obtain the window ID of the main KMess window
KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
KMessApplication *kmessApp = static_cast<KMessApplication *>(QApplication::instance());
WId wId = kmessApp->getContactListWindow()->window()->winId();
if( block )
@@ -555,7 +555,7 @@ void AccountsManager::setupPasswordManager()
{
kmWarning() << "Insecure account passwords found for accounts: " << validAccounts;
int res = KMessageBox::questionYesNoCancel( 0,
int res = KMessageBox::questionTwoActionsCancel( 0,
i18n( "<html>Some insecurely stored account passwords have been found.<br />"
"Do you want to import the passwords to the KDE Wallet "
"named '%1', keep the insecurely stored passwords, or delete "
@@ -577,7 +577,7 @@ void AccountsManager::setupPasswordManager()
"insecurePasswordsDetected" );
switch( res )
{
case KMessageBox::Yes:
case KMessageBox::PrimaryAction:
// Import passwords to the wallet, and remove the plaintext ones
#ifdef KMESSDEBUG_ACCOUNTSMANAGER_KWALLET
@@ -597,7 +597,7 @@ void AccountsManager::setupPasswordManager()
}
break;
case KMessageBox::No:
case KMessageBox::SecondaryAction:
// Only delete the plain text passwords
#ifdef KMESSDEBUG_ACCOUNTSMANAGER_KWALLET
@@ -656,7 +656,7 @@ void AccountsManager::readProperties()
// Add each one of the saved accounts to the internal list
foreach( const QString &handle, accountList )
{
if( Account::isValidEmail( handle ) )
if( Account::isValidHandle( handle ) )
{
Account *account = new Account();
account->readProperties( handle );
@@ -692,7 +692,7 @@ void AccountsManager::showAccountSettings( Account *account, QWidget *parentWind
#endif
CurrentAccount *currentAccount = CurrentAccount::instance();
KMess *kmess = static_cast<KMessApplication*>( kapp )->getContactListWindow();
KMess *kmess = static_cast<KMessApplication *>(QApplication::instance())->getContactListWindow();
bool isCurrentAccount = ( account->getHandle() == currentAccount->getHandle() );
bool isConnectedCurrentAccount = isCurrentAccount && ( kmess->isConnected() );
@@ -716,7 +716,3 @@ void AccountsManager::showAccountSettings( Account *account, QWidget *parentWind
accountSettingsDialog->show();
accountSettingsDialog->raise();
}
#include "accountsmanager.moc"
+1 -1
View File
@@ -22,7 +22,7 @@
#include <QList>
#include <KWallet/Wallet>
#include <kwallet.h>
// Forward declarations
class Account;
+21 -23
View File
@@ -35,11 +35,13 @@
#include "contactswidget.h"
#include <QDir>
#include <QElapsedTimer>
#include <QFile>
#include <QRegExp>
#include <QUrl>
#include <KFileDialog>
#include <KIO/NetAccess>
#include <QFileDialog>
#include <KLocalizedString>
#include <KMessageBox>
@@ -111,7 +113,7 @@ const QString Chat::chooseContact()
default:
// Multiple contacts in the chat.
// TODO: The official client opens a contact-choose dialog here, and starts a new chat with the selected contact.
KMessageBox::sorry( this, i18nc( "Error dialog box text",
KMessageBox::error( this, i18nc( "Error dialog box text",
"You cannot send invitations when there are multiple contacts in a chat. "
"Please start a separate chat with the contact you wanted to send the invitation to." ) );
return QString();
@@ -241,7 +243,7 @@ void Chat::contactTyping( ContactBase *contact, bool forceExpiration )
// Do not add anything to the list if the friendly name is empty
if( ! handle.isEmpty() )
{
QTime startTime = QTime::currentTime();
QElapsedTimer startTime;
// If a contact is still typing, re-insert it in the list, so that the typing start time is updated
if( typingContactsNames_.contains( handle ) )
@@ -273,7 +275,7 @@ void Chat::contactTyping( ContactBase *contact, bool forceExpiration )
}
// Update the list to remove expired typing events
QMutableHashIterator<QString,QTime> it( typingContactsTimes_ );
QMutableHashIterator<QString,QElapsedTimer> it( typingContactsTimes_ );
while( it.hasNext() )
{
it.next();
@@ -398,14 +400,14 @@ const QStringList Chat::getParticipants() const
// Return the icon to use in the tab icon chat
KIcon Chat::getParticipantsTabIcon()
QIcon Chat::getParticipantsTabIcon()
{
const QStringList participants( getParticipants() );
// If there are more participants use group icon
if( participants.count() != 1 )
{
return KIcon( "system-users" );
return QIcon::fromTheme( "system-users" );
}
// Else use the status icon of the current contact
@@ -415,10 +417,10 @@ KIcon Chat::getParticipantsTabIcon()
const ContactBase *contact = currentAccount_->getContactByHandle( handle );
if( contact == 0 )
{
return KIcon( "view-media-artist" );
return QIcon::fromTheme( "view-media-artist" );
}
return KIcon( MsnStatus::getIcon( contact->getStatus() ) );
return QIcon( MsnStatus::getIcon( contact->getStatus() ) );
}
@@ -658,7 +660,7 @@ void Chat::receivedMessage(const ChatMessage &message)
if( currentAccount_ != 0
&& msnSwitchboardConnection_ != 0
&& currentAccount_->getAutoreply()
&& ( lastSentAutoMessage_.isNull() || lastSentAutoMessage_.elapsed() > 120000 ) )
&& ( ! lastSentAutoMessage_.isValid() || lastSentAutoMessage_.elapsed() > 120000 ) )
{
// Send an auto away message every two minutes (if the contact keeps writing)
@@ -734,7 +736,7 @@ void Chat::endChatLogging()
return;
}
KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
KMessApplication *kmessApp = static_cast<KMessApplication *>(QApplication::instance());
bool canDoUserInteraction = ! kmessApp->quitSelected(); // Not if we're exiting
QDir dir;
@@ -811,7 +813,7 @@ void Chat::endChatLogging()
if( canDoUserInteraction )
{
KMessageBox::sorry( getChatWindow(),
KMessageBox::error( getChatWindow(),
i18n( "<html>KMess could not save the log for the chat with &quot;%1&quot;:<br />"
"The chat logs directory, &quot;%2&quot;, does not exist.</html>",
currentAccount_->getContactFriendlyNameByHandle( participants.first() ),
@@ -1510,7 +1512,7 @@ void Chat::slotSendingFailed( const QString &handle, const MimeMessage &message
}
else if( contentType.startsWith( "text/plain" ) && ! message.getBody().isEmpty() )
{
QString body( Qt::escape( message.getBody() ) );
QString body( message.getBody().toHtmlEscaped() );
// Cut down the message a bit if needed
if( body.length() > 16 )
@@ -1571,7 +1573,7 @@ void Chat::startFileTransfer( QList<QUrl> fileList )
#endif
// If no file names were given, ask for a filename
KUrl fileName( KFileDialog::getOpenUrl( KUrl( "kfiledialog:///:fileupload" ) ) );
QUrl fileName( QFileDialog::getOpenFileUrl( getChatWindow() ) );
// Stop if no file was selected
if( fileName.isEmpty() )
@@ -1584,7 +1586,7 @@ void Chat::startFileTransfer( QList<QUrl> fileList )
foreach( const QUrl &fileUrl, fileList )
{
KUrl localFileUrl( KIO::NetAccess::mostLocalUrl( fileUrl, this ) );
QUrl localFileUrl( fileUrl );
// If the url can't be translated to a local file, copy it to disk
if( ! localFileUrl.isLocalFile() )
@@ -1594,7 +1596,7 @@ void Chat::startFileTransfer( QList<QUrl> fileList )
#endif
// Download the remote file to a temporary folder
QString localFilePath;
if( ! KIO::NetAccess::download( fileUrl, localFilePath, this ) )
if( ! KMessShared::downloadToLocalFile( fileUrl, localFilePath ) )
{
#ifdef KMESSDEBUG_CHAT_FILETRANSFER
kmDebug() << "Copy failed.";
@@ -1605,13 +1607,13 @@ void Chat::startFileTransfer( QList<QUrl> fileList )
false,
i18n( "The file &quot;%1&quot; could not be found on "
"your computer, and the download failed.",
localFileUrl.prettyUrl() ),
localFileUrl.toDisplayString() ),
handle ) );
continue;
}
// TODO Remove the temporary file after the transfer
localFileUrl.setUrl( localFilePath );
localFileUrl = QUrl( QUrl::fromLocalFile( localFilePath ) );
}
#ifdef KMESSDEBUG_CHAT_FILETRANSFER
@@ -1654,7 +1656,7 @@ void Chat::slotSendNudge()
ChatMessage::CONTENT_NOTIFICATION_NUDGE,
false,
messageText,
QString::null );
QString() );
showMessage( message );
// Send nudge
@@ -1749,7 +1751,3 @@ void Chat::startChat()
scrollToBottom( true /* forced scrolling */ );
}
#include "chat.moc"
+8 -6
View File
@@ -23,8 +23,10 @@
#include "../network/msnswitchboardconnection.h"
#include <QHash>
#include <QElapsedTimer>
#include <QStringList>
#include <QTimer>
#include <QIcon>
// Forward declarations
@@ -79,7 +81,7 @@ class Chat : public ChatView
// Return the list of contacts in the chat
const QStringList getParticipants() const;
// Return the icon to use in the tab icon chat
KIcon getParticipantsTabIcon();
QIcon getParticipantsTabIcon();
// Return the list of previously sent messages
QStringList &getQuickRetypeList();
// Return the date and time the chat has started
@@ -91,7 +93,7 @@ class Chat : public ChatView
// Return the switchboard connection used by the chat window.
MsnSwitchboardConnection * getSwitchboardConnection() const;
// Invite a contact to the chat
void inviteContacts( const QStringList &contacts );
void inviteContacts( const QStringList &contacts ) override;
// Return whether or not the contact is in this chat. Check also if the chat is exclusive with the contact.
bool isContactInChat( const QString &handle, bool isExclusiveChatWithContact = false );
// Return whether or not the chat is at its first incoming message
@@ -118,7 +120,7 @@ class Chat : public ChatView
void showWink( const QString &handle, const QString &filename, const QString &animationName );
public slots:
void showMessage( const ChatMessage &message );
void showMessage( const ChatMessage &message ) override;
// A message was received from a contact.
void receivedMessage(const ChatMessage &message);
// Change the switchboard connection used by the chat window.
@@ -126,7 +128,7 @@ class Chat : public ChatView
// Send a nudge
void slotSendNudge();
// Send a file to a contact.
void startFileTransfer( QList<QUrl> fileList = QList<QUrl>() );
void startFileTransfer( QList<QUrl> fileList = QList<QUrl>() ) override;
private: // Private methods
// Choose the contact to start an invitation with.
@@ -158,7 +160,7 @@ class Chat : public ChatView
// The last contacts known to have been in the chat. Kept for emergency, when there's no switchboard
QStringList lastKnownContacts_;
// The last time an automessage has been sent
QTime lastSentAutoMessage_;
QElapsedTimer lastSentAutoMessage_;
// The xml chat log writer
ChatHistoryWriter* logWriter_;
// The object that connects to the switchboard server.
@@ -171,7 +173,7 @@ class Chat : public ChatView
// The list of names of contacts which are currently typing
QHash<QString,QString> typingContactsNames_;
// The list of times when the contacts have started typing
QHash<QString,QTime> typingContactsTimes_;
QHash<QString,QElapsedTimer> typingContactsTimes_;
// A timer to update the typing information
QTimer typingTimer_;
// Handle a command from ChatView (e.g. '/online')
+5 -9
View File
@@ -26,10 +26,10 @@
#include <QApplication>
#include <QDir>
#include <QLocale>
#include <QMutexLocker>
#include <KGlobal>
#include <KLocale>
#include <KLocalizedString>
#ifdef KMESSDEBUG_CHATHISTORYMANAGER
@@ -66,11 +66,11 @@ QString ChatHistoryManager::account()
*/
QString ChatHistoryManager::chatHeader( const quint64 timestamp )
{
const QDateTime date( QDateTime::fromTime_t( timestamp ) );
const QDateTime date( QDateTime::fromSecsSinceEpoch( timestamp ) );
return "<header>\n"
"<date>" + KGlobal::locale()->formatDate( date.date(), KLocale::ShortDate ) + "</date>\n"
"<time>" + KGlobal::locale()->formatTime( date.time(), KLocale::ShortDate ) + "</time>\n"
"<date>" + QLocale().toString( date.date(), QLocale::ShortFormat ) + "</date>\n"
"<time>" + QLocale().toString( date.time(), QLocale::ShortFormat ) + "</time>\n"
"</header>\n";
}
@@ -571,7 +571,6 @@ void ChatHistoryManager::setAccount( const QString newAccount )
handle_ = QString();
result_ = RESULT_OK;
timestamps_.clear();
timestamps_.setInsertInOrder( true );
// Refresh the list of contacts
contactsList();
@@ -641,7 +640,6 @@ ConversationList ChatHistoryManager::timestamps()
}
timestamps_.clear();
timestamps_.setInsertInOrder( true );
QDir logsDir( KMessConfig::instance()->getAccountDirectory( account_ ) + "/chatlogs" );
@@ -682,5 +680,3 @@ ConversationList ChatHistoryManager::timestamps()
return timestamps_;
}
+1 -1
View File
@@ -201,7 +201,7 @@ void ChatHistoryWriter::logMessage( const ChatMessage& message )
kmDebug() << "Adding conversation tag..";
#endif
quint64 timestamp = message.getDateTime().toTime_t();
quint64 timestamp = message.getDateTime().toSecsSinceEpoch();
isFirstMessage_ = false;
const QByteArray conversationHeader( "\n\n<conversation timestamp=\""
+ QString::number( timestamp ).toLatin1()
+13 -21
View File
@@ -42,11 +42,9 @@
#include <QTextDocument>
#include <QTest>
#include <KWindowSystem>
#ifdef Q_WS_X11
# include <QX11Info>
#endif
#include <KLocalizedString>
#include <kwindowsystem.h>
#include <kx11extras.h>
// Settings for debugging
#define CHATMASTER_SEND_FILES_MSNFTP 0
@@ -183,7 +181,7 @@ void ChatMaster::connected()
void ChatMaster::disconnected()
{
// Don't waste time disabling the chats when exiting.
KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
KMessApplication *kmessApp = static_cast<KMessApplication *>(QApplication::instance());
if( kmessApp->quitSelected() )
{
return;
@@ -722,7 +720,10 @@ void ChatMaster::raiseChat( Chat *chat, bool force )
// TODO: make this optional, maybe the user doesn't want the windows to span over desktops
if( ! chatWindow->isVisible() || force )
{
KWindowSystem::setOnDesktop( chatWindow->winId(), KWindowSystem::currentDesktop() );
if( KWindowSystem::isPlatformX11() )
{
KX11Extras::setOnDesktop( chatWindow->winId(), KX11Extras::currentDesktop() );
}
}
// Making windows raise and get focus interrupts the user... it's better to make them appear minimized,
@@ -762,11 +763,6 @@ void ChatMaster::raiseChat( Chat *chat, bool force )
chatWindow->show();
}
#ifdef Q_WS_X11
// Bypass focus stealing prevention (code from Quassel)
QX11Info::setAppUserTime( QX11Info::appTime() );
#endif
// Workaround a bug in KWin: force the window to get focus
if( chatWindow->windowState() & Qt::WindowMinimized) {
chatWindow->setWindowState( (chatWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive );
@@ -775,8 +771,8 @@ void ChatMaster::raiseChat( Chat *chat, bool force )
// Set the keyboard focus to the chat window
chatWindow->raise();
KWindowSystem::activateWindow( chatWindow->winId() );
KApplication::setActiveWindow( chatWindow );
KWindowSystem::activateWindow( chatWindow->windowHandle() );
chatWindow->activateWindow();
}
@@ -1055,7 +1051,7 @@ void ChatMaster::slotContactChangedMsnObject( Contact *contact )
kmDebug() << "Contact '" << handle << "' removed its MSN object";
#endif
contact->getExtension()->setContactPicturePath( QString::null );
contact->getExtension()->setContactPicturePath( QString() );
return;
}
@@ -1092,7 +1088,7 @@ void ChatMaster::slotContactChangedMsnObject( Contact *contact )
kmWarning() << "Corrupt picture was already set, "
<< "resetting contact picture." << endl;
#endif
contact->getExtension()->setContactPicturePath( QString::null );
contact->getExtension()->setContactPicturePath( QString() );
}
}
}
@@ -1385,7 +1381,7 @@ void ChatMaster::slotGotInkMessage( const QString &ink, const QString &contactHa
ChatMessage::CONTENT_MESSAGE_INK,
true,
"<img src=\"data:" + imageMimeType + ";"
"base64," + Qt::escape( inkEncodedData ) + "\">",
"base64," + QString::fromLatin1( inkEncodedData ).toHtmlEscaped() + "\">",
contactHandle,
friendlyName,
contactPicture ), switchboard );
@@ -2275,7 +2271,3 @@ ChatWindow *ChatMaster::findWindowForChat( Chat *chat )
}
return window;
}
#include "chatmaster.moc"
+31 -30
View File
@@ -28,12 +28,14 @@
#include <QDateTime>
#include <QFile>
#include <QList>
#include <QLocale>
#include <QRegExp>
#include <QRegularExpression>
#include <QTextDocument>
#include <KLocale>
#include <KStandardDirs>
#include <KUrl>
#include <KLocalizedString>
#include <QUrl>
#include <QFileInfo>
// Originally from libxml/chvalid.h, but with the last check in xmlIsCharQ removed;
// the last check was for four-byte characters, we only check shorts. Removing
@@ -142,7 +144,7 @@ QString ChatMessageStyle::convertMessageList(const QList<ChatMessage*> &messageL
if( messageList.isEmpty() )
{
kmWarning() << "no messages given!";
return QString::null;
return QString();
}
else if( messageList.count() == 1 )
{
@@ -295,7 +297,7 @@ QString ChatMessageStyle::convertMessageRoot()
{
// Indicate the chat style doesn't define the whole header/footer,
// so KMess can use it's default instead.
return QString::null;
return QString();
}
return parsedMessage; // DONE!
}
@@ -307,7 +309,7 @@ QString ChatMessageStyle::convertMessageRoot()
}
}
return QString::null;
return QString();
}
@@ -350,7 +352,7 @@ QString ChatMessageStyle::createFallbackMessage(const ChatMessage &message)
if( ! message.hasHtmlBody() )
{
// Escape HTML, replace all emoticons, links and formatting
RichTextParser::parseMsnString( body, useEmoticons_, false, true, useFormatting_, allowEmoticonLinks_, handle, pendingEmoticonTags_ );
RichTextParser::parseMsnString( body, useEmoticons_, false, true, useFormatting_, allowEmoticonLinks_, handle, &pendingEmoticonTags_ );
// Replace font special effects, like *bold*
if( useFontEffects_ )
@@ -368,11 +370,12 @@ QString ChatMessageStyle::createFallbackMessage(const ChatMessage &message)
QDateTime messageTime = message.getDateTime();
if ( showDate_ )
{
time = KGlobal::locale()->formatDateTime( messageTime, KLocale::ShortDate, showSeconds_ );
time = QLocale().toString( messageTime, showSeconds_ ? QLocale::LongFormat : QLocale::ShortFormat );
}
else
{
time = KGlobal::locale()->formatTime( messageTime.time(), showSeconds_ );
time = showSeconds_ ? QLocale().toString( messageTime.time(), "HH:mm:ss" )
: QLocale().toString( messageTime.time(), QLocale::ShortFormat );
}
}
color = (type == ChatMessage::TYPE_INCOMING || type == ChatMessage::TYPE_OFFLINE_INCOMING)
@@ -447,7 +450,7 @@ QString ChatMessageStyle::convertMessageToXml( const ChatMessage &message, bool
}
#endif
}
QString body = QString::fromUtf16( newutf16, j );
QString body = QString::fromUtf16( reinterpret_cast<const char16_t*>( newutf16 ), j );
// Get message info
int type = message.getType();
@@ -486,7 +489,7 @@ QString ChatMessageStyle::convertMessageToXml( const ChatMessage &message, bool
!isPresence,
(isPresence ? false : useFormatting_),
(isPresence ? false : allowEmoticonLinks_),
(isPresence ? QString() : handle), pendingEmoticonTags_ );
(isPresence ? QString() : handle), &pendingEmoticonTags_ );
if( useFontEffects_ )
{
@@ -504,7 +507,7 @@ QString ChatMessageStyle::convertMessageToXml( const ChatMessage &message, bool
{
// Get the time
const QDateTime &messageDate = message.getDateTime();
timestamp = messageDate.toTime_t();
timestamp = messageDate.toSecsSinceEpoch();
}
@@ -541,15 +544,16 @@ QString ChatMessageStyle::convertMessageToXml( const ChatMessage &message, bool
else
{
QString timeString;
const QDateTime &datetime = QDateTime::fromTime_t( timestamp );
const QDateTime &datetime = QDateTime::fromSecsSinceEpoch( timestamp );
if ( showDate_ )
{
timeString = KGlobal::locale()->formatDateTime( datetime, KLocale::ShortDate, showSeconds_ );
timeString = QLocale().toString( datetime, showSeconds_ ? QLocale::LongFormat : QLocale::ShortFormat );
}
else
{
timeString = KGlobal::locale()->formatTime( datetime.time(), showSeconds_ );
timeString = showSeconds_ ? QLocale().toString( datetime.time(), "HH:mm:ss" )
: QLocale().toString( datetime.time(), QLocale::ShortFormat );
}
xmlMessage = "<message"
@@ -644,7 +648,7 @@ QString ChatMessageStyle::getCssFile() const
QString cssFile( baseFolder_ + name_ + ".css" );
if( ! QFile::exists(cssFile) )
{
return QString::null;
return QString();
}
else
{
@@ -778,7 +782,7 @@ bool ChatMessageStyle::hasStyle() const
void ChatMessageStyle::parseBody(QString &body) const
{
// Replace any newline characters in the message with "<br>" so that carriage returns will show properly.
body = body.replace(QRegExp("\r?\n?$"), QString::null) // Remove last \n
body = body.replace(QRegularExpression("\r?\n?$"), QString()) // Remove last \n
.replace( "\r\n", "<br/>" )
.replace( '\r', "<br/>" )
.replace( '\n', "<br/>" );
@@ -988,8 +992,7 @@ bool ChatMessageStyle::setStyle(const QString &style)
return hasStyle();
}
KStandardDirs *dirs = KGlobal::dirs();
QString path( dirs->findResource( "data", "kmess/styles/" + style + "/" + style + ".xsl" ) );
QString path( KMessShared::findResource( "data", "kmess/styles/" + style + "/" + style + ".xsl" ) );
if(path.isNull())
{
@@ -1005,9 +1008,11 @@ bool ChatMessageStyle::setStyle(const QString &style)
if(styleSheetLoaded)
{
// Update the base folder
KUrl pathUrl;
pathUrl.setPath(path);
baseFolder_ = pathUrl.directory( KUrl::AppendTrailingSlash );
baseFolder_ = QFileInfo( path ).path();
if( ! baseFolder_.endsWith( '/' ) )
{
baseFolder_ += '/';
}
QMap<QString,QString> parameters;
parameters["basepath"] = baseFolder_;
@@ -1070,8 +1075,9 @@ QString ChatMessageStyle::stripDoctype( const QString &parsedMessage )
{
if( parsedMessage.startsWith( "<!DOCTYPE" ) )
{
QRegExp re(">\r?\n?");
int endPos = parsedMessage.indexOf( re );
QRegularExpression re(">\r?\n?");
QRegularExpressionMatch match = re.match( parsedMessage );
int endPos = match.hasMatch() ? match.capturedStart() : -1;
if( endPos == -1 )
{
kmWarning() << "Could not strip DOCTYPE tag: end position not found!";
@@ -1079,15 +1085,10 @@ QString ChatMessageStyle::stripDoctype( const QString &parsedMessage )
}
// Strip both end end possible \r\n character
return parsedMessage.mid( endPos + re.matchedLength() );
return parsedMessage.mid( endPos + match.capturedLength() );
}
else
{
return parsedMessage;
}
}
#include "chatmessagestyle.moc"
+251 -440
View File
@@ -27,53 +27,73 @@
#include <QStringList>
#include <QTimer>
#include <QClipboard>
#include <QLocale>
#include <QUrl>
#include <QWebEngineContextMenuRequest>
#include <QWebEnginePage>
#include <kdeversion.h>
#include <DOM/DOMString>
#include <DOM/Text>
#include <DOM/HTMLDocument>
#include <DOM/HTMLElement>
#include <KHTMLView>
#include <KApplication>
#include <KAction>
#include <QApplication>
#include <QAction>
#include <QIcon>
#include <KLocalizedString>
#include <KStandardAction>
#include <KMenu>
#include <QMenu>
#include <QUrl>
class ChatMessagePage : public QWebEnginePage
{
public:
explicit ChatMessagePage( ChatMessageView *messageView, QObject *parent = nullptr )
: QWebEnginePage( parent )
, messageView_( messageView )
{
}
protected:
bool acceptNavigationRequest( const QUrl &url, NavigationType type, bool isMainFrame ) override
{
Q_UNUSED( isMainFrame );
if( type == QWebEnginePage::NavigationTypeLinkClicked )
{
emit messageView_->openUrlRequest( QUrl( url ) );
return false;
}
return true;
}
private:
ChatMessageView *messageView_;
};
// The constructor
ChatMessageView::ChatMessageView( QWidget *parentWidget, QObject *parent )
: KHTMLPart( parentWidget, parent, DefaultGUI )
: QObject( parent )
, chatClearingMark_(0)
, isEmpty_(true)
, view_( new QWebEngineView( parentWidget ) )
, fontScaleFactor_(100)
, lastMessageId_(0)
{
// Disable features that might do harm or are not useful
setJScriptEnabled( false );
setJavaEnabled( false );
setMetaRefreshEnabled( false );
setOnlyLocalReferences( false );
setSuppressedPopupIndicator( false );
// Enable winks
setPluginsEnabled( true );
#if KDE_IS_VERSION( 4, 1, 0 )
// Add smooth scrolling when possible
view()->setSmoothScrollingMode( KHTMLView::SSMWhenEfficient );
#endif
// Connect signals for browsing
connect( browserExtension(), SIGNAL( openUrlRequestDelayed(const KUrl&,const KParts::OpenUrlArguments&,const KParts::BrowserArguments&) ),
this, SIGNAL( openUrlRequest(const KUrl&) ) );
connect( this, SIGNAL( completed() ),
this, SLOT ( scrollChatToBottom() ) );
view_->setPage( new ChatMessagePage( this, view_ ) );
view_->setContextMenuPolicy( Qt::CustomContextMenu );
connect( view_, &QWidget::customContextMenuRequested, this, [this]( const QPoint &point )
{
QString href;
const QWebEngineContextMenuRequest *request = view_->lastContextMenuRequest();
if( request )
{
href = request->linkUrl().toString();
}
emit popupMenu( href, view_->mapToGlobal( point ) );
} );
connect( view_->page(), &QWebEnginePage::selectionChanged, this, [this]()
{
selectedText_ = view_->page()->selectedText();
} );
// Make sure this widget can't get any focus.
view()->setFocusPolicy( Qt::NoFocus );
// Set a border to the view
view()->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel );
// Initialize the chat style parser
chatStyle_ = new ChatMessageStyle();
@@ -116,72 +136,16 @@ void ChatMessageView::addedEmoticon( QString shortcut )
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Replacing add emoticon links with shortcut '" << shortcut << "'.";
#endif
// The shortcut in emoticon links is url-encoded, convert the original one to match it
shortcut = KUrl::toPercentEncoding( shortcut );
DOM::HTMLElement link, parent, image;
DOM::HTMLDocument document = htmlDocument();
// Find all the list's links which point to this emoticon
DOM::NodeList linksList = document.getElementsByName( "newEmoticon_" + shortcut );
if( linksList.isNull() )
{
return;
}
// Check all the links in the list. The search is done backwards, because when we delete one of the items
// of the list, the list itself shortens down reassigning the indices, and a regular loop would fail
for( long i = (linksList.length() - 1); i >= 0; i-- )
{
link = linksList.item( i );
if( link.isNull() || ! link.isHTMLElement() )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Link null, skipping.";
#endif
continue;
}
// Replace the link with its first child (the emoticon image)
parent = link.parentNode();
image = link.firstChild();
if( parent.isNull() )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Parent null, skipping.";
#endif
continue;
}
if( image.isNull() )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Image null, skipping.";
#endif
continue;
}
parent.replaceChild( image, link );
}
Q_UNUSED( shortcut );
setHtml( rebuildHistory( false ) );
}
void ChatMessageView::addXml( QString xmlString )
{
// Create new HTML node
DOM::HTMLElement newNode = document().createElement( "div" );
newNode.setInnerHTML( chatStyle_->convertXmlMessageList( xmlString ) );
DOM::HTMLElement messageRoot = htmlDocument().getElementById( "messageRoot" );
if( messageRoot.isNull() )
{
messageRoot = htmlDocument().body();
}
messageRoot.appendChild( document().createTextNode("\n") );
messageRoot.appendChild( newNode );
messageRoot.appendChild( document().createTextNode("\n") );
htmlBody_ += "\n<div class=\"messageContainer\">\n"
+ chatStyle_->convertXmlMessageList( xmlString )
+ "\n</div>\n";
renderHtml();
isEmpty_ = false;
}
@@ -192,20 +156,10 @@ void ChatMessageView::addHtmlMessage(const QString &text)
{
lastMessageId_++;
// Create new HTML node
DOM::HTMLElement newNode = document().createElement("div");
newNode.setAttribute( "id", "message" + QString::number(lastMessageId_) );
newNode.setAttribute( "class", "messageContainer" );
newNode.setInnerHTML( text );
DOM::HTMLElement messageRoot = htmlDocument().getElementById("messageRoot");
if( messageRoot.isNull() )
{
messageRoot = htmlDocument().body();
}
messageRoot.appendChild( document().createTextNode("\n") );
messageRoot.appendChild( newNode );
messageRoot.appendChild( document().createTextNode("\n") );
htmlBody_ += "\n<div id=\"message" + QString::number( lastMessageId_ ) + "\" class=\"messageContainer\">\n"
+ text
+ "\n</div>\n";
renderHtml();
isEmpty_ = false;
}
@@ -250,7 +204,7 @@ QString ChatMessageView::getHistory( Account::ChatExportFormat format, bool appe
QString chatHistory;
QString handle( chatMessages_.first()->getContactHandle() );
uint date ( chatMessages_.first()->getDateTime().toTime_t() );
qint64 date( chatMessages_.first()->getDateTime().toSecsSinceEpoch() );
bool oldAllowEmoticonLinks = chatStyle_->getAllowEmoticonLinks();
chatStyle_->setAllowEmoticonLinks( false );
@@ -270,7 +224,7 @@ QString ChatMessageView::getHistory( Account::ChatExportFormat format, bool appe
+ i18nc( "Header of a chat file saved in HTML: %1 is the contact, %2 the date and time",
"Chat with %1<br/>Started on: %2",
handle,
KGlobal::locale()->formatDateTime( QDateTime::fromTime_t( date ), KLocale::ShortDate ) )
QLocale().toString( QDateTime::fromSecsSinceEpoch( date ), QLocale::ShortFormat ) )
+ "\n</div>\n";
chatHistory += rebuildHistory( true );
@@ -283,26 +237,8 @@ QString ChatMessageView::getHistory( Account::ChatExportFormat format, bool appe
return chatHistory;
}
// Get a (deep) copy of the current page source
// TODO: document().cloneNode( true ) doesn't work, so this workaround is
// required. Test if it's been fixed, and add a #define to exclude the
// workaround on fixed KHTML versions.
DOM::Document copy( document().implementation().createHTMLDocument( "" ) );
copy.removeChild( copy.documentElement() );
copy.appendChild( copy.importNode( document().documentElement(), true ) );
// Replace the html body with the chat history to be saved
DOM::HTMLElement messageRoot( copy.getElementById( "messageRoot" ) );
if( messageRoot.isNull() )
{
kmWarning() << "Current style does not define the 'messageRoot' element!";
chatStyle_->setAllowEmoticonLinks( oldAllowEmoticonLinks );
return chatHistory;
}
messageRoot.setInnerHTML( "\n" + chatHistory + "\n" );
chatStyle_->setAllowEmoticonLinks( oldAllowEmoticonLinks );
return copy.toString().string();
return buildHtmlPage( chatHistory );
}
@@ -316,7 +252,7 @@ QString ChatMessageView::getHistory( Account::ChatExportFormat format, bool appe
chatHistory += "\n\n"
+ i18nc( "Header of a single chat saved as plain text chat log: %1 is the chat date and time",
"Chat started on: %1",
KGlobal::locale()->formatDateTime( QDateTime::fromTime_t( date ), KLocale::ShortDate ) )
QLocale().toString( QDateTime::fromSecsSinceEpoch( date ), QLocale::ShortFormat ) )
+ "\n------------------------------------------------------------\n";
QListIterator<ChatMessage*> it( chatMessages_ );
@@ -333,7 +269,7 @@ QString ChatMessageView::getHistory( Account::ChatExportFormat format, bool appe
}
else
{
chatHistory += "(" + KGlobal::locale()->formatTime( chatMessage->getTime() ) + ")"
chatHistory += "(" + QLocale().toString( chatMessage->getTime(), QLocale::ShortFormat ) + ")"
" " + chatMessage->getContactHandle() + ":\n"
" " + chatMessage->getBody().trimmed() + "\n";
}
@@ -342,7 +278,7 @@ QString ChatMessageView::getHistory( Account::ChatExportFormat format, bool appe
// Add system messages etc
else
{
chatHistory += "(" + KGlobal::locale()->formatTime( chatMessage->getTime() ) + ")"
chatHistory += "(" + QLocale().toString( chatMessage->getTime(), QLocale::ShortFormat ) + ")"
" " + chatMessage->getBody().trimmed() + "\n";
lastHandle = QString();
}
@@ -404,6 +340,14 @@ bool ChatMessageView::hasHistory() const
// Whether or not text is selected.
bool ChatMessageView::hasSelection() const
{
return ! selectedText_.isEmpty();
}
// Whether or not the message area is empty
bool ChatMessageView::isEmpty() const
{
@@ -412,6 +356,63 @@ bool ChatMessageView::isEmpty() const
// Return the widget used to display the chat.
QWebEngineView *ChatMessageView::view() const
{
return view_;
}
QWidget *ChatMessageView::widget() const
{
return view_;
}
// Return the current selection as plain text.
QString ChatMessageView::selectedText() const
{
return selectedText_;
}
// Return the font scale percentage.
int ChatMessageView::zoomFactor() const
{
return fontScaleFactor_;
}
// Select all chat text.
void ChatMessageView::selectAll()
{
view_->triggerPageAction( QWebEnginePage::SelectAll );
}
// Set the display font scale.
void ChatMessageView::setFontScaleFactor( int percentage )
{
fontScaleFactor_ = percentage;
view_->setZoomFactor( percentage / 100.0 );
}
// Find text in the chat view.
void ChatMessageView::findText()
{
if( ! selectedText_.isEmpty() )
{
view_->findText( selectedText_ );
}
}
// Generate a new HTML chat log
QString ChatMessageView::rebuildHistory( bool fullHistory )
{
@@ -506,73 +507,8 @@ void ChatMessageView::removeCustomEmoticon( const QString &shortcut )
#ifdef KMESSTEST
KMESS_ASSERT( ! shortcut.isEmpty() );
#endif
// Process all IMG tags
#if KDE_IS_VERSION( 4, 1, 0 )
DOM::NodeList emoticonTags( htmlDocument().getElementsByClassName( "customEmoticon" ) );
#else
// See below (within the loop) for the actual filtering by class name
DOM::NodeList emoticonTags( htmlDocument().getElementsByTagName( "img" ) );
#endif
// Get the original (non-HTML) shortcut
QString originalShortcut( KMessShared::htmlUnescape( shortcut ) );
// Proceed one by one: while removing elements, the list shortens too
for( unsigned long item = emoticonTags.length(); item > 0; --item )
{
DOM::HTMLElement img( emoticonTags.item( item - 1 ) );
#if KDE_IS_VERSION( 4, 1, 0 )
#else
// KDE4.0's KHTML DOM didn't have getElementsByClassName(). We therefore
// have to filter the class name here.
if( ! img.className().string().contains( "customEmoticon" ) )
{
continue;
}
#endif
// Check if the element is valid
if( img.isNull() )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Skipped null element.";
#endif
continue;
}
// Get the image's alternative text attribute; if it's not our custom emoticon, skip
// HACK: Search both by the html and plain version, to avoid skipping strange shortcuts
QString altAttribute( img.getAttribute("alt").string() );
if( altAttribute != shortcut && altAttribute != originalShortcut )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Skipped element:" << img.getAttribute("alt").string() << "while searching for" << originalShortcut;
#endif
continue;
}
// We've found one of the emoticons to delete
DOM::HTMLElement parent( img.parentNode() );
// If the emoticon is contained in a link, remove both.
if( parent.tagName().string() == "a" )
{
img = parent;
parent = parent.parentNode();
}
// The text should be that of the original shortcut, not the html-encoded one
DOM::Text textNode( htmlDocument().createTextNode( originalShortcut ) );
// Replace the link with the image inside with the simple text
parent.replaceChild( textNode, img );
// Force updating the view to instantly display the new image
view()->updateContents( img.getRect() );
}
Q_UNUSED( shortcut );
setHtml( rebuildHistory( false ) );
}
@@ -580,18 +516,9 @@ void ChatMessageView::removeCustomEmoticon( const QString &shortcut )
// Replace the last message with a new contents.
void ChatMessageView::replaceLastMessage(const QString &text)
{
// Fetch the HTML node
QString lastId( "message" + QString::number( lastMessageId_ ) );
DOM::HTMLElement lastNode( htmlDocument().getElementById( lastId ) );
if( lastNode.isNull() || ! lastNode.isHTMLElement() )
{
kmWarning() << "message block with id" + lastId + "not found, appending message instead.";
addHtmlMessage( text );
return;
}
// Replace contents
lastNode.setInnerHTML( text );
Q_UNUSED( text );
htmlBody_ = rebuildHistory( false );
renderHtml();
}
@@ -599,7 +526,10 @@ void ChatMessageView::replaceLastMessage(const QString &text)
// Scroll forward or backward within the chat browser
void ChatMessageView::scrollChat( bool forward, bool fast )
{
view()->scrollBy( 0, ( forward ? +1 : -1 ) * view()->visibleHeight() / ( fast ? 1 : 2 ) );
const QString script = QStringLiteral( "window.scrollBy(0, (%1) * window.innerHeight / %2);" )
.arg( forward ? 1 : -1 )
.arg( fast ? 1 : 2 );
view_->page()->runJavaScript( script );
}
@@ -607,8 +537,7 @@ void ChatMessageView::scrollChat( bool forward, bool fast )
// Force scrolling to the bottom of the chat browser
void ChatMessageView::scrollChatToBottom()
{
int contentsHeight = view()->contentsHeight();
view()->scrollBy( 0, contentsHeight );
view_->page()->runJavaScript( QStringLiteral( "window.scrollTo(0, document.body.scrollHeight);" ) );
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Scrolled view down.";
@@ -620,16 +549,10 @@ void ChatMessageView::scrollChatToBottom()
// Scroll to the bottom of the chat browser if needed
void ChatMessageView::scrollChatToBottomGently()
{
int contentsHeight = view()->contentsHeight();
int visibleHeight = view()->visibleHeight();
// If the user has scrolled up more than one viewport of height, don't move
if( contentsHeight - ( view()->contentsY() + visibleHeight ) > visibleHeight )
{
return;
}
view()->scrollBy( 0, contentsHeight );
view_->page()->runJavaScript( QStringLiteral(
"if ((document.body.scrollHeight - window.scrollY - window.innerHeight) <= window.innerHeight) {"
" window.scrollTo(0, document.body.scrollHeight);"
"}" ) );
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Scrolled view down.";
@@ -644,81 +567,85 @@ void ChatMessageView::setHtml( const QString &newHtmlBody )
// Reset state variables
lastMessageId_ = 0;
isEmpty_ = newHtmlBody.isEmpty();
htmlBody_ = newHtmlBody;
renderHtml();
}
// If the style is not working, prepare a standard HTML page
if( ! chatStyle_->canConvert() )
// Render the current HTML body in the browser widget.
void ChatMessageView::renderHtml()
{
view_->setHtml( buildHtmlPage( htmlBody_ ), QUrl::fromLocalFile( chatStyle_->getBaseFolder() + "/" ) );
}
// Wrap the current style around the body contents.
QString ChatMessageView::buildHtmlPage( const QString &body ) const
{
QString cssFile ( chatStyle_->getCssFile () );
QString baseFolder( chatStyle_->getBaseFolder() );
if( ! cssFile.isEmpty() )
{
QString cssFile ( chatStyle_->getCssFile () );
QString baseFolder( chatStyle_->getBaseFolder() );
if( ! cssFile.isEmpty() )
{
cssFile = " <link href=\"" + cssFile + "\" rel=\"stylesheet\" type=\"text/css\">\n";
}
if( ! baseFolder.isEmpty() )
{
baseFolder = " <base href=\"" + baseFolder + "\" id=\"baseHrefTag\">\n";
}
begin();
// Force standard colors, because chat messages will not work
// correctly with the (dark) color scheme anyway.
write( "<html id=\"ChatMessageView\">\n"
" <head>\n"
" <!-- " + getStyleTag() + " -->\n"
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + encoding() + "\">\n"
+ baseFolder +
" <style type=\"text/css\">\n"
" /* standard colors for compatibility with dark color schemes */\n"
" body { font-size: 10pt; margin: 0; padding: 5px; background-color: #fff; color: #000; }\n"
" a:link { color: blue; }\n"
" a:visited { color: purple; }\n"
" a:hover { color: red; }\n"
" a:active { color: red; }\n"
" </style>\n"
+ cssFile +
" </head>\n"
" <body>\n"
" <div id=\"messageRoot\">\n"
+ newHtmlBody +
" </div>\n"
" </body>\n"
"</html>\n" );
end();
return;
cssFile = " <link href=\"" + cssFile + "\" rel=\"stylesheet\" type=\"text/css\">\n";
}
if( ! baseFolder.isEmpty() )
{
baseFolder = " <base href=\"" + baseFolder + "\" id=\"baseHrefTag\">\n";
}
begin();
// Write the style's root elements
write( chatStyle_->convertMessageRoot() );
// Add the style tag
DOM::NodeList list( document().getElementsByTagName("head") );
if( ! list.isNull() )
// Prefer the style's root page when available, but fall back to a minimal
// compatible page.
QString page;
if( chatStyle_->canConvert() )
{
DOM::Node head = list.item( 0 );
head.insertBefore( document().createComment( getStyleTag() ), head.firstChild() );
}
// Insert under root the given HTML body, but do nothing if we're just clearing it up
// (the new page is empty already)
if( ! newHtmlBody.isEmpty() )
{
DOM::HTMLElement messageRoot = document().getElementById( "messageRoot" );
if( messageRoot.isNull() )
page = chatStyle_->convertMessageRoot();
int insertPos = page.indexOf( "</head>", 0, Qt::CaseInsensitive );
if( insertPos != -1 )
{
kmWarning() << "Chat style does not define the 'messageRoot' element!";
messageRoot = htmlDocument().body();
page.insert( insertPos, " <!-- " + getStyleTag() + " -->\n" );
}
messageRoot.setInnerHTML( "\n" + newHtmlBody + "\n" );
int rootStart = page.indexOf( "id=\"messageRoot\"" );
if( rootStart == -1 )
{
rootStart = page.indexOf( "id='messageRoot'" );
}
if( rootStart != -1 )
{
int divEnd = page.indexOf( '>', rootStart );
if( divEnd != -1 )
{
page.insert( divEnd + 1, "\n" + body + "\n" );
return page;
}
}
kmWarning() << "Chat style does not define the 'messageRoot' element!";
}
// Complete loading
end();
return "<html id=\"ChatMessageView\">\n"
" <head>\n"
" <!-- " + getStyleTag() + " -->\n"
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"
+ baseFolder +
" <style type=\"text/css\">\n"
" body { font-size: 10pt; margin: 0; padding: 5px; background-color: #fff; color: #000; }\n"
" a:link { color: blue; }\n"
" a:visited { color: purple; }\n"
" a:hover { color: red; }\n"
" a:active { color: red; }\n"
" </style>\n"
+ cssFile +
" </head>\n"
" <body>\n"
" <div id=\"messageRoot\">\n"
+ body +
" </div>\n"
" </body>\n"
"</html>\n";
}
@@ -834,20 +761,25 @@ void ChatMessageView::showMessage( const ChatMessage &message )
// Replace an application's accept/reject/cancel links with another text
void ChatMessageView::updateApplicationMessage( const QString &messageId, const QString &newMessage )
{
DOM::HTMLDocument document( htmlDocument() );
DOM::HTMLElement linksSpan = document.getElementById( "app" + messageId + "-links-block" );
// This chat doesn't contain messages for this application, bail out
if( linksSpan.isNull() )
const QString marker = "id=\"app" + messageId + "-links-block\"";
int markerPos = htmlBody_.indexOf( marker );
if( markerPos == -1 )
{
return;
}
// Change the span's ID so it won't trigger changes anymore
linksSpan.setId( DOM::DOMString( "app" + messageId ) );
const int spanStart = htmlBody_.lastIndexOf( "<span", markerPos );
const int spanEnd = htmlBody_.indexOf( "</span>", markerPos );
if( spanStart == -1 || spanEnd == -1 )
{
return;
}
// Replace the links with the given text
linksSpan.setInnerText( DOM::DOMString( newMessage ) );
QString replacement = "<span id=\"app" + messageId + "\">";
replacement += newMessage.toHtmlEscaped();
replacement += "</span>";
htmlBody_.replace( spanStart, spanEnd + 7 - spanStart, replacement );
renderHtml();
}
@@ -934,133 +866,10 @@ void ChatMessageView::updateCustomEmoticon( const QString &code, const QString &
kmWarning() << "can't update custom emoticon, replacement not found (contact=" << handle << ").";
return;
}
// The pattern used to find if the new custom emoticon is already in our theme
QString customEmoticonsPattern( EmoticonManager::instance()->getHtmlPattern( true ).pattern() );
// Process all pending tags, avoid parsing all <img> tags
DOM::HTMLDocument document = htmlDocument();
foreach( const QString &tag, pendingEmoticonTags_ )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Checking DOM element '" << tag << "'";
#endif
// Check if the element is valid
DOM::HTMLElement img = document.getElementById( tag );
if( img.isNull() )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Skipped null element.";
#endif
continue;
}
// Get the image's alternative text attribute
QString imageAltText( img.getAttribute("alt").string() );
// Before converting the alt attribute, save it; we'll use it later
QString originalCode( imageAltText );
// KHTML's DOM converts all HTML entities to text; so we have to convert them back,
// to be able to compare the image's code to the emoticon's (which is already encoded)
KMessShared::htmlEscape( imageAltText );
// See if this element's ALT attribute matches the shortcut
if( img.isNull() || imageAltText != code )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Skipped invalid element (searched '" << code << "', found '" << imageAltText << "').";
#endif
continue;
}
// Also check whether the handle is also set, avoid replacing someone elses code.
if( img.getAttribute("contact") != handle )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Emoticon code found, but different handle: " << img.getAttribute("contact");
#endif
continue;
}
// Update image placeholder attributes (replacing childs is too much trouble).
// Create a regexp to parse the replacement attributes.
QRegExp attribRegExp(
"([a-z]+)=" // words followed by an =
"(?:" // start of options
"'([^']*)'|" // attrib separated by single quote, or..
"\"([^\"]*)\"|" // attrib separated by double quote, or..
"([^ \t\r\n>]+)" // attrib followed by space, newline, tab, endtag
")" // end of options
);
#ifdef KMESSTEST
KMESS_ASSERT( attribRegExp.isValid() );
#endif
int attribPos = 0;
while(true)
{
// Find next attribute
attribPos = attribRegExp.indexIn(replacement, attribPos);
if( attribPos == -1 )
{
break;
}
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Emoticon replacement has attribute: " << attribRegExp.cap(1) << "=" << attribRegExp.cap(2);
#endif
img.setAttribute( attribRegExp.cap(1), attribRegExp.cap(2) );
// Also change the image's class and reset its ID
img.setAttribute( "class", "customEmoticon" );
img.setAttribute( "id", "" );
attribPos += attribRegExp.matchedLength();
}
// Allow the user to "steal" this emoticon
if( handle != CurrentAccount::instance()->getHandle()
&& ! customEmoticonsPattern.contains( code ) )
{
#ifdef KMESSDEBUG_CHATMESSAGEVIEW
kmDebug() << "Inserting emoticon addition link";
#endif
// Copy the original image to a new one we'll modify
DOM::HTMLElement newImage = img.cloneNode( true );
// Remove any title in the emoticon image, as it would be displayed instead of the
// title from the link we're creating
newImage.setAttribute( "title", "" );
// URL-encode the shortcut, so the emoticon adding dialog will get a correct representation,
// even if it contains characters which would fool the link parser.
QString urlCode( KUrl::toPercentEncoding( code ) );
// Create a new 'link' element
// The name attribute is required as, if the user adds the emoticon, we'll want to make all links like this unclickable
DOM::HTMLElement newLink = document.createElement("a");
newLink.setAttribute( "name", "newEmoticon_" + urlCode );
newLink.setAttribute( "title", i18n( "Add this emoticon: %1", code ) ); // Not escaped for " or ', KHTML does it
newLink.setAttribute( "href", "kmess://emoticon/" + handle + "/" + urlCode + "/"
+ KUrl::toPercentEncoding( newImage.getAttribute("src").string() ) );
// Add the new image as child of the new link
newLink.appendChild( newImage );
// And put the link in place of the old image
img.parentNode().replaceChild( newLink, img );
}
}
// Force updating the view to display instantly the new image
view()->updateContents( QRect( view()->contentsX(),
view()->contentsY(),
view()->visibleWidth(),
view()->visibleHeight() ) );
Q_UNUSED( code );
Q_UNUSED( replacement );
Q_UNUSED( handle );
setHtml( rebuildHistory( false ) );
}
//
@@ -1068,26 +877,30 @@ void ChatMessageView::updateCustomEmoticon( const QString &code, const QString &
// Attaches them to slots on this class.
//
// Users of this class can add their own entries to the popup menu by getting
// the KMenu instance representing the popup using ChatMessageView::popupMenu().
// the QMenu instance representing the popup using ChatMessageView::popupMenu().
//
void ChatMessageView::createPopupMenuActions()
{
copyAction_ = KStandardAction::copy( this, SLOT(slotCopyChatText()), this );
selectAllAction_ = KStandardAction::selectAll( this, SLOT(slotSelectAllChatText()), this );
findAction_ = KStandardAction::find( this, SLOT(slotFindChatText()), this );
copyAction_ = new QAction( QIcon::fromTheme( "edit-copy" ), i18n("&Copy Text"), this );
selectAllAction_ = new QAction( QIcon::fromTheme( "edit-select-all" ), i18n("Select &All"), this );
findAction_ = new QAction( QIcon::fromTheme( "edit-find" ), i18n("Find &Text..." ), this );
connect( copyAction_, SIGNAL(triggered(bool)), this, SLOT(slotCopyChatText()) );
connect( selectAllAction_, SIGNAL(triggered(bool)), this, SLOT(slotSelectAllChatText()) );
connect( findAction_, SIGNAL(triggered(bool)), this, SLOT(slotFindChatText()) );
}
//
// Returns a KMenu containing the "basic" items for a popup menu for a chatmessageview
// Returns a QMenu containing the "basic" items for a popup menu for a chatmessageview
// These basic items are "Select All", "Copy Text" and "Find text".
//
// NOTE: It is the CALLER'S responsibility to delete the KMenu instance. It is also their
// responsibility to actually show the menu using KMenu::exec().
// NOTE: It is the CALLER'S responsibility to delete the QMenu instance. It is also their
// responsibility to actually show the menu using QMenu::exec().
//
KMenu *ChatMessageView::popupMenu()
QMenu *ChatMessageView::popupMenu()
{
// Add items to this context menu
KMenu *contextMenu = new KMenu( view() );
QMenu *contextMenu = new QMenu( view() );
// Update the labels a bit though
copyAction_ ->setText( i18n("&Copy Text") );
@@ -1108,7 +921,7 @@ KMenu *ChatMessageView::popupMenu()
void ChatMessageView::slotCopyChatText()
{
// For HTML use selectedTextAsHTML();
kapp->clipboard()->setText( selectedText() );
QApplication::clipboard()->setText( selectedText() );
}
// The user clicked the "find text" option in the context menu
@@ -1122,5 +935,3 @@ void ChatMessageView::slotSelectAllChatText()
{
selectAll();
}
#include "chatmessageview.moc"
+40 -13
View File
@@ -20,25 +20,23 @@
#include "account.h"
#include <KHTMLPart>
#include <KParts/BrowserExtension>
#include <KAction>
#include <QAction>
#include <QUrl>
#include <QWebEngineView>
class ChatMessage;
class ChatMessageStyle;
class CurrentAccount;
class QStringList;
/**
* This class is used to display chat messages.
* A KHTMLPart is used for this because unlike QTextBrowser, KHTML has support for CSS.
*
* @author Diederik van der Boor
* @ingroup Chat
*/
class ChatMessageView : public KHTMLPart
class ChatMessageView : public QObject
{
Q_OBJECT
@@ -58,6 +56,8 @@ class ChatMessageView : public KHTMLPart
QString getStyleTag() const;
// Whether or not there are any messages
bool hasHistory() const;
// Whether or not text is selected.
bool hasSelection() const;
// Whether or not the message area is empty
bool isEmpty() const;
// Delete an emoticon from the chat.
@@ -66,8 +66,16 @@ class ChatMessageView : public KHTMLPart
void updateCustomEmoticon( const QString &code, const QString &replacement, const QString &handle );
// Replace the entire contents with a new chat in XML
void setXml( const QString &newXmlBody );
// Retrieve the KMenu for the context menu.
KMenu* popupMenu();
// Return the widget used to display the chat.
QWebEngineView *view() const;
// Return the widget used to display the chat, for old KHTMLPart call sites.
QWidget *widget() const;
// Retrieve the QMenu for the context menu.
QMenu* popupMenu();
// Return the current selection as plain text.
QString selectedText() const;
// Return the font scale percentage.
int zoomFactor() const;
public slots:
// Finds the links to add a custom emoticon, and remove them because we've already added that emoticon
@@ -89,6 +97,12 @@ class ChatMessageView : public KHTMLPart
void scrollChatToBottom();
// Scroll to the bottom of the chat browser if needed
void scrollChatToBottomGently();
// Select all chat text.
void selectAll();
// Set the display font scale.
void setFontScaleFactor( int percentage );
// Find text in the chat view.
void findText();
// Add the given message to the message browser.
void showMessage( const ChatMessage &message );
// Replace an application's accept/reject/cancel links with another text
@@ -105,6 +119,10 @@ class ChatMessageView : public KHTMLPart
void replaceLastMessage( const QString &text );
// Replace the entire contents with new HTML code
void setHtml( const QString &newHtmlBody );
// Render the current HTML body in the browser widget.
void renderHtml();
// Wrap the current style around the body contents.
QString buildHtmlPage( const QString &body ) const;
// Create the context menu actions. Should only get called once.
void createPopupMenuActions();
@@ -124,6 +142,14 @@ class ChatMessageView : public KHTMLPart
CurrentAccount *currentAccount_;
// Whether or not the chat message area is empty
bool isEmpty_;
// WebEngine replacement for the old KHTMLPart widget.
QWebEngineView *view_;
// Current body contents inserted under the chat style root.
QString htmlBody_;
// Current font scale percentage.
int fontScaleFactor_;
// Last selected text as reported by WebEngine.
QString selectedText_;
// The last messages sent by the same contact. This is used to combine them
QList<ChatMessage*> lastContactMessages_;
// The last message id, for replaceLastMessage()
@@ -131,16 +157,17 @@ class ChatMessageView : public KHTMLPart
// The list of custom emoticons which haven't been received yet
QStringList pendingEmoticonTags_;
// The KActions associated with the context menu
KAction* copyAction_;
KAction* selectAllAction_;
KAction* findAction_;
QAction* copyAction_;
QAction* selectAllAction_;
QAction* findAction_;
signals:
// Signal that there's an application command
void appCommand(QString cookie, QString contact, QString method);
// Signal a click on an URL
void openUrlRequest( const KUrl &url );
void openUrlRequest( const QUrl &url );
// Signal a context-menu request.
void popupMenu( const QString &clickedUrl, const QPoint &point );
};
#endif
+2 -6
View File
@@ -21,7 +21,7 @@
#include <KColorScheme>
#include <KIconLoader>
#include <KLocale>
#include <KLocalizedString>
#include <QFontMetrics>
#include <QPainter>
@@ -102,7 +102,7 @@ void ChatStatusBar::setMessage( MessageType type, const QString& text )
break;
}
pixmap_ = ( iconName == 0 ) ? QPixmap() : SmallIcon( iconName );
pixmap_ = ( iconName == 0 ) ? QPixmap() : QIcon::fromTheme( iconName ).pixmap( 16, 16 );
QTimer::singleShot( GeometryTimeout, this, SLOT( assureVisibleText() ) );
update();
}
@@ -369,7 +369,3 @@ inline int ChatStatusBar::minimumTextHeight() const
{
return minTextHeight_;
}
#include "chatstatusbar.moc"
+2 -2
View File
@@ -64,9 +64,9 @@ class ChatStatusBar: public QWidget
protected:
// Paint the statusbar.
virtual void paintEvent ( QPaintEvent *event);
virtual void paintEvent ( QPaintEvent *event) override;
// Statusbar is resized, update it.
virtual void resizeEvent( QResizeEvent *event);
virtual void resizeEvent( QResizeEvent *event) override;
private slots:
// Update the background color.
+54 -54
View File
@@ -34,19 +34,22 @@
#include <QClipboard>
#include <QDropEvent>
#include <QEvent>
#include <QMimeData>
#include <QRegExp>
#include <QTemporaryFile>
#include <QTextCodec>
#include <QTextDocument>
#include <QTextStream>
#include <QTextOption>
#include <KAction>
#include <KFileDialog>
#include <KHTMLView>
#include <KLocale>
#include <KMenu>
#include <QAction>
#include <QFileDialog>
#include <QIcon>
#include <KLocalizedString>
#include <KLocalizedString>
#include <QMenu>
#include <KMessageBox>
#include <KRun>
#include <QDesktopServices>
#include <KStandardAction>
@@ -63,8 +66,8 @@ ChatView::ChatView( QWidget *parent )
chatMessageView_ = new ChatMessageView( this, this );
connect( chatMessageView_, SIGNAL( popupMenu(const QString&,const QPoint&) ),
this, SLOT ( slotShowContextMenu(const QString&,const QPoint&) ) );
connect( chatMessageView_, SIGNAL( openUrlRequest(const KUrl&) ),
this, SLOT( slotOpenURLRequest(const KUrl&) ) );
connect( chatMessageView_, SIGNAL( openUrlRequest(const QUrl&) ),
this, SLOT( slotOpenURLRequest(const QUrl&) ) );
connect( this, SIGNAL( updateApplicationMessage(const QString&,const QString&) ),
chatMessageView_, SLOT( updateApplicationMessage(const QString&,const QString&) ) );
@@ -119,7 +122,7 @@ void ChatView::editCopy()
return;
}
kapp->clipboard()->setText( chatMessageView_->selectedText() );
QApplication::clipboard()->setText( chatMessageView_->selectedText() );
// use selectedTextAsHTML() and setData() to copy HTML instead of text
}
@@ -249,7 +252,7 @@ bool ChatView::eventFilter( QObject *obj, QEvent *event )
foreach( const QString &handle, handles )
{
// Don't try to invite random strings, nonexistent handles
if( ! Account::isValidEmail( handle )
if( ! Account::isValidHandle( handle )
|| currentAccount_->getContactByHandle( handle ) == 0 )
{
handles.removeAll( handle );
@@ -398,7 +401,7 @@ bool ChatView::saveChatToFile( const QString &path, Account::ChatExportFormat fo
QFileInfo info( file );
kmWarning() << "File save failed! Could not open file" << path << ".";
KMessageBox::sorry( chatMessageView_->view(), i18n( "Could not save chat log in directory '%1'.\n"
KMessageBox::error( chatMessageView_->view(), i18n( "Could not save chat log in directory '%1'.\n"
"Make sure you have permission to write in "
"the folder where logs are being saved.",
info.absolutePath() ) );
@@ -478,12 +481,12 @@ bool ChatView::saveChatToFile( const QString &path, Account::ChatExportFormat fo
// For plain text logs we use the locale codec
if (format == Account::EXPORT_TEXT)
{
textStream.setCodec( QTextCodec::codecForLocale() );
textStream.setEncoding( QStringConverter::System );
}
// For HTML logs (which are created with the UTF-8 charset) we use UTF-8 encoding
else
{
textStream.setCodec( QTextCodec::codecForName("UTF-8") );
textStream.setEncoding( QStringConverter::Utf8 );
}
textStream << chatHistory;
@@ -557,10 +560,11 @@ void ChatView::showSaveChatDialog()
do
{
// Show a dialog to get a filename from the user.
path = KFileDialog::getSaveFileName( path,
path = QFileDialog::getSaveFileName( chatMessageView_->view(),
QString(),
path,
i18nc( "Chat log saving dialog, file type filter",
"*.html *.htm|Web Page (*.html)\n"
"*.txt|Plain Text Document (*.txt)\n" ) );
"Web Page (*.html *.htm);;Plain Text Document (*.txt)" ) );
// Verify if the user has canceled the command
if( path.isEmpty() )
@@ -605,7 +609,7 @@ void ChatView::showSaveChatDialog()
*/
void ChatView::slotAddContact()
{
QString email( chatViewClickedUrl_.url() );
QString email( chatViewClickedUrl_.toString() );
if( ! chatViewClickedUrl_.isValid() )
{
@@ -639,7 +643,7 @@ void ChatView::slotAddContact()
*/
void ChatView::slotAddNewEmoticon()
{
if( ! chatViewClickedUrl_.isValid() || chatViewClickedUrl_.protocol() != "kmess" || chatViewClickedUrl_.host() != "emoticon" )
if( ! chatViewClickedUrl_.isValid() || chatViewClickedUrl_.scheme() != "kmess" || chatViewClickedUrl_.host() != "emoticon" )
{
#ifdef KMESSDEBUG_CHATVIEW
kmDebug() << "Ignoring request for invalid URL: " << chatViewClickedUrl_;
@@ -677,8 +681,8 @@ void ChatView::slotAddNewEmoticon()
}
// URL-Decode the encoded strings
picture = KUrl::fromPercentEncoding( picture.toAscii() );
shortcut = KUrl::fromPercentEncoding( shortcut.toUtf8() );
picture = QUrl::fromPercentEncoding( picture.toLatin1() );
shortcut = QUrl::fromPercentEncoding( shortcut.toUtf8() );
#ifdef KMESSDEBUG_CHATVIEW
kmDebug() << "Showing Add Emoticon dialog - shortcut=" << shortcut << " picture=" << picture;
@@ -707,7 +711,7 @@ void ChatView::slotClearChat()
// The user clicked the "copy address" or "copy email" option in the context menu
void ChatView::slotCopyAddress()
{
QString url( chatViewClickedUrl_.url() );
QString url( chatViewClickedUrl_.toString() );
if( ! chatViewClickedUrl_.isValid() )
{
@@ -728,7 +732,7 @@ void ChatView::slotCopyAddress()
url = url.mid( 7 );
}
kapp->clipboard()->setText( url );
QApplication::clipboard()->setText( url );
// Reset the url
chatViewClickedUrl_.clear();
@@ -756,7 +760,7 @@ void ChatView::slotFindChatText()
*/
void ChatView::slotIgnoreEmoticon()
{
if( ! chatViewClickedUrl_.isValid() || chatViewClickedUrl_.protocol() != "kmess" || chatViewClickedUrl_.host() != "emoticon" )
if( ! chatViewClickedUrl_.isValid() || chatViewClickedUrl_.scheme() != "kmess" || chatViewClickedUrl_.host() != "emoticon" )
{
#ifdef KMESSDEBUG_CHATVIEW
kmDebug() << "Ignoring request for invalid URL: " << chatViewClickedUrl_;
@@ -793,7 +797,7 @@ void ChatView::slotIgnoreEmoticon()
}
// URL-Decode the encoded strings
shortcut = KUrl::fromPercentEncoding( shortcut.toUtf8() );
shortcut = QUrl::fromPercentEncoding( shortcut.toUtf8() );
// Add the emoticon to the contact's blacklist and update the chat
if( contact->manageEmoticonBlackList( true, shortcut ) )
@@ -805,13 +809,13 @@ void ChatView::slotIgnoreEmoticon()
// Open a new url clicked in the khtml widget
void ChatView::slotOpenURLRequest( const KUrl &url )
void ChatView::slotOpenURLRequest( const QUrl &url )
{
chatViewClickedUrl_ = url;
// Internal URLs form: kmess://call_type/parameters?more_parameters
if( url.protocol() == "kmess" )
if( url.scheme() == "kmess" )
{
// Application URLs form: kmess://application/responseType/contactHandle?cookieId
if( url.host() == "application" )
@@ -832,14 +836,15 @@ void ChatView::slotOpenURLRequest( const KUrl &url )
currentAccount_, window(), AccountSettingsDialog::PageChatStyle );
}
}
else if( url.protocol() == "file" )
else if( url.scheme() == "file" )
{
// Obtain the widget of the main KMess window, to correctly link it to the opened app
KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
KMessApplication *kmessApp = static_cast<KMessApplication *>(QApplication::instance());
QWidget *mainWindow = kmessApp->getContactListWindow()->window();
// Execute the local file with the system's default association (KRun auto-deletes itself)
new KRun( url, mainWindow, 0, true );
// Execute the local file with the system's default association.
Q_UNUSED( mainWindow );
QDesktopServices::openUrl( url );
}
else
{
@@ -890,10 +895,10 @@ void ChatView::setInkDrawing( Isf::Drawing* newDrawing )
void ChatView::slotSendAppCommand()
{
// Ignore non-internal links and non-application internal links
if( ! chatViewClickedUrl_.isValid() || chatViewClickedUrl_.protocol() != "kmess" || chatViewClickedUrl_.host() != "application" )
if( ! chatViewClickedUrl_.isValid() || chatViewClickedUrl_.scheme() != "kmess" || chatViewClickedUrl_.host() != "application" )
{
#ifdef KMESSDEBUG_CHATVIEW
kmDebug() << "Not sending invalid application link: " << chatViewClickedUrl_.url();
kmDebug() << "Not sending invalid application link: " << chatViewClickedUrl_.toString();
#endif
return;
@@ -928,10 +933,10 @@ void ChatView::slotSendAppCommand()
// The user right clicked at the KHTMLPart to show a popup.
void ChatView::slotShowContextMenu( const QString &clickedUrl, const QPoint &point )
{
KAction *urlAction = 0;
QAction *urlAction = 0;
// Add items to this context menu
KMenu *contextMenu = chatMessageView_->popupMenu();
QMenu *contextMenu = chatMessageView_->popupMenu();
// separate the "copy/find/select all" actions from the chat-specific ones below.
contextMenu->addSeparator();
@@ -939,42 +944,42 @@ void ChatView::slotShowContextMenu( const QString &clickedUrl, const QPoint &poi
// Analyze incoming URL, if present
if( ! clickedUrl.isEmpty() )
{
KUrl url( clickedUrl );
QUrl url( clickedUrl );
#ifdef KMESSDEBUG_CHATVIEW
kmDebug() << "Clicked URL: " << url.prettyUrl();
kmDebug() << "Clicked URL: " << url.toDisplayString();
#endif
if( url.protocol() == "kmess" && url.host() == "emoticon" )
if( url.scheme() == "kmess" && url.host() == "emoticon" )
{
urlAction = new KAction( KIcon( "list-add" ), i18n("Add this &Emoticon..."), this );
urlAction = new QAction( QIcon::fromTheme( "list-add" ), i18n("Add this &Emoticon..."), this );
connect( urlAction, SIGNAL(triggered(bool)), this, SLOT(slotAddNewEmoticon()) );
contextMenu->addAction( urlAction );
urlAction = new KAction( KIcon( "list-remove" ), i18n("Hide this &Emoticon"), this );
urlAction = new QAction( QIcon::fromTheme( "list-remove" ), i18n("Hide this &Emoticon"), this );
connect( urlAction, SIGNAL(triggered(bool)), this, SLOT(slotIgnoreEmoticon()) );
contextMenu->addAction( urlAction );
}
else if( url.protocol().left( 6 ) == "mailto" )
else if( url.scheme().left( 6 ) == "mailto" )
{
urlAction = new KAction( KIcon( "mail" ), i18n("Send &Email"), this );
urlAction = new QAction( QIcon::fromTheme( "mail" ), i18n("Send &Email"), this );
connect( urlAction, SIGNAL(triggered(bool)), this, SLOT(slotVisitAddress()) );
contextMenu->addAction( urlAction );
urlAction = new KAction( KIcon( "list-add-user" ), i18n("Add &Contact"), this );
urlAction = new QAction( QIcon::fromTheme( "list-add-user" ), i18n("Add &Contact"), this );
connect( urlAction, SIGNAL(triggered(bool)), this, SLOT(slotAddContact()) );
contextMenu->addAction( urlAction );
urlAction = new KAction( KIcon( "copy" ), i18n("Copy E&mail Address"), this );
urlAction = new QAction( QIcon::fromTheme( "copy" ), i18n("Copy E&mail Address"), this );
connect( urlAction, SIGNAL(triggered(bool)), this, SLOT(slotCopyAddress()) );
contextMenu->addAction( urlAction );
}
else
{
urlAction = new KAction( KIcon( "document-open-remote" ), i18n("Visit &Link"), this );
urlAction = new QAction( QIcon::fromTheme( "document-open-remote" ), i18n("Visit &Link"), this );
connect( urlAction, SIGNAL(triggered(bool)), this, SLOT(slotVisitAddress()) );
contextMenu->addAction( urlAction );
urlAction = new KAction( KIcon( "edit-copy" ), i18n("Copy &Address"), this );
urlAction = new QAction( QIcon::fromTheme( "edit-copy" ), i18n("Copy &Address"), this );
connect( urlAction, SIGNAL(triggered(bool)), this, SLOT(slotCopyAddress()) );
contextMenu->addAction( urlAction );
}
@@ -987,8 +992,8 @@ void ChatView::slotShowContextMenu( const QString &clickedUrl, const QPoint &poi
#endif
// Create items
KAction *clearChatAction = KStandardAction::clear( this, SLOT(slotClearChat()), 0 );
KAction *saveToFileAction = KStandardAction::save( this, SLOT(showSaveChatDialog()), 0 );
QAction *clearChatAction = KStandardAction::clear( this, SLOT(slotClearChat()), 0 );
QAction *saveToFileAction = KStandardAction::save( this, SLOT(showSaveChatDialog()), 0 );
// Update the labels a bit though
clearChatAction ->setText( i18n("C&lear Chat") );
@@ -1043,9 +1048,9 @@ void ChatView::slotVisitAddress()
#endif
// Launch the browser for the given URL
if( chatViewClickedUrl_.protocol() == "mailto" )
if( chatViewClickedUrl_.scheme() == "mailto" )
{
currentAccount_->openMailAtCompose( chatViewClickedUrl_.url().mid( 7 ) );
currentAccount_->openMailAtCompose( chatViewClickedUrl_.toString().mid( 7 ) );
}
else
{
@@ -1080,8 +1085,3 @@ void ChatView::updateCustomEmoticon( const QString &handle, const QString &code
const QString &replacement = contact->getEmoticonReplacements()[code];
chatMessageView_->updateCustomEmoticon( code, replacement, handle );
}
#include "chatview.moc"
+3 -3
View File
@@ -99,7 +99,7 @@ class ChatView : public QWidget
private: // Private methods
// Event filter to detect special actions in the message editor.
bool eventFilter( QObject *obj, QEvent *event );
bool eventFilter( QObject *obj, QEvent *event ) override;
// Invite a contact to the chat
virtual void inviteContacts( const QStringList &contacts ) = 0;
// Send a file to a contact.
@@ -117,7 +117,7 @@ class ChatView : public QWidget
// Add an emoticon from the chat to the contact's emoticon blacklist
void slotIgnoreEmoticon();
// Open a new url clicked in the khtml widget
void slotOpenURLRequest( const KUrl &url );
void slotOpenURLRequest( const QUrl &url );
// The user right clicked at the KHTMLPart to show a popup.
void slotShowContextMenu(const QString &url, const QPoint &point);
// The user clicked the "visit address" or "send email" option in the context menu, or clicked a link in the ChatMessageView
@@ -133,7 +133,7 @@ class ChatView : public QWidget
// The embedded khtml part
ChatMessageView *chatMessageView_;
// URL address which has been right-clicked
KUrl chatViewClickedUrl_;
QUrl chatViewClickedUrl_;
// The current ink the user is drawing
Isf::Drawing *inkDrawing_;
// Whether or not the object was initialized
+147 -118
View File
@@ -44,26 +44,35 @@
#include <QBuffer>
#include <QDir>
#include <QDockWidget>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QKeyEvent>
#include <QLocale>
#include <QMimeData>
#include <QMouseEvent>
#include <QRegularExpression>
#include <QShortcut>
#include <QTabBar>
#include <QTabWidget>
#include <QTextDocumentFragment>
#include <QDesktopWidget>
#include <KAction>
#include <QAction>
#include <KActionMenu>
#include <KColorDialog>
#include <KConfigGroup>
#include <KFontDialog>
#include <KHelpMenu>
#include <KMenu>
#include <KMenuBar>
#include <KLocalizedString>
#include <QMenu>
#include <QMenuBar>
#include <KMessageBox>
#include <KStandardAction>
#include <KStatusBar>
#include <KTabBar>
#include <KStandardGuiItem>
#include <QStatusBar>
#include <KToolBar>
#include <KToolInvocation>
#include <KWindowSystem>
#include <kwindowsystem.h>
#include <KStandardShortcut>
#include <KIconLoader>
#include <QColorDialog>
#include <QFontDialog>
#ifdef KMESSDEBUG_CHATWINDOW
#define KMESSDEBUG_CHATWINDOW_TYPING_MESSAGES
@@ -159,20 +168,20 @@ ChatWindow::ChatWindow( QWidget *parent )
messageEdit_->viewport()->installEventFilter( this );
// Set the button icons
standardEmoticonButton_->setIcon( KIcon( "face-smile" ) );
customEmoticonButton_ ->setIcon( KIcon( "face-smile-gearhead-female" ) );
inkButton_ ->setIcon( KIcon( "draw-brush" ) );
winksButton_ ->setIcon( KIcon( "applications-toys" ) );
textButton_ ->setIcon( KIcon( "draw-text" ) );
fontButton_ ->setIcon( KIcon( "preferences-desktop-font" ) );
fontColorButton_ ->setIcon( KIcon( "format-stroke-color" ) );
standardEmoticonButton_->setIcon( QIcon::fromTheme( "face-smile" ) );
customEmoticonButton_ ->setIcon( QIcon::fromTheme( "face-smile-gearhead-female" ) );
inkButton_ ->setIcon( QIcon::fromTheme( "draw-brush" ) );
winksButton_ ->setIcon( QIcon::fromTheme( "applications-toys" ) );
textButton_ ->setIcon( QIcon::fromTheme( "draw-text" ) );
fontButton_ ->setIcon( QIcon::fromTheme( "preferences-desktop-font" ) );
fontColorButton_ ->setIcon( QIcon::fromTheme( "format-stroke-color" ) );
// Set up the buttons for setting ink colour/stroke size/etc.
inkCanvas_->setPenSize( inkPenSize_->value() );
inkColorButton_->setIcon( KIcon( "format-stroke-color" ) );
inkEraseButton_->setIcon( KIcon( "draw-eraser" ) );
inkClearButton_->setIcon( KIcon( "edit-clear" ) );
inkColorButton_->setIcon( QIcon::fromTheme( "format-stroke-color" ) );
inkEraseButton_->setIcon( QIcon::fromTheme( "draw-eraser" ) );
inkClearButton_->setIcon( QIcon::fromTheme( "edit-clear" ) );
connect( inkColorButton_, SIGNAL( clicked() ),
this, SLOT ( slotChangeInkColor() ) );
@@ -183,30 +192,21 @@ ChatWindow::ChatWindow( QWidget *parent )
connect( inkPenSize_, SIGNAL( valueChanged(int) ),
inkCanvas_, SLOT ( setPenSize(int) ) );
// Connect the message edit so that if its displayed color changes,
// it's checked to match the user's chosen color.
connect( messageEdit_, SIGNAL( currentColorChanged(const QColor&) ),
this, SLOT ( editorColorChanged(const QColor&) ) );
// Connect the docks signals
connect( standardEmoticonsDock_, SIGNAL( visibilityChanged(bool) ),
this, SLOT ( slotEmoticonDocksToggled() ) );
connect( customEmoticonsDock_, SIGNAL( visibilityChanged(bool) ),
this, SLOT ( slotEmoticonDocksToggled() ) );
// And the tab widget signals
connect( chatTabs_, SIGNAL( mouseMiddleClick(QWidget*) ),
this, SLOT ( slotTabRemoved(QWidget*) ) );
connect( chatTabs_, SIGNAL( closeRequest(QWidget*) ),
this, SLOT ( slotTabRemoved(QWidget*) ) );
chatTabs_->tabBar()->installEventFilter( this );
connect( chatTabs_, &QTabWidget::tabCloseRequested, this, [this]( int index )
{
slotTabRemoved( chatTabs_->widget( index ) );
} );
connect( chatTabs_, SIGNAL( currentChanged(int) ),
this, SLOT ( slotTabChanged(int) ) );
// Workaround for tab close buttons in KDE 4.0: Enable the buttons on hover
#if KDE_IS_VERSION( 4, 1, 0 )
chatTabs_->setCloseButtonEnabled( true );
#else
chatTabs_->setHoverCloseButton( true );
chatTabs_->setHoverCloseButtonDelayed( true );
#endif
chatTabs_->setTabsClosable( true );
// Create the status bar
statusLabel_ = new ChatStatusBar( this );
@@ -296,7 +296,7 @@ Chat *ChatWindow::addChatTab( Chat *newChat, bool foreground )
nextTabAction_->setEnabled( hasMultipleTabs );
// Tab grouping is disabled, hide the bar
chatTabs_->setTabBarHidden( currentAccount_->getTabbedChatMode() == 2 );
chatTabs_->tabBar()->setVisible( currentAccount_->getTabbedChatMode() != 2 );
return newChat;
}
@@ -372,9 +372,9 @@ bool ChatWindow::closeAllTabs()
// Ask the user for confirmation
if( chatTabs_->count() > 1 // Do not ask if there only is one tab
&& sender() != closeAllAction_ // Do not ask if the user chose the "close all tabs" action
&& ! kapp->sessionSaving() ) // Do not ask if the KDE session is closing
&& ! static_cast<KMessApplication *>(QApplication::instance())->sessionSaving() ) // Do not ask if the KDE session is closing
{
int res = KMessageBox::questionYesNoCancel( this,
int res = KMessageBox::questionTwoActionsCancel( this,
i18n( "<html>There are multiple tabs open in this chat window. "
"Do you want to close the current tab only, or all tabs?<br /><br />"
"<i>Note: You can close all tabs at once by pressing Alt+F4.</i></html>" ),
@@ -386,8 +386,8 @@ bool ChatWindow::closeAllTabs()
"closeOneChatTabInfo" );
switch( res )
{
case KMessageBox::Yes : break;
case KMessageBox::No : return closeTab();
case KMessageBox::PrimaryAction : break;
case KMessageBox::SecondaryAction : return closeTab();
case KMessageBox::Cancel:
default : return false;
}
@@ -451,41 +451,40 @@ void ChatWindow::closeWidgetOrTab()
// Create the menus.
void ChatWindow::createMenus()
{
KAction *closeAction, *saveAction, *quitAction;
KAction *copy, *findAction, *zoomIn, *zoomOut, *clearChatAction;
QAction *closeAction, *saveAction, *clearChatAction;
QAction *contactsDockAction, *standardEmoticonsDockAction, *customEmoticonsDockAction;
// Create the actions for "Chat" menu
inviteButton_ = new KAction ( KIcon("list-add-user"), i18n("&Invite..."), this );
sendAction_ = new KAction ( KIcon("folder-remote"), i18n("Send a &File..."), this );
nudgeAction_ = new KAction ( KIcon("preferences-desktop-notification-bell"), i18n("Send a &Nudge!"), this );
historyMenuAction_ = new KActionMenu ( KIcon("chronometer"), i18n("Chat &History..."), this );
saveAction = new KAction ( KIcon("document-save"), i18n("Save Chat..."), this );
closeAllAction_ = new KAction ( KIcon("dialog-close"), i18n("Close &All Tabs"), this );
inviteButton_ = new QAction ( QIcon::fromTheme( "list-add-user" ), i18n("&Invite..."), this );
sendAction_ = new QAction ( QIcon::fromTheme( "folder-remote" ), i18n("Send a &File..."), this );
nudgeAction_ = new QAction ( QIcon::fromTheme( "preferences-desktop-notification-bell" ), i18n("Send a &Nudge!"), this );
historyMenuAction_ = new KActionMenu ( QIcon::fromTheme( "chronometer" ), i18n("Chat &History..."), this );
saveAction = new QAction ( QIcon::fromTheme( "document-save" ), i18n("Save Chat..."), this );
closeAllAction_ = new QAction ( QIcon::fromTheme( "dialog-close" ), i18n("Close &All Tabs"), this );
closeAction = KStandardAction::close ( this, SLOT( closeWidgetOrTab() ) , actionCollection_ );
quitAction = KStandardAction::quit ( kapp, SLOT( quit() ), actionCollection_ );
KStandardAction::quit ( QApplication::instance(), SLOT( quit() ), actionCollection_ );
// Create the actions for "Edit" menu
changeFontAction_ = new KAction ( KIcon("preferences-desktop-font"), i18n("Change &Font"), this );
changeFontColorAction_ = new KAction ( KIcon("format-stroke-color"), i18n("Change Font &Color"), this );
changeFontAction_ = new QAction ( QIcon::fromTheme( "preferences-desktop-font" ), i18n("Change &Font"), this );
changeFontColorAction_ = new QAction ( QIcon::fromTheme( "format-stroke-color" ), i18n("Change Font &Color"), this );
cutAction_ = KStandardAction::cut ( messageEdit_, SLOT( cut() ), actionCollection_ );
copy = KStandardAction::copy ( messageEdit_, SLOT( copy() ), actionCollection_ );
KStandardAction::copy ( messageEdit_, SLOT( copy() ), actionCollection_ );
pasteAction_ = KStandardAction::paste ( messageEdit_, SLOT( paste() ), actionCollection_ );
findAction = KStandardAction::find ( this, SLOT( editFind() ), actionCollection_ );
KStandardAction::find ( this, SLOT( editFind() ), actionCollection_ );
// Create the actions for "View" menu
emoticonAction_ = new KToggleAction( KIcon("face-smile-big"), i18n("Show &Emoticons"), this );
sessionInfoAction_ = new KToggleAction( KIcon("flag-green"), i18n("Show S&tatus Messages"), this );
zoomIn = KStandardAction::zoomIn ( this, SLOT( viewZoomIn() ), actionCollection_ );
zoomOut = KStandardAction::zoomOut( this, SLOT( viewZoomOut() ), actionCollection_ );
emoticonAction_ = new KToggleAction( QIcon::fromTheme( "face-smile-big" ), i18n("Show &Emoticons"), this );
sessionInfoAction_ = new KToggleAction( QIcon::fromTheme( "flag-green" ), i18n("Show S&tatus Messages"), this );
KStandardAction::zoomIn ( this, SLOT( viewZoomIn() ), actionCollection_ );
KStandardAction::zoomOut( this, SLOT( viewZoomOut() ), actionCollection_ );
prevTabAction_ = KStandardAction::back ( this, SLOT( slotSwitchToLeftTab() ), actionCollection_ );
nextTabAction_ = KStandardAction::forward( this, SLOT( slotSwitchToRightTab() ), actionCollection_ );
clearChatAction = KStandardAction::clear ( this, SLOT( viewClearChat() ), actionCollection_ );
panelsMenuAction_ = new KActionMenu ( KIcon("view-choose"), i18n("&Panels"), this );
panelsMenuAction_ = new KActionMenu ( QIcon::fromTheme( "view-choose" ), i18n("&Panels"), this );
// Create the actions for "Settings" menu
spellCheckAction_ = new KToggleAction( KIcon("tools-check-spelling"), i18n("Use &Spell Checking"), this );
spellCheckAction_ = new KToggleAction( QIcon::fromTheme( "tools-check-spelling" ), i18n("Use &Spell Checking"), this );
showMenuBar_ = KStandardAction::showMenubar( this, SLOT( showMenuBar() ), actionCollection_ );
// Add shorter texts for the toolbar items
@@ -498,35 +497,25 @@ void ChatWindow::createMenus()
nextTabAction_->setText ( i18n("Ne&xt Tab") );
nextTabAction_->setIconText( i18n("Ne&xt Tab") );
// Enable some default action shortcuts (preserve the original ones where needed)
nudgeAction_->setShortcut( QKeySequence( "Alt+Z" ) );
closeAction->setShortcuts( QList<QKeySequence>() << QKeySequence( "Ctrl+W" ) << closeAction->shortcut() );
closeAllAction_->setShortcuts( QList<QKeySequence>() << QKeySequence( "Ctrl+Q" ) << closeAllAction_->shortcut() );
prevTabAction_->setShortcuts( QList<QKeySequence>() << QKeySequence( QKeySequence::PreviousChild ) << prevTabAction_->shortcut() );
nextTabAction_->setShortcuts( QList<QKeySequence>() << QKeySequence( QKeySequence::NextChild ) << nextTabAction_->shortcut() );
// Set up the dock actions
contactsDockAction = contactsDock_ ->toggleViewAction();
standardEmoticonsDockAction = standardEmoticonsDock_->toggleViewAction();
customEmoticonsDockAction = customEmoticonsDock_ ->toggleViewAction();
contactsDockAction->setIcon( KIcon("meeting-attending") );
contactsDockAction->setIcon( QIcon::fromTheme( "meeting-attending" ) );
contactsDockAction->setToolTip( i18n("Enable or disable the contacts panel") );
contactsDockAction->setText( i18nc("Toolbar button","Contacts") );
contactsDockAction->setIconText( i18nc("Toolbar button","Contacts") );
contactsDockAction->setShortcut( QKeySequence( "Ctrl+D" ) );
standardEmoticonsDockAction->setIcon( KIcon("face-smile") );
standardEmoticonsDockAction->setIcon( QIcon::fromTheme( "face-smile" ) );
standardEmoticonsDockAction->setToolTip( i18n("Enable or disable the standard emoticons panel") );
standardEmoticonsDockAction->setText( i18nc("Toolbar button","Emoticons") );
standardEmoticonsDockAction->setIconText( i18nc("Toolbar button","Emoticons") );
standardEmoticonsDockAction->setShortcut( QKeySequence( "Ctrl+E" ) );
customEmoticonsDockAction->setIcon( KIcon("face-smile-gearhead-female") );
customEmoticonsDockAction->setIcon( QIcon::fromTheme( "face-smile-gearhead-female" ) );
customEmoticonsDockAction->setToolTip( i18n("Enable or disable the custom emoticons panel") );
customEmoticonsDockAction->setText( i18nc("Toolbar button","My Emoticons") );
customEmoticonsDockAction->setIconText( i18nc("Toolbar button","My Emoticons") );
customEmoticonsDockAction->setShortcut( QKeySequence( "Ctrl+Y" ) );
// Add the dock toggling actions to the Panels menu
panelsMenuAction_->addAction( contactsDockAction );
@@ -598,6 +587,16 @@ void ChatWindow::createMenus()
// Add actions to actionCollection for "Settings" menu
actionCollection_->addAction( "spellCheck", spellCheckAction_ );
// Enable some default action shortcuts (preserve the original ones where needed)
actionCollection_->setDefaultShortcut( nudgeAction_, QKeySequence( "Alt+Z" ) );
actionCollection_->setDefaultShortcuts( closeAction, QList<QKeySequence>() << QKeySequence( "Ctrl+W" ) << closeAction->shortcut() );
actionCollection_->setDefaultShortcuts( closeAllAction_, QList<QKeySequence>() << QKeySequence( "Ctrl+Q" ) << closeAllAction_->shortcut() );
actionCollection_->setDefaultShortcuts( prevTabAction_, QList<QKeySequence>() << QKeySequence( QKeySequence::PreviousChild ) << prevTabAction_->shortcut() );
actionCollection_->setDefaultShortcuts( nextTabAction_, QList<QKeySequence>() << QKeySequence( QKeySequence::NextChild ) << nextTabAction_->shortcut() );
actionCollection_->setDefaultShortcut( contactsDockAction, QKeySequence( "Ctrl+D" ) );
actionCollection_->setDefaultShortcut( standardEmoticonsDockAction, QKeySequence( "Ctrl+E" ) );
actionCollection_->setDefaultShortcut( customEmoticonsDockAction, QKeySequence( "Ctrl+Y" ) );
}
@@ -647,9 +646,10 @@ void ChatWindow::editFont()
{
QFont selection( currentAccount_->getFont() );
int result = KFontDialog::getFont( selection, KFontChooser::NoDisplayFlags, this );
bool accepted = false;
selection = QFontDialog::getFont( &accepted, selection, this );
if( result != KFontDialog::Accepted )
if( ! accepted )
{
return;
}
@@ -668,8 +668,8 @@ void ChatWindow::editFontColor()
QColor color( currentAccount_->getFontColor() );
// Show the color dialog
int result = KColorDialog::getColor( color, this );
if ( result == KColorDialog::Accepted )
color = QColorDialog::getColor( color, this );
if ( color.isValid() )
{
// Get the string version of the selected color
const QString fontColor( color.name() );
@@ -746,6 +746,19 @@ bool ChatWindow::eventFilter( QObject *obj, QEvent *event )
return false;
}
if( obj == chatTabs_->tabBar() && event->type() == QEvent::MouseButtonRelease )
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event );
if( mouseEvent->button() == Qt::MiddleButton )
{
const int tabIndex = chatTabs_->tabBar()->tabAt( mouseEvent->position().toPoint() );
if( tabIndex >= 0 )
{
return slotTabRemoved( chatTabs_->widget( tabIndex ) );
}
}
}
if ( event->type() == QEvent::KeyPress )
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event );
@@ -986,7 +999,7 @@ bool ChatWindow::eventFilter( QObject *obj, QEvent *event )
#ifdef KMESSDEBUG_CHATWINDOW
kmDebug() << "Setting drawing to the Ink Canvas.";
#endif
QByteArray isfData( url.mid( marker.length() ).toAscii() );
QByteArray isfData( url.mid( marker.length() ).toLatin1() );
Isf::Drawing* drawing = &( Isf::Stream::readerPng( isfData, true ) );
// We need to both set it to the canvas and change the object stored by the chat tab,
@@ -1132,7 +1145,7 @@ bool ChatWindow::handleCommand( QString command )
}
// Parse arguments
QStringList arguments( command.split( " ", QString::SkipEmptyParts ) );
QStringList arguments( command.split( " ", Qt::SkipEmptyParts ) );
if( arguments.isEmpty() )
{
return true;
@@ -1144,7 +1157,7 @@ bool ChatWindow::handleCommand( QString command )
command = command.toLower();
// Get us a kmess handle to call setStatus upon
KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
KMessApplication *kmessApp = static_cast<KMessApplication *>(QApplication::instance());
KMess *kmess = kmessApp->getContactListWindow();
bool isStatusCommand = ( command == "status" );
@@ -1152,7 +1165,7 @@ bool ChatWindow::handleCommand( QString command )
// Check syntax errors
if( isStatusCommand && arguments.isEmpty() )
{
KMessageBox::sorry( this,
KMessageBox::error( this,
i18n( "<html>You used an incorrect syntax for the /status command. The correct syntax "
"is: <b>/status online|away|idle|brb|busy|lunch|phone|invisible</b>.<br/>"
"You can also use shortcuts like <b>/online</b> or <b>/phone</b>.</html>" ),
@@ -1218,7 +1231,7 @@ bool ChatWindow::handleCommand( QString command )
{
if( participants.count() != 1 )
{
KMessageBox::sorry( this,
KMessageBox::error( this,
i18n( "<html>You cannot use the /block command in a group chat.</html>" ),
i18nc( "Caption when trying to block someone in a group chat",
"Cannot use /block command" )
@@ -1231,7 +1244,7 @@ bool ChatWindow::handleCommand( QString command )
{
if( participants.count() != 1 )
{
KMessageBox::sorry( this,
KMessageBox::error( this,
i18n( "<html>You cannot use the /unblock command in a group chat.</html>" ),
i18nc( "Caption when trying to unblock someone in a group chat",
"Cannot use /unblock command!" )
@@ -1263,7 +1276,7 @@ bool ChatWindow::handleCommand( QString command )
return false;
}
KMessageBox::sorry( this,
KMessageBox::error( this,
i18n( "<html>Unknown command <b>%1</b>. If you did not want this "
"message to be a command, prepend your message with another"
" /.</html>", command ),
@@ -1296,12 +1309,8 @@ bool ChatWindow::initialize()
}
// Autosave all GUI settings
#if KDE_IS_VERSION(4,0,70)
setAutoSaveSettings( KMessConfig::instance()->getAccountConfig( currentAccount_->getHandle(), "ChatWindow" ),
true /* save WindowSize */ );
#else
setAutoSaveSettings( "ChatWindow", true /* save WindowSize */ );
#endif
// Read the window properties
readProperties();
@@ -1423,6 +1432,15 @@ bool ChatWindow::queryExit()
// Restore the window properties (called by KMainWindow)
void ChatWindow::readProperties()
{
const KConfigGroup config( KMessConfig::instance()->getAccountConfig( currentAccount_->getHandle(), "ChatWindow" ) );
readProperties( config );
}
// Restore the window properties (called by KMainWindow)
void ChatWindow::readProperties(const KConfigGroup &config )
{
@@ -1454,7 +1472,7 @@ void ChatWindow::readProperties(const KConfigGroup &config )
// Swapping the calls around fixes the problem. But again, I'll be damned if I can figure out
// what's going on.
restoreWindowSize( group );
restoreGeometry( group.readEntry( "WindowGeometry", QByteArray() ) );
restoreState( state );
@@ -1488,6 +1506,15 @@ void ChatWindow::saveChat()
// Save the window properties (called by KMainWindow)
void ChatWindow::saveProperties()
{
KConfigGroup config( KMessConfig::instance()->getAccountConfig( currentAccount_->getHandle(), "ChatWindow" ) );
saveProperties( config );
}
// Save the window properties (called by KMainWindow)
void ChatWindow::saveProperties( KConfigGroup &config )
{
@@ -1506,7 +1533,7 @@ void ChatWindow::saveProperties( KConfigGroup &config )
group.writeEntry( "CurrentZoom", zoomLevel_ );
// Save window size
saveWindowSize( group );
group.writeEntry( "WindowGeometry", saveGeometry() );
group.config()->sync();
}
@@ -1629,6 +1656,7 @@ void ChatWindow::sendMessage()
// Don't send empty messages
if( text.trimmed().isEmpty() )
{
doSendTypingMessages_ = true;
return;
}
@@ -1651,6 +1679,8 @@ void ChatWindow::sendMessage()
// Handle command. If 'false' is returned, send it anyway.
if ( handleCommand( command ) )
{
doSendTypingMessages_ = true;
slotMessageChanged();
return;
}
}
@@ -1686,7 +1716,7 @@ void ChatWindow::sendMessage()
// Replace "\n" with "\r\n" (to follow the Windows linebreak style followed by the MSN servers)
// @TODO Move this server stuff to the network/protocol code
text = text.replace( QRegExp("\r?\n"), "\r\n" );
text = text.replace( QRegularExpression( "\r?\n" ), "\r\n" );
// Send the message to the contact(s)
getCurrentChat()->sendChatMessage( text );
@@ -1716,6 +1746,8 @@ void ChatWindow::sendMessage()
quickRetypeList.append( message.getBody() );
lastSentence_ = QString();
slotMessageChanged();
// Reset the last sentence counter.
// showMessage() updates chatMessages_
indexSentences_ = quickRetypeList.size();
@@ -1745,11 +1777,11 @@ void ChatWindow::setChatWindowIcon()
if ( chat->getParticipants().size() == 1 )
{
userIcon = KIcon( "user-identity" ).pixmap( 60, 60 );
userIcon = QIcon::fromTheme( "user-identity" ).pixmap( 60, 60 );
}
else
{
userIcon = KIcon( "system-users" ).pixmap( 60, 60 );
userIcon = QIcon::fromTheme( "system-users" ).pixmap( 60, 60 );
}
setWindowIcon( KMessShared::drawIconOverlay( userIcon, kmessIcon, kmessIcon.size().width(), kmessIcon.size().height(), .60, .90 ) );
@@ -1892,18 +1924,18 @@ void ChatWindow::showMenuBar()
// Ask the user if he/she really wants to hide the menubar, to avoid mistakes
// TODO: If the user disables the shortcut for the menu action, no shortcuts will be shown
int res = KMessageBox::questionYesNo( this,
int res = KMessageBox::questionTwoActions( this,
i18nc( "Question dialog box message",
"<html>Are you sure you want to hide the menu bar? "
"You will be able to show it again by using this "
"keyboard shortcut: <b>%1</b></html>",
showMenuBar_->shortcut().primary().toString( QKeySequence::NativeText ) ),
showMenuBar_->shortcut().toString( QKeySequence::NativeText ) ),
i18nc( "Dialog box caption: hiding the menu bar", "Hiding the Menu" ),
KStandardGuiItem::yes(),
KStandardGuiItem::no(),
KGuiItem( i18n( "Yes" ) ),
KGuiItem( i18n( "No" ) ),
"hideMenuBarQuestion" );
if( res == KMessageBox::Yes )
if( res == KMessageBox::PrimaryAction )
{
menuBar()->setVisible( showMenuBar_->isChecked() );
}
@@ -1969,7 +2001,8 @@ void ChatWindow::showStatusMessage( QString message, int duration )
void ChatWindow::slotChangeInkColor()
{
QColor color;
if ( KColorDialog::getColor( color ) == QDialog::Accepted )
color = QColorDialog::getColor( color, this );
if ( color.isValid() )
{
inkCanvas_->setPenColor( color );
}
@@ -1983,13 +2016,13 @@ void ChatWindow::slotChangeInkBrush()
if( inkCanvas_->penType() == Isf::InkCanvas::DrawingPen )
{
inkCanvas_->setPenType( Isf::InkCanvas::EraserPen );
inkEraseButton_->setIcon( KIcon( "draw-freehand" ) );
inkEraseButton_->setIcon( QIcon::fromTheme( "draw-freehand" ) );
inkEraseButton_->setToolTip( i18n( "Drawing brush" ) );
}
else
{
inkCanvas_->setPenType( Isf::InkCanvas::DrawingPen );
inkEraseButton_->setIcon( KIcon( "draw-eraser" ) );
inkEraseButton_->setIcon( QIcon::fromTheme( "draw-eraser" ) );
inkEraseButton_->setToolTip( i18n( "Erase brush" ) );
}
}
@@ -2044,7 +2077,7 @@ void ChatWindow::slotGotChatMessage( const ChatMessage &message, Chat *chat )
if( chat != getCurrentChat() )
{
// Paint the text red
chatTabs_->setTabTextColor( chatTabs_->indexOf( chat ), QColor( "red" ) );
chatTabs_->tabBar()->setTabTextColor( chatTabs_->indexOf( chat ), QColor( "red" ) );
// Highlight the window title with the chat with new messages
caption_ = chat->getCaption();
@@ -2072,17 +2105,17 @@ void ChatWindow::slotGotNudge()
// avoid shaking again in a short period.
if( lastShake_.secsTo( QTime::currentTime() ) < 15 )
if( lastShake_.isValid() && lastShake_.elapsed() < 15000 )
{
#ifdef KMESSDEBUG_CHATWINDOW
kmDebug() << "Not shaking the window until"
<< lastShake_.secsTo( QTime::currentTime() ) << "more seconds.";
<< ( 15000 - lastShake_.elapsed() ) / 1000 << "more seconds.";
#endif
return;
}
lastShake_ = QTime::currentTime();
lastShake_.restart();
QTime t;
QElapsedTimer t;
int xp = x();
int yp = y();
@@ -2093,7 +2126,7 @@ void ChatWindow::slotGotNudge()
// Shake the window.
for ( int i = 16; i > 0; )
{
kapp->processEvents();
QApplication::processEvents();
if ( t.elapsed() >= 50 )
{
@@ -2142,7 +2175,7 @@ void ChatWindow::slotGotTypingMessage( Chat *chat )
// Update the color of this chat's tab
// If the color is red, leave it
if( chatTabs_->tabTextColor( tabIndex ) != QColor( "red" ) )
if( chatTabs_->tabBar()->tabTextColor( tabIndex ) != QColor( "red" ) )
{
QColor color;
if( typingContacts.isEmpty() )
@@ -2154,7 +2187,7 @@ void ChatWindow::slotGotTypingMessage( Chat *chat )
color = palette.color( QPalette::Highlight );
}
chatTabs_->setTabTextColor( tabIndex, color );
chatTabs_->tabBar()->setTabTextColor( tabIndex, color );
}
// If the typing message was not intended for the currently active tab, skip
@@ -2271,7 +2304,7 @@ void ChatWindow::slotMessageChanged()
}
// If a command is being typed, don't send a typing message
if( messageEdit_->toPlainText().left( 1 ) == "/" and messageEdit_->toPlainText().left( 2 ) != "//" )
if( messageEdit_->toPlainText().left( 1 ) == "/" && messageEdit_->toPlainText().left( 2 ) != "//" )
{
return;
}
@@ -2322,7 +2355,7 @@ void ChatWindow::slotSendButtonClicked()
// Show the chat history for a contact
void ChatWindow::slotShowChatHistory()
{
const KAction* action = qobject_cast< const KAction* >( sender() );
const QAction* action = qobject_cast< const QAction* >( sender() );
if( ! action )
{
@@ -2344,7 +2377,7 @@ void ChatWindow::slotShowChatHistory()
return;
}
action = qobject_cast< const KAction* >( historyMenuAction_->children().first() );
action = qobject_cast< const QAction* >( historyMenuAction_->children().first() );
KMESS_ASSERT( action );
}
@@ -2588,7 +2621,7 @@ void ChatWindow::slotTabChanged( int currentIndex )
// Reset the color
const QPalette palette;
chatTabs_->setTabTextColor( currentIndex, palette.color( QPalette::WindowText ) );
chatTabs_->tabBar()->setTabTextColor( currentIndex, palette.color( QPalette::WindowText ) );
// Display the new chat contents in the UI. Block the signals to avoid the editors
// from firing the "message changed" signal, which sends a typing message.
@@ -2625,7 +2658,7 @@ void ChatWindow::slotTabChanged( int currentIndex )
contact = currentAccount_->addInvitedContact( handle );
}
action = new KAction( KIcon( MsnStatus::getIconName( contact->getStatus() ) ),
action = new QAction( QIcon::fromTheme( MsnStatus::getIconName( contact->getStatus() ) ),
contact->getFriendlyName( STRING_CLEANED ),
historyMenuAction_ );
action->setData( handle );
@@ -2771,7 +2804,7 @@ void ChatWindow::slotUpdateChatInfo( Chat *chat )
"<dt><b>Connected with account:</b></dt><dd>%3</dd>"
"</dl></html>",
participants.join( "</li><li>" ),
chat->getStartTime().toString( Qt::DefaultLocaleLongDate ),
QLocale().toString( chat->getStartTime(), QLocale::LongFormat ),
currentAccount_->getHandle() ) );
chatTabs_->setTabToolTip( index, toolTip );
@@ -2983,7 +3016,3 @@ void ChatWindow::viewZoomOut()
{
changeZoomFactor( false );
}
#include "chatwindow.moc"
+22 -20
View File
@@ -22,9 +22,10 @@
#include "chatstatusbar.h"
#include <QList>
#include <QElapsedTimer>
#include <QTimer>
#include <KAction>
#include <QAction>
#include <KActionCollection>
#include <KToggleAction>
#include <KXmlGuiWindow>
@@ -39,12 +40,11 @@ class EmoticonsWidget;
class MsnSwitchboardConnection;
class QLabel;
class QAction;
class KActionMenu;
class KConfigGroup;
class KHelpMenu;
class KMenu;
class KTabBar;
class KToolBarButton;
class KToolBarPopupAction;
@@ -85,7 +85,7 @@ class ChatWindow : public KXmlGuiWindow, private Ui::ChatWindow
// Initialize the object
bool initialize();
// The chat window is closing, called by KMainWindow
bool queryClose();
bool queryClose() override;
// The application is exiting, called by KMainWindow
bool queryExit();
// Close a chat tab without user intervention
@@ -103,15 +103,17 @@ class ChatWindow : public KXmlGuiWindow, private Ui::ChatWindow
// Set the zoom factor of the text
void changeZoomFactor( bool increase );
// Filter to catch window activation and keyboard shortcut events
bool eventFilter( QObject *obj, QEvent *event );
bool eventFilter( QObject *obj, QEvent *event ) override;
// Set up the preferences which depend on the current account
bool initializeCurrentAccount();
// Create the menus.
void createMenus();
// Restore the window properties (called by KMainWindow)
void readProperties( const KConfigGroup &config = *((const KConfigGroup *)0) );
void readProperties();
void readProperties( const KConfigGroup &config ) override;
// Save the window properties (called by KMainWindow)
void saveProperties( KConfigGroup &config = *((KConfigGroup *)0) );
void saveProperties();
void saveProperties( KConfigGroup &config ) override;
// Enable or disable the parts of the window which allow user interaction
void setEnabled( bool isEnabled );
// Set the window icon for this chat window
@@ -219,7 +221,7 @@ class ChatWindow : public KXmlGuiWindow, private Ui::ChatWindow
// ActionCollection
KActionCollection *actionCollection_;
// The add emoticon action
KAction *addEmoticonAction_;
QAction *addEmoticonAction_;
// A timer used to make the caption blink on new messages.
QTimer blinkTimer_;
// Whether to blink to upper (true) or lower (false) case
@@ -227,11 +229,11 @@ class ChatWindow : public KXmlGuiWindow, private Ui::ChatWindow
// The stored window caption
QString caption_;
// Action to change own text font
KAction *changeFontAction_;
QAction *changeFontAction_;
// Action to change own text color
KAction *changeFontColorAction_;
QAction *changeFontColorAction_;
// Action to close the window along with all of its tabs
KAction *closeAllAction_;
QAction *closeAllAction_;
// Contacts list Dock Widget
QDockWidget *contactsDock_;
// A pointer to the instance of the current account
@@ -239,11 +241,11 @@ class ChatWindow : public KXmlGuiWindow, private Ui::ChatWindow
// Custom emoticons Dock Widget
QDockWidget *customEmoticonsDock_;
// Action to cut text to the clipboard
KAction *cutAction_;
QAction *cutAction_;
// Whether or not typing messages should be sent (true except the very moment a text message is sent)
bool doSendTypingMessages_;
// The emoticon display toggling action
KAction *emoticonAction_;
QAction *emoticonAction_;
// The first item in the Chat Menu (used to add the Invite menu before it)
QAction *firstChatMenuItem_;
// The menu containing contacts chat history actions
@@ -253,23 +255,23 @@ class ChatWindow : public KXmlGuiWindow, private Ui::ChatWindow
// Whether or not the object was initialized
bool initialized_;
// The contact invite action
KAction *inviteButton_;
QAction *inviteButton_;
// Last sentence in writing
QString lastSentence_;
// The last time the window was shaked
QTime lastShake_;
QElapsedTimer lastShake_;
// Action to switch to the next tab
KAction *nextTabAction_;
QAction *nextTabAction_;
// Action to send a nudge
KAction *nudgeAction_;
QAction *nudgeAction_;
// Action menu containing the panels shortcuts
KActionMenu *panelsMenuAction_;
// Action to paste the clipboard contents
KAction *pasteAction_;
QAction *pasteAction_;
// Action to switch to the previous tab
KAction *prevTabAction_;
QAction *prevTabAction_;
// Action to start a file transfer
KAction *sendAction_;
QAction *sendAction_;
// Toggle actions for showing and hiding the menu bar
KToggleAction *showMenuBar_;
// Toggle action to show/hide the join and part messages
+2 -15
View File
@@ -28,7 +28,7 @@
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="KTabWidget" name="chatTabs_">
<widget class="QTabWidget" name="chatTabs_">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
@@ -53,12 +53,6 @@
<property name="movable">
<bool>true</bool>
</property>
<property name="tabReorderingEnabled">
<bool>true</bool>
</property>
<property name="automaticResizeTabs">
<bool>true</bool>
</property>
</widget>
<widget class="QWidget" name="widgetBox_" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
@@ -501,18 +495,11 @@
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
<customwidgets>
<customwidget>
<class>KTabWidget</class>
<extends>QTabWidget</extends>
<header>ktabwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>KTextEdit</class>
<extends>QTextEdit</extends>
<header>ktextedit.h</header>
<header>KTextEdit</header>
</customwidget>
<customwidget>
<class>Isf::InkCanvas</class>
+43 -42
View File
@@ -37,14 +37,18 @@
#include <QClipboard>
#include <QFileInfo>
#include <QMimeData>
#include <QMouseEvent>
#include <KApplication>
#include <QApplication>
#include <QAction>
#include <KActionMenu>
#include <QIcon>
#include <KIconEffect>
#include <KIconLoader>
#include <KMenu>
#include <KStandardDirs>
#include <KLocalizedString>
#include <QMenu>
#include <QUrl>
// Time in milliseconds before the glowing done for a typing user fades away
@@ -61,7 +65,7 @@ ContactFrame::ContactFrame( QWidget *parent )
, contactPixmapLabelEnabled_(true)
, contactPropertiesDialog_(0)
, detailedContact_(0)
, handle_(QString::null)
, handle_(QString())
, currentMode_(ModeNormal)
, infoLabelEnabled_(true)
, locked_(true)
@@ -71,7 +75,7 @@ ContactFrame::ContactFrame( QWidget *parent )
layout()->setAlignment( Qt::AlignTop | Qt::AlignLeft );
// Just for show
const QPixmap pixmap( KGlobal::dirs()->findResource( "data", "kmess/pics/unknown.png" ) );
const QPixmap pixmap( KMessShared::findResource( "data", "kmess/pics/unknown.png" ) );
contactPixmapLabel_->setPixmap( pixmap );
installEventFilter( this );
@@ -218,29 +222,29 @@ void ContactFrame::contactDestroyed( QObject *object )
void ContactFrame::copyText()
{
// Get the signal sender to find out who called us
KAction *action = static_cast<KAction*>( const_cast<QObject*>( sender() ) );
QAction *action = static_cast<QAction*>( const_cast<QObject*>( sender() ) );
if(KMESS_NULL(action)) return;
if( action == popupCopyFriendlyName_ )
{
kapp->clipboard()->setText( contact_->getFriendlyName( STRING_CLEANED ) );
QApplication::clipboard()->setText( contact_->getFriendlyName( STRING_CLEANED ) );
}
else if( action == popupCopyHandle_ )
{
kapp->clipboard()->setText( handle_ );
QApplication::clipboard()->setText( handle_ );
}
else if( action == popupCopyPersonalMessage_ && detailedContact_ != 0 )
{
kapp->clipboard()->setText( detailedContact_->getPersonalMessage( STRING_CLEANED ) );
QApplication::clipboard()->setText( detailedContact_->getPersonalMessage( STRING_CLEANED ) );
}
else if( action == popupCopyMusic_ && detailedContact_ != 0 )
{
kapp->clipboard()->setText( detailedContact_->getCurrentMediaString() );
QApplication::clipboard()->setText( detailedContact_->getCurrentMediaString() );
}
else if( detailedContact_ != 0 )
{
// Copy the link from PM or Friendly Name
kapp->clipboard()->setText( action->toolTip() );
QApplication::clipboard()->setText( action->toolTip() );
}
}
@@ -328,7 +332,7 @@ bool ContactFrame::eventFilter( QObject *obj, QEvent *event )
const QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event );
// Show the menu regardlessly of where the mouse button has been pressed
showContactPopup( mouseEvent->globalPos() );
showContactPopup( mouseEvent->globalPosition().toPoint() );
return false; // don't stop processing.
}
@@ -353,28 +357,28 @@ bool ContactFrame::initContactPopup()
}
// Initialize context popup actions
popupStartPrivateChat_ = new KAction( KIcon("user-group-new"), i18n("&Start Private Chat"), this );
popupEmailContact_ = new KAction( KIcon("mail-message-new"), i18n("&Send Email"), this );
popupShowHistory_ = new KAction( KIcon("chronometer"), i18n("Chat &History"), this );
popupMsnProfile_ = new KAction( KIcon("preferences-desktop-user"), i18n("&View Profile"), this );
popupContactProperties_ = new KAction( KIcon("user-properties"), i18n("&Properties"), this );
popupStartPrivateChat_ = new QAction( QIcon::fromTheme( "user-group-new" ), i18n("&Start Private Chat"), this );
popupEmailContact_ = new QAction( QIcon::fromTheme( "mail-message-new" ), i18n("&Send Email"), this );
popupShowHistory_ = new QAction( QIcon::fromTheme( "chronometer" ), i18n("Chat &History"), this );
popupMsnProfile_ = new QAction( QIcon::fromTheme( "preferences-desktop-user" ), i18n("&View Profile"), this );
popupContactProperties_ = new QAction( QIcon::fromTheme( "user-properties" ), i18n("&Properties"), this );
popupAddContact_ = new KAction( KIcon("list-add"), i18n("&Add Contact"), this );
popupAllowContact_ = new KAction( KIcon("dialog-ok-apply"), i18n("A&llow Contact"), this );
popupRemoveContact_ = new KAction( KIcon("list-remove-user"), i18n("&Delete Contact"), this );
popupAddContact_ = new QAction( QIcon::fromTheme( "list-add" ), i18n("&Add Contact"), this );
popupAllowContact_ = new QAction( QIcon::fromTheme( "dialog-ok-apply" ), i18n("A&llow Contact"), this );
popupRemoveContact_ = new QAction( QIcon::fromTheme( "list-remove-user" ), i18n("&Delete Contact"), this );
popupBlockContact_ = new KAction( KIcon("dialog-cancel"), i18n("&Block Contact"), this );
popupUnblockContact_ = new KAction( KIcon("dialog-ok"), i18n("&Unblock Contact"), this );
popupBlockContact_ = new QAction( QIcon::fromTheme( "dialog-cancel" ), i18n("&Block Contact"), this );
popupUnblockContact_ = new QAction( QIcon::fromTheme( "dialog-ok" ), i18n("&Unblock Contact"), this );
popupCopyFriendlyName_ = new KAction( i18n("&Friendly Name"), this );
popupCopyPersonalMessage_ = new KAction( i18n("&Personal Message"), this );
popupCopyHandle_ = new KAction( i18n("&Email Address"), this );
popupCopyMusic_ = new KAction( i18n("Song &Name"), this );
popupCopyFriendlyName_ = new QAction( i18n("&Friendly Name"), this );
popupCopyPersonalMessage_ = new QAction( i18n("&Personal Message"), this );
popupCopyHandle_ = new QAction( i18n("&Email Address"), this );
popupCopyMusic_ = new QAction( i18n("Song &Name"), this );
popupPropGeneral_ = new KAction( KIcon("user-properties"), i18n("&Information"), this );
popupPropImages_ = new KAction( KIcon("draw-brush"), i18n("Display Pictures"), this );
popupPropNotes_ = new KAction( KIcon("document-edit"), i18n("&Notes"), this );
popupPropEmoticons_ = new KAction( KIcon("face-smile"), i18n("&Emoticons"), this );
popupPropGeneral_ = new QAction( QIcon::fromTheme( "user-properties" ), i18n("&Information"), this );
popupPropImages_ = new QAction( QIcon::fromTheme( "draw-brush" ), i18n("Display Pictures"), this );
popupPropNotes_ = new QAction( QIcon::fromTheme( "document-edit" ), i18n("&Notes"), this );
popupPropEmoticons_ = new QAction( QIcon::fromTheme( "face-smile" ), i18n("&Emoticons"), this );
// Connect the actions
@@ -416,11 +420,12 @@ bool ContactFrame::initContactPopup()
popupPropMenu_ ->addAction( popupPropEmoticons_ );
// Initialize the popup popup
contactActionPopup_ = new KMenu( handle_, this );
contactActionPopup_ = new QMenu( handle_, this );
// Attach the actions to the menu
// Order is as consistent as possible with the menu in KMessView
contactActionPopup_->addTitle( contact_->getHandle() );
QAction *titleAction = contactActionPopup_->addAction( contact_->getHandle() );
titleAction->setEnabled( false );
contactActionPopup_->addAction( popupStartPrivateChat_ );
contactActionPopup_->addAction( popupEmailContact_ );
contactActionPopup_->addAction( popupShowHistory_ );
@@ -579,13 +584,13 @@ void ContactFrame::showContactPopup( const QPoint &point )
}
links.append( foundLink );
// Put the found link into KAction, replace & with && to avoid shortcut problem and use tooltip
// Put the found link into QAction, replace & with && to avoid shortcut problem and use tooltip
// for future grep of link ( to avoid shortcut problem too )
popupCopyLink_ = new KAction( foundLink.replace( "&", "&&" ), this );
popupCopyLink_ = new QAction( foundLink.replace( "&", "&&" ), this );
popupCopyLink_->setToolTip( foundLink );
connect( popupCopyLink_, SIGNAL( triggered( bool ) ), this, SLOT( copyText() ) );
// Append current KAction to the copy link list
// Append current QAction to the copy link list
copyLinkActionsList_.append( popupCopyLink_ );
// Add action to copy menu
@@ -642,7 +647,7 @@ void ContactFrame::showContactProperties()
// groups multiple times or doesn't display them at all). This resolves the problem.
ContactPropertiesDialog *dialog = new ContactPropertiesDialog(this);
KMess *kmess = static_cast<KMessApplication*>( kapp )->getContactListWindow();
KMess *kmess = static_cast<KMessApplication *>(QApplication::instance())->getContactListWindow();
// HACK: MUST GO AFTER 2.0-final!!
connect( dialog, SIGNAL(addContactToGroup(QString, QString)),
@@ -668,7 +673,7 @@ void ContactFrame::showProfile()
}
// Create a URL to the msn profile page, localized with our system's locale.
const KUrl url( "http://members.msn.com/default.msnw?mem=" + handle_ + "&mkt=" + KGlobal::locale()->language() );
const QUrl url( "https://nina.chat/contacts/" );
// Launch the browser for the given URL
KMessShared::openBrowser( url );
@@ -847,7 +852,7 @@ void ContactFrame::updateStatusWidgets()
}
infoLabel_->setVisible( true );
infoLabel_->setText( mediaEmoticon + Qt::escape( mediaString ) );
infoLabel_->setText( mediaEmoticon + mediaString.toHtmlEscaped() );
infoLabel_->setToolTip( mediaString );
}
else if( ! messageString.isEmpty() )
@@ -868,7 +873,3 @@ void ContactFrame::updateStatusWidgets()
contactPixmapLabel_->setVisible( contactPixmapLabelEnabled_ );
}
#include "contactframe.moc"
+38 -38
View File
@@ -29,9 +29,9 @@ class Contact;
class ContactBase;
class ContactPropertiesDialog;
class CurrentAccount;
class KAction;
class QAction;
class KActionMenu;
class KMenu;
class QMenu;
@@ -80,7 +80,7 @@ class ContactFrame : public QWidget, private Ui::ContactFrame
private: // Private methods
// The personal status message received an event.
bool eventFilter( QObject *obj, QEvent *event );
bool eventFilter( QObject *obj, QEvent *event ) override;
private slots: // Private slots
// Allow this contact to see our MSN status
@@ -118,7 +118,7 @@ class ContactFrame : public QWidget, private Ui::ContactFrame
// The contact whom the frame represents
ContactBase *contact_;
// The menu of actions possible to perform on a given contact
KMenu *contactActionPopup_;
QMenu *contactActionPopup_;
// The contact's image
QPixmap contactPicture_;
// The contact picture date
@@ -132,7 +132,7 @@ class ContactFrame : public QWidget, private Ui::ContactFrame
// The contact's image visible while the contact is typing
QPixmap contactTypingPicture_;
// List of actions with links to copy to the clipboard
QList<KAction*> copyLinkActionsList_;
QList<QAction*> copyLinkActionsList_;
// The detailed contact information, if available
Contact *detailedContact_;
// The contact's handle, saved for performance and for safety
@@ -143,44 +143,44 @@ class ContactFrame : public QWidget, private Ui::ContactFrame
bool infoLabelEnabled_;
// Whether or not is it possible to add or block the contact
bool locked_;
// Contact popup KAction to add the contact to the contact list
KAction *popupAddContact_;
// Contact popup KAction to allow the contact to see the user's status
KAction *popupAllowContact_;
// Contact popup KAction to block the contact
KAction *popupBlockContact_;
// Contact popup QAction to add the contact to the contact list
QAction *popupAddContact_;
// Contact popup QAction to allow the contact to see the user's status
QAction *popupAllowContact_;
// Contact popup QAction to block the contact
QAction *popupBlockContact_;
// Contact popup menu to show the contact's properties window
KAction *popupContactProperties_;
QAction *popupContactProperties_;
// Contact popup menu to show the friendly name/personal message/media copying options
KActionMenu *popupCopyMenu_;
// Contact popup KAction to copy the contact's friendly name to clipboard
KAction *popupCopyFriendlyName_;
// Contact popup KAction to copy the contact's message to clipboard
KAction *popupCopyPersonalMessage_;
// Contact popup KAction to copy the contact's email address to clipboard
KAction *popupCopyHandle_;
// Contact popup KAction to copy links from pm and friendly name
KAction *popupCopyLink_;
// Contact popup KAction to copy contact's media message
KAction *popupCopyMusic_;
// Contact popup KAction to send an email to the contact
KAction *popupEmailContact_;
// Contact popup KAction to show the contact's profile
KAction *popupMsnProfile_;
// Contact popup KAction to remove a contact from the contact list
KAction *popupRemoveContact_;
// Contact popup KAction to show a contact's chat history (if any)
KAction *popupShowHistory_;
// Contact popup KAction to start a private chat with the contact while the user is in a multi-chat
KAction *popupStartPrivateChat_;
// Contact popup KAction to unblock the contact
KAction *popupUnblockContact_;
// Contact popup QAction to copy the contact's friendly name to clipboard
QAction *popupCopyFriendlyName_;
// Contact popup QAction to copy the contact's message to clipboard
QAction *popupCopyPersonalMessage_;
// Contact popup QAction to copy the contact's email address to clipboard
QAction *popupCopyHandle_;
// Contact popup QAction to copy links from pm and friendly name
QAction *popupCopyLink_;
// Contact popup QAction to copy contact's media message
QAction *popupCopyMusic_;
// Contact popup QAction to send an email to the contact
QAction *popupEmailContact_;
// Contact popup QAction to show the contact's profile
QAction *popupMsnProfile_;
// Contact popup QAction to remove a contact from the contact list
QAction *popupRemoveContact_;
// Contact popup QAction to show a contact's chat history (if any)
QAction *popupShowHistory_;
// Contact popup QAction to start a private chat with the contact while the user is in a multi-chat
QAction *popupStartPrivateChat_;
// Contact popup QAction to unblock the contact
QAction *popupUnblockContact_;
// popup actions for the properties menu
KActionMenu *popupPropMenu_;
KAction *popupPropGeneral_;
KAction *popupPropImages_;
KAction *popupPropNotes_;
KAction *popupPropEmoticons_;
QAction *popupPropGeneral_;
QAction *popupPropImages_;
QAction *popupPropNotes_;
QAction *popupPropEmoticons_;
// A timer to time the duration that the typing label is shown
QTimer typingTimer_;
-1
View File
@@ -209,7 +209,6 @@
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
<customwidgets>
<customwidget>
<class>GradientElideLabel</class>
+15 -30
View File
@@ -26,12 +26,15 @@
#include "../utils/kmessconfig.h"
#include <QDockWidget>
#include <QMouseEvent>
#include <QDir>
#include <QMimeData>
#include <QMouseEvent>
#include <QRegularExpression>
#include <KIconEffect>
#include <KIO/NetAccess>
#include <KLocalizedString>
#include <KMessageBox>
#include <QUrl>
// The constructor
ContactsWidget::ContactsWidget( QWidget *parent )
@@ -273,9 +276,9 @@ bool ContactsWidget::eventFilter( QObject *obj, QEvent *event )
return true;
}
KUrl mimeUrl = mimeData->urls().first();
bool isRemoteFile = false;
QUrl mimeUrl = mimeData->urls().first();
QString localFilePath;
QString temporaryFilePath;
QImage pictureData;
if( mimeUrl.isEmpty() )
@@ -284,34 +287,20 @@ bool ContactsWidget::eventFilter( QObject *obj, QEvent *event )
return true;
}
if( mimeUrl.isLocalFile() )
if( ! KMessShared::downloadToLocalFile( mimeUrl, localFilePath, &temporaryFilePath ) )
{
localFilePath = mimeUrl.path();
}
else
{
// File is remote, download it to a local folder
// first because QPixmap doesn't have KIO magic.
// KIO::NetAccess::download fills the localFilePath field.
if( ! KIO::NetAccess::download(mimeUrl, localFilePath, this ) )
{
KMessageBox::sorry( this, i18n( "Downloading of display picture failed" ), i18n("KMess") );
return true;
}
isRemoteFile = true;
KMessageBox::error( this, i18n( "Downloading of display picture failed" ), i18n("KMess") );
return true;
}
if( ! pictureData.load( localFilePath ) )
{
KMessShared::removeDownloadedTempFile( temporaryFilePath );
kmWarning() << "The file dropped is not an image or doesn't exist";
return true;
}
if( isRemoteFile )
{
KIO::NetAccess::removeTempFile( localFilePath );
}
KMessShared::removeDownloadedTempFile( temporaryFilePath );
pictureData = pictureData.scaled( 96, 96, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation ); // Makes smallest edge 96 pixels, preserving aspect ratio
@@ -328,14 +317,14 @@ bool ContactsWidget::eventFilter( QObject *obj, QEvent *event )
if( ! pictureData.save( tempPictureFile, "PNG" ) )
{
KMessageBox::sorry( this,
KMessageBox::error( this,
i18n( "An error occurred while trying to change the display picture.\n"
"Make sure that you have selected an existing image file." ),
i18n( "KMess" ) );
}
QString msnObjectHash( KMessShared::generateFileHash( tempPictureFile ).toBase64() );
const QString safeMsnObjectHash( msnObjectHash.replace( QRegExp("[^a-zA-Z0-9+=]"), "_" ) );
const QString safeMsnObjectHash( msnObjectHash.replace( QRegularExpression("[^a-zA-Z0-9+=]"), "_" ) );
// Save the new display picture with its hash as name, to ensure correct caching
QString pictureName = msnObjectHash + ".png";
@@ -432,7 +421,7 @@ ContactFrame* ContactsWidget::createContactFrame()
this, SIGNAL( contactBlocked( QString, bool ) ) );
// Add it to the viewBox so it appears in the widget
layout_->insertWidget( children().count() - 2, contactFrame );
layout_->insertWidget( layout_->count(), contactFrame );
// put it in the list of frames so we can find it again.
contactFrames_.append( contactFrame );
@@ -613,7 +602,3 @@ void ContactsWidget::slotUpdateDisplayPicture()
userPixmapLabel_->setPixmap( image );
userPixmapLabel_->setProperty( "PictureFileName", pictureFileName );
}
#include "contactswidget.moc"
+1 -1
View File
@@ -91,7 +91,7 @@ class ContactsWidget : public QWidget, private Ui::ContactsWidget
// Return one new contact frame
ContactFrame* createContactFrame();
// The user picture frame received an event
bool eventFilter( QObject *obj, QEvent *event );
bool eventFilter( QObject *obj, QEvent *event ) override;
// Get the most suitable frame size, depending on how many contacts are currently in chat with us
ContactFrame::DisplayMode getBestFrameMode();
// Find the contact frame with the given handle
+8 -8
View File
@@ -32,6 +32,9 @@
#include <QMouseEvent>
#include <QPoint>
#include <QIcon>
#include <KLocalizedString>
// The constructor
@@ -183,7 +186,7 @@ bool EmoticonListWidget::eventFilter( QObject */*obj*/, QEvent *e )
if( e->type() == QEvent::HoverMove )
{
// The cursor mouse is moving over the widget
QListWidgetItem *item = itemAt( static_cast<QHoverEvent*>(e)->pos() );
QListWidgetItem *item = itemAt( static_cast<QHoverEvent*>(e)->position().toPoint() );
// Check if the mouse is over the same emoticon or the selection is changed
if( item == previousItem_ )
@@ -436,10 +439,10 @@ void EmoticonsWidget::showContextMenu( const QListWidgetItem *item, const QPoint
// Create the popup menu for custom emoticon
QMenu menu;
QAction addAction( KIcon( "insert-image" ), i18n( "Add to Chat" ), this );
QAction insertAction( KIcon( "list-add" ), i18n( "Add New" ), this );
QAction editAction( KIcon( "draw-freehand" ), i18n( "Edit" ), this );
QAction removeAction( KIcon( "list-remove" ), i18n( "Remove" ), this );
QAction addAction( QIcon::fromTheme( "insert-image" ), i18n( "Add to Chat" ), this );
QAction insertAction( QIcon::fromTheme( "list-add" ), i18n( "Add New" ), this );
QAction editAction( QIcon::fromTheme( "draw-freehand" ), i18n( "Edit" ), this );
QAction removeAction( QIcon::fromTheme( "list-remove" ), i18n( "Remove" ), this );
menu.addAction( &addAction );
menu.addAction( &insertAction );
@@ -483,6 +486,3 @@ void EmoticonsWidget::showContextMenu( const QListWidgetItem *item, const QPoint
emoticonDialog_->show();
}
#include "emoticonswidget.moc"
+3 -3
View File
@@ -57,7 +57,7 @@ class EmoticonsWidget : public QWidget
protected:
// Event filter for the preview label
bool eventFilter( QObject *obj, QEvent *e );
bool eventFilter( QObject *obj, QEvent *e ) override;
private slots:
// One item was clicked
@@ -121,9 +121,9 @@ class EmoticonListWidget : public QListWidget
protected:
// Reimplement the mouse press event to grep left and right click
void mousePressEvent( QMouseEvent *e );
void mousePressEvent( QMouseEvent *e ) override;
// Reimplement the event filter
bool eventFilter( QObject *obj, QEvent *e );
bool eventFilter( QObject *obj, QEvent *e ) override;
private:
QListWidgetItem *previousItem_;
+12 -14
View File
@@ -19,6 +19,7 @@
#include "../contact/msnobject.h"
#include "../utils/kmessconfig.h"
#include "../utils/kmessshared.h"
#include "../currentaccount.h"
#include "../kmessdebug.h"
@@ -26,12 +27,12 @@
#include <QDomDocument>
#include <QLabel>
#include <QListWidgetItem>
#include <QRegularExpression>
#include <QTextDocument>
#include <KIcon>
#include <QIcon>
#include <KLocalizedString>
#include <KProcess>
#include <KStandardDirs>
WinksWidget::WinksWidget( QWidget *parent )
@@ -78,7 +79,7 @@ void WinksWidget::refresh()
const QDir directory( winksDir_, "*.cab" );
QDir winkDirectory ( winksDir_, "*.png" );
QFileInfo fileInfo;
KIcon icon;
QIcon icon;
QString iconPath;
const QStringList cabFiles( directory.entryList( QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks ) );
@@ -152,7 +153,7 @@ void WinksWidget::refresh()
}
// Add the item
QListWidgetItem *item = new QListWidgetItem( KIcon( iconPath ), "", list_ );
QListWidgetItem *item = new QListWidgetItem( QIcon( iconPath ), "", list_ );
item->setData( Qt::UserRole, file );
item->setToolTip( winkFriendly );
}
@@ -173,7 +174,7 @@ WinksWidget::CABEXTRACTOR WinksWidget::getHtmlFromWink( const QString &filename,
if( ! metaFile.exists() )
{
// Check if cabextract is installed
if( KStandardDirs::findExe( "cabextract" ).isEmpty() )
if( KMessShared::findExecutable( "cabextract" ).isEmpty() )
{
return NOTINSTALLED;
}
@@ -211,11 +212,12 @@ WinksWidget::CABEXTRACTOR WinksWidget::getHtmlFromWink( const QString &filename,
}
// Parse the XML
QString xmlErrorMessage;
QDomDocument xml;
if( ! xml.setContent( &metaFile, true, &xmlErrorMessage ) )
const QDomDocument::ParseResult parseResult =
xml.setContent( &metaFile, QDomDocument::ParseOption::UseNamespaceProcessing );
if( ! parseResult )
{
kmWarning() << "parsing of wink XML failed: " << xmlErrorMessage << "!";
kmWarning() << "parsing of wink XML failed: " << parseResult.errorMessage << "!";
return UNKNOW;
}
@@ -274,8 +276,8 @@ WinksWidget::CABEXTRACTOR WinksWidget::getHtmlFromWink( const QString &filename,
}
// Escape data for inclusion in HTML.
animation = Qt::escape(animation).replace("\"", "&quot;"); // quotes are not escaped by QStyleSheet::escape().
animationType = animationType.remove( QRegExp("[^a-zA-Z0-9\\-/]") );
animation = animation.toHtmlEscaped().replace("\"", "&quot;" );
animationType = animationType.remove( QRegularExpression( "[^a-zA-Z0-9\\-/]" ) );
const QString filePath( winksDir + "/" + animation );
@@ -347,7 +349,3 @@ const MsnObject WinksWidget::getMsnObjectWinkSelected()
// Finally, return the msn object
return MsnObject( handle, fileInfo.baseName(), winkFriendly, MsnObject::WINK, data, stamp );
}
#include "winkswidget.moc"
+27 -23
View File
@@ -23,17 +23,17 @@
#include <stdlib.h>
#include <string.h>
#include <libxml/globals.h>
#include <libxml/parser.h>
#include <libxslt/xsltconfig.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h> // After xsltconfig and xsltInternals or it breaks compiling on some libxslt versions.
#include <QFile>
#include <QRegExp>
#include <QFileInfo>
#include <QRegularExpression>
#include <KLocale>
#include <KUrl>
#include <KLocalizedString>
#include <QUrl>
/*
@@ -51,8 +51,7 @@ XslTransformation::XslTransformation()
, xslParamCount_(0)
{
// Init libxml
xmlLoadExtDtdDefaultValue = 0;
xmlSubstituteEntitiesDefault( 1 );
xmlInitParser();
}
@@ -83,7 +82,7 @@ XslTransformation::~XslTransformation()
QString XslTransformation::convertXmlString( const QString &xml ) const
{
// Asserts
if( KMESS_NULL(styleSheet_) ) return QString::null;
if( KMESS_NULL(styleSheet_) ) return QString();
// Intermediate variables
QString result;
@@ -98,11 +97,15 @@ QString XslTransformation::convertXmlString( const QString &xml ) const
QByteArray xmlCString = xml.toUtf8();
// Create XmlDoc
sourceXmlDoc = xmlParseMemory( xmlCString.data(), xmlCString.length() );
sourceXmlDoc = xmlReadMemory( xmlCString.constData(),
static_cast<int>( xmlCString.size() ),
0,
0,
XML_PARSE_NOENT | XML_PARSE_NONET );
if( sourceXmlDoc == 0 )
{
kmWarning() << "could not parse the XML data.";
return QString::null;
return QString();
}
// Apply XSL
@@ -119,8 +122,8 @@ QString XslTransformation::convertXmlString( const QString &xml ) const
// Load result in a QString, strip xml header and last \n from result string
result = QString::fromUtf8( reinterpret_cast<char*>( xmlData ), xmlDataSize );
result = result.replace( QRegExp("^<\\?xml [^?]+\\?>\n?"), QString::null )
.replace( QRegExp("\r?\n?$"), QString::null );
result = result.replace( QRegularExpression( "^<\\?xml [^?]+\\?>\n?" ), QString() )
.replace( QRegularExpression( "\r?\n?$" ), QString() );
// Reverse calls to free intermediate results too.
// You gotta love C-API's.. ;-)
@@ -137,7 +140,7 @@ cleanSource:
// when the parsing of user parameters failed.
if( result.isEmpty() )
{
return QString::null;
return QString();
}
else
{
@@ -193,10 +196,6 @@ void XslTransformation::setStylesheet(const QString &xslFileName)
xslDoc_ = 0;
}
// Get file path
KUrl fileUrl(xslFileName);
// QByteArray basePath = fileUrl.directory( KUrl::AppendTrailingSlash ).toUtf8();
// Open XSL file
QFile file(xslFileName);
if( ! file.open(QIODevice::ReadOnly) )
@@ -210,7 +209,12 @@ void XslTransformation::setStylesheet(const QString &xslFileName)
file.close();
// Parse file data as XML
xslDoc_ = xmlParseMemory( fileData.data(), fileData.size() );
const QByteArray baseUrl = QUrl::fromLocalFile( QFileInfo( xslFileName ).absoluteFilePath() ).toEncoded();
xslDoc_ = xmlReadMemory( fileData.constData(),
static_cast<int>( fileData.size() ),
baseUrl.constData(),
0,
XML_PARSE_NOENT | XML_PARSE_NONET );
if(xslDoc_ == 0)
{
kmWarning() << "could not parse XML from '" << xslFileName << "'!";
@@ -250,7 +254,7 @@ void XslTransformation::setStylesheet(const QString &xslFileName)
{
kmWarning() << "'xsl' and 'kmess' namespaces not found in '"
<< xslFileName << "' chat style, "
<< "chat style can't be translated." << endl;
<< "chat style can't be translated." << Qt::endl;
}
else
{
@@ -284,7 +288,7 @@ void XslTransformation::updateParametersList()
// Delete the previous parameter list
for( int i = 0; i < xslParamCount_; i++ )
{
delete xslParams_[i];
free( xslParams_[i] );
}
delete[] xslParams_;
@@ -327,7 +331,7 @@ void XslTransformation::updateXslTranslations( xmlNode *node, const xmlNs *xslNs
// <xsl:text kmess:translate="true">fdsfsd</xsl:text>
// the contents is trimmed to avoid translations are broken too easily.
QRegExp trimmer("^([ \t\r\n\f\v]+)(.+)([ \t\r\n\f\v]+)$");
const QRegularExpression trimmer( "^([ \t\r\n\f\v]+)(.+)([ \t\r\n\f\v]+)$" );
// Browse all child nodes
for( xmlNode *curNode = node; curNode != 0; curNode = curNode->next )
@@ -369,7 +373,8 @@ void XslTransformation::updateXslTranslations( xmlNode *node, const xmlNs *xslNs
// Trim and simplyfy spaces to avoid breaking translations too easily.
// Ignore <xsl:text> </xsl:text> nodes.
bool timmed = trimmer.indexIn( content ) != -1;
const QRegularExpressionMatch trimMatch = trimmer.match( content );
bool timmed = trimMatch.hasMatch();
content = content.simplified();
if( content.isEmpty() )
{
@@ -381,7 +386,7 @@ void XslTransformation::updateXslTranslations( xmlNode *node, const xmlNs *xslNs
content = i18nc( "chat-style-text", content.toLatin1() );
if( timmed )
{
content = trimmer.cap(1) + content + trimmer.cap(3);
content = trimMatch.captured( 1 ) + content + trimMatch.captured( 3 );
}
#ifdef KMESSDEBUG_XSLTRANSFORMATION
@@ -400,4 +405,3 @@ void XslTransformation::updateXslTranslations( xmlNode *node, const xmlNs *xslNs
updateXslTranslations( curNode->children, xslNs, kmessNs );
}
}
-2
View File
@@ -606,5 +606,3 @@ void Contact::setStatus( const Status newStatus, bool showBaloon )
emit contactOnline( this, showBaloon );
}
}
#include "contact.moc"
+4 -4
View File
@@ -87,7 +87,7 @@ class Contact : public ContactBase
// Return the contact's display picture, scaled to the right size for the contact list.
QPixmap & getScaledDisplayPicture();
// Return the path to the contact's picture
const QString getContactPicturePath() const;
const QString getContactPicturePath() const override;
// Return the current media type
const QString & getCurrentMediaType() const;
// Return the current media type
@@ -95,7 +95,7 @@ class Contact : public ContactBase
// Return a pointer to the extension class
ContactExtension *getExtension() const;
// Return the contact's friendly name
const QString& getFriendlyName( FormattingMode mode = STRING_CLEANED ) const;
const QString& getFriendlyName( FormattingMode mode = STRING_CLEANED ) const override;
// Return the group ID's the contact is added to
const QStringList& getGroupIds() const;
// Return the contact's globally unique identifier
@@ -107,7 +107,7 @@ class Contact : public ContactBase
// Return the contact's personal message
const QString & getPersonalMessage( FormattingMode mode = STRING_CLEANED ) const;
// Return the contact's status
Status getStatus() const;
Status getStatus() const override;
// Return the contact's true friendly name, regardless of extension
const QString& getTrueFriendlyName( FormattingMode mode = STRING_CLEANED ) const;
// Return an MSN Object
@@ -149,7 +149,7 @@ class Contact : public ContactBase
// Set wether or not the contact is on pending list
void setPending( bool isPending );
// Set the contacts Personal message
void setPersonalStatus(const QString &message, const QString &mediaType = QString::null, const QString &mediaString = QString::null);
void setPersonalStatus(const QString &message, const QString &mediaType = QString(), const QString &mediaString = QString());
// Set whether or not the contact is on the reverse list
void setReverse(bool reverse);
// Set the contact's status
+3 -9
View File
@@ -25,8 +25,7 @@
#include <QFile>
#include <QImage>
#include <KLocale>
#include <KStandardDirs>
#include <KLocalizedString>
@@ -258,7 +257,7 @@ void ContactBase::detectClientName( uint capabilities, const MsnObject *msnObjec
{
pictureClientName = "Mercury";
}
else if( pictureLocation == "kopete.tmp" or pictureLocation == "1.tmp" )
else if( pictureLocation == "kopete.tmp" || pictureLocation == "1.tmp" )
{
pictureClientName = "Kopete";
}
@@ -442,8 +441,7 @@ const QString & ContactBase::getClientFullName() const
// Return the default contact picture path
QString ContactBase::getContactDefaultPicturePath() const
{
KStandardDirs *dirs = KGlobal::dirs();
return dirs->findResource( "data", "kmess/pics/unknown.png" );
return KMessShared::findResource( "data", "kmess/pics/unknown.png" );
}
@@ -732,7 +730,3 @@ void ContactBase::slotApplicationListAborted()
applicationList_->deleteLater();
applicationList_ = 0;
}
#include "contactbase.moc"
+9 -12
View File
@@ -21,8 +21,9 @@
#include "../kmessdebug.h"
#include <QFile>
#include <QLocale>
#include <KLocale>
#include <KLocalizedString>
#include <KConfigGroup>
@@ -104,7 +105,7 @@ const QString ContactExtension::getContactPicturePath() const
return pictureFile_;
}
return QString::null;
return QString();
}
@@ -117,7 +118,7 @@ const QString ContactExtension::getContactSoundPath() const
return soundFile_;
}
return QString::null;
return QString();
}
@@ -179,8 +180,8 @@ void ContactExtension::readProperties( const KConfigGroup &config )
// in saveProperties() !
alternativeName_ = extensionGroup.readEntry("alternativeName", "" );
alternativePictureFile_ = extensionGroup.readEntry("alternativePictureFile", "" );
lastSeen_ = QDateTime::fromTime_t( extensionGroup.readEntry("lastSeen", 0 ) );
lastMessageDate_ = QDateTime::fromTime_t( extensionGroup.readEntry("lastMessageDate", 0 ) );
lastSeen_ = QDateTime::fromSecsSinceEpoch( extensionGroup.readEntry("lastSeen", 0 ) );
lastMessageDate_ = QDateTime::fromSecsSinceEpoch( extensionGroup.readEntry("lastMessageDate", 0 ) );
disableNotifications_ = extensionGroup.readEntry("disableNotifications", false );
notes_ = extensionGroup.readEntry("notes", "" );
pictureFile_ = extensionGroup.readEntry("pictureFile", "" );
@@ -238,12 +239,12 @@ void ContactExtension::saveProperties( KConfigGroup &config )
if( ! lastSeen_.isNull() && lastSeen_.isValid() )
{
extensionGroup.writeEntry( "lastSeen", lastSeen_.toTime_t() );
extensionGroup.writeEntry( "lastSeen", lastSeen_.toSecsSinceEpoch() );
}
if( ! lastMessageDate_.isNull() && lastMessageDate_.isValid() )
{
extensionGroup.writeEntry( "lastMessageDate", lastMessageDate_.toTime_t() );
extensionGroup.writeEntry( "lastMessageDate", lastMessageDate_.toSecsSinceEpoch() );
}
extensionGroup.writeEntry( "pictureFile", pictureFile_ );
@@ -305,7 +306,7 @@ void ContactExtension::setContactPicturePath( const QString & _newVal )
if ( fileDat.open( QIODevice::WriteOnly | QIODevice::Text ) )
{
QTextStream out( &fileDat );
out << QDate::currentDate ().toString( Qt::SystemLocaleDate );
out << QLocale().toString( QDate::currentDate(), QLocale::ShortFormat );
fileDat.close();
}
}
@@ -367,7 +368,3 @@ void ContactExtension::setUseAlternativeName( bool _newVal)
if ( needUpdate == true ) emit changedFriendlyName();
}
#include "contactextension.moc"
-4
View File
@@ -189,7 +189,3 @@ void Group::setExpanded(bool expanded)
{
isExpanded_ = expanded;
}
#include "group.moc"
-3
View File
@@ -53,6 +53,3 @@ Status InvitedContact::getStatus() const
// Since no status updates are returned for a contact not on the list, return "Invisible".
return STATUS_INVISIBLE;
}
#include "invitedcontact.moc"
+2 -2
View File
@@ -42,9 +42,9 @@ class InvitedContact : public ContactBase
// The destructor
virtual ~InvitedContact();
// Return the path to the contact's picture
const QString getContactPicturePath() const;
const QString getContactPicturePath() const override;
// Return the contact's status
Status getStatus() const;
Status getStatus() const override;
};
#endif
+27 -4
View File
@@ -59,12 +59,35 @@ MsnObject::MsnObject(const MsnObject &other)
, type_(other.type_)
, sha1d_(other.sha1d_)
, sha1c_(other.sha1c_)
, stamp_(other.stamp_)
{
}
MsnObject& MsnObject::operator=( const MsnObject &other )
{
if( this == &other )
{
return *this;
}
creator_ = other.creator_;
friendly_ = other.friendly_;
location_ = other.location_;
original_ = other.original_;
size_ = other.size_;
type_ = other.type_;
sha1d_ = other.sha1d_;
sha1c_ = other.sha1c_;
stamp_ = other.stamp_;
return *this;
}
MsnObject::MsnObject( const QString &creator, const QString &location,
const QString &friendly, MsnObjectType type,
const QByteArray &fileData, const QByteArray &stamp )
@@ -98,12 +121,12 @@ QString MsnObject::getAttribute( const QString& name, const QString& object )
int index = findAttribute.indexIn( object );
// Return if found
if( index >= 0 && findAttribute.numCaptures() > 0 )
if( index >= 0 && ! findAttribute.cap( 1 ).isEmpty() )
{
return findAttribute.cap( 1 );
}
return QString::null;
return QString();
}
@@ -194,7 +217,8 @@ void MsnObject::loadObject( const QString& object )
// Don't check for invalid characters in the encoded string, QByteArray does it
const QByteArray friendlyUcs2( QByteArray::fromBase64( friendlyEncoded.toUtf8() ) );
friendly_ = QString::fromUtf16( reinterpret_cast<const ushort*>( friendlyUcs2.data() ), friendlyUcs2.size() ).toUtf8();
friendly_ = QString::fromUtf16( reinterpret_cast<const char16_t*>( friendlyUcs2.constData() ),
friendlyUcs2.size() / int( sizeof( char16_t ) ) ).toUtf8();
}
@@ -311,4 +335,3 @@ bool MsnObject::hasChanged( const QString &newObj ) const
// The data hash is not available: use the full object hash
return ( sha1c_ != getAttribute( "SHA1C", newObj ).toUtf8() );
}
+5
View File
@@ -70,6 +70,11 @@ class MsnObject
*/
MsnObject(const MsnObject &other);
/**
* Assignment operator.
*/
MsnObject& operator=( const MsnObject &other );
/**
* Create an MsnObject based on the provided attributes.
* Hashes will be calculated automatically.
+13 -13
View File
@@ -19,15 +19,16 @@
#include "../kmessdebug.h"
#include <KAction>
#include <QAction>
#include <QIcon>
#include <KIconEffect>
#include <KIconLoader>
#include <KLocale>
#include <KMenu>
#include <KLocalizedString>
#include <QMenu>
// Initialize the status menu
KMenu* MsnStatus::statusMenu_( 0 );
QMenu* MsnStatus::statusMenu_( 0 );
MsnStatus::~MsnStatus()
{
@@ -214,21 +215,22 @@ QString MsnStatus::getName( const Status status )
* Be sure to actually attach the returned menu to some toolbar or the like,
* or it won't be properly deleted.
*
* @return KMenu with a QAction for each available Status
* @return QMenu with a QAction for each available Status
*/
KMenu *MsnStatus::getStatusMenu()
QMenu *MsnStatus::getStatusMenu()
{
if( statusMenu_ != 0 )
{
return statusMenu_;
}
statusMenu_ = new KMenu();
statusMenu_->addTitle( KIcon( "go-jump" ), i18n( "&My Status" ) );
statusMenu_->setIcon( KIcon( "go-jump" ) );
statusMenu_ = new QMenu();
QAction *titleAction = statusMenu_->addAction( QIcon::fromTheme( "go-jump" ), i18n( "&My Status" ) );
titleAction->setEnabled( false );
statusMenu_->setIcon( QIcon::fromTheme( "go-jump" ) );
statusMenu_->setTitle( i18n( "&My Status" ) );
Status status;
KAction *action;
QAction *action;
// This loop assumes that a) STATES_NUMBER is the last item of the Status enum, and
// b) STATUS_OFFLINE is the second last. Fun stuff happens if it is not the case.
@@ -237,7 +239,7 @@ KMenu *MsnStatus::getStatusMenu()
// Setting the action's data allows us to later retrieve the
// Status from a triggered QAction
status = (Status) index;
action = new KAction( KIcon( getIcon( status ) ), getName( status ), statusMenu_ );
action = new QAction( QIcon( getIcon( status ) ), getName( status ), statusMenu_ );
action->setData( status );
// The disconnection action is a bit special :)
@@ -289,5 +291,3 @@ Status MsnStatus::codeToStatus( const QString &status )
return STATUS_ONLINE;
}
}
+3 -3
View File
@@ -22,7 +22,7 @@
// Forward declarations
class KMenu;
class QMenu;
@@ -89,7 +89,7 @@ class MsnStatus
// Returns the localized name for a status
static QString getName( const Status status );
// Create and return a menu with all the states
static KMenu *getStatusMenu();
static QMenu *getStatusMenu();
// Convert a three-letter code to a status
static Status codeToStatus( const QString &status );
@@ -97,7 +97,7 @@ class MsnStatus
private: // Private static properties
// The status menu
static KMenu *statusMenu_;
static QMenu *statusMenu_;
};
-12
View File
@@ -179,14 +179,6 @@ QString CurrentAccount::getContactFriendlyNameByHandle( const QString &handle, F
// Return the contact last dragged
const ContactBase* CurrentAccount::getContactLastDragged() const
{
// currently a stub
return 0;
}
// Return the contact list as read-only
const ContactList * CurrentAccount::getContactList() const
{
@@ -503,7 +495,3 @@ void CurrentAccount::slotInvitedContactLeftAllChats( ContactBase *contact )
// Delete after all slots are processed.
contact->deleteLater();
}
#include "currentaccount.moc"
+1 -3
View File
@@ -58,7 +58,7 @@ class CurrentAccount : public Account
// Receive notice that some emails were deleted
void changeNoEmails( int change );
// Copy an account
virtual void copyAccount( const Account *account );
virtual void copyAccount( const Account *account ) override;
// Delete the instance of the contact list
static void destroy();
// Return whether or not to autoreply to messages
@@ -69,8 +69,6 @@ class CurrentAccount : public Account
QString getContactFriendlyNameByHandle(const QString &handle, FormattingMode mode = STRING_CLEANED ) const;
// Return the contact list as read-only
const ContactList * getContactList() const;
// Return the contact which was last dragged.
const ContactBase* getContactLastDragged() const;
// Return the email URL
const QString& getEmailUrl() const;
// Return the external IP, as seen from the MSN server.
+7 -8
View File
@@ -23,6 +23,9 @@
#include "../currentaccount.h"
#include "../kmessdebug.h"
#include <QIcon>
#include <KLocalizedString>
/**
@@ -35,7 +38,7 @@
* @param parent Parent widget
*/
AddContactDialog::AddContactDialog( QString &handle, QStringList &groupsId, QWidget *parent )
: KDialog( parent )
: KMessDialog( parent )
, Ui::AddContactDialog()
{
// Set up the interface and the dialog
@@ -57,7 +60,7 @@ AddContactDialog::AddContactDialog( QString &handle, QStringList &groupsId, QWid
// Lock the dialog height, it's ugly otherwise
restoreDialogSize( KMessConfig::instance()->getGlobalConfig( "AddContactDialog" ) );
icon_->setPixmap( KIcon( "list-add-user" ).pixmap( 48, 48 ) );
icon_->setPixmap( QIcon::fromTheme( "list-add-user" ).pixmap( 48, 48 ) );
// Fill up the groups list from the contactlist data
const QList< Group* >& groupList( CurrentAccount::instance()->getContactList()->getGroupList() );
@@ -125,7 +128,7 @@ void AddContactDialog::interfaceChanged()
* or "a@bc"), the MSN Servers disconnect you and send you a so called ".NET message" with the error details.
* This basic set of tests is more than enough to pass the server requirements.
*
* Other than the usual address validation (see the Account::isValidEmail() method), MSN will kick you out if
* Other than the usual handle validation (see the Account::isValidHandle() method), MSN will kick you out if
* you try adding an address having ".co" as top level domain. So we ensure it has not. This is probably due
* to people keeping mistyping ".com" when adding people to their list - all random 2-character domains are
* allowed, except ".co".
@@ -133,7 +136,7 @@ void AddContactDialog::interfaceChanged()
// If the mail address seems correct, accept it
if( ! emailAddress.isEmpty()
&& Account::isValidEmail( emailAddress )
&& Account::isValidHandle( emailAddress )
&& ! emailAddress.endsWith( ".co" ) )
{
enableButtonOk( true );
@@ -164,7 +167,3 @@ const QStringList AddContactDialog::getSelectedGroups() const
return selectedGroups;
}
#include "addcontactdialog.moc"
+2 -2
View File
@@ -20,7 +20,7 @@
#include "ui_addcontactdialog.h"
#include <KDialog>
#include "../utils/kmessdialog.h"
@@ -34,7 +34,7 @@
* @author Valerio Pilo <valerio@kmess.org>
* @ingroup Dialogs
*/
class AddContactDialog : public KDialog, private Ui::AddContactDialog
class AddContactDialog : public KMessDialog, private Ui::AddContactDialog
{
Q_OBJECT
+15 -13
View File
@@ -22,8 +22,9 @@
#include "../emoticonmanager.h"
#include "../kmessdebug.h"
#include <KFileDialog>
#include <QFileDialog>
#include <KIconLoader>
#include <KLocalizedString>
#include <KMessageBox>
@@ -42,7 +43,7 @@
* @param parent Parent widget
*/
AddEmoticonDialog::AddEmoticonDialog( EmoticonTheme *theme, QWidget *parent )
: KDialog( parent )
: KMessDialog( parent )
, Ui::AddEmoticonDialog()
, theme_(theme)
, isEditing_(false)
@@ -109,10 +110,13 @@ AddEmoticonDialog::~AddEmoticonDialog()
*/
void AddEmoticonDialog::choosePicture()
{
KUrl file( pictureEdit_->text() );
QUrl file( pictureEdit_->text() );
// Choose a file, filtering out all files but the preselected image types
file = KFileDialog::getImageOpenUrl( file, this );
file = QFileDialog::getOpenFileUrl( this,
QString(),
file,
QStringLiteral( "Images (*.png *.jpg *.jpeg *.gif *.bmp *.webp);;All Files (*)" ) );
if( file.isEmpty() || ! file.isLocalFile() )
{
@@ -262,7 +266,7 @@ void AddEmoticonDialog::slotButtonClicked( int button )
// If the Cancel button has been pressed, close without saving
if( button != Ok )
{
KDialog::slotButtonClicked( button );
KMessDialog::slotButtonClicked( button );
return;
}
@@ -299,10 +303,12 @@ void AddEmoticonDialog::slotButtonClicked( int button )
kmDebug() << "Asking for overwrite.";
#endif
int result = KMessageBox::questionYesNo( this,
int result = KMessageBox::questionTwoActions( this,
i18n( "The emoticon \"%1\" already exists. Do you want to replace it?", shortcut ),
i18n("Add New Emoticon") );
if ( result == KMessageBox::Yes )
i18n("Add New Emoticon"),
KGuiItem( i18n( "Yes" ) ),
KGuiItem( i18n( "No" ) ) );
if ( result == KMessageBox::PrimaryAction )
{
theme_->removeEmoticon( shortcut );
}
@@ -370,7 +376,7 @@ void AddEmoticonDialog::slotButtonClicked( int button )
{
kmWarning() << "File sizes do not match: "
<< originalPicture.fileName() << " (" << originalPicture.size() << ")"
<< " != " << newThemePicture.fileName() << " (" << newThemePicture.size() << ")" << endl;
<< " != " << newThemePicture.fileName() << " (" << newThemePicture.size() << ")" << Qt::endl;
return;
}
}
@@ -407,7 +413,3 @@ void AddEmoticonDialog::slotButtonClicked( int button )
accept();
}
#include "addemoticondialog.moc"
+3 -3
View File
@@ -20,7 +20,7 @@
#include "ui_addemoticondialog.h"
#include <KDialog>
#include "../utils/kmessdialog.h"
#include <QMovie>
#include <QObject>
@@ -38,7 +38,7 @@ class EmoticonTheme;
* @author Valerio Pilo <valerio@kmess.org>
* @ingroup Dialogs
*/
class AddEmoticonDialog : public KDialog, private Ui::AddEmoticonDialog
class AddEmoticonDialog : public KMessDialog, private Ui::AddEmoticonDialog
{
Q_OBJECT
@@ -58,7 +58,7 @@ class AddEmoticonDialog : public KDialog, private Ui::AddEmoticonDialog
// Controls the OK button by checking the dialog's widgets
void interfaceChanged();
// Adds the new emoticon to the theme if the Ok button has been pressed
void slotButtonClicked( int button );
void slotButtonClicked( int button ) override;
private:
// Preselected shortcut text
-1
View File
@@ -200,7 +200,6 @@
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
<resources/>
<connections/>
</ui>
+2 -5
View File
@@ -19,11 +19,12 @@
#include "../utils/kmessconfig.h"
#include <KLocalizedString>
// The constructor
AwayMessageDialog::AwayMessageDialog( QWidget *parent )
: KDialog( parent )
: KMessDialog( parent )
, Ui::AwayMessageDialog()
{
// Set up the interface and the dialog
@@ -70,7 +71,3 @@ bool AwayMessageDialog::useMessage(QString &message)
message = messageEdit_->toPlainText();
return true;
}
#include "awaymessagedialog.moc"
+2 -2
View File
@@ -20,7 +20,7 @@
#include "ui_awaymessagedialog.h"
#include <KDialog>
#include "../utils/kmessdialog.h"
@@ -31,7 +31,7 @@
* @author Mike K. Bennett
* @ingroup Dialogs
*/
class AwayMessageDialog : public KDialog, private Ui::AwayMessageDialog
class AwayMessageDialog : public KMessDialog, private Ui::AwayMessageDialog
{
Q_OBJECT
+13 -16
View File
@@ -38,13 +38,13 @@
#include <QClipboard>
#include <QTextCharFormat>
#include <KApplication>
#include <QApplication>
#include <QIcon>
#include <KIconLoader>
#include <KMessageBox>
#include <KLocalizedString>
#include <KDateTime>
#include <KMenu>
#include <KAction>
#include <KHTMLView>
#include <QMenu>
#include <QAction>
#include <KStandardAction>
@@ -55,7 +55,7 @@
// Constructor
ChatHistoryDialog::ChatHistoryDialog( QWidget *parent )
: KDialog( parent )
: KMessDialog( parent )
, model_( new QStandardItemModel( this ) )
, proxyModel_( new QSortFilterProxyModel( this ) )
{
@@ -67,12 +67,13 @@ ChatHistoryDialog::ChatHistoryDialog( QWidget *parent )
setHelp( "using-chat-history" );
setWindowTitle( i18nc( "Dialog window title", "Chat History" ) );
loadingLabel_->hide();
loadingLabel_->setIcon( QIcon::fromTheme( "process-working" ) );
// Let the dialog destroy itself when it's done
setAttribute( Qt::WA_DeleteOnClose );
// Set a nice icon
setWindowIcon( KMessShared::drawIconOverlay( KIconLoader::global()->loadIcon( "kmess", KIconLoader::Panel ), KIcon( "chronometer" ).pixmap( 20, 20 ) ) );
setWindowIcon( KMessShared::drawIconOverlay( KIconLoader::global()->loadIcon( "kmess", KIconLoader::Panel ), QIcon::fromTheme( "chronometer" ).pixmap( 20, 20 ) ) );
// Create the chat view to show the chat logs
chatView_ = new ChatMessageView( mainWidget );
@@ -100,7 +101,7 @@ ChatHistoryDialog::ChatHistoryDialog( QWidget *parent )
}
else
{
KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
KMessApplication *kmessApp = static_cast<KMessApplication *>(QApplication::instance());
// When disconnected or using a guest account, the accounts list will default to the
// first available account
@@ -227,7 +228,7 @@ void ChatHistoryDialog::showAvailableDates( const QModelIndex &index )
QDate lastDate;
foreach( quint64 timestamp, list )
{
lastDate = QDateTime::fromTime_t( timestamp ).date();
lastDate = QDateTime::fromSecsSinceEpoch( timestamp ).date();
// Set the calendar's first and last available dates, while we're at it
if( timestamp == list.first() )
@@ -328,8 +329,8 @@ void ChatHistoryDialog::showLogs( const QDate& day )
// Find all chat log timestamps in the specified day
// Get the initial and final timestamps of the range
const quint64 startingDate = QDateTime( day, QTime( 0, 0 ) ).toTime_t();
const quint64 endingDate = QDateTime( day, QTime( 23, 59 ) ).toTime_t();
const quint64 startingDate = QDateTime( day, QTime( 0, 0 ) ).toSecsSinceEpoch();
const quint64 endingDate = QDateTime( day, QTime( 23, 59 ) ).toSecsSinceEpoch();
#ifdef KMESSDEBUG_CHATHISTORYDIALOG_VERBOSE
@@ -475,11 +476,7 @@ void ChatHistoryDialog::slotShowContextMenu( const QString &clickedUrl, const QP
{
Q_UNUSED( clickedUrl )
KMenu *popup = chatView_->popupMenu();
QMenu *popup = chatView_->popupMenu();
popup->exec( point );
delete popup;
}
#include "chathistorydialog.moc"
+2 -2
View File
@@ -24,7 +24,7 @@
#include <QMutex>
#include <QPoint>
#include <KDialog>
#include "../utils/kmessdialog.h"
#include "ui_chathistorydialog.h"
@@ -37,7 +37,7 @@ class ChatMessageView;
class ChatHistoryDialog : public KDialog, private Ui::historyDialog
class ChatHistoryDialog : public KMessDialog, private Ui::historyDialog
{
Q_OBJECT
+9 -12
View File
@@ -29,10 +29,10 @@
</item>
<item>
<widget class="KLineEdit" name="searchEdit_">
<property name="clickMessage">
<property name="placeholderText">
<string>Search through contacts...</string>
</property>
<property name="showClearButton" stdset="0">
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
@@ -101,9 +101,6 @@
<height>22</height>
</size>
</property>
<property name="icons">
<string notr="true" extracomment="Do not translate: icon file name">process-working</string>
</property>
</widget>
</item>
<item>
@@ -182,19 +179,19 @@
</widget>
<customwidgets>
<customwidget>
<class>KAnimatedButton</class>
<extends>QToolButton</extends>
<header>kanimatedbutton.h</header>
<class>KComboBox</class>
<extends>QComboBox</extends>
<header>KComboBox</header>
</customwidget>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
<header>KLineEdit</header>
</customwidget>
<customwidget>
<class>KComboBox</class>
<extends>QComboBox</extends>
<header>kcombobox.h</header>
<class>KAnimatedButton</class>
<extends>QToolButton</extends>
<header>KAnimatedButton</header>
</customwidget>
</customwidgets>
<tabstops>
+4 -4
View File
@@ -22,12 +22,13 @@
#include "../utils/kmessconfig.h"
#include <KLocalizedString>
/**
* Constructor
*
* This KDialog creates a QTabWidget which holds ContactAddedUserWidget instances. New
* This KMessDialog creates a QTabWidget which holds ContactAddedUserWidget instances. New
* instances can be added by calling addTab().
*
* @param contactHandle Reference to the handle of the contact that has added you
@@ -35,7 +36,7 @@
* @param parent Parent window of this one
*/
ContactAddedUserDialog::ContactAddedUserDialog( const QString& contactHandle, const QString& contactFriendlyName, QWidget* parent )
: KDialog(parent)
: KMessDialog(parent)
{
tabWidget_ = new QTabWidget( this );
setMainWidget( tabWidget_ );
@@ -45,7 +46,7 @@ ContactAddedUserDialog::ContactAddedUserDialog( const QString& contactHandle, co
setAttribute( Qt::WA_DeleteOnClose );
//adjust or restore saved size
adjustSize();
setButtons(KDialog::Close);
setButtons(KMessDialog::Close);
restoreDialogSize( KMessConfig::instance()->getGlobalConfig( "ContactAddedUserDialog" ));
// Update the window properties
@@ -134,4 +135,3 @@ void ContactAddedUserDialog::slotTabDeleted()
}
}
+2 -2
View File
@@ -18,7 +18,7 @@
#ifndef CONTACTADDEDUSERDIALOG_H
#define CONTACTADDEDUSERDIALOG_H
#include <KDialog>
#include "../utils/kmessdialog.h"
class QTabWidget;
@@ -30,7 +30,7 @@ class QTabWidget;
* @author Mike K. Bennett, Timo Tambet
* @ingroup Dialogs
*/
class ContactAddedUserDialog : public KDialog
class ContactAddedUserDialog : public KMessDialog
{
Q_OBJECT
+10 -7
View File
@@ -25,7 +25,9 @@
#include "../currentaccount.h"
#include "../kmessdebug.h"
#include "../utils/kmessconfig.h"
#include <kstandardguiitem.h>
#include <QPushButton>
#include <KStandardGuiItem>
#include <KLocalizedString>
@@ -46,8 +48,13 @@ ContactAddedUserWidget::ContactAddedUserWidget( const QString& contactHandle, co
{
setupUi( this );
buttonbox->addButton( KStandardGuiItem::ok(), QDialogButtonBox::AcceptRole, this, SLOT( accept()));
buttonbox->addButton( KStandardGuiItem::discard(), QDialogButtonBox::RejectRole, this, SLOT( reject()));
QPushButton *okButton = buttonbox->addButton( KStandardGuiItem::ok().text(), QDialogButtonBox::AcceptRole );
okButton->setIcon( KStandardGuiItem::ok().icon() );
connect( okButton, SIGNAL(clicked()), this, SLOT(accept()) );
QPushButton *discardButton = buttonbox->addButton( KStandardGuiItem::discard().text(), QDialogButtonBox::RejectRole );
discardButton->setIcon( KStandardGuiItem::discard().icon() );
connect( discardButton, SIGNAL(clicked()), this, SLOT(reject()) );
if( contactHandle == contactFriendlyName )
{
@@ -148,7 +155,3 @@ void ContactAddedUserWidget::reject()
// The widget is not necessary anymore, delete it
deleteLater();
}
#include "contactaddeduserwidget.moc"
+1 -9
View File
@@ -142,7 +142,7 @@
</spacer>
</item>
<item>
<widget class="KDialogButtonBox" name="buttonbox">
<widget class="QDialogButtonBox" name="buttonbox">
<property name="standardButtons">
<set>QDialogButtonBox::NoButton</set>
</property>
@@ -151,14 +151,6 @@
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
<customwidgets>
<customwidget>
<class>KDialogButtonBox</class>
<extends>QDialogButtonBox</extends>
<header>kdialogbuttonbox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
+2 -4
View File
@@ -137,11 +137,9 @@ void ContactEntry::click( bool deselect )
}
else
{
color = palette.color( QPalette::Background );
color = palette.color( QPalette::Window );
}
palette.setColor( QPalette::Background, color );
palette.setColor( QPalette::Window, color );
setPalette( palette );
}
#include "contactentry.moc"
+1 -1
View File
@@ -51,7 +51,7 @@ class ContactEntry : public QWidget, private Ui::ContactEntry
protected:
// Event Filter to catch mouse click
bool eventFilter( QObject *obj, QEvent *event );
bool eventFilter( QObject *obj, QEvent *event ) override;
private:
// Handle
+47 -36
View File
@@ -25,22 +25,26 @@
#include "../currentaccount.h"
#include "../kmessdebug.h"
#include <QAudioOutput>
#include <QMediaPlayer>
#include <QTextDocument>
#include <KFileDialog>
#include <QFileDialog>
#include <QIcon>
#include <KLocalizedString>
#include <KMessageBox>
#include <kmimetype.h>
#include <KIconEffect>
#include <KIconLoader>
#include <KStandardDirs>
#include <Phonon/BackendCapabilities>
#include <KStandardGuiItem>
#include <QMimeDatabase>
#include <math.h>
ContactPropertiesDialog::ContactPropertiesDialog( QWidget *parent )
: KDialog( parent )
: KMessDialog( parent )
, Ui::ContactProperties()
, ok_( false )
, mediaSound_(0)
@@ -84,8 +88,8 @@ ContactPropertiesDialog::ContactPropertiesDialog( QWidget *parent )
// Allow the user to select a local existing file.
soundSelect_->setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly );
connect( soundSelect_, SIGNAL( urlSelected ( const KUrl & ) ),
this, SLOT ( checkNotificationSoundFile( const KUrl & ) ) );
connect( soundSelect_, SIGNAL( urlSelected ( const QUrl & ) ),
this, SLOT ( checkNotificationSoundFile( const QUrl & ) ) );
}
@@ -177,7 +181,10 @@ void ContactPropertiesDialog::applyChanges()
// Choose a picture file (KFile dialog)
void ContactPropertiesDialog::choosePicture()
{
const KUrl file( KFileDialog::getImageOpenUrl( alternativePicturePath_ , this ) );
const QUrl file( QFileDialog::getOpenFileUrl( this,
QString(),
QUrl::fromLocalFile( alternativePicturePath_ ),
QStringLiteral( "Images (*.png *.jpg *.jpeg *.gif *.bmp *.webp);;All Files (*)" ) ) );
if ( ! file.isEmpty() )
{
@@ -398,8 +405,8 @@ void ContactPropertiesDialog::setupWidgets()
{
lastSeenString = i18n( "Connected" );
}
else if( extension->getLastSeen().toTime_t() == 0
|| extension->getLastSeen().toTime_t() == UINT_MAX
else if( extension->getLastSeen().toSecsSinceEpoch() == 0
|| extension->getLastSeen().toSecsSinceEpoch() == UINT_MAX
|| extension->getLastSeen().isNull() )
{
lastSeenString = i18n( "Not seen yet" );
@@ -409,8 +416,8 @@ void ContactPropertiesDialog::setupWidgets()
lastSeenString = extension->getLastSeen().toString();
}
if( extension->getLastMessageDate().toTime_t() == 0
|| extension->getLastMessageDate().toTime_t() == UINT_MAX
if( extension->getLastMessageDate().toSecsSinceEpoch() == 0
|| extension->getLastMessageDate().toSecsSinceEpoch() == UINT_MAX
|| extension->getLastMessageDate().isNull() )
{
lastMessageString = i18n( "No messages yet" );
@@ -453,7 +460,7 @@ void ContactPropertiesDialog::setupWidgets()
}
soundSelectLabel_->setBuddy(soundSelect_);
soundSelect_->setUrl( extension->getContactSoundPath() );
soundSelect_->setUrl( QUrl::fromLocalFile( extension->getContactSoundPath() ) );
// Set the group list
const QStringList& groupIdsList = contact_->getGroupIds();
@@ -533,7 +540,7 @@ void ContactPropertiesDialog::slotButtonClicked( int button )
// If the Cancel button has been pressed, close without saving
if( button != Ok )
{
KDialog::slotButtonClicked( button );
KMessDialog::slotButtonClicked( button );
return;
}
@@ -577,7 +584,8 @@ void ContactPropertiesDialog::slotPictureSelectionChanged()
// The play sound button has been pressed
void ContactPropertiesDialog::slotPlaySound()
{
const QString currentFile( soundSelect_->url().url() );
const QUrl currentUrl( soundSelect_->url() );
const QString currentFile( currentUrl.isLocalFile() ? currentUrl.toLocalFile() : currentUrl.toString() );
if( currentFile.isEmpty() )
{
return;
@@ -586,22 +594,30 @@ void ContactPropertiesDialog::slotPlaySound()
// Initialize the media sound object and connect it with slot sound finished
if( mediaSound_ == 0 )
{
mediaSound_ = Phonon::createPlayer( Phonon::NotificationCategory );
connect( mediaSound_, SIGNAL( finished() ), this, SLOT( slotSoundFinished() ) );
mediaSound_ = new QMediaPlayer( this );
mediaSound_->setAudioOutput( new QAudioOutput( mediaSound_ ) );
connect( mediaSound_, &QMediaPlayer::playbackStateChanged,
this, [this]( QMediaPlayer::PlaybackState state )
{
if( state == QMediaPlayer::StoppedState )
{
slotSoundFinished();
}
} );
}
// If the state is playing, stop the sound media and reset the icon
if( mediaSound_->state() == Phonon::PlayingState )
if( mediaSound_->playbackState() == QMediaPlayer::PlayingState )
{
mediaSound_->stop();
playButton_->setIcon( KIcon( "media-playback-start" ) );
playButton_->setIcon( QIcon::fromTheme( "media-playback-start" ) );
return;
}
// Play the sound and change the icon
mediaSound_->setCurrentSource( currentFile );
mediaSound_->setSource( QUrl::fromLocalFile( currentFile ) );
mediaSound_->play();
playButton_->setIcon( KIcon( "media-playback-stop" ) );
playButton_->setIcon( QIcon::fromTheme( "media-playback-stop" ) );
}
@@ -637,7 +653,7 @@ void ContactPropertiesDialog::slotRemoveEmoticon()
void ContactPropertiesDialog::slotSoundFinished()
{
// When sound finished, change reset the icon
playButton_->setIcon( KIcon( "media-playback-start" ) );
playButton_->setIcon( QIcon::fromTheme( "media-playback-start" ) );
}
@@ -661,15 +677,15 @@ void ContactPropertiesDialog::slotUsePicture()
}
// Ask confirmation to the user
int result = KMessageBox::questionYesNo( this,
int result = KMessageBox::questionTwoActions( this,
i18nc( "Dialog box text",
"Are you sure you want to use the display "
"picture of this contact?" ),
i18n( "Copy Contact Picture" ),
KStandardGuiItem::yes(),
KStandardGuiItem::no(),
KGuiItem( i18n( "Yes" ) ),
KGuiItem( i18n( "No" ) ),
QString( "copyContactPicture" ) );
if( result == KMessageBox::No )
if( result == KMessageBox::SecondaryAction )
{
return;
}
@@ -705,24 +721,19 @@ void ContactPropertiesDialog::slotUsePicture()
// Check if the fileformat is supported by Phonon
bool ContactPropertiesDialog::checkNotificationSoundFile( const KUrl &url ) {
// Check if the fileformat is supported by Qt Multimedia
bool ContactPropertiesDialog::checkNotificationSoundFile( const QUrl &url ) {
#ifdef KMESSDEBUG_CONTACTPROPERTIES
kmDebug() << "Checking filetype";
#endif
if( Phonon::BackendCapabilities::availableMimeTypes().contains(
KMimeType::findByUrl( url.url() )->name()) )
if( QMimeDatabase().mimeTypeForUrl( url ).name().startsWith( "audio/" ) )
{
return true;
}
KMessageBox::sorry( this, i18n( "The selected filetype is not supported by Phonon." ), i18n( "Unsupported filetype" ) );
soundSelect_->setUrl( KUrl( contact_->getExtension()->getContactSoundPath() ) );
KMessageBox::error( this, i18n( "The selected filetype is not supported by Qt Multimedia." ), i18n( "Unsupported filetype" ) );
soundSelect_->setUrl( QUrl::fromLocalFile( contact_->getExtension()->getContactSoundPath() ) );
return false;
}
#include "contactpropertiesdialog.moc"
+10 -8
View File
@@ -20,8 +20,10 @@
#include "ui_contactpropertiesdialog.h"
#include <KDialog>
#include <Phonon/MediaObject>
#include <QMediaPlayer>
#include <QUrl>
#include "../utils/kmessdialog.h"
class Contact;
@@ -34,7 +36,7 @@ class Contact;
* @author Michael Curtis
* @ingroup Dialogs
*/
class ContactPropertiesDialog : public KDialog, private Ui::ContactProperties
class ContactPropertiesDialog : public KMessDialog, private Ui::ContactProperties
{
Q_OBJECT
@@ -56,7 +58,7 @@ class ContactPropertiesDialog : public KDialog, private Ui::ContactProperties
bool launch( Contact *contact, DefaultTab defaultTab = Information );
protected:
bool eventFilter(QObject *obj, QEvent *event);
bool eventFilter(QObject *obj, QEvent *event) override;
private: // Private methods
void applyChanges();
@@ -72,7 +74,7 @@ class ContactPropertiesDialog : public KDialog, private Ui::ContactProperties
// Restore the original contact picture
void restoreContactPicture();
// The Ok or Cancel button has been pressed
void slotButtonClicked( int button );
void slotButtonClicked( int button ) override;
// The "Clear cache" button has been pressed
void slotClearCache();
// The user has selected or deselected something in the emoticon blacklist
@@ -87,8 +89,8 @@ class ContactPropertiesDialog : public KDialog, private Ui::ContactProperties
void slotSoundFinished();
// Use the selected picture as personal image
void slotUsePicture();
// Check if the fileformat is supported by Phonon
bool checkNotificationSoundFile( const KUrl &url );
// Check if the fileformat is supported by Qt Multimedia
bool checkNotificationSoundFile( const QUrl &url );
private: // Private attributes
// Alternative picture path
@@ -98,7 +100,7 @@ class ContactPropertiesDialog : public KDialog, private Ui::ContactProperties
// Whether or not OK was pressed.
bool ok_;
// Sound media object
Phonon::MediaObject *mediaSound_;
QMediaPlayer *mediaSound_;
signals:
void addContactToGroup ( QString contact, QString id );
+1 -1
View File
@@ -496,7 +496,7 @@
<customwidget>
<class>KUrlRequester</class>
<extends>QFrame</extends>
<header>kurlrequester.h</header>
<header>KUrlRequester</header>
</customwidget>
</customwidgets>
<resources/>
+10 -10
View File
@@ -24,11 +24,15 @@
#include "../model/contactlist.h"
#include "../utils/kmessconfig.h"
#include <QIcon>
#include <KIconLoader>
#include <KLocalizedString>
// Constructor
InviteDialog::InviteDialog( const QStringList &usersAlreadyInChat, QStringList &usersToInvite, QWidget *parent )
: KDialog( parent )
: KMessDialog( parent )
, Ui::InviteDialog()
{
// Set up the interface and the dialog
@@ -49,13 +53,13 @@ InviteDialog::InviteDialog( const QStringList &usersAlreadyInChat, QStringList &
invitedLayout_->addStretch();
// Set buttons
addButton_ ->setIcon( KIcon( "go-next" ) );
removeButton_->setIcon( KIcon( "go-previous" ) );
addButton_ ->setIcon( QIcon::fromTheme( "go-next" ) );
removeButton_->setIcon( QIcon::fromTheme( "go-previous" ) );
connect( addButton_, SIGNAL( clicked() ), this, SLOT( addContact() ) );
connect( removeButton_, SIGNAL( clicked() ), this, SLOT( removeContact() ) );
// Set the other contact button
otherButton_->setIcon( KIcon( "contact-new" ) );
otherButton_->setIcon( QIcon::fromTheme( "contact-new" ) );
connect( otherButton_, SIGNAL( clicked() ), this, SLOT( addOtherContactEntry() ) );
connect( otherEdit_, SIGNAL( returnPressed() ), this, SLOT( addOtherContactEntry() ) );
@@ -132,10 +136,9 @@ void InviteDialog::addOtherContactEntry()
const QString handle( otherEdit_->text() );
otherEdit_->setText( "" );
// Check if the handle is empty or if the users to invite list contains already it
// or if account isn't valid email
// Check if the handle is empty or already invited, or if it is not a valid handle.
if( handle.isEmpty() || usersToInvite_.contains( handle )
|| ! Account::isValidEmail( handle ) )
|| ! Account::isValidHandle( handle ) )
{
return;
}
@@ -273,6 +276,3 @@ void InviteDialog::updateInterface( const QStringList &usersAlreadyInChat, bool
}
}
}
#include "invitedialog.moc"
+3 -1
View File
@@ -20,11 +20,13 @@
#include "ui_invitedialog.h"
#include "../utils/kmessdialog.h"
class ContactEntry;
class InviteDialog : public KDialog, private Ui::InviteDialog
class InviteDialog : public KMessDialog, private Ui::InviteDialog
{
Q_OBJECT
+9 -6
View File
@@ -26,7 +26,8 @@
#include <QFileDialog>
#include <KMessageBox>
#include <KIcon>
#include <QIcon>
#include <KLocalizedString>
ListExportDialog::ListExportDialog( QWidget *parent )
@@ -41,8 +42,8 @@ ListExportDialog::ListExportDialog( QWidget *parent )
connect( selectAllButton_, SIGNAL( clicked() ), this, SLOT( slotSelectAll() ) );
connect( deselectAllButton_, SIGNAL( clicked() ), this, SLOT( slotDeselectAll() ) );
exportButton_->setIcon( KIcon( "document-export" ) );
closeButton_ ->setIcon( KIcon( "dialog-close" ) );
exportButton_->setIcon( QIcon::fromTheme( "document-export" ) );
closeButton_ ->setIcon( QIcon::fromTheme( "dialog-close" ) );
setupWidgets();
}
@@ -155,7 +156,11 @@ void ListExportDialog::slotExport()
QFile file( fileName );
if( file.exists() )
{
if( KMessageBox::questionYesNo( this, i18n( "The file %1 already exists, do you want to overwrite?", fileName ), i18n( "File exists" ) ) == KMessageBox::No )
if( KMessageBox::questionTwoActions( this,
i18n( "The file %1 already exists, do you want to overwrite?", fileName ),
i18n( "File exists" ),
KGuiItem( i18n( "Yes" ) ),
KGuiItem( i18n( "No" ) ) ) == KMessageBox::SecondaryAction )
{
return;
}
@@ -301,5 +306,3 @@ void ListExportDialog::slotSelectAll()
{
selectAll();
}
#include "listexportdialog.moc"
+28 -33
View File
@@ -28,16 +28,14 @@
#include <QRegExp>
#include <QSize>
#include <QDateTime>
#include <QTabWidget>
#include <QTextCodec>
#include <QTextStream>
#include <kdeversion.h>
#include <KFileDialog>
#include <KLocale>
#include <QFileDialog>
#include <KLocalizedString>
#include <KMessageBox>
#include <KTabWidget>
#include <KTextBrowser>
#include <kdeversion.h>
// Declare the instance
@@ -99,7 +97,7 @@ void _kmessNetSent(QObject *connection, const QByteArray &message)
// Constructor
NetworkWindow::NetworkWindow( QWidget *parent )
: KDialog( parent, Qt::Dialog ) // Explicitly set the window type to disable the destructive close behavior
: KMessDialog( parent, Qt::Dialog ) // Explicitly set the window type to disable the destructive close behavior
, Ui::NetworkWindow()
{
// Set up the dialog and its buttons
@@ -114,13 +112,12 @@ NetworkWindow::NetworkWindow( QWidget *parent )
setupUi( mainWidget );
setMainWidget( mainWidget );
// Set up the behavior of the Tab Widget
#if KDE_IS_VERSION(4,1,0)
connectionTabs_->setCloseButtonEnabled( true );
#else
connectionTabs_->setHoverCloseButton( true );
#endif
connect( connectionTabs_, SIGNAL( closeRequest(QWidget*) ), this, SLOT( closeTab(QWidget*) ) );
// Set up the behavior of the tab widget
connectionTabs_->setTabsClosable( true );
connect( connectionTabs_, &QTabWidget::tabCloseRequested, this, [this]( int index )
{
closeTab( connectionTabs_->widget( index ) );
} );
connect( connectionTabs_, SIGNAL( currentChanged(int) ), this, SLOT( slotUpdateWidgets(int) ) );
// Set up the behavior of the Send button
@@ -130,9 +127,9 @@ NetworkWindow::NetworkWindow( QWidget *parent )
setButtonText( User1, i18n("S&ave Tab") );
setButtonText( User2, i18n("C&lear Tab") );
setButtonText( User3, i18n("C&lose All Tabs") );
setButtonIcon( User1, KIcon("document-save") );
setButtonIcon( User2, KIcon("edit-clear-list") );
setButtonIcon( User3, KIcon("edit-clear") );
setButtonIcon( User1, QIcon::fromTheme( "document-save" ) );
setButtonIcon( User2, QIcon::fromTheme( "edit-clear-list" ) );
setButtonIcon( User3, QIcon::fromTheme( "edit-clear" ) );
connect( this, SIGNAL( user1Clicked() ), this, SLOT( saveCurrentTab() ) );
connect( this, SIGNAL( user2Clicked() ), this, SLOT( clearCurrentTab() ) );
connect( this, SIGNAL( user3Clicked() ), this, SLOT( closeAllTabs() ) );
@@ -376,8 +373,8 @@ NetworkWindow::~NetworkWindow()
}
// Default
// return QString::null;
return formatDescription( QString::null ); // always add time.
// return QString();
return formatDescription( QString() ); // always add time.
}
@@ -399,8 +396,8 @@ NetworkWindow::~NetworkWindow()
}
else
{
// return QString::null;
return formatDescription( QString::null ); // always add time.
// return QString();
return formatDescription( QString() ); // always add time.
}
}
@@ -858,7 +855,7 @@ NetworkWindow::~NetworkWindow()
// Convert to HTML.
// Remove last <br> because KTextBrowser::append() already adds it.
logMessage = formatString( utf8Message );
logMessage = logMessage.replace(QRegExp("<br>$"), QString::null);
logMessage = logMessage.replace(QRegExp("<br>$"), QString());
if( entry->type == TYPE_FTP
|| entry->type == TYPE_NS
@@ -988,7 +985,8 @@ NetworkWindow::~NetworkWindow()
&& message[ p2pDataStart ] == '\x80' )
{
// Webcam invitation
QString camMessage( QString::fromUtf16( reinterpret_cast<const ushort *>( dataPtr + 10 ), ( safeSize - 10 - 1 ) / 2 ) );
QString camMessage( QString::fromUtf16( reinterpret_cast<const char16_t *>( dataPtr + 10 ),
( safeSize - 10 - 1 ) / int( sizeof( char16_t ) ) ) );
logMessage += "\n<br>" + formatRawData( incoming, message, p2pDataStart, 10, 1 ) // 1 per col.
+ "\n<br>" + formatString( camMessage )
@@ -1091,7 +1089,7 @@ NetworkWindow::~NetworkWindow()
connectionViews_.insert( connection, entry );
// Add new tab
connectionTabs_->addTab( entry->logView, KIcon( "edit-select-all" ), connection->objectName() );
connectionTabs_->addTab( entry->logView, QIcon::fromTheme( "edit-select-all" ), connection->objectName() );
// Enable the Close All Tabs button
enableButton( User3, ( connectionViews_.count() > 1 ) );
@@ -1141,7 +1139,7 @@ NetworkWindow::~NetworkWindow()
return;
}
KDialog::show();
KMessDialog::show();
}
@@ -1155,7 +1153,7 @@ NetworkWindow::~NetworkWindow()
QString path;
QString name( connectionTabs_->tabText( connectionTabs_->currentIndex() ) );
path = KFileDialog::getSaveFileName( KUrl(), "*.html" );
path = QFileDialog::getSaveFileName( this, QString(), QString(), "*.html" );
if( path.isEmpty() )
return;
@@ -1181,7 +1179,7 @@ NetworkWindow::~NetworkWindow()
if( failed || ! file.exists() )
{
KMessageBox::sorry( this, i18n("Could not save the Network Window log. Make sure you have permission to write in the folder where it is being saved.") );
KMessageBox::error( this, i18n("Could not save the Network Window log. Make sure you have permission to write in the folder where it is being saved.") );
}
}
@@ -1353,16 +1351,16 @@ NetworkWindow::~NetworkWindow()
else if( ! payload.endsWith( "\r\n" ) )
{
// Warn the developer that the payloads must end with a newline
int result = KMessageBox::warningYesNo( this,
int result = KMessageBox::warningTwoActions( this,
i18n( "The payload you are trying to send does not end with the "
"required newline ('\\r\\n')!<br />"
"Do you want KMess to add it for you?" ),
i18n( "Network Window" ),
KStandardGuiItem::yes(),
KStandardGuiItem::no(),
KGuiItem( i18n( "Yes" ) ),
KGuiItem( i18n( "No" ) ),
"noPayloadWarning" );
// Append the missing newline to the payload
if( result == KMessageBox::Yes )
if( result == KMessageBox::PrimaryAction )
{
payload.append( "\r\n" );
}
@@ -1434,6 +1432,3 @@ NetworkWindow::~NetworkWindow()
return;
}
}
#include "networkwindow.moc"
+2 -4
View File
@@ -26,10 +26,8 @@
#include <QDateTime>
#include <QHash>
#include <KDialog>
#include "../utils/kmessdialog.h"
// Forward declarations
class KTabWidget;
class KTextBrowser;
@@ -41,7 +39,7 @@ class KTextBrowser;
* @author Diederik van der Boor
* @ingroup Dialogs
*/
class NetworkWindow : public KDialog, private Ui::NetworkWindow
class NetworkWindow : public KMessDialog, private Ui::NetworkWindow
{
Q_OBJECT
+1 -18
View File
@@ -162,7 +162,7 @@
</widget>
</item>
<item>
<widget class="KTabWidget" name="connectionTabs_" >
<widget class="QTabWidget" name="connectionTabs_" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
<horstretch>0</horstretch>
@@ -172,27 +172,10 @@
<property name="elideMode" >
<enum>Qt::ElideRight</enum>
</property>
<property name="tabReorderingEnabled" >
<bool>true</bool>
</property>
<property name="tabCloseActivatePrevious" >
<bool>true</bool>
</property>
<property name="automaticResizeTabs" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KTabWidget</class>
<extends>QTabWidget</extends>
<header>ktabwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+14 -12
View File
@@ -19,13 +19,17 @@
#include "../kmessdebug.h"
#include <QDir>
#include <QPixmap>
#include <QTime>
#include <QTimer>
#include <KLocale>
#include <KRun>
#include <KLocalizedString>
#include <KIconLoader>
#include <KMimeType>
#include <KUrl>
#include <QUrl>
#include <QDesktopServices>
#include <QMimeDatabase>
@@ -59,7 +63,7 @@ TransferEntry::TransferEntry( QWidget *parent, const QString filename, const ulo
if( preview_.isNull() )
{
// Get a default icon pixmap
QString iconTitle( KMimeType::iconNameForUrl( KUrl( filename_) ) );
QString iconTitle( QMimeDatabase().mimeTypeForFile( filename_, QMimeDatabase::MatchExtension ).iconName() );
preview_ = loader->loadIcon( iconTitle, KIconLoader::NoGroup, iconLabel_->width() );
if( ! preview_.isNull() )
@@ -175,7 +179,7 @@ void TransferEntry::failTransfer( const QString &message )
#endif
// Update the widgets
if(message == 0 || message.isEmpty())
if( message.isEmpty() )
{
statusLabel_->setText( i18n("Failed!") );
}
@@ -241,11 +245,11 @@ void TransferEntry::openClicked()
// The file:// prefix must be followed by a full path
if( ! filename_.startsWith( "file://" ) )
{
new KRun( "file://" + filename_, window() );
QDesktopServices::openUrl( QUrl::fromLocalFile( filename_ ) );
}
else
{
new KRun( filename_, window() );
QDesktopServices::openUrl( QUrl::fromUserInput( filename_, QDir::currentPath(), QUrl::AssumeLocalFile ) );
}
}
@@ -266,12 +270,12 @@ QString TransferEntry::toReadableBytes( ulong bytes )
if(bytes > 1048576)
{
// Using '%.2f' instead of '%.1f' removes the ".0" part, but it's less pretty.
format.sprintf("%.1f", (double) bytes / 1048576.0);
format = QString::number( (double) bytes / 1048576.0, 'f', 1 );
return i18n( "%1 MB", format );
}
else if(bytes > 1024)
{
format.sprintf("%.1f", (double) bytes / 1024.0);
format = QString::number( (double) bytes / 1024.0, 'f', 1 );
return i18n( "%1 kB", format );
}
else
@@ -390,5 +394,3 @@ void TransferEntry::updateTransferRate()
statusLabel_->setText( statusText_ + " " + speedText_ );
}
#include "transferentry.moc"
+1 -1
View File
@@ -53,7 +53,7 @@ public:
public slots:
// Mark the transfer as failed
void failTransfer( const QString &message = QString::null );
void failTransfer( const QString &message = QString() );
// Mark the transfer as complete
void finishTransfer();
// Set a status message

Some files were not shown because too many files have changed in this diff Show More