diff --git a/CMakeLists.txt b/CMakeLists.txt index 56c4761..90ef1fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,272 +1,99 @@ -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 +include(KDEInstallDirs) +include(KDECMakeSettings) +include(KDECompilerSettings NO_POLICY_SCOPE) -# Check for cmake, same as minimum for KDE 4.0.0 -CMAKE_MINIMUM_REQUIRED( VERSION 2.4.5 ) +set(QT_DEFAULT_MAJOR_VERSION 6) +find_package(Qt6 REQUIRED COMPONENTS Core Core5Compat DBus Gui Multimedia Network Test WebEngineWidgets Widgets Xml) +find_package(KF6 REQUIRED COMPONENTS + Codecs + Completion + Config + ConfigWidgets + CoreAddons + Crash + IdleTime + I18n + IconThemes + KIO + Notifications + NotifyConfig + Parts + Service + Solid + StatusNotifierItem + TextWidgets + WidgetsAddons + WindowSystem + Wallet + XmlGui +) -# Check for KDE 4 -FIND_PACKAGE( KDE4 REQUIRED ) -INCLUDE( KDE4Defaults ) +find_package(LibXml2 REQUIRED) +find_package(LibXslt REQUIRED) +find_package(GCrypt REQUIRED) -# 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. +set(ISFQT_IS_BUNDLED TRUE) +set(USE_BUNDLED_LIBRARIES ISFQT) +set(WANT_GIF OFF CACHE BOOL "Disable ISF fortified GIF while porting to Qt6" FORCE) +add_subdirectory(contrib/isf-qt) - 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 ) +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 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" ) +set(KMESS_VERSION "6.0_alpha1") +set(KMESS_ENABLE_DEBUG_OUTPUT 0) +set(KMESS_BUILT_DEBUGFULL FALSE) +set(HAVE_LIBISFQT 1) +set(HAVE_NEW_TRAY 1) -# 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(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) -# 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 ) +add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050F00 -DQT_NO_URL_CAST_FROM_STRING) -# 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() +# 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 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 ) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/config-kmess.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config-kmess.h) -# 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" ) +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${LIBXML2_INCLUDE_DIR} + ${LIBXSLT_INCLUDE_DIR} + ${GCRYPT_INCLUDE_DIRS} +) -# 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 - -# 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) diff --git a/contrib/isf-qt/CMakeLists.txt b/contrib/isf-qt/CMakeLists.txt index 9a5a230..b677461 100644 --- a/contrib/isf-qt/CMakeLists.txt +++ b/contrib/isf-qt/CMakeLists.txt @@ -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() - diff --git a/contrib/isf-qt/include/QMatrix b/contrib/isf-qt/include/QMatrix new file mode 100644 index 0000000..4d21dd6 --- /dev/null +++ b/contrib/isf-qt/include/QMatrix @@ -0,0 +1,8 @@ +#ifndef ISFQT_QMATRIX_COMPAT_H +#define ISFQT_QMATRIX_COMPAT_H + +#include + +using QMatrix = QTransform; + +#endif diff --git a/contrib/isf-qt/src/CMakeLists.txt b/contrib/isf-qt/src/CMakeLists.txt index eed2b4e..21fc918 100644 --- a/contrib/isf-qt/src/CMakeLists.txt +++ b/contrib/isf-qt/src/CMakeLists.txt @@ -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 ) diff --git a/contrib/isf-qt/src/isfqt-internal.h b/contrib/isf-qt/src/isfqt-internal.h index 95eb5ba..1aad098 100644 --- a/contrib/isf-qt/src/isfqt-internal.h +++ b/contrib/isf-qt/src/isfqt-internal.h @@ -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 diff --git a/contrib/isf-qt/src/isfqt.cpp b/contrib/isf-qt/src/isfqt.cpp index f7777f2..8b5a974 100644 --- a/contrib/isf-qt/src/isfqt.cpp +++ b/contrib/isf-qt/src/isfqt.cpp @@ -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() ) { @@ -705,4 +705,3 @@ QByteArray Stream::writerPng( const Drawing& drawing, bool encodeToBase64 ) } } - diff --git a/contrib/isf-qt/src/isfqtdrawing.cpp b/contrib/isf-qt/src/isfqtdrawing.cpp index b91ecc2..444e148 100644 --- a/contrib/isf-qt/src/isfqtdrawing.cpp +++ b/contrib/isf-qt/src/isfqtdrawing.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -726,4 +727,3 @@ void Drawing::updateBoundingRect() #endif } - diff --git a/contrib/isf-qt/src/tagsparser.cpp b/contrib/isf-qt/src/tagsparser.cpp index 290200a..c570084 100644 --- a/contrib/isf-qt/src/tagsparser.cpp +++ b/contrib/isf-qt/src/tagsparser.cpp @@ -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( 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 - " @@ -1612,4 +1612,3 @@ QByteArray TagsParser::analyzePayload( StreamData* streamData, const quint64 pay return result; } - diff --git a/data/icons/CMakeLists.txt b/data/icons/CMakeLists.txt index 0b2cbf6..d6ef8ab 100644 --- a/data/icons/CMakeLists.txt +++ b/data/icons/CMakeLists.txt @@ -1,6 +1,4 @@ -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 diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index a53ca07..160531e 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -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. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3ee7403..0773ec5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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,28 +232,13 @@ 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} ) diff --git a/src/account.cpp b/src/account.cpp index 7405f2a..e68ab76 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -19,17 +19,17 @@ #include "contact/msnobject.h" #include "utils/kmessconfig.h" +#include "utils/kmessshared.h" #include "accountsmanager.h" #include "kmessdebug.h" #include #include +#include #include -#include -#include -#include +#include #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."; diff --git a/src/account.h b/src/account.h index c0c0ea6..a4010a4 100644 --- a/src/account.h +++ b/src/account.h @@ -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) diff --git a/src/accountaction.cpp b/src/accountaction.cpp index 74df846..228fbfa 100644 --- a/src/accountaction.cpp +++ b/src/accountaction.cpp @@ -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. diff --git a/src/accountaction.h b/src/accountaction.h index 53bc591..7f9eeea 100644 --- a/src/accountaction.h +++ b/src/accountaction.h @@ -18,7 +18,8 @@ #ifndef ACCOUNTACTION_H #define ACCOUNTACTION_H -#include +#include +#include // 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 diff --git a/src/accountsmanager.cpp b/src/accountsmanager.cpp index 50aae18..09f65bc 100644 --- a/src/accountsmanager.cpp +++ b/src/accountsmanager.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include @@ -177,7 +177,7 @@ void AccountsManager::deleteAccount( Account *account ) emit accountDeleted( account ); QString handle( account->getHandle() ); - KMessApplication *kmessApp = static_cast( kapp ); + KMessApplication *kmessApp = static_cast(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( kapp ); + KMessApplication *kmessApp = static_cast(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( "Some insecurely stored account passwords have been found.
" "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( kapp )->getContactListWindow(); + KMess *kmess = static_cast(QApplication::instance())->getContactListWindow(); bool isCurrentAccount = ( account->getHandle() == currentAccount->getHandle() ); bool isConnectedCurrentAccount = isCurrentAccount && ( kmess->isConnected() ); diff --git a/src/accountsmanager.h b/src/accountsmanager.h index 6239a0c..9be88f4 100644 --- a/src/accountsmanager.h +++ b/src/accountsmanager.h @@ -22,7 +22,7 @@ #include -#include +#include // Forward declarations class Account; diff --git a/src/chat/chat.cpp b/src/chat/chat.cpp index 4441146..c970a6d 100644 --- a/src/chat/chat.cpp +++ b/src/chat/chat.cpp @@ -35,11 +35,13 @@ #include "contactswidget.h" #include +#include #include #include +#include -#include -#include +#include +#include #include @@ -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 it( typingContactsTimes_ ); + QMutableHashIterator 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( kapp ); + KMessApplication *kmessApp = static_cast(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( "KMess could not save the log for the chat with "%1":
" "The chat logs directory, "%2", does not exist.", 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 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 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 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 fileList ) false, i18n( "The file "%1" 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 diff --git a/src/chat/chat.h b/src/chat/chat.h index 89ed9dd..c7b0895 100644 --- a/src/chat/chat.h +++ b/src/chat/chat.h @@ -23,8 +23,10 @@ #include "../network/msnswitchboardconnection.h" #include +#include #include #include +#include // 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 @@ -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 typingContactsNames_; // The list of times when the contacts have started typing - QHash typingContactsTimes_; + QHash typingContactsTimes_; // A timer to update the typing information QTimer typingTimer_; // Handle a command from ChatView (e.g. '/online') diff --git a/src/chat/chathistorymanager.cpp b/src/chat/chathistorymanager.cpp index edca1e0..3401cb2 100644 --- a/src/chat/chathistorymanager.cpp +++ b/src/chat/chathistorymanager.cpp @@ -26,10 +26,10 @@ #include #include +#include #include -#include -#include +#include #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 "
\n" - "" + KGlobal::locale()->formatDate( date.date(), KLocale::ShortDate ) + "\n" - "\n" + "" + QLocale().toString( date.date(), QLocale::ShortFormat ) + "\n" + "\n" "
\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_; } - - diff --git a/src/chat/chathistorywriter.cpp b/src/chat/chathistorywriter.cpp index 92b7bf1..e6ce412 100644 --- a/src/chat/chathistorywriter.cpp +++ b/src/chat/chathistorywriter.cpp @@ -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 #include -#include - -#ifdef Q_WS_X11 -# include -#endif +#include +#include +#include // 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( kapp ); + KMessApplication *kmessApp = static_cast(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, "", + "base64," + QString::fromLatin1( inkEncodedData ).toHtmlEscaped() + "\">", contactHandle, friendlyName, contactPicture ), switchboard ); diff --git a/src/chat/chatmessagestyle.cpp b/src/chat/chatmessagestyle.cpp index 89df68b..d934d73 100644 --- a/src/chat/chatmessagestyle.cpp +++ b/src/chat/chatmessagestyle.cpp @@ -28,12 +28,14 @@ #include #include #include +#include #include +#include #include -#include -#include -#include +#include +#include +#include // 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 &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(); } @@ -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) @@ -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 = "" 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", "
" ) .replace( '\r', "
" ) .replace( '\n', "
" ); @@ -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 parameters; parameters["basepath"] = baseFolder_; @@ -1070,8 +1075,9 @@ QString ChatMessageStyle::stripDoctype( const QString &parsedMessage ) { if( parsedMessage.startsWith( "\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,7 +1085,7 @@ 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 { @@ -1090,4 +1096,3 @@ QString ChatMessageStyle::stripDoctype( const QString &parsedMessage ) #include "chatmessagestyle.moc" - diff --git a/src/chat/chatmessageview.cpp b/src/chat/chatmessageview.cpp index 5cb9532..1f72c64 100644 --- a/src/chat/chatmessageview.cpp +++ b/src/chat/chatmessageview.cpp @@ -27,53 +27,73 @@ #include #include #include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include - -#include -#include +#include +#include +#include +#include #include -#include +#include +#include + +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
\n" + + chatStyle_->convertXmlMessageList( xmlString ) + + "\n
\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
\n" + + text + + "\n
\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
Started on: %2", handle, - KGlobal::locale()->formatDateTime( QDateTime::fromTime_t( date ), KLocale::ShortDate ) ) + QLocale().toString( QDateTime::fromSecsSinceEpoch( date ), QLocale::ShortFormat ) ) + "\n\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 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 = " \n"; - } - if( ! baseFolder.isEmpty() ) - { - baseFolder = " \n"; - } - - begin(); - - // Force standard colors, because chat messages will not work - // correctly with the (dark) color scheme anyway. - write( "\n" - " \n" - " \n" - " \n" - + baseFolder + - " \n" - + cssFile + - " \n" - " \n" - "
\n" - + newHtmlBody + - "
\n" - " \n" - "\n" ); - end(); - - return; + cssFile = " \n"; + } + if( ! baseFolder.isEmpty() ) + { + baseFolder = " \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( "", 0, Qt::CaseInsensitive ); + if( insertPos != -1 ) { - kmWarning() << "Chat style does not define the 'messageRoot' element!"; - messageRoot = htmlDocument().body(); + page.insert( insertPos, " \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 "\n" + " \n" + " \n" + " \n" + + baseFolder + + " \n" + + cssFile + + " \n" + " \n" + "
\n" + + body + + "
\n" + " \n" + "\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( "", markerPos ); + if( spanStart == -1 || spanEnd == -1 ) + { + return; + } - // Replace the links with the given text - linksSpan.setInnerText( DOM::DOMString( newMessage ) ); + QString replacement = ""; + replacement += newMessage.toHtmlEscaped(); + replacement += ""; + 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 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 diff --git a/src/chat/chatmessageview.h b/src/chat/chatmessageview.h index b83a50e..6a5787e 100644 --- a/src/chat/chatmessageview.h +++ b/src/chat/chatmessageview.h @@ -20,25 +20,23 @@ #include "account.h" -#include -#include -#include +#include +#include +#include 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 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 - diff --git a/src/chat/chatstatusbar.cpp b/src/chat/chatstatusbar.cpp index 286d673..700375c 100644 --- a/src/chat/chatstatusbar.cpp +++ b/src/chat/chatstatusbar.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -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(); } diff --git a/src/chat/chatview.cpp b/src/chat/chatview.cpp index fe196c8..37e48ea 100644 --- a/src/chat/chatview.cpp +++ b/src/chat/chatview.cpp @@ -34,19 +34,22 @@ #include #include #include +#include #include #include #include #include +#include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include -#include +#include #include @@ -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( kapp ); + KMessApplication *kmessApp = static_cast(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 { @@ -1084,4 +1089,3 @@ void ChatView::updateCustomEmoticon( const QString &handle, const QString &code #include "chatview.moc" - diff --git a/src/chat/chatview.h b/src/chat/chatview.h index 52e0e34..f586a41 100644 --- a/src/chat/chatview.h +++ b/src/chat/chatview.h @@ -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 diff --git a/src/chat/chatwindow.cpp b/src/chat/chatwindow.cpp index fe93ea0..059dfb1 100644 --- a/src/chat/chatwindow.cpp +++ b/src/chat/chatwindow.cpp @@ -44,26 +44,35 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include #include -#include -#include +#include #include -#include #include -#include #include -#include -#include +#include +#include +#include #include #include -#include -#include +#include +#include #include -#include -#include +#include #include +#include +#include +#include #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() ) ); @@ -193,20 +202,15 @@ ChatWindow::ChatWindow( QWidget *parent ) 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 +300,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 +376,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(QApplication::instance())->sessionSaving() ) // Do not ask if the KDE session is closing { - int res = KMessageBox::questionYesNoCancel( this, + int res = KMessageBox::questionTwoActionsCancel( this, i18n( "There are multiple tabs open in this chat window. " "Do you want to close the current tab only, or all tabs?

" "Note: You can close all tabs at once by pressing Alt+F4." ), @@ -386,8 +390,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 +455,41 @@ void ChatWindow::closeWidgetOrTab() // Create the menus. void ChatWindow::createMenus() { - KAction *closeAction, *saveAction, *quitAction; - KAction *copy, *findAction, *zoomIn, *zoomOut, *clearChatAction; + QAction *closeAction, *saveAction, *quitAction; + QAction *copy, *findAction, *zoomIn, *zoomOut, *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_ ); + quitAction = 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_ ); pasteAction_ = KStandardAction::paste ( messageEdit_, SLOT( paste() ), actionCollection_ ); findAction = 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 ); + 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 ); zoomIn = KStandardAction::zoomIn ( this, SLOT( viewZoomIn() ), actionCollection_ ); zoomOut = 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 @@ -510,19 +514,19 @@ void ChatWindow::createMenus() 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") ); @@ -647,9 +651,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 +673,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 +751,19 @@ bool ChatWindow::eventFilter( QObject *obj, QEvent *event ) return false; } + if( obj == chatTabs_->tabBar() && event->type() == QEvent::MouseButtonRelease ) + { + QMouseEvent *mouseEvent = static_cast( 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( event ); @@ -986,7 +1004,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 +1150,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 +1162,7 @@ bool ChatWindow::handleCommand( QString command ) command = command.toLower(); // Get us a kmess handle to call setStatus upon - KMessApplication *kmessApp = static_cast( kapp ); + KMessApplication *kmessApp = static_cast(QApplication::instance()); KMess *kmess = kmessApp->getContactListWindow(); bool isStatusCommand = ( command == "status" ); @@ -1152,7 +1170,7 @@ bool ChatWindow::handleCommand( QString command ) // Check syntax errors if( isStatusCommand && arguments.isEmpty() ) { - KMessageBox::sorry( this, + KMessageBox::error( this, i18n( "You used an incorrect syntax for the /status command. The correct syntax " "is: /status online|away|idle|brb|busy|lunch|phone|invisible.
" "You can also use shortcuts like /online or /phone." ), @@ -1218,7 +1236,7 @@ bool ChatWindow::handleCommand( QString command ) { if( participants.count() != 1 ) { - KMessageBox::sorry( this, + KMessageBox::error( this, i18n( "You cannot use the /block command in a group chat." ), i18nc( "Caption when trying to block someone in a group chat", "Cannot use /block command" ) @@ -1231,7 +1249,7 @@ bool ChatWindow::handleCommand( QString command ) { if( participants.count() != 1 ) { - KMessageBox::sorry( this, + KMessageBox::error( this, i18n( "You cannot use the /unblock command in a group chat." ), i18nc( "Caption when trying to unblock someone in a group chat", "Cannot use /unblock command!" ) @@ -1263,7 +1281,7 @@ bool ChatWindow::handleCommand( QString command ) return false; } - KMessageBox::sorry( this, + KMessageBox::error( this, i18n( "Unknown command %1. If you did not want this " "message to be a command, prepend your message with another" " /.", command ), @@ -1296,12 +1314,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(); @@ -1454,7 +1468,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 ); @@ -1506,7 +1520,7 @@ void ChatWindow::saveProperties( KConfigGroup &config ) group.writeEntry( "CurrentZoom", zoomLevel_ ); // Save window size - saveWindowSize( group ); + group.writeEntry( "WindowGeometry", saveGeometry() ); group.config()->sync(); } @@ -1686,7 +1700,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 ); @@ -1745,11 +1759,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 +1906,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", "Are you sure you want to hide the menu bar? " "You will be able to show it again by using this " "keyboard shortcut: %1", - 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 +1983,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 +1998,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 +2059,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 +2087,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 +2108,7 @@ void ChatWindow::slotGotNudge() // Shake the window. for ( int i = 16; i > 0; ) { - kapp->processEvents(); + QApplication::processEvents(); if ( t.elapsed() >= 50 ) { @@ -2142,7 +2157,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 +2169,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 +2286,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 +2337,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 +2359,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 +2603,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 +2640,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 +2786,7 @@ void ChatWindow::slotUpdateChatInfo( Chat *chat ) "
Connected with account:
%3
" "", participants.join( "
  • " ), - chat->getStartTime().toString( Qt::DefaultLocaleLongDate ), + QLocale().toString( chat->getStartTime(), QLocale::LongFormat ), currentAccount_->getHandle() ) ); chatTabs_->setTabToolTip( index, toolTip ); diff --git a/src/chat/chatwindow.h b/src/chat/chatwindow.h index 01134c7..41da141 100644 --- a/src/chat/chatwindow.h +++ b/src/chat/chatwindow.h @@ -22,9 +22,10 @@ #include "chatstatusbar.h" #include +#include #include -#include +#include #include #include #include @@ -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; @@ -219,7 +219,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 +227,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 +239,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 +253,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 diff --git a/src/chat/chatwindow.ui b/src/chat/chatwindow.ui index e5af393..bd60a9c 100644 --- a/src/chat/chatwindow.ui +++ b/src/chat/chatwindow.ui @@ -28,7 +28,7 @@ false - + 0 @@ -53,12 +53,6 @@ true - - true - - - true - @@ -503,16 +497,10 @@ qPixmapFromMimeSource - - KTabWidget - QTabWidget -
    ktabwidget.h
    - 1 -
    KTextEdit QTextEdit -
    ktextedit.h
    +
    KTextEdit
    Isf::InkCanvas diff --git a/src/chat/contactframe.cpp b/src/chat/contactframe.cpp index 5cc0c07..3992d2d 100644 --- a/src/chat/contactframe.cpp +++ b/src/chat/contactframe.cpp @@ -37,14 +37,18 @@ #include #include +#include #include -#include +#include +#include #include +#include #include #include -#include -#include +#include +#include +#include // 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( const_cast( sender() ) ); + QAction *action = static_cast( const_cast( 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() ); } } @@ -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( kapp )->getContactListWindow(); + KMess *kmess = static_cast(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() ) diff --git a/src/chat/contactframe.h b/src/chat/contactframe.h index 2263b56..0c8b258 100644 --- a/src/chat/contactframe.h +++ b/src/chat/contactframe.h @@ -29,9 +29,9 @@ class Contact; class ContactBase; class ContactPropertiesDialog; class CurrentAccount; -class KAction; +class QAction; class KActionMenu; -class KMenu; +class QMenu; @@ -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 copyLinkActionsList_; + QList 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_; diff --git a/src/chat/contactswidget.cpp b/src/chat/contactswidget.cpp index a8c72ff..61f77a2 100644 --- a/src/chat/contactswidget.cpp +++ b/src/chat/contactswidget.cpp @@ -26,12 +26,15 @@ #include "../utils/kmessconfig.h" #include -#include #include +#include +#include +#include #include -#include +#include #include +#include // 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"; diff --git a/src/chat/emoticonswidget.cpp b/src/chat/emoticonswidget.cpp index 8837b32..e4bf7e9 100644 --- a/src/chat/emoticonswidget.cpp +++ b/src/chat/emoticonswidget.cpp @@ -32,6 +32,9 @@ #include #include +#include +#include + // The constructor @@ -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 ); diff --git a/src/chat/winkswidget.cpp b/src/chat/winkswidget.cpp index e8cfa84..78a63dc 100644 --- a/src/chat/winkswidget.cpp +++ b/src/chat/winkswidget.cpp @@ -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 #include #include +#include #include -#include +#include #include #include -#include 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; } @@ -274,8 +275,8 @@ WinksWidget::CABEXTRACTOR WinksWidget::getHtmlFromWink( const QString &filename, } // Escape data for inclusion in HTML. - animation = Qt::escape(animation).replace("\"", """); // quotes are not escaped by QStyleSheet::escape(). - animationType = animationType.remove( QRegExp("[^a-zA-Z0-9\\-/]") ); + animation = animation.toHtmlEscaped().replace("\"", """ ); + animationType = animationType.remove( QRegularExpression( "[^a-zA-Z0-9\\-/]" ) ); const QString filePath( winksDir + "/" + animation ); diff --git a/src/chat/xsltransformation.cpp b/src/chat/xsltransformation.cpp index 1583a00..d82cd25 100644 --- a/src/chat/xsltransformation.cpp +++ b/src/chat/xsltransformation.cpp @@ -30,10 +30,10 @@ #include // After xsltconfig and xsltInternals or it breaks compiling on some libxslt versions. #include -#include +#include -#include -#include +#include +#include /* @@ -83,7 +83,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; @@ -102,7 +102,7 @@ QString XslTransformation::convertXmlString( const QString &xml ) const if( sourceXmlDoc == 0 ) { kmWarning() << "could not parse the XML data."; - return QString::null; + return QString(); } // Apply XSL @@ -119,8 +119,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( 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 +137,7 @@ cleanSource: // when the parsing of user parameters failed. if( result.isEmpty() ) { - return QString::null; + return QString(); } else { @@ -194,8 +194,7 @@ void XslTransformation::setStylesheet(const QString &xslFileName) } // Get file path - KUrl fileUrl(xslFileName); -// QByteArray basePath = fileUrl.directory( KUrl::AppendTrailingSlash ).toUtf8(); + QUrl fileUrl(xslFileName); // Open XSL file QFile file(xslFileName); @@ -250,7 +249,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 { @@ -327,7 +326,7 @@ void XslTransformation::updateXslTranslations( xmlNode *node, const xmlNs *xslNs // fdsfsd // 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 +368,8 @@ void XslTransformation::updateXslTranslations( xmlNode *node, const xmlNs *xslNs // Trim and simplyfy spaces to avoid breaking translations too easily. // Ignore 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 +381,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 +400,3 @@ void XslTransformation::updateXslTranslations( xmlNode *node, const xmlNs *xslNs updateXslTranslations( curNode->children, xslNs, kmessNs ); } } - diff --git a/src/contact/contact.h b/src/contact/contact.h index fa27348..4fe14af 100644 --- a/src/contact/contact.h +++ b/src/contact/contact.h @@ -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 diff --git a/src/contact/contactbase.cpp b/src/contact/contactbase.cpp index be11a4f..b5a5b8f 100644 --- a/src/contact/contactbase.cpp +++ b/src/contact/contactbase.cpp @@ -25,8 +25,7 @@ #include #include -#include -#include +#include @@ -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" ); } diff --git a/src/contact/contactextension.cpp b/src/contact/contactextension.cpp index d13d0db..706215e 100644 --- a/src/contact/contactextension.cpp +++ b/src/contact/contactextension.cpp @@ -21,8 +21,9 @@ #include "../kmessdebug.h" #include +#include -#include +#include #include @@ -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(); } } diff --git a/src/contact/msnobject.cpp b/src/contact/msnobject.cpp index a12c404..03bfca1 100644 --- a/src/contact/msnobject.cpp +++ b/src/contact/msnobject.cpp @@ -98,12 +98,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(); } @@ -311,4 +311,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() ); } - diff --git a/src/contact/msnstatus.cpp b/src/contact/msnstatus.cpp index 0f076a5..9118c2e 100644 --- a/src/contact/msnstatus.cpp +++ b/src/contact/msnstatus.cpp @@ -19,15 +19,16 @@ #include "../kmessdebug.h" -#include +#include +#include #include #include -#include -#include +#include +#include // 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; } } - - diff --git a/src/contact/msnstatus.h b/src/contact/msnstatus.h index 64c63fa..777d593 100644 --- a/src/contact/msnstatus.h +++ b/src/contact/msnstatus.h @@ -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_; }; diff --git a/src/currentaccount.cpp b/src/currentaccount.cpp index 76e8b89..db66260 100644 --- a/src/currentaccount.cpp +++ b/src/currentaccount.cpp @@ -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 { diff --git a/src/currentaccount.h b/src/currentaccount.h index 66870f9..b11669d 100644 --- a/src/currentaccount.h +++ b/src/currentaccount.h @@ -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. diff --git a/src/dialogs/addcontactdialog.cpp b/src/dialogs/addcontactdialog.cpp index c551c57..254293f 100644 --- a/src/dialogs/addcontactdialog.cpp +++ b/src/dialogs/addcontactdialog.cpp @@ -23,6 +23,9 @@ #include "../currentaccount.h" #include "../kmessdebug.h" +#include +#include + /** @@ -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 ); diff --git a/src/dialogs/addcontactdialog.h b/src/dialogs/addcontactdialog.h index e6d5b3f..9354694 100644 --- a/src/dialogs/addcontactdialog.h +++ b/src/dialogs/addcontactdialog.h @@ -20,7 +20,7 @@ #include "ui_addcontactdialog.h" -#include +#include "../utils/kmessdialog.h" @@ -34,7 +34,7 @@ * @author Valerio Pilo * @ingroup Dialogs */ -class AddContactDialog : public KDialog, private Ui::AddContactDialog +class AddContactDialog : public KMessDialog, private Ui::AddContactDialog { Q_OBJECT diff --git a/src/dialogs/addemoticondialog.cpp b/src/dialogs/addemoticondialog.cpp index b9ee797..0803e48 100644 --- a/src/dialogs/addemoticondialog.cpp +++ b/src/dialogs/addemoticondialog.cpp @@ -22,8 +22,9 @@ #include "../emoticonmanager.h" #include "../kmessdebug.h" -#include +#include #include +#include #include @@ -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; } } diff --git a/src/dialogs/addemoticondialog.h b/src/dialogs/addemoticondialog.h index efaea85..a0424cf 100644 --- a/src/dialogs/addemoticondialog.h +++ b/src/dialogs/addemoticondialog.h @@ -20,7 +20,7 @@ #include "ui_addemoticondialog.h" -#include +#include "../utils/kmessdialog.h" #include #include @@ -38,7 +38,7 @@ class EmoticonTheme; * @author Valerio Pilo * @ingroup Dialogs */ -class AddEmoticonDialog : public KDialog, private Ui::AddEmoticonDialog +class AddEmoticonDialog : public KMessDialog, private Ui::AddEmoticonDialog { Q_OBJECT diff --git a/src/dialogs/awaymessagedialog.cpp b/src/dialogs/awaymessagedialog.cpp index a8a57db..7820121 100644 --- a/src/dialogs/awaymessagedialog.cpp +++ b/src/dialogs/awaymessagedialog.cpp @@ -19,11 +19,12 @@ #include "../utils/kmessconfig.h" +#include // The constructor AwayMessageDialog::AwayMessageDialog( QWidget *parent ) -: KDialog( parent ) +: KMessDialog( parent ) , Ui::AwayMessageDialog() { // Set up the interface and the dialog diff --git a/src/dialogs/awaymessagedialog.h b/src/dialogs/awaymessagedialog.h index fe0ccc8..95847a1 100644 --- a/src/dialogs/awaymessagedialog.h +++ b/src/dialogs/awaymessagedialog.h @@ -20,7 +20,7 @@ #include "ui_awaymessagedialog.h" -#include +#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 diff --git a/src/dialogs/chathistorydialog.cpp b/src/dialogs/chathistorydialog.cpp index 91a7501..4d52d4d 100644 --- a/src/dialogs/chathistorydialog.cpp +++ b/src/dialogs/chathistorydialog.cpp @@ -38,13 +38,13 @@ #include #include -#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include #include @@ -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( kapp ); + KMessApplication *kmessApp = static_cast(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,7 +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; } diff --git a/src/dialogs/chathistorydialog.h b/src/dialogs/chathistorydialog.h index acbe126..8ae2f2a 100644 --- a/src/dialogs/chathistorydialog.h +++ b/src/dialogs/chathistorydialog.h @@ -24,7 +24,7 @@ #include #include -#include +#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 diff --git a/src/dialogs/chathistorydialog.ui b/src/dialogs/chathistorydialog.ui index b6edd89..2ca4a06 100644 --- a/src/dialogs/chathistorydialog.ui +++ b/src/dialogs/chathistorydialog.ui @@ -29,10 +29,10 @@ - + Search through contacts... - + true @@ -101,9 +101,6 @@ 22 - - process-working -
    @@ -182,19 +179,19 @@
    - KAnimatedButton - QToolButton -
    kanimatedbutton.h
    + KComboBox + QComboBox +
    KComboBox
    KLineEdit QLineEdit -
    klineedit.h
    +
    KLineEdit
    - KComboBox - QComboBox -
    kcombobox.h
    + KAnimatedButton + QToolButton +
    KAnimatedButton
    diff --git a/src/dialogs/contactaddeduserdialog.cpp b/src/dialogs/contactaddeduserdialog.cpp index 48a3b30..abae77a 100644 --- a/src/dialogs/contactaddeduserdialog.cpp +++ b/src/dialogs/contactaddeduserdialog.cpp @@ -22,12 +22,13 @@ #include "../utils/kmessconfig.h" +#include /** * 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() } } - diff --git a/src/dialogs/contactaddeduserdialog.h b/src/dialogs/contactaddeduserdialog.h index 3dfe922..301f34e 100644 --- a/src/dialogs/contactaddeduserdialog.h +++ b/src/dialogs/contactaddeduserdialog.h @@ -18,7 +18,7 @@ #ifndef CONTACTADDEDUSERDIALOG_H #define CONTACTADDEDUSERDIALOG_H -#include +#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 diff --git a/src/dialogs/contactaddeduserwidget.cpp b/src/dialogs/contactaddeduserwidget.cpp index 98bd6a4..74dd3a0 100644 --- a/src/dialogs/contactaddeduserwidget.cpp +++ b/src/dialogs/contactaddeduserwidget.cpp @@ -25,7 +25,9 @@ #include "../currentaccount.h" #include "../kmessdebug.h" #include "../utils/kmessconfig.h" -#include +#include +#include +#include @@ -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 ) { diff --git a/src/dialogs/contactaddeduserwidget.ui b/src/dialogs/contactaddeduserwidget.ui index dcaedba..d95c07c 100644 --- a/src/dialogs/contactaddeduserwidget.ui +++ b/src/dialogs/contactaddeduserwidget.ui @@ -142,7 +142,7 @@ - + QDialogButtonBox::NoButton @@ -152,13 +152,6 @@ qPixmapFromMimeSource - - - KDialogButtonBox - QDialogButtonBox -
    kdialogbuttonbox.h
    -
    -
    diff --git a/src/dialogs/contactentry.cpp b/src/dialogs/contactentry.cpp index 623c421..23eb78e 100644 --- a/src/dialogs/contactentry.cpp +++ b/src/dialogs/contactentry.cpp @@ -137,10 +137,10 @@ 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 ); } diff --git a/src/dialogs/contactpropertiesdialog.cpp b/src/dialogs/contactpropertiesdialog.cpp index 52a27ee..d981ee7 100644 --- a/src/dialogs/contactpropertiesdialog.cpp +++ b/src/dialogs/contactpropertiesdialog.cpp @@ -25,22 +25,26 @@ #include "../currentaccount.h" #include "../kmessdebug.h" +#include +#include #include -#include +#include +#include +#include #include -#include #include #include -#include -#include +#include + +#include #include 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,21 +721,20 @@ 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; } diff --git a/src/dialogs/contactpropertiesdialog.h b/src/dialogs/contactpropertiesdialog.h index a87b164..084fa51 100644 --- a/src/dialogs/contactpropertiesdialog.h +++ b/src/dialogs/contactpropertiesdialog.h @@ -20,8 +20,10 @@ #include "ui_contactpropertiesdialog.h" -#include -#include +#include +#include + +#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 @@ -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 ); diff --git a/src/dialogs/contactpropertiesdialog.ui b/src/dialogs/contactpropertiesdialog.ui index 030cc0a..c20f4b7 100644 --- a/src/dialogs/contactpropertiesdialog.ui +++ b/src/dialogs/contactpropertiesdialog.ui @@ -496,7 +496,7 @@ KUrlRequester QFrame -
    kurlrequester.h
    +
    KUrlRequester
    diff --git a/src/dialogs/invitedialog.cpp b/src/dialogs/invitedialog.cpp index 77ceade..48db0f8 100644 --- a/src/dialogs/invitedialog.cpp +++ b/src/dialogs/invitedialog.cpp @@ -24,11 +24,15 @@ #include "../model/contactlist.h" #include "../utils/kmessconfig.h" +#include +#include +#include + // 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; } diff --git a/src/dialogs/invitedialog.h b/src/dialogs/invitedialog.h index b657d2d..6218578 100644 --- a/src/dialogs/invitedialog.h +++ b/src/dialogs/invitedialog.h @@ -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 diff --git a/src/dialogs/listexportdialog.cpp b/src/dialogs/listexportdialog.cpp index e5d2548..e11c376 100644 --- a/src/dialogs/listexportdialog.cpp +++ b/src/dialogs/listexportdialog.cpp @@ -26,7 +26,8 @@ #include #include -#include +#include +#include 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; } diff --git a/src/dialogs/networkwindow.cpp b/src/dialogs/networkwindow.cpp index 4ec6574..d086a5e 100644 --- a/src/dialogs/networkwindow.cpp +++ b/src/dialogs/networkwindow.cpp @@ -28,16 +28,14 @@ #include #include #include +#include #include #include -#include -#include -#include +#include +#include #include -#include #include -#include // 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
    because KTextBrowser::append() already adds it. logMessage = formatString( utf8Message ); - logMessage = logMessage.replace(QRegExp("
    $"), QString::null); + logMessage = logMessage.replace(QRegExp("
    $"), QString()); if( entry->type == TYPE_FTP || entry->type == TYPE_NS @@ -1091,7 +1088,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 +1138,7 @@ NetworkWindow::~NetworkWindow() return; } - KDialog::show(); + KMessDialog::show(); } @@ -1155,7 +1152,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 +1178,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 +1350,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')!
    " "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" ); } diff --git a/src/dialogs/networkwindow.h b/src/dialogs/networkwindow.h index 7a39b45..2cebbaf 100644 --- a/src/dialogs/networkwindow.h +++ b/src/dialogs/networkwindow.h @@ -26,10 +26,8 @@ #include #include -#include +#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 diff --git a/src/dialogs/networkwindow.ui b/src/dialogs/networkwindow.ui index 437a66d..a2e9428 100644 --- a/src/dialogs/networkwindow.ui +++ b/src/dialogs/networkwindow.ui @@ -162,7 +162,7 @@
    - + 0 @@ -172,27 +172,10 @@ Qt::ElideRight - - true - - - true - - - true - - - - KTabWidget - QTabWidget -
    ktabwidget.h
    - 1 -
    -
    diff --git a/src/dialogs/transferentry.cpp b/src/dialogs/transferentry.cpp index f813a69..20c1541 100644 --- a/src/dialogs/transferentry.cpp +++ b/src/dialogs/transferentry.cpp @@ -19,13 +19,17 @@ #include "../kmessdebug.h" +#include #include +#include +#include -#include -#include +#include #include -#include -#include +#include + +#include +#include @@ -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 diff --git a/src/dialogs/transferentry.h b/src/dialogs/transferentry.h index 702a374..5e12714 100644 --- a/src/dialogs/transferentry.h +++ b/src/dialogs/transferentry.h @@ -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 diff --git a/src/dialogs/transferentry.ui b/src/dialogs/transferentry.ui index 0e26d58..798b6fd 100644 --- a/src/dialogs/transferentry.ui +++ b/src/dialogs/transferentry.ui @@ -254,52 +254,17 @@ KSqueezedTextLabel QLabel -
    ksqueezedtextlabel.h
    +
    KSqueezedTextLabel
    KUrlLabel QLabel -
    kurllabel.h
    +
    KUrlLabel
    KUrlLabel - KSqueezedTextLabel - KProgressDialog - + KSqueezedTextLabel - - - openLabel_ - leftClickedUrl() - TransferEntry - openClicked() - - - 325 - 18 - - - 20 - 20 - - - - - cancelLabel_ - leftClickedUrl() - TransferEntry - cancelClicked() - - - 325 - 40 - - - 20 - 20 - - - - + diff --git a/src/dialogs/transferwindow.cpp b/src/dialogs/transferwindow.cpp index 5f784a7..d9c1f8d 100644 --- a/src/dialogs/transferwindow.cpp +++ b/src/dialogs/transferwindow.cpp @@ -21,7 +21,10 @@ #include "../kmessdebug.h" #include "transferentry.h" -#include +#include + +#include +#include @@ -56,14 +59,14 @@ TransferWindow::TransferWindow( QWidget *parent ) // Set up the Clean Up and close button closeButton_->setFocus(); - closeButton_ ->setIcon( KIcon( "dialog-close" ) ); - cleanupButton_->setIcon( KIcon( "trash-empty" ) ); + closeButton_ ->setIcon( QIcon::fromTheme( "dialog-close" ) ); + cleanupButton_->setIcon( QIcon::fromTheme( "trash-empty" ) ); connect( cleanupButton_, SIGNAL( clicked() ), this, SLOT( cleanUp() ) ); connect( closeButton_, SIGNAL( clicked() ), this, SLOT( hide() ) ); // Set up the Download and Upload buttons - downloadButton_->setIcon( KIcon( "go-down" ) ); - uploadButton_ ->setIcon( KIcon( "go-up" ) ); + downloadButton_->setIcon( QIcon::fromTheme( "go-down" ) ); + uploadButton_ ->setIcon( QIcon::fromTheme( "go-up" ) ); connect( downloadButton_, SIGNAL( toggled( bool ) ), this, SLOT( slotDownloadButtonToggled( bool ) ) ); connect( uploadButton_, SIGNAL( toggled( bool ) ), this, SLOT( slotUploadButtonToggled( bool ) ) ); @@ -122,7 +125,7 @@ int TransferWindow::addEntry( const QString filename, ulong filesize, bool incom // Show the window show(); - KWindowSystem::demandAttention( winId() ); + QApplication::alert( this ); return currentEntryID_; } diff --git a/src/dialogs/transferwindow.h b/src/dialogs/transferwindow.h index cd8736e..15af978 100644 --- a/src/dialogs/transferwindow.h +++ b/src/dialogs/transferwindow.h @@ -58,7 +58,7 @@ class TransferWindow : public KMainWindow, private Ui::TransferWindow public slots: // Mark a transfer as failed - void failTransfer( int transferID, const QString &message = QString::null ); + void failTransfer( int transferID, const QString &message = QString() ); // Mark a transfer as complete void finishTransfer( int transferID ); // Set the status message of a transfer diff --git a/src/dialogs/userpicturesdialog.cpp b/src/dialogs/userpicturesdialog.cpp index 64e91f6..6f2b1a8 100644 --- a/src/dialogs/userpicturesdialog.cpp +++ b/src/dialogs/userpicturesdialog.cpp @@ -23,13 +23,14 @@ #include +#include #include // Constructor UserPicturesDialog::UserPicturesDialog( QWidget *parent ) - : KDialog( parent ) + : KMessDialog( parent ) { // Setup the user interface setObjectName( "UserPictures" ); @@ -37,7 +38,7 @@ UserPicturesDialog::UserPicturesDialog( QWidget *parent ) setupUi( mainWidget ); setMainWidget( mainWidget ); - setButtons( KDialog::User1 | KDialog::Ok | KDialog::Close ); + setButtons( KMessDialog::User1 | KMessDialog::Ok | KMessDialog::Close ); setDefaultButton( Ok ); setButtonText( Ok, i18n( "&Use" ) ); @@ -124,10 +125,12 @@ void UserPicturesDialog::deletePicture() } // Request confirmation - int result = KMessageBox::questionYesNo( this, - i18n( "Are you sure you want to delete this display picture?", - i18nc( "Dialog box title", "Delete Display Picture" ) ) ); - if( result != KMessageBox::Yes ) + int result = KMessageBox::questionTwoActions( this, + i18n( "Are you sure you want to delete this display picture?" ), + i18nc( "Dialog box title", "Delete Display Picture" ), + KGuiItem( i18n( "Yes" ) ), + KGuiItem( i18n( "No" ) ) ); + if( result != KMessageBox::PrimaryAction ) { return; } @@ -192,18 +195,18 @@ void UserPicturesDialog::slotButtonClicked( int button ) { switch( button ) { - case KDialog::Ok: + case KMessDialog::Ok: usePicture(); accept(); break; - case KDialog::User1: + case KMessDialog::User1: deletePicture(); return; break; default: - KDialog::slotButtonClicked( button ); + KMessDialog::slotButtonClicked( button ); break; } } diff --git a/src/dialogs/userpicturesdialog.h b/src/dialogs/userpicturesdialog.h index be2c93c..6845ab1 100644 --- a/src/dialogs/userpicturesdialog.h +++ b/src/dialogs/userpicturesdialog.h @@ -20,7 +20,7 @@ #include "ui_userpicturesdialog.h" -#include +#include "../utils/kmessdialog.h" @@ -29,7 +29,7 @@ * @author Antonio Nastasi * @ingroup Dialogs */ -class UserPicturesDialog : public KDialog, private Ui::UserPicturesDialog +class UserPicturesDialog : public KMessDialog, private Ui::UserPicturesDialog { Q_OBJECT diff --git a/src/emoticon.cpp b/src/emoticon.cpp index f2e1e6d..1d22de3 100644 --- a/src/emoticon.cpp +++ b/src/emoticon.cpp @@ -23,10 +23,10 @@ #include #include +#include #include //#include -#include #ifdef KMESSDEBUG_EMOTICONS @@ -42,9 +42,9 @@ * @param tooltip The name of this emoticon: it will be displayed as tooltip in the Emoticons Widget */ Emoticon::Emoticon( const QString &pictureName, const QString &tooltip ) - : pictureDirectory_(QString::null) + : pictureDirectory_(QString()) , pictureName_(pictureName) - , picturePath_(QString::null) + , picturePath_(QString()) , height_(EMOTICONS_DEFAULT_SIZE) , isCustomEmoticon_(false) , originalPictureName_(pictureName) @@ -272,13 +272,14 @@ bool Emoticon::isValidShortcut( const QString &shortcut ) { // NOTE: If you update this regexp, in dialogs/addemoticondialog.cpp there is // a string which needs to be updated in interfaceChanged(). - return ! shortcut.contains( QRegExp( + static const QRegularExpression invalidShortcutPattern( "^/.+" // Shortcuts which start with / interfere with the text commands "|" "\\[[A-Z]+\\]" // [anything] is reserved for text formatting "|" "^.{8,}$" // Messenger only supports shortcuts long a maximum of 7 chars - , Qt::CaseInsensitive ) ); + , QRegularExpression::CaseInsensitiveOption ); + return ! invalidShortcutPattern.match( shortcut ).hasMatch(); } @@ -348,8 +349,6 @@ void Emoticon::update() QImage emoticonData; QString emoticonPath; QStringList allowedTypes; - KStandardDirs *dirs = KGlobal::dirs(); - // These are the allowed types for emoticon pictures. Add more to support more formats. // Search in the KDE API Docs for "QImageIO" class to find out which formats are supported, and how to add more. allowedTypes << "png" << "gif" << "mng" << "jpg"; @@ -374,10 +373,10 @@ void Emoticon::update() } else { - picturePath_ = dirs->findResource( "emoticons", emoticonPath + '/' + pictureName_ + '.' + pictureType ); + picturePath_ = KMessShared::findResource( "emoticons", emoticonPath + '/' + pictureName_ + '.' + pictureType ); } - if( ! picturePath_.isNull() && KStandardDirs::exists( picturePath_ ) ) + if( ! picturePath_.isNull() && QFileInfo::exists( picturePath_ ) ) { found = true; break; @@ -390,9 +389,9 @@ void Emoticon::update() foreach( const QString &pictureType, allowedTypes ) { // Search in KMess' default theme folder - picturePath_ = dirs->findResource( "emoticons", "KMess-new/" + originalPictureName_ + "." + pictureType ); + picturePath_ = KMessShared::findResource( "emoticons", "KMess-new/" + originalPictureName_ + "." + pictureType ); - if( ! picturePath_.isNull() && KStandardDirs::exists( picturePath_ ) ) + if( ! picturePath_.isNull() && QFileInfo::exists( picturePath_ ) ) { break; } diff --git a/src/emoticon.h b/src/emoticon.h index 1aa7698..bd54c74 100644 --- a/src/emoticon.h +++ b/src/emoticon.h @@ -18,6 +18,7 @@ #ifndef EMOTICON_H #define EMOTICON_H +#include #include diff --git a/src/emoticonmanager.h b/src/emoticonmanager.h index d8aba3b..105f5ba 100644 --- a/src/emoticonmanager.h +++ b/src/emoticonmanager.h @@ -75,7 +75,7 @@ class EmoticonManager : public QObject public slots: // Load an account's emoticon themes - void connected( QString handle = QString::null ); + void connected( QString handle = QString() ); // Unload the custom emoticon theme of the current account void disconnected(); diff --git a/src/emoticontheme.cpp b/src/emoticontheme.cpp index 96e3f2b..d881a37 100644 --- a/src/emoticontheme.cpp +++ b/src/emoticontheme.cpp @@ -24,12 +24,12 @@ #include #include #include +#include #include #include -#include +#include #include -#include #ifdef KMESSDEBUG_EMOTICONS @@ -399,7 +399,7 @@ QString EmoticonTheme::getThemeIcon( QString themeDir ) #ifdef KMESSDEBUG_EMOTICON_THEMES kmDebug() << "Could not open '" << themeFileName << "'"; #endif - return QString::null; + return QString(); } // Then try to parse it @@ -411,7 +411,7 @@ QString EmoticonTheme::getThemeIcon( QString themeDir ) kmDebug() << "Failure parsing '" << themeFileName << "': " << xmlError; #endif xmlFile.close(); - return QString::null; + return QString(); } const QDomNodeList allEmoticons( xml.elementsByTagName( "emoticon" ) ); @@ -429,7 +429,7 @@ QString EmoticonTheme::getThemeIcon( QString themeDir ) } // The theme contained no valid emoticons - return QString::null; + return QString(); } @@ -624,16 +624,17 @@ bool EmoticonTheme::saveTheme() if( ! xmlFile.open( QIODevice::WriteOnly ) ) { kmWarning() << "Save failed - couldn't open file '" << themeFileName << "'."; - KMessageBox::sorry( 0, i18n("Could not save the emoticon theme. Make sure you have permission to write to the theme folder '%1'.", themePath_ ) ); + KMessageBox::error( 0, i18n("Could not save the emoticon theme. Make sure you have permission to write to the theme folder '%1'.", themePath_ ) ); return false; } QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QTextStream xmlOutput( &xmlFile ); - xmlOutput.setCodec( codec ); + xmlOutput.setEncoding( QStringConverter::Utf8 ); + Q_UNUSED( codec ); // Start the XML tree by writing the root tag - xmlOutput << "" << endl << "" << endl << endl; + xmlOutput << "" << Qt::endl << "" << Qt::endl << Qt::endl; foreach( Emoticon *emoticon, emoticons_ ) { @@ -646,7 +647,7 @@ bool EmoticonTheme::saveTheme() const QString file( QFileInfo( emoticon->getPicturePath() ).baseName() ); // New emoticon: the file name is encoded as HTML to avoid XML parsing errors - xmlOutput << "\t" << endl; + xmlOutput << "\t" << Qt::endl; // Add a for each shortcut which maps to this emoticon, const QStringList &codes = emoticon->getShortcuts(); @@ -656,15 +657,15 @@ bool EmoticonTheme::saveTheme() QString code( *it ); KMessShared::htmlEscape( code ); - xmlOutput << "\t\t" << code << "" << endl; + xmlOutput << "\t\t" << code << "" << Qt::endl; } // End of emoticon - xmlOutput << "\t" << endl << endl; + xmlOutput << "\t" << Qt::endl << Qt::endl; } // Close the XML tree by closing the root - xmlOutput << "" << endl; + xmlOutput << "" << Qt::endl; // Close the file, we're done xmlFile.close(); @@ -684,8 +685,6 @@ bool EmoticonTheme::saveTheme() */ void EmoticonTheme::setThemeName( const QString &newThemeName ) { - KStandardDirs *dirs = KGlobal::dirs(); - // Try to find the theme between all possible locations if( isCustomTheme_ ) { @@ -695,7 +694,7 @@ void EmoticonTheme::setThemeName( const QString &newThemeName ) else { // Standard themes can be in the KDE global emoticons dir, or in the ~/.kde/share/emoticons folder, and possibly elsewhere - themePath_ = dirs->findResourceDir( "emoticons", newThemeName + "/emoticons.xml" ); + themePath_ = KMessShared::findResourceDir( "emoticons", newThemeName + "/emoticons.xml" ); // findResourceDir() only returns the base path for the file you pass to it. themePath_ += newThemeName + "/"; diff --git a/src/emoticontheme.h b/src/emoticontheme.h index 1ce2d8f..69154e3 100644 --- a/src/emoticontheme.h +++ b/src/emoticontheme.h @@ -21,6 +21,7 @@ #include "emoticon.h" #include +#include diff --git a/src/initialview.cpp b/src/initialview.cpp index 2f2e7f8..7cec6aa 100644 --- a/src/initialview.cpp +++ b/src/initialview.cpp @@ -27,11 +27,28 @@ #include #include -#include +#include #include #include -#include -#include +#include +#include + +static QNetworkInformation::Reachability currentNetworkReachability() +{ + if( QNetworkInformation::instance() == nullptr ) + { + QNetworkInformation::loadBackendByFeatures( QNetworkInformation::Features( QNetworkInformation::Feature::Reachability ) ); + } + + QNetworkInformation *networkInformation = QNetworkInformation::instance(); + return networkInformation ? networkInformation->reachability() : QNetworkInformation::Reachability::Unknown; +} + +static bool hasInternetReachability( QNetworkInformation::Reachability reachability ) +{ + return reachability == QNetworkInformation::Reachability::Online + || reachability == QNetworkInformation::Reachability::Unknown; +} /** * Reconnection timeout @@ -49,19 +66,19 @@ InitialView::InitialView( QWidget *parent ) : QWidget( parent ) , Ui::InitialView() , isConnectingUI_( false ) - , networkStatus_( Solid::Networking::Connected ) + , networkStatus_( QNetworkInformation::Reachability::Online ) , reconnectionRemainingSeconds_( 30 ) , triedConnecting_( false ) { // Set up the UI first setupUi( this ); - // Set the username box with the last used email address + // Set the username box with the last used handle config_ = KMessConfig::instance()->getGlobalConfig( "InitialView" ); - lastUsedHandle_ = config_.readEntry( "defaultHandle", "me@hotmail.com" ); + lastUsedHandle_ = config_.readEntry( "defaultHandle", "me@escargot.chat" ); // Enable auto completion - handleCombobox_->setCompletionMode( KGlobalSettings::CompletionPopup ); + handleCombobox_->setCompletionMode( KCompletion::CompletionPopup ); // Select an image to load into the main screen.. mmmm, eggs! QString imageName; @@ -128,9 +145,13 @@ InitialView::InitialView( QWidget *parent ) connect( AccountsManager::instance(), SIGNAL( passwordsReady() ), this, SLOT ( updateView() ) ); - // Use Solid to find out whether we're connected or not, and apply the status immediately - connect( Solid::Networking::notifier(), SIGNAL( statusChanged(Solid::Networking::Status) ), - this, SLOT ( slotConnectionStatusChanged(Solid::Networking::Status) ) ); + // Use Qt to find out whether we're connected or not, and apply the status immediately. + QNetworkInformation::loadBackendByFeatures( QNetworkInformation::Features( QNetworkInformation::Feature::Reachability ) ); + if( QNetworkInformation *networkInformation = QNetworkInformation::instance() ) + { + connect( networkInformation, &QNetworkInformation::reachabilityChanged, + this, &InitialView::slotConnectionStatusChanged ); + } // Set the initial status of the widgets reset(); @@ -282,10 +303,11 @@ void InitialView::reconnect( QString handle, bool connectImmediately ) switch( networkStatus_ ) { - // We're connected to the network, try connecting now - case Solid::Networking::Connected: + // We're connected to the Internet, try connecting now. + case QNetworkInformation::Reachability::Online: + case QNetworkInformation::Reachability::Unknown: #ifdef KMESSDEBUG_INITIALVIEW - kmDebug() << "Network status: Connected. Scheduling reconnection."; + kmDebug() << "Network status: Online/unknown. Scheduling reconnection."; #endif if( connectImmediately ) { @@ -298,45 +320,18 @@ void InitialView::reconnect( QString handle, bool connectImmediately ) break; - // The network connection is down, wait for it to come up again - case Solid::Networking::Unconnected: - case Solid::Networking::Connecting: + // The Internet connection is down or limited to local/site reachability, wait for it to come up again. + case QNetworkInformation::Reachability::Disconnected: + case QNetworkInformation::Reachability::Local: + case QNetworkInformation::Reachability::Site: #ifdef KMESSDEBUG_INITIALVIEW - kmDebug() << "Network status: Unconnected/connecting. Waiting for a connection."; + kmDebug() << "Network status: Not online. Waiting for a connection."; #endif setEnabled( false ); statusMessage( i18nc( "Status message on login screen", "Waiting for an Internet connection to reconnect...
    Reconnect now!", "kmess://reconnect/" ) ); return; - - - // The connection is being brought down, wait for it - case Solid::Networking::Disconnecting: -#ifdef KMESSDEBUG_INITIALVIEW - kmDebug() << "Network status: disconnecting. Waiting a moment for reconnection."; -#endif - reconnectionRemainingSeconds_ = 30; - return; - - - // The network connection status is not known, wait a while before reconnecting - case Solid::Networking::Unknown: - -#ifdef KMESSDEBUG_INITIALVIEW - kmDebug() << "Network status: Unknown. Scheduling reconnection."; -#endif - // When the user starts kmess and the connection status is unknown, connect immediately. - if( connectImmediately ) - { - reconnectionRemainingSeconds_ = 0; - } - else - { - reconnectionRemainingSeconds_ = 30; - } - - break; } // Start the reconnection delay timer @@ -350,12 +345,12 @@ void InitialView::reconnect( QString handle, bool connectImmediately ) /** * @brief Update the view when the network connection status changes * - * This method receives KDE's Solid network connection status changes, and updates the view's widgets + * This method receives Qt network reachability changes, and updates the view's widgets * to reflect it. * - * @param newStatus The new status of the network connection + * @param newStatus The new reachability status of the network connection */ -void InitialView::slotConnectionStatusChanged( Solid::Networking::Status newStatus ) +void InitialView::slotConnectionStatusChanged( QNetworkInformation::Reachability newStatus ) { networkStatus_ = newStatus; @@ -363,19 +358,18 @@ void InitialView::slotConnectionStatusChanged( Solid::Networking::Status newStat QString status; switch( networkStatus_ ) { - case Solid::Networking::Unknown: status = "Unknown"; break; - case Solid::Networking::Unconnected: status = "Unconnected"; break; - case Solid::Networking::Disconnecting: status = "Disconnecting"; break; - case Solid::Networking::Connecting: status = "Connecting"; break; - case Solid::Networking::Connected: status = "Connected"; break; + case QNetworkInformation::Reachability::Unknown: status = "Unknown"; break; + case QNetworkInformation::Reachability::Disconnected: status = "Disconnected"; break; + case QNetworkInformation::Reachability::Local: status = "Local"; break; + case QNetworkInformation::Reachability::Site: status = "Site"; break; + case QNetworkInformation::Reachability::Online: status = "Online"; break; default: status = "Other (not known)"; break; } kmDebug() << "The network connection status has changed to:" << status << "."; #endif - // If Solid is unable to retrieve the status, assume we're connected - if( networkStatus_ == Solid::Networking::Connected - || networkStatus_ == Solid::Networking::Unknown ) + // If Qt is unable to retrieve the status, assume we're connected. + if( hasInternetReachability( networkStatus_ ) ) { if( ! triedConnecting_ ) { @@ -407,7 +401,7 @@ void InitialView::slotConnectionStatusChanged( Solid::Networking::Status newStat } else { - // Solid connection is not up. + // Internet reachability is not up. // Reset the dialog, keep the "isConnecting" status setEnabled( ! triedConnecting_ ); if( triedConnecting_ ) @@ -532,7 +526,7 @@ void InitialView::updateView() } else { - picturePath = KGlobal::dirs()->findResource( "data", "kmess/pics/kmesspic.png" ); + picturePath = KMessShared::findResource( "data", "kmess/pics/kmesspic.png" ); pictureLabel_->setEnabled( false ); } @@ -570,8 +564,7 @@ void InitialView::updateView() // User typed a new account name // Set the default picture - KStandardDirs *dirs = KGlobal::dirs(); - QPixmap picture( dirs->findResource( "data", "kmess/pics/kmesspic.png" ) ); + QPixmap picture( KMessShared::findResource( "data", "kmess/pics/kmesspic.png" ) ); if( ! picture.isNull() ) { pictureLabel_->setPixmap( picture ); @@ -586,7 +579,7 @@ void InitialView::updateView() rememberAutoLoginCheckBox_->setChecked ( false ); // Clear password again - passwordEdit_->setText( QString::null ); + passwordEdit_->setText( QString() ); initialStatus_->setCurrentIndex( 0 ); } @@ -638,7 +631,7 @@ void InitialView::reset() // Update the view again with regard to the current network status updateView(); statusMessage(); - slotConnectionStatusChanged( Solid::Networking::status() ); + slotConnectionStatusChanged( currentNetworkReachability() ); } @@ -724,7 +717,7 @@ bool InitialView::startConnecting( const QString handle, bool emitConnectionSign if( handle.isEmpty() || password.isEmpty() ) { statusMessage( i18nc( "Status message on login screen", - "Please enter both your email address and password" ), + "Please enter both your username and password" ), 10000 ); // Select the box with the error @@ -740,10 +733,10 @@ bool InitialView::startConnecting( const QString handle, bool emitConnectionSign } // Also don't connect if the handle is invalid - if( ! Account::isValidEmail( handle ) ) + if( ! Account::isValidHandle( handle ) ) { statusMessage( i18nc( "Status message on login screen", - "Please enter a valid email address" ), + "Please enter a valid username" ), 10000 ); handleCombobox_->setFocus(); @@ -831,7 +824,7 @@ void InitialView::slotClickedUrl( const QString &url ) return; } - KMessShared::openBrowser( KUrl( url ) ); + KMessShared::openBrowser( QUrl::fromUserInput( url, QString(), QUrl::AssumeLocalFile ) ); } @@ -881,7 +874,7 @@ bool InitialView::eventFilter(QObject *obj, QEvent *event) } else { - glowingImage = QImage( KGlobal::dirs()->findResource( "data", "kmess/pics/kmesspic.png" ) ); + glowingImage = QImage( KMessShared::findResource( "data", "kmess/pics/kmesspic.png" ) ); } KIconEffect::toGamma( glowingImage, 0.8f ); @@ -897,7 +890,7 @@ bool InitialView::eventFilter(QObject *obj, QEvent *event) } else { - picture = QPixmap( KGlobal::dirs()->findResource( "data", "kmess/pics/kmesspic.png" ) ); + picture = QPixmap( KMessShared::findResource( "data", "kmess/pics/kmesspic.png" ) ); } pictureLabel_->setPixmap( picture ); @@ -908,7 +901,7 @@ bool InitialView::eventFilter(QObject *obj, QEvent *event) int newIndex = handleCombobox_->currentIndex(); - if( wheelEvent->delta() > 0 ) + if( wheelEvent->angleDelta().y() > 0 ) { newIndex--; diff --git a/src/initialview.h b/src/initialview.h index d1f5e36..2cdb817 100644 --- a/src/initialview.h +++ b/src/initialview.h @@ -22,10 +22,12 @@ #include "contact/msnstatus.h" #include +#include #include #include -#include +#include +#include // Forward declarations @@ -66,7 +68,6 @@ class InitialView : public QWidget, private Ui::InitialView private: // Private methods // The users picture received an event. bool eventFilter( QObject *obj, QEvent *ev ); - public slots: // Public slots // A profile was selected from the drop-down list, or written manually. void updateView(); @@ -91,7 +92,7 @@ class InitialView : public QWidget, private Ui::InitialView // The connect/disconnect button has been clicked void slotConnectClicked(); // Detect changes in the status of the internet connection - void slotConnectionStatusChanged( Solid::Networking::Status newStatus ); + void slotConnectionStatusChanged( QNetworkInformation::Reachability newStatus ); // Execute the browser for a clicked UI link void slotClickedUrl( const QString &url ); @@ -107,7 +108,7 @@ class InitialView : public QWidget, private Ui::InitialView // Loader for icons KIconLoader *loader_; // The current status of the network connection - Solid::Networking::Status networkStatus_; + QNetworkInformation::Reachability networkStatus_; // Account to reconnect with QString reconnectionHandle_; // Number of seconds left before reconnection diff --git a/src/initialview.ui b/src/initialview.ui index 33549d3..7769ef2 100644 --- a/src/initialview.ui +++ b/src/initialview.ui @@ -157,7 +157,7 @@ - Email address: + Username: false @@ -176,7 +176,7 @@ - Enter here the email address of your registered Passport or Live account + Enter here the username of your registered NINA/Escargot account true @@ -444,10 +444,10 @@ New Account - https://accountservices.passport.net/reg.srf + https://account.nina.chat/register/ - <html>Click here to register a new Live account, which you can use to connect to MSN.<br/>You can also use your existing email address</html> + <html>Click here to register a new NINA/Escargot account, which you can use to connect to the restored MSN Messenger service.<br/>You can also use your existing email address</html> @@ -479,10 +479,10 @@ Password forgotten? - https://login.live.com/resetpw.srf + https://account.nina.chat/login/ - <html>Click here to go to the Live web site, to reset your account's password</html> + <html>Click here to go to account.nina.chat, to manage your account's password</html> @@ -560,15 +560,15 @@ qPixmapFromMimeSource - - KUrlLabel - QLabel -
    kurllabel.h
    -
    KComboBox QComboBox -
    kcombobox.h
    +
    KComboBox
    +
    + + KUrlLabel + QLabel +
    KUrlLabel
    diff --git a/src/kmess.cpp b/src/kmess.cpp index 98e82c2..277477c 100644 --- a/src/kmess.cpp +++ b/src/kmess.cpp @@ -43,6 +43,23 @@ #include "notification/addressbooknotifications.h" #include "notification/systemtraywidget.h" #include "settings/accountsettingsdialog.h" + +static QNetworkInformation::Reachability currentNetworkReachability() +{ + if( QNetworkInformation::instance() == nullptr ) + { + QNetworkInformation::loadBackendByFeatures( QNetworkInformation::Features( QNetworkInformation::Feature::Reachability ) ); + } + + QNetworkInformation *networkInformation = QNetworkInformation::instance(); + return networkInformation ? networkInformation->reachability() : QNetworkInformation::Reachability::Unknown; +} + +static bool hasInternetReachability( QNetworkInformation::Reachability reachability ) +{ + return reachability == QNetworkInformation::Reachability::Online + || reachability == QNetworkInformation::Reachability::Unknown; +} #include "utils/idletimer.h" #include "utils/kmessconfig.h" #include "utils/kmessdbus.h" @@ -61,19 +78,20 @@ #include "kmessview.h" #include +#include #include +#include +#include +#include #include #include -#include -#include -#include +#include #include -#include -#include +#include #include -#include -#include +#include +#include #include @@ -256,9 +274,11 @@ void KMess::addNewGroup() newGroupName = i18n( "New Group" ); // Launch a dialog to get a new group name - newGroupName = KInputDialog::getText(i18nc( "Dialog box title", "Add a Group" ), + newGroupName = QInputDialog::getText(this, + i18nc( "Dialog box title", "Add a Group" ), i18n( "Enter a name for the new group:" ), - newGroupName, &okPressed, this); + QLineEdit::Normal, + newGroupName, &okPressed); if(okPressed) { @@ -280,7 +300,7 @@ void KMess::addNewGroup() void KMess::applicationClosing() { // Prepare closing, KMessInterface::queryClose() accepted the close request. - // After this method returns, KApplication::aboutToQuit() also kicks in, handled by KMessApplication. + // After this method returns, QApplication::aboutToQuit() also kicks in, handled by KMessApplication. if( chatMaster_ != 0 ) { @@ -501,12 +521,12 @@ void KMess::changedStatus( Account *account ) #ifdef KMESSDEBUG_KMESS kmDebug() << "Changed status to" << MsnStatus::getCode( newStatus ) - << "Autoreply is" << currentAccount_->getAutoreply() << endl; + << "Autoreply is" << currentAccount_->getAutoreply() << Qt::endl; #endif // Make sure the drop down list matches the user's status - QList menuActions( status_->findChildren() ); - foreach( KAction *action, menuActions ) + QList menuActions( status_->findChildren() ); + foreach( QAction *action, menuActions ) { if( (Status) action->data().toInt() == newStatus ) { @@ -595,7 +615,7 @@ void KMess::showRemoveContactDialog(QString handle) { QString message( i18n( "Are you sure you want to remove the contact %1 from your contact list?", handle ) ); - int result = KMessageBox::warningYesNoCancel( this, message, i18n( "Remove Contact" ) + int result = KMessageBox::warningTwoActionsCancel( this, message, i18n( "Remove Contact" ) , KGuiItem(i18n("Remove"), "edit-delete") // Yes , KGuiItem(i18n("Remove and Block"), "list-remove") // No , KStandardGuiItem::cancel() @@ -606,12 +626,12 @@ void KMess::showRemoveContactDialog(QString handle) switch( result ) { // User has pressed "Remove and block" - case KMessageBox::No : + case KMessageBox::SecondaryAction : msnNotificationConnection_->removeContact( handle, true ); break; // User has pressed "Remove only" - case KMessageBox::Yes : + case KMessageBox::PrimaryAction : msnNotificationConnection_->removeContact( handle, false ); break; @@ -693,11 +713,12 @@ void KMess::showRenameGroupDialog( QString groupId ) const QString& currentName = group->getName(); // Launch a dialog to get a new group name - const QString newGroupName( KInputDialog::getText( i18n( "Rename Group" ), + const QString newGroupName( QInputDialog::getText( this, + i18n( "Rename Group" ), i18n( "Enter a new name for this group:" ), + QLineEdit::Normal, currentName, - &okPressed, - this ) ); + &okPressed ) ); if( okPressed && currentName != newGroupName ) { @@ -968,44 +989,29 @@ void KMess::reconnect() -// Create the program's default directories in .kde/share/apps/ +// Create the program's default data directory. bool KMess::createDirectories() { #ifdef KMESSDEBUG_KMESS kmDebug() << "Creating default directories."; #endif - KStandardDirs *dirs = KGlobal::dirs(); - QString localKdeDir; - QDir appsDir, kmessDir; + const QString kmessPath = QStandardPaths::writableLocation( QStandardPaths::AppDataLocation ); + QDir dir; - localKdeDir = dirs->localkdedir(); #ifdef KMESSDEBUG_KMESS - kmDebug() << "Local KDE dir is " << localKdeDir << "."; + kmDebug() << "Local app data dir is " << kmessPath << "."; #endif - appsDir.setPath( localKdeDir + "/share/apps" ); - if ( appsDir.exists() ) + if( kmessPath.isEmpty() || ! dir.mkpath( kmessPath ) ) { - kmessDir.setPath( appsDir.absolutePath() + "/kmess" ); #ifdef KMESSDEBUG_KMESS - kmDebug() << "kmess dir should be at " << kmessDir.absolutePath() << "."; + kmDebug() << "Could not create" << kmessPath; #endif - if ( !kmessDir.exists() ) - { -#ifdef KMESSDEBUG_KMESS - kmDebug() << "Creating kmess dir."; -#endif - appsDir.mkdir( kmessDir.absolutePath() ); - } + return false; } -#ifdef KMESSDEBUG_KMESS - else - { - kmDebug() << "" << appsDir.absolutePath() << " doesn't exist!"; - } -#endif + #ifdef KMESSTEST - KMESS_ASSERT( kmessDir.exists() ); + KMESS_ASSERT( QDir( kmessPath ).exists() ); #endif return true; @@ -1079,25 +1085,25 @@ void KMess::slotContactAddedUserDialogChoice( const QString &handle, const QStri /** * @brief Update the UI when the network connection status changes * - * This method receives KDE's Solid network connection status changes, and updates the view's widgets + * This method receives Qt network reachability changes, and updates the view's widgets * to reflect it. * - * @param newStatus The new status of the network connection + * @param newStatus The new reachability status of the network connection */ -void KMess::slotConnectionStatusChanged( Solid::Networking::Status newStatus ) +void KMess::slotConnectionStatusChanged( QNetworkInformation::Reachability newStatus ) { #ifdef KMESSDEBUG_KMESSINTERFACE - kmDebug() << "Solid status changed to " << newStatus; + kmDebug() << "Network reachability changed to " << static_cast( newStatus ); #endif - // If Solid is unable to retrieve the status, assume we're connected - bool isNetConnected = ( newStatus == Solid::Networking::Connected || newStatus == Solid::Networking::Unknown ); + // If Qt is unable to retrieve the status, assume we're connected. + bool isNetConnected = hasInternetReachability( newStatus ); // Do not disable the connection menu if we're connected already if( isConnected() ) { // Do update the status message if the network is down - if( newStatus == Solid::Networking::Unconnected ) + if( newStatus == QNetworkInformation::Reachability::Disconnected ) { // TODO: this slightly interferes with the "Pings lost..." message, and doesn't recover directly if solid indicates so. statusMessage( i18n("Connection could be down..."), false ); @@ -1198,7 +1204,7 @@ void KMess::disconnected() #endif // Set the caption - setCaption( QString::null ); + setCaption( QString() ); } @@ -1272,10 +1278,14 @@ bool KMess::initialize() return false; } - // Use Solid to find out whether we're connected or not, and disable the Connect menu if we are not - connect( Solid::Networking::notifier(), SIGNAL( statusChanged(Solid::Networking::Status) ), - this, SLOT ( slotConnectionStatusChanged(Solid::Networking::Status) ) ); - slotConnectionStatusChanged( Solid::Networking::status() ); + // Use Qt to find out whether we're connected or not, and disable the Connect menu if we are not. + QNetworkInformation::loadBackendByFeatures( QNetworkInformation::Features( QNetworkInformation::Feature::Reachability ) ); + if( QNetworkInformation *networkInformation = QNetworkInformation::instance() ) + { + connect( networkInformation, &QNetworkInformation::reachabilityChanged, + this, &KMess::slotConnectionStatusChanged ); + } + slotConnectionStatusChanged( currentNetworkReachability() ); // Connect current account signals for Now Listening connect( currentAccount_, SIGNAL( changedStatus() ), @@ -1496,9 +1506,9 @@ bool KMess::initNotifications() // Add check whether the 'eventsrc' file can be found. // The warning is a bit obtruisive, but should help to user to fix the problem. - if( KGlobal::dirs()->findResource( "data", "kmess/kmess.notifyrc" ).isNull() ) + if( KMessShared::findResource( "data", "kmess/kmess.notifyrc" ).isNull() ) { - QString dirs( KGlobal::dirs()->findDirs( "data", QString() ).join("/kmess
    ") ); + QString dirs( KMessShared::findResourceDirs( "data", QString() ).join("/kmess
    ") ); if( ! dirs.isEmpty() ) { dirs = "
    " + dirs + "/kmess"; @@ -1602,18 +1612,12 @@ bool KMess::initProxy() // config changes, KMess will need to be restarted if the user changes them. // No proxy, done already! - if( ! KProtocolManager::useProxy() ) - { -#ifdef KMESSDEBUG_KMESS - kmDebug() << "No proxy support is needed (kde's proxy is turned off)."; -#endif - return true; - } - - QString proxyAddress( KProtocolManager::proxyForUrl( KUrl( "https://www.kmess.org/" ) ) ); + const QList proxies = QNetworkProxyFactory::systemProxyForQuery( + QNetworkProxyQuery( QUrl( "https://www.kmess.org/" ) ) ); + const QNetworkProxy systemProxy = proxies.isEmpty() ? QNetworkProxy( QNetworkProxy::NoProxy ) : proxies.first(); // No need to use the proxy for HTTPS traffic - if( proxyAddress.isEmpty() || proxyAddress == "DIRECT" ) + if( systemProxy.type() == QNetworkProxy::NoProxy ) { #ifdef KMESSDEBUG_KMESS kmDebug() << "No proxy support is needed (no proxy is needed for HTTPS traffic)."; @@ -1622,29 +1626,10 @@ bool KMess::initProxy() } #ifdef KMESSDEBUG_KMESS - kmDebug() << "Proxy URL:" << proxyAddress; + kmDebug() << "Proxy:" << systemProxy.hostName() << systemProxy.port(); #endif - KUrl proxyUrl( proxyAddress ); - QNetworkProxy::ProxyType proxyType = QNetworkProxy::NoProxy; - - // Configure the proxy - if( proxyUrl.protocol() == "socks" ) - { - proxyType = QNetworkProxy::Socks5Proxy; - } - else - { - proxyType = QNetworkProxy::HttpProxy; - } - - // Set the default proxy for the whole application - QNetworkProxy appProxy( proxyType, - proxyUrl.host(), - (quint16) proxyUrl.port(), - proxyUrl.user(), - proxyUrl.pass() ); - QNetworkProxy::setApplicationProxy( appProxy ); + QNetworkProxy::setApplicationProxy( systemProxy ); return true; } @@ -1839,7 +1824,7 @@ void KMess::showUserProfile() } const QString url( currentAccount_->getUrlInformation().value( "PROFILE" ) ); - KMessShared::openBrowser( KUrl( url ) ); + KMessShared::openBrowser( QUrl::fromUserInput( url, QString(), QUrl::AssumeLocalFile ) ); } diff --git a/src/kmess.dox b/src/kmess.dox index 526ac90..408b05b 100644 --- a/src/kmess.dox +++ b/src/kmess.dox @@ -49,7 +49,7 @@ * Working with an undocumented protocol also means developers need to take care of * situations that can't be forseen. It's impossible to make guesses about error handling; * e.g. having a list of things which the server may send differently. - * Code needs to verify it's boundaries, and warn (e.g. with kWarning()) + * Code needs to verify it's boundaries, and warn (e.g. with kmWarning()) * when received data can't be processed correctly. * * The code is filled with assertion tests and strict validations of the data being parsed. @@ -60,8 +60,8 @@ * * To prevent crashes in unexpected situations, tests are added to detect null-pointers and warn appropriately. * As rule of thumb: - * - Normal debugging messages are displayed with kDebug(). - * - Serious errors are displayed with kWarning(). + * - Normal debugging messages are displayed with kmDebug(). + * - Serious errors are displayed with kmWarning(). * - Debugging messages should only be displayed when the program is compiled in debug mode. * - Warning messages may also be displayed by the final packaged executable. * - Null pointers are checked using: if(KMESS_NULL(..)) return;. @@ -101,8 +101,8 @@ * When KMess is compiled in debug mode, the debug code between * the \#ifdef KMESSTEST and \#ifdef KMESSDEBUG_... statements will be compiled. * Most macro's are simple defines to enable debug output for certain classes. - * Debug messages are outputed with kDebug(). For warnings visible to the end-user, - * the kWarning() function is used instead. These warnings are not embedded in \#ifdef blocks. + * Debug messages are outputed with kmDebug(). For warnings visible to the end-user, + * the kmWarning() function is used instead. These warnings are not embedded in \#ifdef blocks. * * Macros are also use to optionally wrap function calls to handle debug output. * The KMESS_NULL macro is used to prevent crashes in unexpected situations. @@ -276,4 +276,3 @@ * A package to store utility classes. * By keeping the utilities here, these classes won't clutter up other modules. */ - diff --git a/src/kmess.h b/src/kmess.h index a2103f4..d466b19 100644 --- a/src/kmess.h +++ b/src/kmess.h @@ -23,10 +23,9 @@ #include #include +#include #include -#include - // Forward declarations class Account; class AccountAction; @@ -99,7 +98,7 @@ class KMess : public KMessInterface private: // Private methods // The application is closing, after queryClose() was approved void applicationClosing(); - // Create the program's default directories in .kde/share/apps/ + // Create the program's default data directory. bool createDirectories(); // Initialize the chat master bool initChatMaster(); @@ -171,7 +170,7 @@ class KMess : public KMessInterface // Open the transfer manager void showTransferWindow(); // Detect changes in the status of the internet connection - void slotConnectionStatusChanged( Solid::Networking::Status newStatus ); + void slotConnectionStatusChanged( QNetworkInformation::Reachability newStatus ); // The user was presented the "contact added user" dialog and has made a choice void slotContactAddedUserDialogChoice( const QString &handle, const QStringList &groupIds, const int code ); // A connection has been made with the notification server. diff --git a/src/kmessapplication.cpp b/src/kmessapplication.cpp index 09886d9..c80c6f7 100644 --- a/src/kmessapplication.cpp +++ b/src/kmessapplication.cpp @@ -22,20 +22,21 @@ #include "kmesstest.h" #include "kmessdebug.h" #include "utils/crashhandler.h" +#include "utils/kmessshared.h" #include "config-kmess.h" -#include +#include #include -#include +#include /** * The application constructor */ -KMessApplication::KMessApplication() - : KApplication() +KMessApplication::KMessApplication( int &argc, char **argv ) + : QApplication( argc, argv ) , contactListWindow_(0) , quitSelected_(false) { @@ -45,21 +46,29 @@ KMessApplication::KMessApplication() // Install a message handler, so KMESS_ASSERT won't do a exit(1) or abort() // It makes debugging output on Windows disappear, so don't use it there #ifndef Q_OS_WIN - qInstallMsgHandler( kmessDebugPrinter ); + qInstallMessageHandler( kmessDebugPrinter ); #endif #ifdef KMESSTEST kmDebug() << "Starting KMess " KMESS_VERSION " on" << QDateTime::currentDateTime().toString( Qt::ISODate ); - kmDebug() << "Compiled with KDE" KDE_VERSION_STRING ", Qt" QT_VERSION_STR; - kmDebug() << "Running on KDE" << KDE::versionString() << ", Qt" << qVersion(); + kmDebug() << "Compiled with KDE Frameworks" KCOREADDONS_VERSION_STRING ", Qt" QT_VERSION_STR; + kmDebug() << "Running on Qt" << qVersion(); #endif // Install our crash handler. CrashHandler::activate(); +} + + + +void KMessApplication::initialize( const QCommandLineParser &parser ) +{ + // KMessApplication is created from main.cpp. + // It continues the initialisation of the application. // Start remaining initialisation initializePaths(); - initializeMainWindow(); + initializeMainWindow( parser ); } @@ -108,11 +117,9 @@ bool KMessApplication::getUseTestServer() const /** * Initialisation of the main window. */ -void KMessApplication::initializeMainWindow() +void KMessApplication::initializeMainWindow( const QCommandLineParser &parser ) { - // Fetch the command line arguments - KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); - QString autologinHandle( args->getOption( "autologin" ) ); + const QString autologinHandle( parser.value( "autologin" ) ); // Enable KDE session restore. // We should use KMainWindow's RESTORE macro, or the kRestoreMainWindows @@ -123,7 +130,7 @@ void KMessApplication::initializeMainWindow() // So we just manually restore the KMess main window, which is the // contact list window. int restoredWindow = -1; - if( kapp->isSessionRestored() ) + if( isSessionRestored() ) { int n = 0; while( KMainWindow::canBeRestored( ++n ) ) @@ -152,21 +159,18 @@ void KMessApplication::initializeMainWindow() return; } - // Initialize KApplication - setTopWidget( contactListWindow_ ); - // Apply our own quit policy. // Only quit when the user wanted to, or KDE is logging out. setQuitOnLastWindowClosed( false ); connect( this, SIGNAL(lastWindowClosed()), this, SLOT(slotLastWindowClosed()) ); connect( this, SIGNAL(aboutToQuit()), this, SLOT(slotAboutToQuit()) ); -#if ( KMESS_DEBUG == 1 ) - // The debug build allows to use an alternative server - testServerAddress_ = args->getOption( "server" ); + // Allow overriding the Escargot dispatch server for local testing. + testServerAddress_ = parser.value( "server" ); +#if ( KMESS_DEBUG == 1 ) // The debug build allows to run tests from the command line. - QString testName( args->getOption( "runtest" ) ); + QString testName( parser.value( "runtest" ) ); if( ! testName.isEmpty() ) { // KMessTest is deleted when the app closes @@ -178,7 +182,7 @@ void KMessApplication::initializeMainWindow() #endif // We found session data for the Contact List, to restore it - if( kapp->isSessionRestored() && restoredWindow != -1 ) + if( isSessionRestored() && restoredWindow != -1 ) { // Wait for the user passwords AccountsManager::instance()->readPasswords( true ); @@ -190,7 +194,7 @@ void KMessApplication::initializeMainWindow() // Start auto login if needed, then show the login screen contactListWindow_->checkAutologin( autologinHandle ); - if( ! args->isSet( "hidden" ) ) + if( ! parser.isSet( "hidden" ) ) { contactListWindow_->show(); } @@ -205,14 +209,14 @@ void KMessApplication::initializeMainWindow() void KMessApplication::initializePaths() { // Add compile time paths as fallback - KGlobal::dirs() -> addPrefix( KMESS_PREFIX ); + KMessShared::addResourcePrefix( KMESS_PREFIX ); KIconLoader::global() -> addAppDir( KMESS_PREFIX "/share" ); // Test whether the prefix is correct. - if( KGlobal::dirs()->findResource( "appdata", "pics/kmesspic.png" ).isNull() ) + if( KMessShared::findResource( "appdata", "pics/kmesspic.png" ).isNull() ) { kmWarning() << "KMess could not find resources in the search paths: " - << KGlobal::dirs()->findDirs( "appdata", QString::null ).join(", ") << endl; + << KMessShared::findResourceDirs( "appdata", QString() ).join(", ") << Qt::endl; } } @@ -271,6 +275,16 @@ bool KMessApplication::quitSelected() const +/** + * Return whether the session manager is saving the current desktop session. + */ +bool KMessApplication::sessionSaving() const +{ + return isSavingSession(); +} + + + /** * Tell the application that quit was selected */ diff --git a/src/kmessapplication.h b/src/kmessapplication.h index ec18765..924bee0 100644 --- a/src/kmessapplication.h +++ b/src/kmessapplication.h @@ -18,15 +18,16 @@ #ifndef KMESSAPPLICATION_H #define KMESSAPPLICATION_H -#include +#include class KMess; +class QCommandLineParser; /** - * @brief KApplication subclass to handle quit requests. + * @brief QApplication subclass to handle quit requests. * * This class stores the data to close or quit KMess correctly. * When quitSelected() is false, the main window should only close. @@ -37,7 +38,7 @@ class KMess; * @author Mike K. Bennett (original work), Diederik van der Boor (new class) * @ingroup Root */ -class KMessApplication : public KApplication +class KMessApplication : public QApplication { Q_OBJECT @@ -45,7 +46,7 @@ class KMessApplication : public KApplication public: // Constructor - KMessApplication(); + KMessApplication( int &argc, char **argv ); // Destructor virtual ~KMessApplication(); @@ -58,15 +59,18 @@ class KMessApplication : public KApplication bool getUseTestServer() const; // Return true if quit was selected bool quitSelected() const; + // Return whether the current desktop session is being saved + bool sessionSaving() const; // Tell the application that quit was selected void setQuitSelected(bool quitSelected); + void initialize( const QCommandLineParser &parser ); private slots: void slotAboutToQuit(); void slotLastWindowClosed(); private: // private methods - void initializeMainWindow(); + void initializeMainWindow( const QCommandLineParser &parser ); void initializePaths(); private: diff --git a/src/kmessdebug.cpp b/src/kmessdebug.cpp index 009a414..6a52f99 100644 --- a/src/kmessdebug.cpp +++ b/src/kmessdebug.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include @@ -102,17 +102,19 @@ bool _kmessAssert( const char *assertion, const char *file, int line ) /** * @brief A Qt debug message handler. * - * This function can be installed using @code qInstallMsgHandler( kmessDebugPrinter ); @endcode + * This function can be installed using @code qInstallMessageHandler( kmessDebugPrinter ); @endcode * It's used to avoid unwanted exit(1) or abort() calls. * * @param type The debug message type, generated by qDebug(), qFatal(), etc.. * @param message The message to print. * @ingroup Debug */ -void kmessDebugPrinter( QtMsgType type, const char *message ) +void kmessDebugPrinter( QtMsgType type, const QMessageLogContext &, const QString &message ) { - bool isAssert = ( strncmp( message, "ASSERT", 7 ) == 0 ); // 'ASSERT failure' or 'ASSERT: ' - static QTime timer; + const QByteArray localMessage = message.toLocal8Bit(); + const char *messageData = localMessage.constData(); + bool isAssert = ( strncmp( messageData, "ASSERT", 7 ) == 0 ); // 'ASSERT failure' or 'ASSERT: ' + static QElapsedTimer timer; if( ! timer.isValid() ) timer.start(); float elapsed = (float)timer.elapsed() / (float)1000; @@ -120,7 +122,7 @@ void kmessDebugPrinter( QtMsgType type, const char *message ) if( isAssert ) { // can be qWarning() by us or qFatal() from Qt. - fprintf( stderr, "%.3f> kmess(%d) %s\n", elapsed, getpid(), message ); + fprintf( stderr, "%.3f> kmess(%d) %s\n", elapsed, getpid(), messageData ); #ifdef KMESSTEST // Crash on qFatal() from Qt, called from Q_ASSERT() @@ -136,19 +138,19 @@ void kmessDebugPrinter( QtMsgType type, const char *message ) switch( type ) { case QtDebugMsg: - fprintf( stderr, "%.3f> %s\n", elapsed, message ); + fprintf( stderr, "%.3f> %s\n", elapsed, messageData ); break; case QtWarningMsg: - fprintf( stderr, "%.3f> WARNING: %s\n", elapsed, message ); + fprintf( stderr, "%.3f> WARNING: %s\n", elapsed, messageData ); break; case QtCriticalMsg: - fprintf( stderr, "%.3f> CRITICAL: %s\n", elapsed, message ); + fprintf( stderr, "%.3f> CRITICAL: %s\n", elapsed, messageData ); break; case QtFatalMsg: - fprintf( stderr, "%.3f> FATAL: %s\n", elapsed, message ); + fprintf( stderr, "%.3f> FATAL: %s\n", elapsed, messageData ); #ifdef KMESSTEST abort(); @@ -158,4 +160,3 @@ void kmessDebugPrinter( QtMsgType type, const char *message ) } } } - diff --git a/src/kmessdebug.h b/src/kmessdebug.h index 9469d07..e80611b 100644 --- a/src/kmessdebug.h +++ b/src/kmessdebug.h @@ -20,11 +20,11 @@ #include "config-kmess.h" -#include - -// Since all debugging code uses kmDebug(), this is also a good -// reason to include this file by default so no one else has to. -#include +#include +#include +#include +#include +#include #if ( KMESS_DEBUG == 1 ) @@ -136,36 +136,27 @@ #endif -// Fix compiling with KDE 3.2 -#ifndef KDE_ISUNLIKELY - #define KDE_ISUNLIKELY -#endif - - - -// KDE custom debug logging functions - -/** - * @brief Register a KDE debug area. - * - * This function will be used by kmDebug(), kWarning() calls throughout KMess - * to enable debug output. - * - * @return Debug area number - */ -inline int debugArea() +template +inline void qSort( Container &container ) { -#if KDE_IS_VERSION( 4, 4, 0 ) - static int s_area = KDebug::registerArea( "kmess" ); - return s_area; -#else - return 5130; // This number was assigned to us in KDE 4.3 -#endif + std::sort( container.begin(), container.end() ); } -#define kmDebug() kDebug( debugArea() ) -#define kmWarning() kWarning( debugArea() ) -#define kmError() kError( debugArea() ) +template +inline void qSort( RandomAccessIterator begin, RandomAccessIterator end ) +{ + std::sort( begin, end ); +} + +template +inline void qSort( RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan ) +{ + std::sort( begin, end, lessThan ); +} + +#define kmDebug() qDebug() +#define kmWarning() qWarning() +#define kmError() qCritical() @@ -178,20 +169,20 @@ inline int debugArea() // Wrapper macro for warn-if-null methods. // This idea was taken from Q_ASSERT (qglobal.h). - // Using KDE_ISUNLIKELY so the compiler optimizes branching. + // Using Q_UNLIKELY so the compiler optimizes branching. // Silent version: #define KMESS_NULL(x) (x != 0) - #define KMESS_NULL(x) ( KDE_ISUNLIKELY((x) == 0) && _kmessWarnNull((x) == 0, #x, c_funcinfo, __FILE__, __LINE__) ) + #define KMESS_NULL(x) ( Q_UNLIKELY((x) == 0) && _kmessWarnNull((x) == 0, #x, c_funcinfo, __FILE__, __LINE__) ) // Warn if a pre- or post- condition fails // Idea taken from Q_ASSERT, too, but without terminating the application; // this is often useful with P2P code, some details may change and using KMESS_ASSERT // KMess would die a lot. - #define KMESS_ASSERT(cond) ( KDE_ISUNLIKELY((cond) == 0) && _kmessAssert( #cond, __FILE__, __LINE__) ) + #define KMESS_ASSERT(cond) ( Q_UNLIKELY((cond) == 0) && _kmessAssert( #cond, __FILE__, __LINE__) ) #else // Warns that a pointer was null bool _kmessWarnNull(bool isNull, const char *var, const char *funcinfo); - #define KMESS_NULL(x) ( KDE_ISUNLIKELY((x) == 0) && _kmessWarnNull((x) == 0, #x, c_funcinfo) ) + #define KMESS_NULL(x) ( Q_UNLIKELY((x) == 0) && _kmessWarnNull((x) == 0, #x, c_funcinfo) ) // Avoid asserts in release versions #define KMESS_ASSERT(cond) @@ -228,7 +219,7 @@ inline int debugArea() // A Qt debug message handler to avoid unwanted exit(1) or abort() calls. -void kmessDebugPrinter( QtMsgType type, const char *msg ); +void kmessDebugPrinter( QtMsgType type, const QMessageLogContext &context, const QString &msg ); #endif // KMESSDEBUG_H diff --git a/src/kmessinterface.cpp b/src/kmessinterface.cpp index 9c2c439..6ca1d53 100644 --- a/src/kmessinterface.cpp +++ b/src/kmessinterface.cpp @@ -35,20 +35,21 @@ #include #include +#include #include #include -#include #include -#include -#include -#include +#include +#include +#include +#include #include #include +#include #include -#include +#include #include -#include -#include +#include @@ -154,17 +155,17 @@ void KMessInterface::showTransferWindow() // Create the menus void KMessInterface::createMenus() { - KAction *close, *quit; - KAction *newAccount; + QAction *close, *quit; + QAction *newAccount; QStringList states; QStringList viewModes, listPictureSizes; // Create the actions for "Connect" menu status_ = MsnStatus::getStatusMenu(); - connectActionMenu_ = new KActionMenu ( KIcon("network-connect"), i18n("&Connect"), this ); - disconnect_ = new KAction ( KIcon("network-disconnect"), i18n("&Disconnect"), this ); - showProfile_ = new KAction ( KIcon("preferences-desktop-user"), i18n("Show My &Profile"), this ); + connectActionMenu_ = new KActionMenu ( QIcon::fromTheme( "network-connect" ), i18n("&Connect"), this ); + disconnect_ = new QAction ( QIcon::fromTheme( "network-disconnect" ), i18n("&Disconnect"), this ); + showProfile_ = new QAction ( QIcon::fromTheme( "preferences-desktop-user" ), i18n("Show My &Profile"), this ); close = KStandardAction::close( this, SLOT( menuClose() ), actionCollection_ ); quit = KStandardAction::quit ( this, SLOT( menuQuit() ), actionCollection_ ); @@ -172,24 +173,24 @@ void KMessInterface::createMenus() showAllowedAction_ = new KToggleAction( i18n("Show &Allowed Contacts"), this ); showOfflineAction_ = new KToggleAction( i18n("Show &Offline Contacts"), this ); showRemovedAction_ = new KToggleAction( i18n("Show &Removed Contacts"), this ); - showHistoryBoxAction_ = new KToggleAction( KIcon("chronometer"), i18n("Show &History Box"), this ); - showSearchAction_ = new KToggleAction( KIcon("edit-find-user"), i18n("&Show Search Bar"), this ); + showHistoryBoxAction_ = new KToggleAction( QIcon::fromTheme( "chronometer" ), i18n("Show &History Box"), this ); + showSearchAction_ = new KToggleAction( QIcon::fromTheme( "edit-find-user" ), i18n("&Show Search Bar"), this ); showEmptyAction_ = new KToggleAction( i18n("Show &Empty Groups"), this ); - listPictureSize_ = new KSelectAction( KIcon("view-list-tree"), i18n("&Display Pictures Size"), this ); - viewMode_ = new KSelectAction( KIcon("view-list-tree"), i18n("&Sort Contacts by"), this ); - showTransferAction_ = new KAction ( KIcon("document-open-remote"), i18n("Show &Transfer Window..."), this ); + listPictureSize_ = new KSelectAction( QIcon::fromTheme( "view-list-tree" ), i18n("&Display Pictures Size"), this ); + viewMode_ = new KSelectAction( QIcon::fromTheme( "view-list-tree" ), i18n("&Sort Contacts by"), this ); + showTransferAction_ = new QAction ( QIcon::fromTheme( "document-open-remote" ), i18n("Show &Transfer Window..."), this ); showStatusBar_ = KStandardAction::showStatusbar( this, SLOT( showStatusBar() ), this ); showMenuBar_ = KStandardAction::showMenubar ( this, SLOT( showMenuBar() ), this ); // Create the actions for "Actions" menu - newContact_ = new KAction( KIcon("list-add-user"), i18n("New &Contact..."), this ); - newGroup_ = new KAction( KIcon("user-group-new"), i18n("New &Group..."), this ); - exportList_ = new KAction( KIcon("document-export"),i18n("&Export Contact List..."), this ); - showHistory_ = new KAction( KIcon("chronometer"), i18n("Show Chat &History..."), this ); - newAccount = new KAction( KIcon("user-identity"), i18n("New &Account..."), this ); - showSettingsAction_ = new KAction( KIcon("configure"), i18n("Configure Account..."), this ); - globalSettings_ = new KAction( KIcon("kmess"), i18n("Configure &KMess..."), this ); - contextMenuAction_ = new KAction( KIcon("preferences-contact-list"), i18n("Show Selection &Menu"), this ); + newContact_ = new QAction( QIcon::fromTheme( "list-add-user" ), i18n("New &Contact..."), this ); + newGroup_ = new QAction( QIcon::fromTheme( "user-group-new" ), i18n("New &Group..."), this ); + exportList_ = new QAction( QIcon::fromTheme( "document-export" ),i18n("&Export Contact List..."), this ); + showHistory_ = new QAction( QIcon::fromTheme( "chronometer" ), i18n("Show Chat &History..."), this ); + newAccount = new QAction( QIcon::fromTheme( "user-identity" ), i18n("New &Account..."), this ); + showSettingsAction_ = new QAction( QIcon::fromTheme( "configure" ), i18n("Configure Account..."), this ); + globalSettings_ = new QAction( QIcon::fromTheme( "kmess" ), i18n("Configure &KMess..."), this ); + contextMenuAction_ = new QAction( QIcon::fromTheme( "preferences-contact-list" ), i18n("Show Selection &Menu"), this ); // Populate PictureSize select listPictureSizes << i18n( "Do Not Display" ) @@ -291,7 +292,7 @@ void KMessInterface::createMenus() #ifdef KMESS_NETWORK_WINDOW - showNetworkAction_ = new KAction( KIcon("network-workgroup"), i18n("Show &Network Window..."), this ); + showNetworkAction_ = new QAction( QIcon::fromTheme( "network-workgroup" ), i18n("Show &Network Window..."), this ); connect( showNetworkAction_, SIGNAL( triggered(bool) ), this, SLOT ( showNetworkWindow() ) ); @@ -322,12 +323,12 @@ void KMessInterface::enableMenus(bool connected) { if ( connected ) { - disconnect_->setIcon( KIcon("network-connect") ); + disconnect_->setIcon( QIcon::fromTheme( "network-connect" ) ); stateChanged("connected"); } else { - disconnect_->setIcon( KIcon("network-disconnect") ); + disconnect_->setIcon( QIcon::fromTheme( "network-disconnect" ) ); stateChanged("disconnected"); } } @@ -389,12 +390,8 @@ bool KMessInterface::initialize() setupGUI( ( Keys | Create | Save ), "kmessinterfaceui.rc" ); // Autosave all GUI settings -#if KDE_IS_VERSION(4,0,70) setAutoSaveSettings( KMessConfig::instance()->getGlobalConfig( "ContactListWindow" ), true /* save WindowSize */ ); -#else - setAutoSaveSettings( "ContactListWindow", true /* save WindowSize */ ); -#endif // Autosave all GUI settings setAutoSaveSettings( "KMessInterface", true /* save WindowSize */ ); @@ -473,7 +470,7 @@ void KMessInterface::menuQuit() #endif // Tell the application manager we want to quit - KMessApplication *app = static_cast(kapp); + KMessApplication *app = static_cast(QApplication::instance()); app->setQuitSelected(true); close(); // Close this window, initiates quit @@ -484,7 +481,7 @@ void KMessInterface::menuQuit() // Reject quitting unless the quit menu was pressed Called automatically by KMainWindow::closeEvent bool KMessInterface::queryExit() { - KMessApplication *kmessApp = static_cast(kapp); + KMessApplication *kmessApp = static_cast(QApplication::instance()); // With KDE 4 this function is also called when another KMainWindow (like the network window) closes. // Reject an attempt to quit if the user didn't select quit manually, or is logging out from KDE. @@ -516,11 +513,11 @@ bool KMessInterface::queryExit() // Tell the user that KMess hides in the systray Called automatically by KMainWindow::closeEvent bool KMessInterface::queryClose() { - KMessApplication *kmessApp = static_cast(kapp); + KMessApplication *kmessApp = static_cast(QApplication::instance()); // Only allow KMess to quit if: // - the "quit" option was used from the menu - // - the session manager wants to quit (we're called from KApplication::commitData()) + // - the session manager wants to quit if( kmessApp->quitSelected() || kmessApp->sessionSaving() ) { @@ -575,7 +572,6 @@ void KMessInterface::readProperties( const KConfigGroup &config ) // Resize the window to decent dimensions if there's no saved state. resize( 300, 500 ); - restoreWindowSize( group ); // Pull in the window size and position QSize windowsize = group.readEntry( "Size", QSize() ); @@ -671,18 +667,18 @@ void KMessInterface::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", "Are you sure you want to hide the menu bar? " "You will be able to show it again by using this " "keyboard shortcut: %1", - 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() ); } @@ -812,7 +808,7 @@ void KMessInterface::updateOnlineTimer() onlineTime_ ++; - timeText.sprintf( "%02i:%02i", onlineTime_ / 60, onlineTime_ % 60 ); + timeText = QString::asprintf( "%02i:%02i", onlineTime_ / 60, onlineTime_ % 60 ); statusTimer_->setText( timeText ); } diff --git a/src/kmessinterface.h b/src/kmessinterface.h index 9530349..8e1d254 100644 --- a/src/kmessinterface.h +++ b/src/kmessinterface.h @@ -29,12 +29,12 @@ // Forward declarations class QHBox; class QLabel; -class KAction; +class QAction; class KActionMenu; class KConfig; class KHelpMenu; class KMessTest; -class KMenu; +class QMenu; class KSelectAction; class KToggleAction; class SystemTrayWidget; @@ -122,13 +122,13 @@ class KMessInterface : public KXmlGuiWindow protected: // Protected attributes // The action to show the context-sensitive menu - KAction *contextMenuAction_; + QAction *contextMenuAction_; // The menu for "connect..." with a profile KActionMenu *connectActionMenu_; // The "disconnect" menu item - KAction *disconnect_; + QAction *disconnect_; // The menu for global settings - KAction *globalSettings_; + QAction *globalSettings_; // View list pictures mode KSelectAction *listPictureSize_; // Action to toggle the history box @@ -136,19 +136,19 @@ class KMessInterface : public KXmlGuiWindow // Action to toggle the contact list search bar KToggleAction *showSearchAction_; // Action to display the settings for the connected account - KAction *showSettingsAction_; + QAction *showSettingsAction_; // Toggle actions for showing allowed, offline, and removed contacts, and empty groups. KToggleAction *showAllowedAction_, *showOfflineAction_, *showRemovedAction_, *showEmptyAction_; // Show the network window - KAction *showNetworkAction_; + QAction *showNetworkAction_; // Toggle actions for showing and hiding the menu bar KToggleAction *showMenuBar_; // Toggle actions for showing and hiding the status bar KToggleAction *showStatusBar_; // Show the transfer manager - KAction *showTransferAction_; + QAction *showTransferAction_; // The selection menu for the user's status - KMenu *status_; + QMenu *status_; // The system tray widget SystemTrayWidget *systemTrayWidget_; // The menu for selecting the view mode. @@ -182,7 +182,7 @@ class KMessInterface : public KXmlGuiWindow private: // Private attributes // Export list action - KAction *exportList_; + QAction *exportList_; // Whether the status is a warning or not bool isErrorStatus_; // Whether or not the object was initialized @@ -191,7 +191,7 @@ class KMessInterface : public KXmlGuiWindow QString message_; // Some action menus that the child doesn't need, but need to be // made visible/invisible - KAction *newContact_, *newGroup_, *showProfile_, *showHistory_; + QAction *newContact_, *newGroup_, *showProfile_, *showHistory_; // Minutes online unsigned int onlineTime_; // Online interval timer @@ -203,7 +203,7 @@ class KMessInterface : public KXmlGuiWindow // Online timer QLabel *statusTimer_; // The view menu - stored here because it needs to be enabled/disabled - KMenu *viewMenu_; + QMenu *viewMenu_; }; #endif diff --git a/src/kmesstest.cpp b/src/kmesstest.cpp index a25ce0f..7c51f8f 100644 --- a/src/kmesstest.cpp +++ b/src/kmesstest.cpp @@ -72,7 +72,7 @@ KMessTest::KMessTest(KMess *kmess) , kmess_(kmess) { // Used to quit. Could also be useful to the tests - kmessApp_ = static_cast( kapp ); + kmessApp_ = static_cast(QApplication::instance()); setObjectName("KMessTest"); } @@ -881,7 +881,7 @@ void KMessTest::testOfflineMessages() else { name = "Warning: This message is a bug; the contact should be found in the contact list!"; - picture = QString::null; + picture = QString(); } ChatMessage message2( ChatMessage::TYPE_OFFLINE_INCOMING, diff --git a/src/kmessview.cpp b/src/kmessview.cpp index c04b060..d797a8d 100644 --- a/src/kmessview.cpp +++ b/src/kmessview.cpp @@ -36,26 +36,28 @@ #include "kmessviewdelegate.h" #include +#include #include #include #include +#include #include +#include #include +#include #include #include -#include +#include #include -#include -#include -#include +#include +#include #include #include -#include -#include +#include +#include #include -#include -#include +#include #ifdef KMESSDEBUG_CONTACTLISTMODELTEST @@ -273,7 +275,7 @@ bool KMessView::initialize( QAbstractItemModel *viewModel ) // Create a menu for the status button // Set the menu into button and connect the signals - KMenu *menu = MsnStatus::getStatusMenu(); + QMenu *menu = MsnStatus::getStatusMenu(); statusButton_->setMenu( menu ); connect( statusButton_, SIGNAL( clicked() ), statusButton_, SLOT ( showMenu() ) ); @@ -437,7 +439,7 @@ void KMessView::toggleShowSearchFrame( bool show ) if( show ) { searchFrame_->show(); - searchEdit_->setClickMessage( i18n( "Search in contact list..." ) ); + searchEdit_->setPlaceholderText( i18n( "Search in contact list..." ) ); } else { @@ -514,9 +516,9 @@ bool KMessView::eventFilter(QObject *obj, QEvent *event) } else { - KUrl mimeUrl = mimeData->urls().first(); - bool isRemoteFile = false; + QUrl mimeUrl = mimeData->urls().first(); QString localFilePath; + QString temporaryFilePath; QImage pictureData; if( mimeUrl.isEmpty() ) @@ -525,35 +527,21 @@ bool KMessView::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") ); + KMessageBox::error( this, i18n( "Downloading of display picture failed" ), i18n("KMess") ); - return true; - } - - isRemoteFile = true; + 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 @@ -570,14 +558,14 @@ bool KMessView::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"; @@ -701,37 +689,37 @@ bool KMessView::initContactListView( QAbstractItemModel *viewModel ) bool KMessView::initContactPopup() { // Initialize context menu actions - chatWithContact_ = new KAction( KIcon("user-group-new"), i18n("Cha&t"), this ); - emailContact_ = new KAction( KIcon("mail-message-new"), i18n("&Send Email"), this ); - msnProfile_ = new KAction( KIcon("preferences-desktop-user"), i18n("&View Profile"), this ); - chatHistory_ = new KAction( KIcon("chronometer"), i18n("Show Chat &History..."), this ); - contactProperties_ = new KAction( KIcon("user-properties"), i18n("&Properties"), this ); + chatWithContact_ = new QAction( QIcon::fromTheme( "user-group-new" ), i18n("Cha&t"), this ); + emailContact_ = new QAction( QIcon::fromTheme( "mail-message-new" ), i18n("&Send Email"), this ); + msnProfile_ = new QAction( QIcon::fromTheme( "preferences-desktop-user" ), i18n("&View Profile"), this ); + chatHistory_ = new QAction( QIcon::fromTheme( "chronometer" ), i18n("Show Chat &History..."), this ); + contactProperties_ = new QAction( QIcon::fromTheme( "user-properties" ), i18n("&Properties"), this ); - addContact_ = new KAction( KIcon("list-add"), i18n("&Add Contact"), this ); - allowContact_ = new KAction( KIcon("dialog-ok-apply"), i18n("A&llow Contact"), this ); - blockContact_ = new KAction( KIcon("dialog-cancel"), i18n("&Block Contact"), this ); - unblockContact_ = new KAction( KIcon("dialog-ok"), i18n("&Unblock Contact"), this ); - removeContact_ = new KAction( KIcon("list-remove-user"), i18n("&Delete Contact"), this ); - removeFromGroup_ = new KAction( KIcon("list-remove"), i18n("&Remove From Group"), this ); + addContact_ = new QAction( QIcon::fromTheme( "list-add" ), i18n("&Add Contact"), this ); + allowContact_ = new QAction( QIcon::fromTheme( "dialog-ok-apply" ), i18n("A&llow Contact"), this ); + blockContact_ = new QAction( QIcon::fromTheme( "dialog-cancel" ), i18n("&Block Contact"), this ); + unblockContact_ = new QAction( QIcon::fromTheme( "dialog-ok" ), i18n("&Unblock Contact"), this ); + removeContact_ = new QAction( QIcon::fromTheme( "list-remove-user" ), i18n("&Delete Contact"), this ); + removeFromGroup_ = new QAction( QIcon::fromTheme( "list-remove" ), i18n("&Remove From Group"), 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 ); // Connect the actions - connect( chatWithContact_, SIGNAL(activated()), this, SLOT(slotForwardStartChat()) ); - connect( emailContact_, SIGNAL(activated()), this, SLOT(slotEmailContact()) ); - connect( msnProfile_, SIGNAL(activated()), this, SLOT(slotShowContactProfile()) ); - connect( chatHistory_, SIGNAL(activated()), this, SLOT(slotShowChatHistory()) ); - connect( contactProperties_, SIGNAL(activated()), this, SLOT(slotShowContactProperties()) ); + connect( chatWithContact_, SIGNAL(triggered(bool)), this, SLOT(slotForwardStartChat()) ); + connect( emailContact_, SIGNAL(triggered(bool)), this, SLOT(slotEmailContact()) ); + connect( msnProfile_, SIGNAL(triggered(bool)), this, SLOT(slotShowContactProfile()) ); + connect( chatHistory_, SIGNAL(triggered(bool)), this, SLOT(slotShowChatHistory()) ); + connect( contactProperties_, SIGNAL(triggered(bool)), this, SLOT(slotShowContactProperties()) ); - connect( addContact_, SIGNAL(activated()), this, SLOT(slotForwardAddContact()) ); - connect( allowContact_, SIGNAL(activated()), this, SLOT(slotForwardAllowContact()) ); - connect( blockContact_, SIGNAL(activated()), this, SLOT(slotForwardBlockContact()) ); - connect( unblockContact_, SIGNAL(activated()), this, SLOT(slotForwardUnblockContact()) ); - connect( removeContact_, SIGNAL(activated()), this, SLOT(slotForwardRemoveContact()) ); - connect( removeFromGroup_, SIGNAL(activated()), this, SLOT(slotForwardRemoveFromGroup())); + connect( addContact_, SIGNAL(triggered(bool)), this, SLOT(slotForwardAddContact()) ); + connect( allowContact_, SIGNAL(triggered(bool)), this, SLOT(slotForwardAllowContact()) ); + connect( blockContact_, SIGNAL(triggered(bool)), this, SLOT(slotForwardBlockContact()) ); + connect( unblockContact_, SIGNAL(triggered(bool)), this, SLOT(slotForwardUnblockContact()) ); + connect( removeContact_, SIGNAL(triggered(bool)), this, SLOT(slotForwardRemoveContact()) ); + connect( removeFromGroup_, SIGNAL(triggered(bool)), this, SLOT(slotForwardRemoveFromGroup())); connect( popupCopyFriendlyName_, SIGNAL(triggered(bool)), this, SLOT( copyText() ) ); connect( popupCopyPersonalMessage_, SIGNAL(triggered(bool)), this, SLOT( copyText() ) ); @@ -761,7 +749,7 @@ bool KMessView::initContactPopup() // Initialize the popup menu // If you re-organize the menu, also consider updating ContactFrame. - contactActionPopup_ = new KMenu( "KMess", this ); + contactActionPopup_ = new QMenu( "KMess", this ); contactActionPopup_->addAction( chatWithContact_ ); contactActionPopup_->addAction( emailContact_ ); @@ -797,19 +785,19 @@ bool KMessView::initContactPopup() bool KMessView::initGroupPopup() { // Initialize context menu actions - moveGroupDown_ = new KAction( KIcon("arrow-down"), i18n("Move Group &Down"), this ); - moveGroupUp_ = new KAction( KIcon("arrow-up"), i18n("Move Group &Up"), this ); - removeGroup_ = new KAction( KIcon("edit-delete"), i18n("Re&move Group"), this ); - renameGroup_ = new KAction( KIcon("edit-rename"), i18n("Re&name Group"), this ); + moveGroupDown_ = new QAction( QIcon::fromTheme( "arrow-down" ), i18n("Move Group &Down"), this ); + moveGroupUp_ = new QAction( QIcon::fromTheme( "arrow-up" ), i18n("Move Group &Up"), this ); + removeGroup_ = new QAction( QIcon::fromTheme( "edit-delete" ), i18n("Re&move Group"), this ); + renameGroup_ = new QAction( QIcon::fromTheme( "edit-rename" ), i18n("Re&name Group"), this ); // Connect the actions - connect( moveGroupDown_, SIGNAL(activated()), this, SLOT( slotMoveGroupDown()) ); - connect( moveGroupUp_, SIGNAL(activated()), this, SLOT( slotMoveGroupUp()) ); - connect( removeGroup_, SIGNAL(activated()), this, SLOT(slotForwardRemoveGroup()) ); - connect( renameGroup_, SIGNAL(activated()), this, SLOT(slotForwardRenameGroup()) ); + connect( moveGroupDown_, SIGNAL(triggered(bool)), this, SLOT( slotMoveGroupDown()) ); + connect( moveGroupUp_, SIGNAL(triggered(bool)), this, SLOT( slotMoveGroupUp()) ); + connect( removeGroup_, SIGNAL(triggered(bool)), this, SLOT(slotForwardRemoveGroup()) ); + connect( renameGroup_, SIGNAL(triggered(bool)), this, SLOT(slotForwardRenameGroup()) ); // Initialize the popup menu - groupActionPopup_ = new KMenu( "KMess", this ); + groupActionPopup_ = new QMenu( "KMess", this ); groupActionPopup_->addAction( moveGroupUp_ ); groupActionPopup_->addAction( moveGroupDown_ ); @@ -827,13 +815,13 @@ bool KMessView::initGroupPopup() void KMessView::rebuildContactActions() { // Remove all copy and move actions - foreach( KAction *action, groupCopyActionsList_ ) + foreach( QAction *action, groupCopyActionsList_ ) { copyContactToGroup_->removeAction( action ); groupCopyActionsList_.removeAll( action ); delete action; } - foreach( KAction *action, groupMoveActionsList_ ) + foreach( QAction *action, groupMoveActionsList_ ) { moveContactToGroup_->removeAction( action ); groupMoveActionsList_.removeAll( action ); @@ -854,8 +842,8 @@ void KMessView::rebuildContactActions() // but KActions only support the name, we'll use the Qt objectName to store // their internal id const QString& id = group->getId(); - KAction *copyAction = new KAction( group->getName(), copyContactToGroup_ ); - KAction *moveAction = new KAction( group->getName(), moveContactToGroup_ ); + QAction *copyAction = new QAction( group->getName(), copyContactToGroup_ ); + QAction *moveAction = new QAction( group->getName(), moveContactToGroup_ ); copyAction->setObjectName( id ); moveAction->setObjectName( id ); @@ -895,7 +883,7 @@ void KMessView::slotGroupChanged( const QModelIndex &index ) } // Do nothing if the group is empty - if( index.child( 0, 0 ) == QModelIndex() ) + if( viewModel_->index( 0, 0, index ) == QModelIndex() ) { return; } @@ -1009,9 +997,9 @@ void KMessView::showContextMenu( const QPoint &point ) } // Show all copy and move actions - foreach( KAction *action, groupCopyActionsList_ ) + foreach( QAction *action, groupCopyActionsList_ ) action->setVisible( true ); - foreach( KAction *action, groupMoveActionsList_ ) + foreach( QAction *action, groupMoveActionsList_ ) action->setVisible( true ); // Then hide only the invalid choices @@ -1019,7 +1007,7 @@ void KMessView::showContextMenu( const QPoint &point ) int enabledMoveActions = groupMoveActionsList_.count(); foreach( const QString &groupId, contactGroups ) { - foreach( KAction *action, groupCopyActionsList_ ) + foreach( QAction *action, groupCopyActionsList_ ) { // See initContactPopup() for the choice of using objectName to store the group ID if( action->objectName() == groupId ) @@ -1029,7 +1017,7 @@ void KMessView::showContextMenu( const QPoint &point ) break; } } - foreach( KAction *action, groupMoveActionsList_ ) + foreach( QAction *action, groupMoveActionsList_ ) { // See initContactPopup() for the choice of using objectName to store the group ID if( action->objectName() == groupId ) @@ -1064,13 +1052,14 @@ void KMessView::showContextMenu( const QPoint &point ) //Initialize index, link RegExp and found boolean for insert separator only at first found link int pos = 0; - QRegExp linkRegExp( "(http://|https://|ftp://|sftp://|www\\..)\\S+" ); + QRegularExpression linkRegExp( "(http://|https://|ftp://|sftp://|www\\..)\\S+" ); - while( ( pos = linkRegExp.indexIn( nameAndPm, pos ) ) != -1 ) + QRegularExpressionMatch match; + while( ( match = linkRegExp.match( nameAndPm, pos ) ).hasMatch() ) { // Grep the found link and update the position for the next cycle - QString foundLink( linkRegExp.cap( 0 ) ); - pos += linkRegExp.matchedLength(); + QString foundLink( match.captured( 0 ) ); + pos = match.capturedEnd(); // Skip duplicated links if( links.contains( foundLink ) ) @@ -1079,13 +1068,13 @@ void KMessView::showContextMenu( 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 ) - KAction *popupCopyLink = new KAction( foundLink.replace( '&', "&&" ), this ); + QAction *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 groupCopyLinkActionsList_.append( popupCopyLink ); // Add action to copy menu @@ -1138,8 +1127,8 @@ void KMessView::showContextMenu( const QPoint &point ) void KMessView::copyText() { // Grep the action sender for copy the tooltip that contains the information - KAction *action = static_cast( const_cast( sender() ) ); - kapp->clipboard()->setText( action->toolTip() ); + QAction *action = static_cast( const_cast( sender() ) ); + QApplication::clipboard()->setText( action->toolTip() ); } @@ -1233,7 +1222,7 @@ void KMessView::showToolTip( const QPoint &point ) } tipText = tipText.arg( "" + - mediaEmoticon + Qt::escape( mediaString ) + + mediaEmoticon + mediaString.toHtmlEscaped() + "
    " ); } else @@ -1277,7 +1266,7 @@ void KMessView::showToolTip( const QPoint &point ) if( ! clientName.isEmpty() ) { tipText = tipText.arg( propertyLine.arg( i18nc( "Contact Live Messenger client label in list tooltip", "Client" ) ) - .arg( Qt::escape( clientName ) ) ); + .arg( clientName.toHtmlEscaped() ) ); } else { @@ -1306,8 +1295,8 @@ void KMessView::showToolTip( const QPoint &point ) { lastSeenString = i18n( "Connected" ); } - else if( lastSeen.toTime_t() == 0 - || lastSeen.toTime_t() == UINT_MAX + else if( lastSeen.toSecsSinceEpoch() == 0 + || lastSeen.toSecsSinceEpoch() == UINT_MAX || lastSeen.isNull() ) { lastSeenString = i18n( "Not seen yet" ); @@ -1323,8 +1312,8 @@ void KMessView::showToolTip( const QPoint &point ) // Add last message date const QDateTime lastMessage( itemData[ "lastMessage" ].toDateTime() ); QString lastMessageString; - if( lastMessage.toTime_t() == 0 - || lastMessage.toTime_t() == UINT_MAX + if( lastMessage.toSecsSinceEpoch() == 0 + || lastMessage.toSecsSinceEpoch() == UINT_MAX || lastMessage.isNull() ) { lastMessageString = i18n( "No messages yet" ); @@ -1398,7 +1387,7 @@ void KMessView::slotEmailContact() void KMessView::slotItemDoubleClicked( const QModelIndex &index ) { // Detect accidental clicks - if( KGlobalSettings::singleClick() ) + if( QGuiApplication::styleHints()->singleClickActivation() ) { #ifdef KMESSDEBUG_KMESSVIEW_GENERAL kmDebug() << "Accidental double click detected, skipping click event."; @@ -1414,7 +1403,7 @@ void KMessView::slotItemDoubleClicked( const QModelIndex &index ) void KMessView::slotItemSingleClicked( const QModelIndex &index ) { bool accidental = false; - if( ! KGlobalSettings::singleClick() ) + if( ! QGuiApplication::styleHints()->singleClickActivation() ) { #ifdef KMESSDEBUG_KMESSVIEW_GENERAL kmDebug() << "Accidental single click detected, skipping click event."; @@ -1447,7 +1436,7 @@ void KMessView::slotItemClicked( const QModelIndex &index, const bool accidental case ContactListModelItem::ItemGroup: // Do nothing if the group is empty - if( index.child( 0, 0 ) == QModelIndex() ) + if( viewModel_->index( 0, 0, index ) == QModelIndex() ) { return; } @@ -1941,7 +1930,7 @@ void KMessView::slotSearchContact( const QString& searchFor ) searchExpression = searchFor.mid( regexpMagic.length() ); // Colorize the search bar when using regexps, according to if they're valid or invalid - if( QRegExp( searchExpression ).isValid() ) + if( QRegularExpression( searchExpression ).isValid() ) { searchEdit_->setStyleSheet( "background-color: #bbffbb" ); } @@ -1953,7 +1942,7 @@ void KMessView::slotSearchContact( const QString& searchFor ) else { // Remove trailing spaces and other unneeded (invisible) characters, then escape the searchstring - searchExpression = QRegExp::escape( searchFor.simplified() ); + searchExpression = QRegularExpression::escape( searchFor.simplified() ); searchEdit_->setStyleSheet( "" ); } @@ -2038,13 +2027,13 @@ void KMessView::slotShowChatHistory() { if( currentAccount_->getSaveChats() ) { - KMessageBox::sorry( this, + KMessageBox::error( this, i18n( "No chat logs could be found for this contact." ), i18n( "No chat history found" ) ); } else { - KMessageBox::sorry( this, + KMessageBox::error( this, i18n( "No chat logs could be found for this contact. Note that new chats are not logged; if you want your chats to be logged, you can enable it in your account settings." ), i18n( "No chat history found") ); } @@ -2068,7 +2057,8 @@ void KMessView::slotShowContactProfile() } const QString handle( itemData[ "handle" ].toString() ); - KMessShared::openBrowser( KUrl( "http://members.msn.com/default.msnw?mem=" + handle + "&mkt=" + KGlobal::locale()->language() + "&pgmarket" ) ); + Q_UNUSED( handle ); + KMessShared::openBrowser( QUrl( "https://nina.chat/contacts/" ) ); } diff --git a/src/kmessview.h b/src/kmessview.h index e119a67..52e1eea 100644 --- a/src/kmessview.h +++ b/src/kmessview.h @@ -40,9 +40,9 @@ class QItemSelectionModel; class QSignalMapper; class QToolTip; -class KAction; +class QAction; class KActionMenu; -class KMenu; +class QMenu; @@ -176,33 +176,33 @@ class KMessView : public QWidget, private Ui::KMessView private: // Private attributes // KActions used in the contact popup menu - KAction *addContact_; - KAction *allowContact_; - KAction *blockContact_; - KAction *unblockContact_; - KAction *chatWithContact_; - KAction *msnProfile_; - KAction *chatHistory_; - KAction *removeContact_; - KAction *removeFromGroup_; - KAction *emailContact_; - KAction *contactProperties_; + QAction *addContact_; + QAction *allowContact_; + QAction *blockContact_; + QAction *unblockContact_; + QAction *chatWithContact_; + QAction *msnProfile_; + QAction *chatHistory_; + QAction *removeContact_; + QAction *removeFromGroup_; + QAction *emailContact_; + QAction *contactProperties_; // KActions uses in the group popup menu - KAction *moveGroupDown_; - KAction *moveGroupUp_; - KAction *removeGroup_; - KAction *renameGroup_; - // KAction uses in the copy popup menu + QAction *moveGroupDown_; + QAction *moveGroupUp_; + QAction *removeGroup_; + QAction *renameGroup_; + // QAction uses in the copy popup menu KActionMenu *popupCopyMenu_; - KAction *popupCopyFriendlyName_; - KAction *popupCopyPersonalMessage_; - KAction *popupCopyHandle_; - KAction *popupCopyMusic_; - QList groupCopyLinkActionsList_; + QAction *popupCopyFriendlyName_; + QAction *popupCopyPersonalMessage_; + QAction *popupCopyHandle_; + QAction *popupCopyMusic_; + QList groupCopyLinkActionsList_; // The menu of actions possible to perform on a given contact - KMenu *contactActionPopup_; + QMenu *contactActionPopup_; // The menu of actions possible to perform on a given group - KMenu *groupActionPopup_; + QMenu *groupActionPopup_; // KSelectActions used in the contact popup menu KActionMenu *moveContactToGroup_; KActionMenu *copyContactToGroup_; @@ -213,9 +213,9 @@ class KMessView : public QWidget, private Ui::KMessView // A pointer to the instance of the current account CurrentAccount *currentAccount_; // List of groups between which the user can copy contacts - QList groupCopyActionsList_; + QList groupCopyActionsList_; // List of groups between which the user can move contacts - QList groupMoveActionsList_; + QList groupMoveActionsList_; // Whether or not the object has been initialized bool initialized_; // The background pixmap diff --git a/src/kmessview.ui b/src/kmessview.ui index 5da5a09..904708b 100644 --- a/src/kmessview.ui +++ b/src/kmessview.ui @@ -560,12 +560,12 @@ KLineEdit QLineEdit -
    klineedit.h
    +
    KLineEdit
    KUrlLabel QLabel -
    kurllabel.h
    +
    KUrlLabel
    InlineEditLabel @@ -579,27 +579,9 @@ - KLineEdit KSqueezedTextLabel - KUrlLabel + KUrlLabel - - - emailLabel_ - leftClickedUrl() - KMessView - slotEmailLabelClicked() - - - 20 - 20 - - - 20 - 20 - - - - + diff --git a/src/kmessviewdelegate.cpp b/src/kmessviewdelegate.cpp index 0db5702..bbf4ee2 100644 --- a/src/kmessviewdelegate.cpp +++ b/src/kmessviewdelegate.cpp @@ -34,8 +34,7 @@ #include #include -#include -#include +#include /// Default spacing between items @@ -296,7 +295,7 @@ void KMessViewDelegate::paint( QPainter *painter, const QStyleOptionViewItem &op { text = i18nc( "Group name in the contact list with online/total contacts of that group" , "%1 (%2/%3)" - , Qt::escape( itemData[ "name" ].toString() ) + , itemData[ "name" ].toString().toHtmlEscaped() , itemData[ "onlineContacts" ].toString() , itemData[ "totalContacts" ].toString() ); } @@ -304,7 +303,7 @@ void KMessViewDelegate::paint( QPainter *painter, const QStyleOptionViewItem &op { text = i18nc( "Group name in the contact list with total contacts of that group" , "%1 (%2)" - , Qt::escape( itemData[ "name" ].toString() ) + , itemData[ "name" ].toString().toHtmlEscaped() , itemData[ "totalContacts" ].toString() ); } @@ -315,7 +314,7 @@ void KMessViewDelegate::paint( QPainter *painter, const QStyleOptionViewItem &op QTextOption textOpt; textOpt.setWrapMode( QTextOption::NoWrap ); - if( ( fm.width( text ) + labelRect.height() ) > labelRect.width() ) + if( ( fm.horizontalAdvance( text ) + labelRect.height() ) > labelRect.width() ) { QPixmap label( labelRect.size() ); label.fill( Qt::transparent ); @@ -403,11 +402,11 @@ void KMessViewDelegate::paint( QPainter *painter, const QStyleOptionViewItem &op const QString mediaType( itemData[ "mediaType" ].toString() ); if( mediaType == "Music" ) { - messageString = mediaEmoticonMusic_ + "" + Qt::escape( mediaString ) + ""; + messageString = mediaEmoticonMusic_ + "" + mediaString.toHtmlEscaped() + ""; } else if( mediaType == "Gaming" || mediaType == "Game" ) { - messageString = mediaEmoticonGaming_ + "" + Qt::escape( mediaString ) + ""; + messageString = mediaEmoticonGaming_ + "" + mediaString.toHtmlEscaped() + ""; } else { @@ -443,7 +442,7 @@ void KMessViewDelegate::paint( QPainter *painter, const QStyleOptionViewItem &op textDocument_->setHtml( text ); QFontMetrics fm( painter->font() ); - const int labelWidth = fm.width( text ); + const int labelWidth = fm.horizontalAdvance( text ); // Paint directly when it fits in the available space... // The + rect.height() is to have a nicer effect when resizing the window :) @@ -521,7 +520,7 @@ QSize KMessViewDelegate::sizeHint( const QStyleOptionViewItem &option, const QMo // the height of the item should be // large enough to accommodate the font. - QFont generalFont = KGlobalSettings::generalFont(); + QFont generalFont = QApplication::font(); QFontMetricsF metrics( generalFont ); QSize size( KIconLoader::SizeSmall + 2, KIconLoader::SizeSmall + 4 ); @@ -572,4 +571,3 @@ QSize KMessViewDelegate::sizeHint( const QStyleOptionViewItem &option, const QMo return size; } } - diff --git a/src/main.cpp b/src/main.cpp index 6ade6a2..9824b85 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,9 +21,11 @@ #include "kmessdebug.h" #include -#include #include +#include +#include + /** @@ -36,22 +38,26 @@ int main(int argc, char *argv[]) { Q_INIT_RESOURCE( isfqtresources ); + + // Create the application before KAboutData and QCommandLineParser, as required by KF6. + KMessApplication kmessApp( argc, argv ); + KLocalizedString::setApplicationDomain( "kmess" ); + // Init about dialog. // Tab 1: General KAboutData aboutData( "kmess", // internal name - 0, // catalog name - ki18n("KMess"), // program name + i18n("KMess"), // program name KMESS_VERSION, // app version from config-kmess.h - ki18n("A Live Messenger client for KDE"), // short description - KAboutData::License_GPL, // license - ki18n("(c) 2002-2012, Mike K. Bennett\n" // copyright + i18n("A Live Messenger client for KDE"), // short description + KAboutLicense::GPL, // license + i18n("(c) 2002-2012, Mike K. Bennett\n" // copyright "(c) 2005-2012, Diederik van der Boor\n" "(c) 2007-2012, Valerio Pilo\n" "(c) 2008-2012, Antonio Nastasi\n" "(c) 2008-2012, Ruben Vandamme\n" "(c) 2009-2012, Sjors Gielen\n" "(c) 2009-2012, Adam Goossens\n"), - KLocalizedString(), + QString(), "http://www.kmess.org/", // home page "bugs" "@" "kmess" "." "org" // address for bugs ); @@ -60,160 +66,168 @@ int main(int argc, char *argv[]) // Tab 2: Authors // TODO: escape the special characters to some Unicode format. (how?) - aboutData.addAuthor( ki18n("Mike K. Bennett"), ki18n("Developer and project founder"), "mkb137" "@" "users.sourceforge" "." "net" ); - aboutData.addAuthor( ki18n("Michael Curtis"), ki18n("Developer"), "mdcurtis" "@" "users.sourceforge" "." "net" ); - aboutData.addAuthor( ki18n("Jan Tönjes"), ki18n("Project support"), "jan" "@" "kmess" "." "org" ); - aboutData.addAuthor( ki18n("Diederik van der Boor"), ki18n("Current developer"), "diederik" "@" "kmess" "." "org" ); - aboutData.addAuthor( ki18n("Valerio Pilo"), ki18n("Current developer"), "valerio" "@" "kmess" "." "org" ); - aboutData.addAuthor( ki18n("Antonio Nastasi"), ki18n("Current developer"), "sifcenter" "@" "gmail" "." "com" ); - aboutData.addAuthor( ki18n("Ruben Vandamme"), ki18n("Current developer"), "vandammeru" "@" "gmail" "." "com" ); - aboutData.addAuthor( ki18n("Sjors Gielen"), ki18n("Current developer"), "sjors" "@" "kmess" "." "com" ); - aboutData.addAuthor( ki18n("Adam Goossens"), ki18n("Current developer"), "fontknocker""@" "gmail" "." "com" ); + aboutData.addAuthor( i18n("Mike K. Bennett"), i18n("Developer and project founder"), "mkb137" "@" "users.sourceforge" "." "net" ); + aboutData.addAuthor( i18n("Michael Curtis"), i18n("Developer"), "mdcurtis" "@" "users.sourceforge" "." "net" ); + aboutData.addAuthor( i18n("Jan Tönjes"), i18n("Project support"), "jan" "@" "kmess" "." "org" ); + aboutData.addAuthor( i18n("Diederik van der Boor"), i18n("Current developer"), "diederik" "@" "kmess" "." "org" ); + aboutData.addAuthor( i18n("Valerio Pilo"), i18n("Current developer"), "valerio" "@" "kmess" "." "org" ); + aboutData.addAuthor( i18n("Antonio Nastasi"), i18n("Current developer"), "sifcenter" "@" "gmail" "." "com" ); + aboutData.addAuthor( i18n("Ruben Vandamme"), i18n("Current developer"), "vandammeru" "@" "gmail" "." "com" ); + aboutData.addAuthor( i18n("Sjors Gielen"), i18n("Current developer"), "sjors" "@" "kmess" "." "com" ); + aboutData.addAuthor( i18n("Adam Goossens"), i18n("Current developer"), "fontknocker""@" "gmail" "." "com" ); // Tab 3: Credits - aboutData.addCredit( ki18n("Jan Tönjes"), ki18n("German translation, testing, documentation, web master, project management, etc..."), "jan" "." "toenjes" "@" "web" "." "de"); - aboutData.addCredit( ki18n("Dane Harnett"), ki18n("Web design"), "dynamitedane" "@" "hotmail" "." "com"); - aboutData.addCredit( ki18n("David Vignoni"), ki18n("Main and yellow/blue/violet emoticon sets, Italian translation"), "dvgn" "@" "libero" "." "it"); - aboutData.addCredit( ki18n("Julien Joubin"), ki18n("Cartoon emoticons"), "jujubinche" "@" "netscape" "." "net"); - aboutData.addCredit( ki18n("Christian Müller"), ki18n("Default sound theme"), "cmue81" "@" "gmx" "." "de"); - aboutData.addCredit( ki18n("Michael Anderton"), ki18n("KMess icon in Oxygen style"), "mike" "." "s" "." "anderton" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Jan Tönjes"), i18n("German translation, testing, documentation, web master, project management, etc..."), "jan" "." "toenjes" "@" "web" "." "de"); + aboutData.addCredit( i18n("Dane Harnett"), i18n("Web design"), "dynamitedane" "@" "hotmail" "." "com"); + aboutData.addCredit( i18n("David Vignoni"), i18n("Main and yellow/blue/violet emoticon sets, Italian translation"), "dvgn" "@" "libero" "." "it"); + aboutData.addCredit( i18n("Julien Joubin"), i18n("Cartoon emoticons"), "jujubinche" "@" "netscape" "." "net"); + aboutData.addCredit( i18n("Christian Müller"), i18n("Default sound theme"), "cmue81" "@" "gmx" "." "de"); + aboutData.addCredit( i18n("Michael Anderton"), i18n("KMess icon in Oxygen style"), "mike" "." "s" "." "anderton" "@" "gmail" "." "com"); // Translations // Sorted by Alphabetic order of language. - aboutData.addCredit( ki18n("Panagiotis Papadopoulos"), ki18n("Translations Maintainer"), "pano_90" "@" "gmx" "." "net"); + aboutData.addCredit( i18n("Panagiotis Papadopoulos"), i18n("Translations Maintainer"), "pano_90" "@" "gmx" "." "net"); - aboutData.addCredit( ki18n("Mohamed Aser"), ki18n("Arabic translation, internationalization of file saving fix" "." ""), "mohasr" "@" "link" "." "net"); - aboutData.addCredit( ki18n("Youssef Chahibi"), ki18n("More Arabic translation"), "chahibi" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Mohamed Aser"), i18n("Arabic translation, internationalization of file saving fix" "." ""), "mohasr" "@" "link" "." "net"); + aboutData.addCredit( i18n("Youssef Chahibi"), i18n("More Arabic translation"), "chahibi" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Mauricio Rother"), ki18n("Brazilian Portuguese translation"), "mauricio" "@" "digicomm" "." "com.br"); - aboutData.addCredit( ki18n("Leonel Freire"), ki18n("More Brazilian Portuguese translation"), "leonelfreire" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Sergio Rafael Lemke"), ki18n("More Brazilian Portuguese translation"), "bedi" "." "com" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Morris Arozi Moraes"), ki18n("More Brazilian Portuguese translation")); + aboutData.addCredit( i18n("Mauricio Rother"), i18n("Brazilian Portuguese translation"), "mauricio" "@" "digicomm" "." "com.br"); + aboutData.addCredit( i18n("Leonel Freire"), i18n("More Brazilian Portuguese translation"), "leonelfreire" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Sergio Rafael Lemke"), i18n("More Brazilian Portuguese translation"), "bedi" "." "com" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Morris Arozi Moraes"), i18n("More Brazilian Portuguese translation")); - aboutData.addCredit( ki18n("Jaume Cornadó"), ki18n("Catalan translation"), "jaumec" "@" "lleida" "." "net"); - aboutData.addCredit( ki18n("Adrià Arrufat"), ki18n("More Catalan translation"), "swiftscythe" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Jaume Cornadó"), i18n("Catalan translation"), "jaumec" "@" "lleida" "." "net"); + aboutData.addCredit( i18n("Adrià Arrufat"), i18n("More Catalan translation"), "swiftscythe" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Lin Haoxiang"), ki18n("Simplified Chinese translation, file send bug fix, proxy connect code"), "linhaoxiang" "@" "hotmail" "." "com"); - aboutData.addCredit( ki18n("Liu Sizhuang"), ki18n("More Simplified Chinese translation"), "chinatslsz" "@" "hotmail.com"); - aboutData.addCredit( ki18n("Cheng Yang"), ki18n("More Simplified Chinese translation"), "yangzju" "@" "gmail.com"); - aboutData.addCredit( ki18n("Yen-chou Chen"), ki18n("Traditional Chinese translation"), "yenchou" "." "mse90" "@" "nctu" "." "edu" "." "tw"); - aboutData.addCredit( ki18n("Tryneeds-Chinese"), ki18n("More Traditional Chinese translation"), "tryneeds@gmail.com"); + aboutData.addCredit( i18n("Lin Haoxiang"), i18n("Simplified Chinese translation, file send bug fix, proxy connect code"), "linhaoxiang" "@" "hotmail" "." "com"); + aboutData.addCredit( i18n("Liu Sizhuang"), i18n("More Simplified Chinese translation"), "chinatslsz" "@" "hotmail.com"); + aboutData.addCredit( i18n("Cheng Yang"), i18n("More Simplified Chinese translation"), "yangzju" "@" "gmail.com"); + aboutData.addCredit( i18n("Yen-chou Chen"), i18n("Traditional Chinese translation"), "yenchou" "." "mse90" "@" "nctu" "." "edu" "." "tw"); + aboutData.addCredit( i18n("Tryneeds-Chinese"), i18n("More Traditional Chinese translation"), "tryneeds@gmail.com"); - aboutData.addCredit( ki18n("Lars Sommer"), ki18n("Danish translation"), "admin" "@" "lasg" "." "dk"); - aboutData.addCredit( ki18n("Pascal d'Hermilly"), ki18n("More Danish translation"), "pascal" "@" "tipisoft" "." "dk"); + aboutData.addCredit( i18n("Lars Sommer"), i18n("Danish translation"), "admin" "@" "lasg" "." "dk"); + aboutData.addCredit( i18n("Pascal d'Hermilly"), i18n("More Danish translation"), "pascal" "@" "tipisoft" "." "dk"); - aboutData.addCredit( ki18n("Arend van Beelen Jr."), ki18n("Dutch translation"), "arend" "@" "auton" "." "nl"); - aboutData.addCredit( ki18n("Diederik van der Boor"), ki18n("More Dutch translation"), "diederik" "@" "kmess" "." "org"); - aboutData.addCredit( ki18n("Jaap Woldringh"), ki18n("More Dutch translation"), "jjh" "." "woldringh" "@" "planet" "." "nl"); - aboutData.addCredit( ki18n("Elve"), ki18n("More Dutch translation"), "elve" "@" "savage-elve" "." "net"); - aboutData.addCredit( ki18n("Sander Pientka"), ki18n("More Dutch translation"), "cumulus0007" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Heimen Stoffels"), ki18n("More Dutch translation"), "djmusic121" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Arend van Beelen Jr."), i18n("Dutch translation"), "arend" "@" "auton" "." "nl"); + aboutData.addCredit( i18n("Diederik van der Boor"), i18n("More Dutch translation"), "diederik" "@" "kmess" "." "org"); + aboutData.addCredit( i18n("Jaap Woldringh"), i18n("More Dutch translation"), "jjh" "." "woldringh" "@" "planet" "." "nl"); + aboutData.addCredit( i18n("Elve"), i18n("More Dutch translation"), "elve" "@" "savage-elve" "." "net"); + aboutData.addCredit( i18n("Sander Pientka"), i18n("More Dutch translation"), "cumulus0007" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Heimen Stoffels"), i18n("More Dutch translation"), "djmusic121" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Panagiotis Papadopoulos"), ki18n("More German translation, Greek translation"), "pano_90" "@" "gmx" "." "net"); - aboutData.addCredit( ki18n("Dimitrios Glentadakis"), ki18n("More Greek translation"), "dglent" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Panagiotis Papadopoulos"), i18n("More German translation, Greek translation"), "pano_90" "@" "gmx" "." "net"); + aboutData.addCredit( i18n("Dimitrios Glentadakis"), i18n("More Greek translation"), "dglent" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Jyri Toomessoo"), ki18n("Estonian translation"), "nuubik" "@" "hotmail" "." "com"); - aboutData.addCredit( ki18n("Markus Vuori"), ki18n("Finnish translation"), "markus" "@" "vuoret" "." "net"); - aboutData.addCredit( ki18n("Joonas Niilola"), ki18n("More Finnish translation"), "juippis" "@" "roskakori" "." "org"); - aboutData.addCredit( ki18n("Jussi Timperi"), ki18n("More Finnish translation"), "jussi.timperi" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Antony Hussi"), ki18n("More Finnish translation"), "antony.hussi" "@" "tranciend" "." "com"); + aboutData.addCredit( i18n("Jyri Toomessoo"), i18n("Estonian translation"), "nuubik" "@" "hotmail" "." "com"); + aboutData.addCredit( i18n("Markus Vuori"), i18n("Finnish translation"), "markus" "@" "vuoret" "." "net"); + aboutData.addCredit( i18n("Joonas Niilola"), i18n("More Finnish translation"), "juippis" "@" "roskakori" "." "org"); + aboutData.addCredit( i18n("Jussi Timperi"), i18n("More Finnish translation"), "jussi.timperi" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Antony Hussi"), i18n("More Finnish translation"), "antony.hussi" "@" "tranciend" "." "com"); - aboutData.addCredit( ki18n("Choplair"), ki18n("French translation"), "pachilor" "@" "yahoo" "." "co" "." "jp"); - aboutData.addCredit( ki18n("Vincent Fretin"), ki18n("More French translation, MSN6 emoticon definitions"), "fretinvincent" "@" "hotmail" "." "com"); - aboutData.addCredit( ki18n("Andrea Blankenstijn"), ki18n("More French translation"), "darkan9el" "@" "gmail" "." "com" ); // or "andrea" "@" "zenephiris" "." "ch" - aboutData.addCredit( ki18n("Barthe Guillaume"), ki18n("More French translation"), "gu_barthe" "@" "yahoo" "." "fr" ); - aboutData.addCredit( ki18n("Scias"), ki18n("More French translation"), "shining" "." "scias" "@" "gmail" "." "com" ); - aboutData.addCredit( ki18n("Grégory Bellier"), ki18n("More French translation"), "gregory" "." "bellier" "@" "gmail" "." "com" ); - aboutData.addCredit( ki18n("Anthony Rey"), ki18n("More French translation"), "gnuk" "@" "mailoo" "." "org"); + aboutData.addCredit( i18n("Choplair"), i18n("French translation"), "pachilor" "@" "yahoo" "." "co" "." "jp"); + aboutData.addCredit( i18n("Vincent Fretin"), i18n("More French translation, MSN6 emoticon definitions"), "fretinvincent" "@" "hotmail" "." "com"); + aboutData.addCredit( i18n("Andrea Blankenstijn"), i18n("More French translation"), "darkan9el" "@" "gmail" "." "com" ); // or "andrea" "@" "zenephiris" "." "ch" + aboutData.addCredit( i18n("Barthe Guillaume"), i18n("More French translation"), "gu_barthe" "@" "yahoo" "." "fr" ); + aboutData.addCredit( i18n("Scias"), i18n("More French translation"), "shining" "." "scias" "@" "gmail" "." "com" ); + aboutData.addCredit( i18n("Grégory Bellier"), i18n("More French translation"), "gregory" "." "bellier" "@" "gmail" "." "com" ); + aboutData.addCredit( i18n("Anthony Rey"), i18n("More French translation"), "gnuk" "@" "mailoo" "." "org"); - aboutData.addCredit( ki18n("Páder Rezső"), ki18n("Hungarian translation"), "rezso" "@" "rezso" "." "net"); - aboutData.addCredit( ki18n("Pauli Henrik"), ki18n("More Hungarian translation"), "henrik.pauli" "@" "drangolin" "." "net"); - aboutData.addCredit( ki18n("Valerio Pilo"), ki18n("More Italian translation"), "valerio" "@" "kmess" "." "org"); - aboutData.addCredit( ki18n("Vincenzo Reale"), ki18n("More Italian translation"), "smart2128" "@" "baslug" "." "org"); - aboutData.addCredit( ki18n("Andrea Decorte"), ki18n("More Italian translation, Group selection in 'contact added user' dialog"), "adecorte" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Páder Rezső"), i18n("Hungarian translation"), "rezso" "@" "rezso" "." "net"); + aboutData.addCredit( i18n("Pauli Henrik"), i18n("More Hungarian translation"), "henrik.pauli" "@" "drangolin" "." "net"); + aboutData.addCredit( i18n("Valerio Pilo"), i18n("More Italian translation"), "valerio" "@" "kmess" "." "org"); + aboutData.addCredit( i18n("Vincenzo Reale"), i18n("More Italian translation"), "smart2128" "@" "baslug" "." "org"); + aboutData.addCredit( i18n("Andrea Decorte"), i18n("More Italian translation, Group selection in 'contact added user' dialog"), "adecorte" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Daniel E. Moctezuma"), ki18n("Japanese translation"), "dmoctezuma" "@" "kmess" "." "org"); - aboutData.addCredit( ki18n("Park Dong Cheon"), ki18n("Korean translation"), "pdc" "@" "kaist" "." "ac.kr"); - aboutData.addCredit( ki18n("Øyvind Sæther"), ki18n("Norsk Bokmål translation"), "oyvind" "@" "sather" "." "tk"); + aboutData.addCredit( i18n("Daniel E. Moctezuma"), i18n("Japanese translation"), "dmoctezuma" "@" "kmess" "." "org"); + aboutData.addCredit( i18n("Park Dong Cheon"), i18n("Korean translation"), "pdc" "@" "kaist" "." "ac.kr"); + aboutData.addCredit( i18n("Øyvind Sæther"), i18n("Norsk Bokmål translation"), "oyvind" "@" "sather" "." "tk"); - aboutData.addCredit( ki18n("Zoran Milovanović"), ki18n("Serbian translation"), "provalisam" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Zoran Milovanović"), i18n("Serbian translation"), "provalisam" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Rastislav Krupanský"), ki18n("Slovak translation"), "ra100" "@" "atlas" "." "sk"); - aboutData.addCredit( ki18n("Matjaž Kaše"), ki18n("Slovenian translation"), "matjaz" "." "kase" "@" "g-kabel" "." "si"); + aboutData.addCredit( i18n("Rastislav Krupanský"), i18n("Slovak translation"), "ra100" "@" "atlas" "." "sk"); + aboutData.addCredit( i18n("Matjaž Kaše"), i18n("Slovenian translation"), "matjaz" "." "kase" "@" "g-kabel" "." "si"); - aboutData.addCredit( ki18n("Johanna Gersch"), ki18n("Spanish translation")); - aboutData.addCredit( ki18n("J.C.A. Javi"), ki18n("More Spanish translation"), "yovoya30ks" "@" "hotmail" "." "com"); - aboutData.addCredit( ki18n("Alejandro Araiza Alvarado"), ki18n("More Spanish translation"), "mebrelith" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Jaume Corbí"), ki18n("More Spanish translation"), "jaume4" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Christian Kaiser"), ki18n("More Spanish translation"), "k39" "@" "users" "." "sourceforge" "." "net"); - aboutData.addCredit( ki18n("Juan Pablo González Tognarelli"), ki18n("More Spanish translation"), "jotapesan" "@" "gmail" "." "com" ); - aboutData.addCredit( ki18n("Alexis Daniel Medina Medina"), ki18n("More Spanish translation"), "alexismedina" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Manuel Ramírez"), ki18n("More Spanish translation"), "elpreto" "@" "kde" "." "org" "." "ar"); - aboutData.addCredit( ki18n("Mauricio Muñoz Lucero"), ki18n("More Spanish translation"), "real" "." "mml" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Johanna Gersch"), i18n("Spanish translation")); + aboutData.addCredit( i18n("J.C.A. Javi"), i18n("More Spanish translation"), "yovoya30ks" "@" "hotmail" "." "com"); + aboutData.addCredit( i18n("Alejandro Araiza Alvarado"), i18n("More Spanish translation"), "mebrelith" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Jaume Corbí"), i18n("More Spanish translation"), "jaume4" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Christian Kaiser"), i18n("More Spanish translation"), "k39" "@" "users" "." "sourceforge" "." "net"); + aboutData.addCredit( i18n("Juan Pablo González Tognarelli"), i18n("More Spanish translation"), "jotapesan" "@" "gmail" "." "com" ); + aboutData.addCredit( i18n("Alexis Daniel Medina Medina"), i18n("More Spanish translation"), "alexismedina" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Manuel Ramírez"), i18n("More Spanish translation"), "elpreto" "@" "kde" "." "org" "." "ar"); + aboutData.addCredit( i18n("Mauricio Muñoz Lucero"), i18n("More Spanish translation"), "real" "." "mml" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Christian Lundgren"), ki18n("Swedish translation"), "zeflunk" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Mattias Newzella"), ki18n("More Swedish translation"), "newzella" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Christian Lundgren"), i18n("Swedish translation"), "zeflunk" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Mattias Newzella"), i18n("More Swedish translation"), "newzella" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Rachan Hongpairote"), ki18n("Thai translation"), "rachanh" "@" "yahoo" "." "com"); - aboutData.addCredit( ki18n("Gorkem Cetin"), ki18n("Turkish translation"), "gorkem" "@" "gelecek" "." "com" "." "tr"); - aboutData.addCredit( ki18n("Barbaros Ulutas"), ki18n("More Turkish translation"), "ulutas" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Uğur Çetin"), ki18n("More Turkish translation"), "ugur" "." "jnmbk" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Rachan Hongpairote"), i18n("Thai translation"), "rachanh" "@" "yahoo" "." "com"); + aboutData.addCredit( i18n("Gorkem Cetin"), i18n("Turkish translation"), "gorkem" "@" "gelecek" "." "com" "." "tr"); + aboutData.addCredit( i18n("Barbaros Ulutas"), i18n("More Turkish translation"), "ulutas" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Uğur Çetin"), i18n("More Turkish translation"), "ugur" "." "jnmbk" "@" "gmail" "." "com"); // Other contributors - aboutData.addCredit( ki18n("Richard Conway"), ki18n("MSNP12 support, various patches"), "richardconway" "@" "users" "." "sourceforge.net"); - aboutData.addCredit( ki18n("Guido Solinas"), ki18n("Pictures in contact list code, contact client info, chat font zoom"), "whereismwhite" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Pedro Ferreira"), ki18n("File transfer thumbnails"), "pedro." "ferreira" "@" "fe" "." "up.pt"); - aboutData.addCredit( ki18n("Liu Sizhuang"), ki18n("P4-Context field support"), "chinatslsz" "@" "hotmail.com"); - aboutData.addCredit( ki18n("Scott Morgan"), ki18n("Xinerama fixes"), "blumf" "@" "blumf" "." "freeserve" "." "co" "." "uk"); - aboutData.addCredit( ki18n("Laurence Anderson"), ki18n("Original file receive code"), "l.d" "." "anderson" "@" "warwick" ".ac.uk"); - aboutData.addCredit( ki18n("Matteo Nardi"), ki18n("KWallet support"), "91.matteo" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Adam Goossens"), ki18n("Notifications blocking option, winks disabling option, last message date feature"), "fontknocker" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Sjors Gielen"), ki18n("IRC-like commands in the chat window"), "dazjorz" "@" "dazjorz" "." "com"); - aboutData.addCredit( ki18n("Dario Freddi"), ki18n("Chat history dialog"), "drf_av" "@" "users" "." "sourceforge" "." "net"); + aboutData.addCredit( i18n("Richard Conway"), i18n("MSNP12 support, various patches"), "richardconway" "@" "users" "." "sourceforge.net"); + aboutData.addCredit( i18n("Guido Solinas"), i18n("Pictures in contact list code, contact client info, chat font zoom"), "whereismwhite" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Pedro Ferreira"), i18n("File transfer thumbnails"), "pedro." "ferreira" "@" "fe" "." "up.pt"); + aboutData.addCredit( i18n("Liu Sizhuang"), i18n("P4-Context field support"), "chinatslsz" "@" "hotmail.com"); + aboutData.addCredit( i18n("Scott Morgan"), i18n("Xinerama fixes"), "blumf" "@" "blumf" "." "freeserve" "." "co" "." "uk"); + aboutData.addCredit( i18n("Laurence Anderson"), i18n("Original file receive code"), "l.d" "." "anderson" "@" "warwick" ".ac.uk"); + aboutData.addCredit( i18n("Matteo Nardi"), i18n("KWallet support"), "91.matteo" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Adam Goossens"), i18n("Notifications blocking option, winks disabling option, last message date feature"), "fontknocker" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Sjors Gielen"), i18n("IRC-like commands in the chat window"), "dazjorz" "@" "dazjorz" "." "com"); + aboutData.addCredit( i18n("Dario Freddi"), i18n("Chat history dialog"), "drf_av" "@" "users" "." "sourceforge" "." "net"); // Lin Haoxiang (file send bug fix, proxy connect code) already above // Mohamed Aser (internationalization of file saving fix) already above - aboutData.addCredit( ki18n("Alexandre Peixoto Ferreira"), ki18n("Various internationalization fixes"), "alexandref" "@" "o2" ".net" ".br"); - aboutData.addCredit( ki18n("Choe Hwanjin"), ki18n("Various internationalization fixes" "." ""), "hjchoe" "@" "hancom" "." "com"); + aboutData.addCredit( i18n("Alexandre Peixoto Ferreira"), i18n("Various internationalization fixes"), "alexandref" "@" "o2" ".net" ".br"); + aboutData.addCredit( i18n("Choe Hwanjin"), i18n("Various internationalization fixes" "." ""), "hjchoe" "@" "hancom" "." "com"); // Vincent Fretin (MSN6 emoticon definitions) already above - aboutData.addCredit( ki18n("Damien Sandras"), ki18n("GnomeMeeting developer"), "dsandras" "@" "seconix" "." "com"); - aboutData.addCredit( ki18n("Tobias Tönjes"), ki18n("Guy with a bag over his head"), ""); - aboutData.addCredit( ki18n("Camille Begue"), ki18n("Chat History functionality when disconnected, autologin checkbox on login screen"), "prsieux" "@" "@gmail" "." "com"); - aboutData.addCredit( ki18n("David López"), ki18n("Nudge button in chat"), "grannost" "@" "gmail" "." "com" ); - aboutData.addCredit( ki18n("Pieterjan Camerlynck"), ki18n("Roaming Service support"), "pieterjan" "." "camerlynck" "@" "gmail" "." "com" ); - aboutData.addCredit( ki18n("Anastasios Bourazanis"), ki18n("Emoticon preview in settings page,clickable contact properties dialog text"), "a.brzns" "@" "gmail" "." "com"); - aboutData.addCredit( ki18n("Marco Mentasti"), ki18n("Internationalization fixes, drag'n'drop of images into display pictures"), "marcomentasti" "@" "gmail" "." "com" ); - aboutData.addCredit( ki18n("Francesco Nwokeka"), ki18n("Now Listening toggle button above the contact list."), "" ); - aboutData.addCredit( ki18n("Timo Tambet"), ki18n("Contact Changed and Group Changed notifications, contact added user dialog tabbing"), "ttambet" "@" "gmail" "." "com" ); + aboutData.addCredit( i18n("Damien Sandras"), i18n("GnomeMeeting developer"), "dsandras" "@" "seconix" "." "com"); + aboutData.addCredit( i18n("Tobias Tönjes"), i18n("Guy with a bag over his head"), ""); + aboutData.addCredit( i18n("Camille Begue"), i18n("Chat History functionality when disconnected, autologin checkbox on login screen"), "prsieux" "@" "@gmail" "." "com"); + aboutData.addCredit( i18n("David López"), i18n("Nudge button in chat"), "grannost" "@" "gmail" "." "com" ); + aboutData.addCredit( i18n("Pieterjan Camerlynck"), i18n("Roaming Service support"), "pieterjan" "." "camerlynck" "@" "gmail" "." "com" ); + aboutData.addCredit( i18n("Anastasios Bourazanis"), i18n("Emoticon preview in settings page,clickable contact properties dialog text"), "a.brzns" "@" "gmail" "." "com"); + aboutData.addCredit( i18n("Marco Mentasti"), i18n("Internationalization fixes, drag'n'drop of images into display pictures"), "marcomentasti" "@" "gmail" "." "com" ); + aboutData.addCredit( i18n("Francesco Nwokeka"), i18n("Now Listening toggle button above the contact list."), "" ); + aboutData.addCredit( i18n("Timo Tambet"), i18n("Contact Changed and Group Changed notifications, contact added user dialog tabbing"), "ttambet" "@" "gmail" "." "com" ); // Other apps - aboutData.addCredit( ki18n("KMerlin (kmerlin.olsd.de)"), ki18n("Inspiration and assorted code")); - aboutData.addCredit( ki18n("Kopete (kopete.kde.org)"), ki18n("Old popup balloons code, initial p2p code, MSN challenge handler")); - aboutData.addCredit( ki18n("KScreensaver"), ki18n("Idle timer code")); - aboutData.addCredit( ki18n("BasKet"), ki18n("Close-to-tray icon screenshot code")); - aboutData.addCredit( ki18n("Amarok"), ki18n("Custom crash handler implementation, System tray icon overlay implementation")); - aboutData.addCredit( ki18n("Quassel"), ki18n("KNotify not giving focus bug fix and KWin focus stealing prevention workaround")); + aboutData.addCredit( i18n("KMerlin (kmerlin.olsd.de)"), i18n("Inspiration and assorted code")); + aboutData.addCredit( i18n("Kopete (kopete.kde.org)"), i18n("Old popup balloons code, initial p2p code, MSN challenge handler")); + aboutData.addCredit( i18n("KScreensaver"), i18n("Idle timer code")); + aboutData.addCredit( i18n("BasKet"), i18n("Close-to-tray icon screenshot code")); + aboutData.addCredit( i18n("Amarok"), i18n("Custom crash handler implementation, System tray icon overlay implementation")); + aboutData.addCredit( i18n("Quassel"), i18n("KNotify not giving focus bug fix and KWin focus stealing prevention workaround")); // Nice community detail (very subtle at the bottom..) - aboutData.addCredit( ki18n("Your name here?"), ki18n("You are welcome to send bugfixes and patches to the KMess help forum!\nIf you feel your name is missing here, please contact us too!"), "you@kmess.org"); + aboutData.addCredit( i18n("Your name here?"), i18n("You are welcome to send bugfixes and patches to the KMess help forum!\nIf you feel your name is missing here, please contact us too!"), "you@kmess.org"); // Add the translation names from the .po file: - aboutData.setTranslator( ki18nc("NAME OF TRANSLATORS", "Your names"), - ki18nc("EMAIL OF TRANSLATORS", "Your email addresses") ); + aboutData.setTranslator( i18nc("NAME OF TRANSLATORS", "Your names"), + i18nc("EMAIL OF TRANSLATORS", "Your email addresses") ); + KAboutData::setApplicationData( aboutData ); // Configure command line options // Those are handled in KMessApplication. - KCmdLineOptions options; - options.add( "hidden", ki18n("Do not show the contact list window initially") ); - options.add( "autologin ", ki18n("Autologin with the given email address") ); + QCommandLineParser parser; + aboutData.setupCommandLine( &parser ); + parser.addOption( QCommandLineOption( QStringLiteral( "hidden" ), + i18n("Do not show the contact list window initially") ) ); + parser.addOption( QCommandLineOption( QStringLiteral( "autologin" ), + i18n("Autologin with the given username"), + QStringLiteral( "username" ) ) ); + parser.addOption( QCommandLineOption( QStringLiteral( "server" ), + i18n("Connect to the specified server instead of the default Escargot server.\n" + "Use \"localhost\" or \"127.0.0.1\" to connect to a local test server."), + QStringLiteral( "address" ) ) ); // For the developer build, // make sure we can run tests fast. #ifdef KMESSTEST - options.add( "runtest ", ki18n("Run a debug test (developer build only)") ); - options.add( "server
    ", - ki18n("Connect to the specified server instead of the official Live server.\n" - "Use \"localhost\" or \"127.0.0.1\" to connect to a local KMess Test Server.") ); + parser.addOption( QCommandLineOption( QStringLiteral( "runtest" ), + i18n("Run a debug test (developer build only)"), + QStringLiteral( "test" ) ) ); #endif @@ -223,14 +237,10 @@ int main(int argc, char *argv[]) CrashHandler::setAppName( QLatin1String( argv[0] ) ); } - // Parse command line - // Also pass about data for the arguments help dialog. - KCmdLineArgs::init( argc, argv, &aboutData ); - KCmdLineArgs::addCmdLineOptions( options ); + parser.process( kmessApp ); + aboutData.processCommandLine( &parser ); - // Create the KApplication object - // and start the event loop - KMessApplication kmessApp; + kmessApp.initialize( parser ); return kmessApp.exec(); } diff --git a/src/model/contactlist.cpp b/src/model/contactlist.cpp index 10167b8..44b9142 100644 --- a/src/model/contactlist.cpp +++ b/src/model/contactlist.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #ifdef KMESSDEBUG_CONTACTLIST @@ -989,7 +989,7 @@ Qt::ItemFlags ContactList::flags( const QModelIndex &index ) const { if( ! index.isValid() ) { - return 0; + return Qt::NoItemFlags; } ContactListModelItem *item = static_cast( index.internalPointer() ); @@ -999,7 +999,7 @@ Qt::ItemFlags ContactList::flags( const QModelIndex &index ) const #ifdef KMESSDEBUG_CONTACTLISTMODEL kmDebug() << "Invalid target item!"; #endif - return 0; + return Qt::NoItemFlags; } const Group *group; diff --git a/src/model/contactlistmodelfilter.cpp b/src/model/contactlistmodelfilter.cpp index b9f402c..c4f6820 100644 --- a/src/model/contactlistmodelfilter.cpp +++ b/src/model/contactlistmodelfilter.cpp @@ -49,6 +49,18 @@ ContactListModelFilter::ContactListModelFilter( QObject *parent ) +QString ContactListModelFilter::filterRegExp() const +{ + return filterRegularExpression().pattern(); +} + + +void ContactListModelFilter::setFilterRegExp( const QString &pattern ) +{ + setFilterRegularExpression( QRegularExpression( pattern, QRegularExpression::CaseInsensitiveOption ) ); +} + + /** * Dumps the contact list contents to the debug output * @@ -175,7 +187,7 @@ bool ContactListModelFilter::filterAcceptsRow( int sourceRow, const QModelIndex& // Manage contact searches: the list view sets the filter expression, and we use it here; // however only contacts within their original group are shown - if( ! filterRegExp().isEmpty() ) + if( ! filterRegularExpression().pattern().isEmpty() ) { isVisible = ( itemData[ "group" ] != SpecialGroups::ONLINE && itemData[ "group" ] != SpecialGroups::OFFLINE ); @@ -211,7 +223,7 @@ bool ContactListModelFilter::filterAcceptsRow( int sourceRow, const QModelIndex& * - If it is disabled: an offline contact should always be hidden *except when searching*. */ case Account::VIEW_BYGROUP: - isVisible = ( showOffline_ || contactStatus != STATUS_OFFLINE || ! filterRegExp().isEmpty() ); + isVisible = ( showOffline_ || contactStatus != STATUS_OFFLINE || ! filterRegularExpression().pattern().isEmpty() ); break; /** @@ -239,18 +251,18 @@ bool ContactListModelFilter::filterAcceptsRow( int sourceRow, const QModelIndex& */ if( id == SpecialGroups::ALLOWED ) { - isVisible = ( showAllowed_ || ! filterRegExp().isEmpty() ); + isVisible = ( showAllowed_ || ! filterRegularExpression().pattern().isEmpty() ); break; } else if( id == SpecialGroups::REMOVED ) { - isVisible = ( showRemoved_ || ! filterRegExp().isEmpty() ); + isVisible = ( showRemoved_ || ! filterRegularExpression().pattern().isEmpty() ); break; } // if we are searching in a group which is not special, and contains at least 1 contact (total), // show it: its data must be available in the model for searching. - if( ! filterRegExp().isEmpty() + if( ! filterRegularExpression().pattern().isEmpty() && ( itemData[ "isSpecialGroup" ].toBool() == false || id == SpecialGroups::INDIVIDUALS ) && itemData[ "totalContacts" ].toInt() > 0 ) { @@ -275,7 +287,7 @@ bool ContactListModelFilter::filterAcceptsRow( int sourceRow, const QModelIndex& } else if( id == SpecialGroups::OFFLINE ) { - isVisible = ( showOffline_ || ! filterRegExp().isEmpty() ); + isVisible = ( showOffline_ || ! filterRegularExpression().pattern().isEmpty() ); } else { @@ -325,7 +337,7 @@ bool ContactListModelFilter::filterAcceptsRow( int sourceRow, const QModelIndex& } else if( id == SpecialGroups::OFFLINE ) { - isVisible = ( showOffline_ || ! filterRegExp().isEmpty() ); + isVisible = ( showOffline_ || ! filterRegularExpression().pattern().isEmpty() ); } else if( id == SpecialGroups::INDIVIDUALS ) { diff --git a/src/model/contactlistmodelfilter.h b/src/model/contactlistmodelfilter.h index d76500e..dab4e14 100644 --- a/src/model/contactlistmodelfilter.h +++ b/src/model/contactlistmodelfilter.h @@ -18,6 +18,7 @@ #ifndef CONTACTLISTMODELFILTER_H #define CONTACTLISTMODELFILTER_H +#include #include #include "account.h" @@ -48,6 +49,9 @@ class ContactListModelFilter : public QSortFilterProxyModel ContactListModelFilter( QObject* parent = 0 ); // Sets the given sourceModel to be processed by the proxy model. void setSourceModel( QAbstractItemModel *sourceModel ); + // KDE4/Qt4 compatibility wrappers backed by Qt6 regular expressions. + QString filterRegExp() const; + void setFilterRegExp( const QString &pattern ); protected: // Protected methods diff --git a/src/network/applications/application.cpp b/src/network/applications/application.cpp index a70a06d..bfee702 100644 --- a/src/network/applications/application.cpp +++ b/src/network/applications/application.cpp @@ -23,7 +23,7 @@ #include -#include +#include @@ -216,9 +216,9 @@ void Application::endApplication() // Signal that this instance should be deleted, if there are no ongoing tasks that would break if the class gets deleted. if( doDelayDeletion_ ) { - // This happens when a KFileDialog or messagebox is dislayed. A sub event loop is started + // This happens when a file dialog or messagebox is displayed. A sub event loop is started // which could cause a delete signal to get through. In effect, KMess will crash because once - // the KFileDialog returns the code runs in that deleted part. + // the file dialog returns the code runs in that deleted part. #ifdef KMESSDEBUG_APPLICATION kmDebug() << "delayDeletion is in effect, waiting for the derived class to call endApplication() again."; #endif @@ -253,7 +253,7 @@ QString Application::generateCookie() const // Get a random number in the given range. number = rand()%maxNumber; // Convert the number to a QCString - cookie.sprintf("%d", number); + cookie = QString::number( number ); // Return the cookie return cookie; } diff --git a/src/network/applications/application.h b/src/network/applications/application.h index 580fae1..511c310 100644 --- a/src/network/applications/application.h +++ b/src/network/applications/application.h @@ -70,7 +70,7 @@ class Application : public QObject // The destructor virtual ~Application(); // The contact cancelled the session - virtual void contactAborted(const QString &message = QString::null); + virtual void contactAborted(const QString &message = QString()); // Return the chat the application was originally created for (may be null). Chat *getChat() const; // Return the handle of the other contact @@ -110,7 +110,7 @@ class Application : public QObject }; // The contact rejected the invitation - void contactRejected(const QString &message = QString::null); + void contactRejected(const QString &message = QString()); // Step one of a contact-started chat: the contact invites the user virtual void contactStarted1_ContactInvitesUser(const MimeMessage& message); // Step two of a contact-started chat: the user accepts diff --git a/src/network/applications/filetransfer.cpp b/src/network/applications/filetransfer.cpp index 92ba412..dfb9061 100644 --- a/src/network/applications/filetransfer.cpp +++ b/src/network/applications/filetransfer.cpp @@ -28,11 +28,11 @@ #include #include -#include +#include // It wouldn't hurt if these GUI specific features are removed here. // That would make this class GUI-independant and only emit signals for possible GUI actions. -#include +#include #include #include "../../dialogs/transferwindow.h" @@ -220,13 +220,12 @@ void FileTransfer::contactStarted2_UserAccepts() while( ! hasFile ) { // Set an initial path to the file - KUrl startDir = KFileDialog::getStartUrl( startFolder, recentFolderTag ); - startDir.addPath( suggestedFileName_ ); + const QString startPath = QDir( startFolder ).filePath( suggestedFileName_ ); delayDeletion( true ); // Ask the user for a file. - filePath_ = KFileDialog::getSaveFileName( startDir.url() ); + filePath_ = QFileDialog::getSaveFileName( nullptr, QString(), startPath ); delayDeletion( false ); if( isClosing() ) @@ -631,12 +630,12 @@ QString FileTransfer::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 diff --git a/src/network/applications/filetransfer.h b/src/network/applications/filetransfer.h index e5304a9..46d32a0 100644 --- a/src/network/applications/filetransfer.h +++ b/src/network/applications/filetransfer.h @@ -24,7 +24,7 @@ #include -#include +#include class MsnFtpConnection; diff --git a/src/network/applications/filetransferp2p.cpp b/src/network/applications/filetransferp2p.cpp index 4f18659..89b2e4e 100644 --- a/src/network/applications/filetransferp2p.cpp +++ b/src/network/applications/filetransferp2p.cpp @@ -31,11 +31,13 @@ #include #include // for Qt::escape() -#include +#include #include -#include +#include #include -#include +#include + +#include @@ -196,7 +198,7 @@ void FileTransferP2P::contactStarted1_ContactInvitesUser(const MimeMessage &mess // Generate a default preview icon // The "preview_" value is displayed later in the transfer window too. KIconLoader *loader = KIconLoader::global(); - QString iconTitle ( KMimeType::iconNameForUrl( KUrl( suggestedFileName_ ) ) ); + QString iconTitle ( QMimeDatabase().mimeTypeForFile( suggestedFileName_, QMimeDatabase::MatchExtension ).iconName() ); preview_ = QImage( loader->iconPath( iconTitle, 48, false ) ); // Save as PNG for encoding @@ -240,7 +242,7 @@ void FileTransferP2P::contactStarted1_ContactInvitesUser(const MimeMessage &mess html.prepend( "\""" + " alt=\"" + suggestedFileName_.toHtmlEscaped() + "\" />" "
    " ); } @@ -306,13 +308,12 @@ void FileTransferP2P::contactStarted2_UserAccepts() while( ! hasFile ) { // Set an initial path to the file - KUrl startDir = KFileDialog::getStartUrl( startFolder, recentFolderTag ); - startDir.addPath( suggestedFileName_ ); + const QString startPath = QDir( startFolder ).filePath( suggestedFileName_ ); delayDeletion( true ); // Ask the user for a file. - filePath_ = KFileDialog::getSaveFileName( startDir.url() ); + filePath_ = QFileDialog::getSaveFileName( nullptr, QString(), startPath ); delayDeletion( false ); if( isClosing() ) @@ -737,12 +738,12 @@ QString FileTransferP2P::toReadableBytes(uint 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 diff --git a/src/network/applications/filetransferp2p.h b/src/network/applications/filetransferp2p.h index 6a549f2..fa8c860 100644 --- a/src/network/applications/filetransferp2p.h +++ b/src/network/applications/filetransferp2p.h @@ -57,7 +57,7 @@ class FileTransferP2P : public P2PApplication private: // The contact cancelled the session - void contactAborted(const QString &message = QString::null); + void contactAborted(const QString &message = QString()); // Step one of a contact-started chat: the contact invites the user void contactStarted1_ContactInvitesUser(const MimeMessage& message); // Step two of a contact-started chat: the user accepts diff --git a/src/network/applications/mimeapplication.cpp b/src/network/applications/mimeapplication.cpp index a75a484..332d4b9 100644 --- a/src/network/applications/mimeapplication.cpp +++ b/src/network/applications/mimeapplication.cpp @@ -21,7 +21,7 @@ #include "../../kmessdebug.h" #include "../mimemessage.h" -#include +#include diff --git a/src/network/applications/msnobjecttransferp2p.cpp b/src/network/applications/msnobjecttransferp2p.cpp index efbe7e2..5fbfb9f 100644 --- a/src/network/applications/msnobjecttransferp2p.cpp +++ b/src/network/applications/msnobjecttransferp2p.cpp @@ -228,7 +228,7 @@ void MsnObjectTransferP2P::contactStarted1_gotEmoticonRequest() QByteArray data = pictureFile.readAll(); pictureFile.close(); - MsnObject testObject( CurrentAccount::instance()->getHandle(), msnObject_.getLocation(), QString::null, MsnObject::EMOTICON, data ); + MsnObject testObject( CurrentAccount::instance()->getHandle(), msnObject_.getLocation(), QString(), MsnObject::EMOTICON, data ); #ifdef KMESSDEBUG_MSNOBJECTTRANSFER_P2P kmDebug() << "msnObject_: " << msnObject_.objectString(); diff --git a/src/network/applications/p2papplication.cpp b/src/network/applications/p2papplication.cpp index 79e3f18..227d798 100644 --- a/src/network/applications/p2papplication.cpp +++ b/src/network/applications/p2papplication.cpp @@ -28,7 +28,7 @@ #include -#include +#include #ifdef KMESSDEBUG_P2PAPPLICATION @@ -2879,7 +2879,7 @@ void P2PApplication::sendSlpError( const QString &statusLine, if(sessionID == 0) { // Used to indicate a general error - content = QString::null; + content = QString(); contentType = "null"; contentLength = 0; } diff --git a/src/network/applications/p2papplication.h b/src/network/applications/p2papplication.h index 61d156c..0da7582 100644 --- a/src/network/applications/p2papplication.h +++ b/src/network/applications/p2papplication.h @@ -119,7 +119,7 @@ class P2PApplication : public P2PApplicationBase virtual ~P2PApplication(); // The contact cancelled the session - virtual void contactAborted(const QString &message = QString::null); + virtual void contactAborted(const QString &message = QString()); // Returns the branch. QString getBranch() const; // Returns the call ID (identifies the invitation). diff --git a/src/network/applications/p2papplicationbase.cpp b/src/network/applications/p2papplicationbase.cpp index 76d7ddb..a7edf8c 100644 --- a/src/network/applications/p2papplicationbase.cpp +++ b/src/network/applications/p2papplicationbase.cpp @@ -31,7 +31,7 @@ #include #include -#include +#include #ifdef KMESSDEBUG_P2PAPPLICATION @@ -1915,7 +1915,7 @@ bool P2PApplicationBase::sendP2PMessageImpl(const QByteArray &messageData, int f ackData->totalSize = totalSize; ackData->ackSessionID = ackSessionID; ackData->messageType = messageType; // used later to handle certain ACKs. - ackData->sentTime = currentTime.toTime_t(); + ackData->sentTime = currentTime.toSecsSinceEpoch(); outgoingMessages_.append(ackData); } else diff --git a/src/network/chatinformation.cpp b/src/network/chatinformation.cpp index 22b02ab..1c4869c 100644 --- a/src/network/chatinformation.cpp +++ b/src/network/chatinformation.cpp @@ -28,7 +28,7 @@ ChatInformation::ChatInformation( MsnNotificationConnection *parent, const QStri , contactHandle_(handle) , notificationConnection_(parent) , port_(0) - , requestTime_( QDateTime::currentDateTime().toTime_t() ) + , requestTime_( QDateTime::currentDateTime().toSecsSinceEpoch() ) , transactionId_(transactionId) , userStartedChat_(true) { @@ -47,7 +47,7 @@ ChatInformation::ChatInformation( MsnNotificationConnection *parent, const QStri , ip_(ip) , notificationConnection_(parent) , port_(port) - , requestTime_( QDateTime::currentDateTime().toTime_t() ) + , requestTime_( QDateTime::currentDateTime().toSecsSinceEpoch() ) , transactionId_(0) , userStartedChat_(false) { diff --git a/src/network/chatmessage.h b/src/network/chatmessage.h index ae3194b..4d2500a 100644 --- a/src/network/chatmessage.h +++ b/src/network/chatmessage.h @@ -79,10 +79,10 @@ class ChatMessage bool isIncoming, const QString & body, const QString & contactHandle, - const QString & contactName = QString::null, - const QString & contactPicturePath = QString::null, + const QString & contactName = QString(), + const QString & contactPicturePath = QString(), const QFont & font = QFont(), - const QString & fontColor = QString::null, + const QString & fontColor = QString(), const QDateTime & time = QDateTime::currentDateTime() ); // The destructor diff --git a/src/network/extra/directconnectionbase.cpp b/src/network/extra/directconnectionbase.cpp index c1b1840..7d99034 100644 --- a/src/network/extra/directconnectionbase.cpp +++ b/src/network/extra/directconnectionbase.cpp @@ -49,6 +49,7 @@ DirectConnectionBase::DirectConnectionBase( QObject *parent ) , timeout_(false) , writeHandlerCount_(0) { + lastActivity_.start(); connect( &connectionTimer_, SIGNAL( timeout() ), this, SLOT ( slotConnectionTimeout() )); @@ -279,7 +280,7 @@ QString DirectConnectionBase::getRemoteIp() const { if(socket_ == 0) { - return QString::null; + return QString(); } QHostAddress address = socket_->peerAddress(); @@ -312,7 +313,7 @@ QString DirectConnectionBase::getSocketError() const } else if(socket_ == 0) { - return QString::null; + return QString(); } else { diff --git a/src/network/extra/directconnectionbase.h b/src/network/extra/directconnectionbase.h index a501572..6c4e472 100644 --- a/src/network/extra/directconnectionbase.h +++ b/src/network/extra/directconnectionbase.h @@ -19,7 +19,7 @@ #define DIRECTCONNECTIONBASE_H #include -#include +#include #include @@ -130,7 +130,7 @@ class DirectConnectionBase : public QObject protected: // Protected attributes // Time of last activity - QTime lastActivity_; + QElapsedTimer lastActivity_; private: // Private attributes // Additional write buffer when the socket reports it can't write all data. diff --git a/src/network/extra/msndirectconnection.cpp b/src/network/extra/msndirectconnection.cpp index 29a3bf7..0469e93 100644 --- a/src/network/extra/msndirectconnection.cpp +++ b/src/network/extra/msndirectconnection.cpp @@ -116,7 +116,7 @@ bool MsnDirectConnection::sendMessage(const QByteArray &message) if( ! writeBlock( lengthField ) && ! hasTemporaryWriteError() ) { kmWarning() << "Unable to send the preamble block " - "(contact=" << contactHandle_ << ")." << endl; + "(contact=" << contactHandle_ << ")." << Qt::endl; return false; } @@ -175,7 +175,7 @@ void MsnDirectConnection::slotSocketDataReceived() { kmWarning() << "read error on socket " "(read=" << noBytesRead << " peek=" << noBytesPeeked << - " offset=" << preambleOffset_ << " contact=" << contactHandle_ << ")." << endl; + " offset=" << preambleOffset_ << " contact=" << contactHandle_ << ")." << Qt::endl; closeConnection(); return; @@ -185,7 +185,7 @@ void MsnDirectConnection::slotSocketDataReceived() #ifdef KMESSDEBUG_DIRECTCONNECTION_GENERAL kmDebug() << "read partial size preamble message " "(read=" << noBytesRead << " offset=" << preambleOffset_ << - " peek=" << noBytesPeeked << ")." << endl; + " peek=" << noBytesPeeked << ")." << Qt::endl; #endif // Received partial preamble message. @@ -202,7 +202,7 @@ void MsnDirectConnection::slotSocketDataReceived() { #ifdef KMESSDEBUG_DIRECTCONNECTION_GENERAL kmDebug() << "will wait for " - "the remaining " << ( 4 - noBytesRead ) << " bytes of the size preamble message..." << endl; + "the remaining " << ( 4 - noBytesRead ) << " bytes of the size preamble message..." << Qt::endl; #endif preambleOffset_ = noBytesRead; @@ -233,7 +233,7 @@ void MsnDirectConnection::slotSocketDataReceived() kmWarning() << "received unexpected large block length, " "aborting transfer " "(length=" << remainingBlockBytes_ << - " contact=" << contactHandle_ << ")!" << endl; + " contact=" << contactHandle_ << ")!" << Qt::endl; closeConnection(); return; } @@ -245,7 +245,7 @@ void MsnDirectConnection::slotSocketDataReceived() #ifdef KMESSDEBUG_DIRECTCONNECTION_RECEIVING kmDebug() << "4 bytes read, " - << "next block size is " << remainingBlockBytes_ << " bytes." << endl; + << "next block size is " << remainingBlockBytes_ << " bytes." << Qt::endl; #endif // End if there are no more bytes waiting to be read. @@ -265,7 +265,7 @@ void MsnDirectConnection::slotSocketDataReceived() "(returned " << noBytesRead << " block size=" << buffer_.size() << " buffer offset=" << bufferOffset_ << - " contact=" << contactHandle_ << ")" << endl; + " contact=" << contactHandle_ << ")" << Qt::endl; closeConnection(); return; } @@ -288,7 +288,7 @@ void MsnDirectConnection::slotSocketDataReceived() #ifdef KMESSDEBUG_DIRECTCONNECTION_RECEIVING kmDebug() << "read " - << noBytesRead << " bytes, " << remainingBlockBytes_ << " remaining." << endl; + << noBytesRead << " bytes, " << remainingBlockBytes_ << " remaining." << Qt::endl; #endif #ifdef KMESSTEST KMESS_ASSERT( (int) (bufferOffset_ + remainingBlockBytes_) == buffer_.size() ); @@ -310,7 +310,7 @@ void MsnDirectConnection::slotSocketDataReceived() else { kmWarning() << "received unexpected preamble packet, ignoring" - << " (data=" << buffer_.data() << " contact=" << contactHandle_ << ")." << endl; + << " (data=" << buffer_.data() << " contact=" << contactHandle_ << ")." << Qt::endl; } } else diff --git a/src/network/extra/msnftpconnection.cpp b/src/network/extra/msnftpconnection.cpp index 02e9bef..1dc5879 100644 --- a/src/network/extra/msnftpconnection.cpp +++ b/src/network/extra/msnftpconnection.cpp @@ -25,6 +25,7 @@ #include #include +#include #ifdef KMESSDEBUG_MSNFTP #define KMESSDEBUG_MSNFTP_GENERAL diff --git a/src/network/extra/msnftpconnection.h b/src/network/extra/msnftpconnection.h index ef5f96e..a327606 100644 --- a/src/network/extra/msnftpconnection.h +++ b/src/network/extra/msnftpconnection.h @@ -24,7 +24,7 @@ #include -#include +#include class QIODevice; diff --git a/src/network/mimemessage.cpp b/src/network/mimemessage.cpp index 936b21f..370409c 100644 --- a/src/network/mimemessage.cpp +++ b/src/network/mimemessage.cpp @@ -23,9 +23,7 @@ #include #include -#include -#include -#include +#include @@ -193,7 +191,7 @@ QString MimeMessage::decodeRFC2047String(const QByteArray &aStr) const char *pos, *beg, *end, *mid=0; QByteArray str, cstr, LWSP_buffer; char encoding='Q', ch; - bool valid, lastWasEncodedWord=FALSE; + bool valid, lastWasEncodedWord = false; const int maxLen=200; int i; @@ -239,13 +237,13 @@ QString MimeMessage::decodeRFC2047String(const QByteArray &aStr) const { result += LWSP_buffer + pos[0]; LWSP_buffer = 0; - lastWasEncodedWord = FALSE; + lastWasEncodedWord = false; continue; } // found possible encoded-word beg = pos+2; end = beg; - valid = TRUE; + valid = true; // parse charset name charset = ""; for (i=2,pos+=2; i=maxLen) valid = FALSE; + if (*pos!='?' || i<4 || i>=maxLen) valid = false; else { // get encoding and check delimiting question marks encoding = (char) toupper(pos[1]); if (pos[2]!='?' || (encoding!='Q' && encoding!='B')) - valid = FALSE; + valid = false; pos+=3; i+=3; } @@ -273,7 +271,7 @@ QString MimeMessage::decodeRFC2047String(const QByteArray &aStr) const ++pos; } end = pos+2;//end now points to the first char after the encoded string - if (i>=maxLen || !*pos) valid = FALSE; + if (i>=maxLen || !*pos) valid = false; } if (valid) { @@ -303,7 +301,7 @@ QString MimeMessage::decodeRFC2047String(const QByteArray &aStr) const result += codec->toUnicode(cstr); } - lastWasEncodedWord = TRUE; + lastWasEncodedWord = true; *pos = ch; pos = end -1; @@ -317,7 +315,7 @@ QString MimeMessage::decodeRFC2047String(const QByteArray &aStr) const result += LWSP_buffer; result += *pos++; result += *pos; - lastWasEncodedWord = FALSE; + lastWasEncodedWord = false; } LWSP_buffer = 0; } @@ -350,7 +348,7 @@ QTextCodec* MimeMessage::getCodecByName(const QByteArray& codecName ) return 0; } - return KGlobal::charsets()->codecForName( codecName.toLower() ); + return QTextCodec::codecForName( codecName.toLower() ); } @@ -365,8 +363,8 @@ void MimeMessage::getFieldAndValue(QString& field, QString& value, const int ind } else { - field = QString::null; - value = QString::null; + field = QString(); + value = QString(); } } @@ -452,7 +450,7 @@ QString MimeMessage::getSubValue(const QString& field, const QString& subField) return parameter; } } - return QString::null; + return QString(); } @@ -543,7 +541,7 @@ void MimeMessage::print() const if( binaryBody_.isEmpty() ) { - kmDebug() << "Body:" << endl << body_; + kmDebug() << "Body:" << Qt::endl << body_; } else { @@ -612,7 +610,7 @@ void MimeMessage::splitLine(QString& field, QString& value, const QString& line) } else { - value = QString::null; + value = QString(); } } else diff --git a/src/network/mimemessage.h b/src/network/mimemessage.h index ba60000..a70bb4c 100644 --- a/src/network/mimemessage.h +++ b/src/network/mimemessage.h @@ -20,6 +20,7 @@ #include +#include #include @@ -67,7 +68,7 @@ class MimeMessage // The total number of fields uint getNoFields() const; // Get a sub-value of a value that has multiple parameters - QString getSubValue(const QString& field, const QString& subField = QString::null) const; + QString getSubValue(const QString& field, const QString& subField = QString()) const; // Get a value given a field QString getValue(const QString& field) const; // Test whether a given field exists in the message header diff --git a/src/network/msnchallengehandler.cpp b/src/network/msnchallengehandler.cpp index 6caf296..9540d53 100644 --- a/src/network/msnchallengehandler.cpp +++ b/src/network/msnchallengehandler.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #define PRODUCT_KEY "ILTXC!4IXB5FB*PX" @@ -137,7 +138,7 @@ qint64 MSNChallengeHandler::createHashKey(const QVector& md5Integers, const QVector& challengeIntegers) { #ifdef KMESSDEBUG_CHALLENGEHANDLER - kDebug(14140) << "Creating 64-bit key."; + qDebug() << "Creating 64-bit key."; #endif qint64 magicNumber = 0x0E79A9C1L, high = 0L, low = 0L; @@ -193,4 +194,3 @@ const QString& MSNChallengeHandler::getProductId() const { return productId_; } - diff --git a/src/network/msnconnection.cpp b/src/network/msnconnection.cpp index d93a6c5..40f8d48 100644 --- a/src/network/msnconnection.cpp +++ b/src/network/msnconnection.cpp @@ -24,7 +24,7 @@ #include "multipacketmessage.h" #include "soap/httpsoapconnection.h" -#include +#include #include #ifdef KMESSDEBUG_CONNECTION // Area-specific debug statements @@ -761,7 +761,7 @@ int MsnConnection::sendMimeMessage( AckType ackType, const MimeMessage &message int ack = ack_++; QString command; - command.sprintf("MSG %u %s %u\r\n", ack, ackTypeStr, rawMessage.size()); + command = QString::asprintf( "MSG %u %s %u\r\n", ack, ackTypeStr, rawMessage.size() ); // Write the data writeBinaryData( command.toUtf8() + rawMessage ); diff --git a/src/network/msnconnection.h b/src/network/msnconnection.h index 36fb496..6f1f012 100644 --- a/src/network/msnconnection.h +++ b/src/network/msnconnection.h @@ -32,7 +32,6 @@ class QByteArray; class MimeMessage; class MsnSocketBase; class MultiPacketMessage; -class QStringList; diff --git a/src/network/msnnotificationconnection.cpp b/src/network/msnnotificationconnection.cpp index 20034fa..b6a4645 100644 --- a/src/network/msnnotificationconnection.cpp +++ b/src/network/msnnotificationconnection.cpp @@ -34,14 +34,15 @@ #include "mimemessage.h" #include "msnchallengehandler.h" +#include #include // for Qt::escape() #include #include #include #include -#include -#include +#include "../utils/kmessdialog.h" +#include #include #include @@ -68,6 +69,38 @@ */ #define NOTIFICATION_COMMAND_INTERVAL_TIMEOUT 30000 + +namespace +{ + +QString msnHandleDomain( const QString &handle ) +{ + const int atPosition = handle.indexOf( '@' ); + if( atPosition == -1 ) + { + return "escargot.chat"; + } + + return handle.mid( atPosition + 1 ); +} + + + +QString msnHandleUser( const QString &handle ) +{ + const int atPosition = handle.indexOf( '@' ); + if( atPosition == -1 ) + { + return handle; + } + + return handle.left( atPosition ); +} + +} + + + /** * @brief The constructor * @@ -82,6 +115,7 @@ MsnNotificationConnection::MsnNotificationConnection() goneOnline_(false), initialized_(false), isInitiatingConnection_(false), + legacyMsnAuthentication_(false), lastStatus_(-1), offlineImService_(0), passportLoginService_(0), @@ -366,7 +400,7 @@ void MsnNotificationConnection::changeCurrentMedia( const QString &application, // Update current media string QString media( application + "\\0" + mediaType + "\\0" + ( enabled ? "1" : "0" ) + "\\0" + formatString + "\\0" + arguments.join( "\\0" ) ); - lastCurrentMedia_ = Qt::escape( media ); + lastCurrentMedia_ = media.toHtmlEscaped(); // Send personal status and current media putUux(); @@ -393,6 +427,11 @@ void MsnNotificationConnection::changedMsnObject() changeStatus(currentAccount_->getStatus()); } + if( legacyMsnAuthentication_ ) + { + return; + } + RoamingService *roamingService = createRoamingService(); roamingService->updateDisplayPicture(); } @@ -428,6 +467,15 @@ void MsnNotificationConnection::changeFriendlyName( QString newName ) changeProperty("MFN", newName); + if( legacyMsnAuthentication_ ) + { + if( !initialStatusSent_ ) + { + goOnline(); + } + return; + } + AddressBookService *addressBook = createAddressBookService(); addressBook->contactUpdate( AddressBookService::PROPERTY_FRIENDLYNAME, newName ); @@ -453,6 +501,11 @@ void MsnNotificationConnection::changePersonalProperties( const QString& cid, in const QString blpToSend( ( blp == 0 ) ? "BL" : "AL" ); sendCommand( "BLP", blpToSend ); + if( legacyMsnAuthentication_ ) + { + return; + } + // Check if necessary to retrieve information ( like pm, picture ) from msn storage // using roaming service RoamingService *roamingService = createRoamingService(); @@ -477,9 +530,14 @@ void MsnNotificationConnection::changePersonalMessage( QString newMessage ) kmDebug() << "Changing personal message to " << newMessage; #endif - lastPsm_ = Qt::escape(newMessage); + lastPsm_ = newMessage.toHtmlEscaped(); putUux(); + if( legacyMsnAuthentication_ ) + { + return; + } + RoamingService *roamingService = createRoamingService(); roamingService->updateProfile(); } @@ -544,7 +602,7 @@ void MsnNotificationConnection::changeProperty( QString handle, QString type, QS if( contact->getGuid().isEmpty() ) { kmWarning() << "Can't change property, contact GUID is empty" - << " (contact=" << handle << " property=" << type << ")." << endl; + << " (contact=" << handle << " property=" << type << ")." << Qt::endl; return; } @@ -633,7 +691,7 @@ void MsnNotificationConnection::checkSwitchboardsTimeout() #endif // Delete any pending switchboard - uint now = QDateTime::currentDateTime().toTime_t(); + uint now = QDateTime::currentDateTime().toSecsSinceEpoch(); foreach( ChatInformation *switchboardInfo, openRequests_ ) { if( ( now - switchboardInfo->getTime() ) > 60 ) @@ -674,6 +732,7 @@ void MsnNotificationConnection::closeConnection() offlineImService_ = 0; passportLoginService_ = 0; isInitiatingConnection_ = false; + legacyMsnAuthentication_ = false; initialStatusSent_ = false; goneOnline_ = false; lastStatus_ = -1; @@ -1010,8 +1069,8 @@ void MsnNotificationConnection::goOnline() changeStatus( (Status)initialStatus ); // Reset status fields. - lastCurrentMedia_ = QString::null; - lastPsm_ = QString::null; + lastCurrentMedia_ = QString(); + lastPsm_ = QString(); // Start with default personal message (may be empty) changePersonalMessage( currentAccount_->getPersonalMessage( STRING_ORIGINAL ) ); @@ -1019,7 +1078,7 @@ void MsnNotificationConnection::goOnline() // When the account supports email (e.g. Hotmail), request the URL's. // This didn't give problems with non-email accounts, // but restricted accounts return a "710" error for this command. - if( currentAccount_->getEmailSupported() ) + if( currentAccount_->getEmailSupported() && ! legacyMsnAuthentication_ ) { // The ACK is temporary stored as inbox-command, // so the response can be mapped back to the requested folder. @@ -1155,7 +1214,26 @@ void MsnNotificationConnection::gotCvr( const QStringList& command ) initialStatusSent_ = false; // Send the USR command - sendCommand( "USR", "SSO I " + currentAccount_->getHandle() ); + sendCommand( "USR", "SSO I " + KMessShared::normalizeMsnHandle( currentAccount_->getHandle() ) ); +} + + + +// Send the legacy MSN MD5 authentication response +void MsnNotificationConnection::putLegacyMsnAuthResponse( const QString &challenge ) +{ + if(KMESS_NULL(currentAccount_)) return; + + QString password( currentAccount_->getTemporaryPassword() ); + if( password.isEmpty() ) + { + password = currentAccount_->getPassword(); + } + + const QByteArray digest( QCryptographicHash::hash( ( challenge + password ).toUtf8(), + QCryptographicHash::Md5 ).toHex() ); + + sendCommand( "USR", "MD5 S " + QString::fromLatin1( digest ) ); } @@ -1197,7 +1275,7 @@ void MsnNotificationConnection::gotIln( const QStringList& command ) // Check if the received MSN object is empty, a "0" (Kopete), or shorter than the string "" if( msnObject.isEmpty() || msnObject.compare( QString( "0" ) ) <= 0 || msnObject.length() < 12 ) { - msnObject = QString::null; + msnObject = QString(); } #ifdef KMESSDEBUG_NOTIFICATION_GENERAL @@ -1387,7 +1465,7 @@ void MsnNotificationConnection::gotUbx( const QStringList &command, const QByteA if( command[3].toInt() == 0 ) { // Size is 0, no personal message - contact->setPersonalStatus( QString::null ); + contact->setPersonalStatus( QString() ); } else { @@ -1428,7 +1506,7 @@ void MsnNotificationConnection::gotUbx( const QStringList &command, const QByteA #ifdef KMESSDEBUG_NOTIFICATION_GENERAL kmDebug() << "CurrentMedia is set, but not enabled."; #endif - currentMedia = QString::null; + currentMedia = QString(); } else { @@ -1500,9 +1578,10 @@ void MsnNotificationConnection::gotUsr( const QStringList& command ) // they close the connection before the USR. This is a nice workaround: if the connection gets // closed before this point, we just try again with HTTP, which usually works. isInitiatingConnection_ = false; + legacyMsnAuthentication_ = false; const QString& policy = command[4]; // Policy - nonceBase64_ = command[5].toAscii(); // Base64 nonce + nonceBase64_ = command[5].toLatin1(); // Base64 nonce // Change statusbar emit statusMessage( i18n("Authenticating..."), false ); @@ -1511,10 +1590,26 @@ void MsnNotificationConnection::gotUsr( const QStringList& command ) passportLoginService_ = createPassportLoginService(); passportLoginService_->login( policy ); } + else if( step == "MD5" ) + { + // Snailboat/Escargot supports legacy MSN authentication through + // MD5(challenge + stored password), as used by older MSN clients. + isInitiatingConnection_ = false; + legacyMsnAuthentication_ = true; + emit statusMessage( i18n("Authenticating..."), false ); + + if( command.count() < 5 || command[3] != "S" ) + { + kmWarning() << "Received unexpected legacy MSN authentication command:" << command; + return; + } + + putLegacyMsnAuthResponse( command[4] ); + } else if( step == "OK" ) { // This is a confirmation message. Get the user's friendly name from the message. - bool isVerified = ( command[4].toInt() == 1 ); + bool isVerified = ( command.count() > 4 ? command[4].toInt() == 1 : true ); currentAccount_->setVerified( isVerified ); #ifdef KMESSDEBUG_NOTIFICATION_GENERAL @@ -1531,10 +1626,20 @@ void MsnNotificationConnection::gotUsr( const QStringList& command ) emit statusMessage( i18n( "Authenticated" ), false ); - // Retrieve from with one SOAP request the membership list ( where there are the lists for - // FL AL BL contacts ) - AddressBookService *addressBook = createAddressBookService(); - addressBook->retrieveMembershipLists(); + if( legacyMsnAuthentication_ ) + { + // Escargot/Snailboat handles the legacy MSN protocol. Avoid the old + // Microsoft AddressBook SOAP endpoints, which are no longer available. + emit statusMessage( i18n("Waiting for contact list..."), false ); + putAdl(); + } + else + { + // Retrieve from with one SOAP request the membership list ( where there are the lists for + // FL AL BL contacts ) + AddressBookService *addressBook = createAddressBookService(); + addressBook->retrieveMembershipLists(); + } } else { @@ -1551,9 +1656,9 @@ void MsnNotificationConnection::gotVer( const QStringList& command ) if(KMESS_NULL(currentAccount_)) return; - // Send some fake info about the current version + // Identify KMess while keeping the MSNP compatibility in the VER command. // First parameter is the locale-id (0x0409 is U.S. English). - sendCommand( "CVR", "0x0409 winnt 5.1 i386 MSNMSGR 7.5.0324 msmsgs " + currentAccount_->getHandle() ); + sendCommand( "CVR", "0x0409 linux 6.0 x86_64 KMESS " KMESS_VERSION " kmess " + KMessShared::normalizeMsnHandle( currentAccount_->getHandle() ) ); } @@ -1670,15 +1775,13 @@ void MsnNotificationConnection::putAdl( const QString &handle, int list ) // If handle is present then the adl isn't initial ADL command, so use command for add someone into one list if( ! handle.isEmpty() ) { - const QStringList splittedHandle( handle.split( "@" ) ); - const QString payload( "" - "" - "" + "" + "" "" "" ); - sendPayloadMessage( "ADL", QString::null, payload.arg( QString::number( list ) ) ); + sendPayloadMessage( "ADL", QString(), payload.arg( QString::number( list ) ) ); return; } @@ -1692,7 +1795,7 @@ void MsnNotificationConnection::putAdl( const QString &handle, int list ) return; } - QHashIterator< QString,Contact* > i( contactList ); + const QList contacts( contactList.values() ); const Contact *currentContact = 0; QString adlList; @@ -1700,11 +1803,9 @@ void MsnNotificationConnection::putAdl( const QString &handle, int list ) bool send = false; int userType = 1; - while( i.hasNext() ) + for( int contactIndex = 0; contactIndex < contacts.count(); ++contactIndex ) { - i.next(); - - currentContact = i.value(); + currentContact = contacts.at( contactIndex ); if( currentContact == 0 ) { continue; @@ -1729,8 +1830,7 @@ void MsnNotificationConnection::putAdl( const QString &handle, int list ) // Add to ADL command only user in at least one list if( list != 0 ) { - // Split the domain from handle - const QStringList splittedHandle( currentContact->getHandle().split( "@" ) ); + const QString handle( currentContact->getHandle() ); // Set the user type userType = 1; @@ -1739,15 +1839,15 @@ void MsnNotificationConnection::putAdl( const QString &handle, int list ) userType = 2; } - currentAdl = ""; // Check if the buffer is too large ( 7500 bytes maximum ) if( currentAdl.toLatin1().size() + adlList.toLatin1().size() >= 7450 ) { - // Switch to true the send variable and go back to previous element + // Switch to true and process this contact again after sending. send = true; - i.previous(); + --contactIndex; } else { @@ -1763,9 +1863,9 @@ void MsnNotificationConnection::putAdl( const QString &handle, int list ) } // Send the buffer if the send variable is true or the current contact is the last of the list - if( send || ! i.hasNext() ) + if( send || contactIndex == contacts.count() - 1 ) { - sendPayloadMessage( "ADL", QString::null, "" + adlList + "" ); + sendPayloadMessage( "ADL", QString(), "" + adlList + "" ); adlList = ""; send = false; } @@ -1785,7 +1885,7 @@ void MsnNotificationConnection::putRml( const QString &handle, int list ) "" "" ); - sendPayloadMessage( "RML", QString::null, payload.arg( QString::number( list ) ) ); + sendPayloadMessage( "RML", QString(), payload.arg( QString::number( list ) ) ); } @@ -1984,7 +2084,7 @@ bool MsnNotificationConnection::openConnection() contactList_->reset( true ); #ifdef KMESS_NETWORK_WINDOW - KMESS_NET_INIT(this, "NS messenger.hotmail.com"); + KMESS_NET_INIT(this, "NS ds.escargot.nina.chat"); #endif emit statusMessage( i18n( "Connecting..." ), false ); @@ -2222,6 +2322,12 @@ void MsnNotificationConnection::parseMimeMessage( const QStringList& command, co { // After a certain ammount of messages, the XML is replaced with "too-large". // Use SOAP to request the actual mail data. + if( legacyMsnAuthentication_ ) + { + kmWarning() << "Skipping legacy offline-IM metadata SOAP request."; + return; + } + if( offlineImService_ == 0 ) { offlineImService_ = createOfflineImService(); @@ -2344,7 +2450,7 @@ void MsnNotificationConnection::parsePayloadMessage( const QStringList &command, else { kmWarning() << "Unhandled payload command: " << command[0] << "!" - << " (message dump follows)\n" << QString::fromUtf8(payload.data(), payload.size()) << endl; + << " (message dump follows)\n" << QString::fromUtf8(payload.data(), payload.size()) << Qt::endl; } } @@ -2368,7 +2474,7 @@ void MsnNotificationConnection::putUux() "{F26D1F07-95E2-403C-BC18-D4BFED493428}" "" ); - sendPayloadMessage( "UUX", QString::null, xml ); + sendPayloadMessage( "UUX", QString(), xml ); } @@ -2463,6 +2569,12 @@ void MsnNotificationConnection::receivedMailData( QDomElement mailData ) // Start a new client if there are pending messages, and no OfflineImService is active if( ! pendingOfflineImMessages_.isEmpty() ) { + if( legacyMsnAuthentication_ ) + { + kmWarning() << "Skipping legacy offline-IM SOAP download."; + return; + } + // Initialize on demand if( offlineImService_ == 0 ) { @@ -2543,7 +2655,7 @@ void MsnNotificationConnection::receivedOfflineIm( const QString &messageId, con if( pendingOfflineImMessages_.removeAll( messageId ) == 0 ) { kmWarning() << "Could not remove " - "message '" << messageId << "' from the list!" << endl; + "message '" << messageId << "' from the list!" << Qt::endl; } @@ -2591,7 +2703,7 @@ void MsnNotificationConnection::receivedOfflineIm( const QString &messageId, con else { name = from; - picture = QString::null; + picture = QString(); } } @@ -2604,7 +2716,7 @@ void MsnNotificationConnection::receivedOfflineIm( const QString &messageId, con name, picture, QFont(), - QString::null, + QString(), offlineIm->date ) ); } @@ -2671,7 +2783,7 @@ void MsnNotificationConnection::removeContactFromGroup(QString handle, QString g // Remove the current media advertising in the personal status. void MsnNotificationConnection::removeCurrentMedia() { - lastCurrentMedia_ = QString::null; + lastCurrentMedia_ = QString(); putUux(); } @@ -3007,7 +3119,7 @@ void MsnNotificationConnection::slotWarning( const QString &warning, bool isImpo { if( isImportant ) { - KMessageBox::sorry( 0, + KMessageBox::error( 0, i18nc( "Connection warning: dialog box with message", "

    Warning: %1

    ", warning ), i18nc( "Error dialog box title", "MSN Warning" ) ); @@ -3181,7 +3293,7 @@ void MsnNotificationConnection::slotError( QString error, MsnSocketBase::ErrorTy "may be required to access the network.

    " "

    Click here to visit the Messenger service " "status page.

    ", - "http://status.messenger.msn.com/Status.aspx" ); + "https://escargot.chat/support/" ); // Do not attempt to reconnect tryReconnecting = false; break; @@ -3211,7 +3323,7 @@ void MsnNotificationConnection::slotError( QString error, MsnSocketBase::ErrorTy "or the Live Messenger servers may be temporarily unavailable.

    " "

    Click here to visit the Messenger service " "status page.

    ", - "http://status.messenger.msn.com/Status.aspx" ); + "https://escargot.chat/support/" ); break; // Report errors caused by the user @@ -3297,7 +3409,7 @@ void MsnNotificationConnection::slotErrorEventActivated( NotificationManager::Ev return; } - KDialog *dialog; + KMessDialog *dialog; QString developerInfo; const QMap &info = settings.data.toMap(); @@ -3322,17 +3434,11 @@ void MsnNotificationConnection::slotErrorEventActivated( NotificationManager::Ev // We need to create a non-modal informative message box: a modal one would block // execution here, and if the user dismisses the box after the notification has // already been deleted by KDE, kmess would crash. - dialog = new KDialog( 0 ); + dialog = new KMessDialog( 0 ); dialog->setAttribute( Qt::WA_DeleteOnClose ); - dialog->setButtons( KDialog::Ok ); - KMessageBox::createKMessageBox( dialog, - QMessageBox::Information, - info["detailedMessage"].toString() + developerInfo, - QStringList(), - QString(), - 0, - KMessageBox::Notify | KMessageBox::AllowLink | KMessageBox::NoExec, - QString() ); + dialog->setButtons( KMessDialog::Ok ); + dialog->setCaption( i18n( "Notification" ) ); + dialog->setMainWidget( new QLabel( info["detailedMessage"].toString() + developerInfo, dialog ) ); dialog->show(); break; diff --git a/src/network/msnnotificationconnection.h b/src/network/msnnotificationconnection.h index 8cb97db..d837532 100644 --- a/src/network/msnnotificationconnection.h +++ b/src/network/msnnotificationconnection.h @@ -249,6 +249,8 @@ class MsnNotificationConnection : public MsnConnection void putUux(); // Send the version command void putVer(); + // Send a legacy MSN MD5 authentication response + void putLegacyMsnAuthResponse( const QString &challenge ); // Parse a regular command void parseCommand( const QStringList& command ); // Parse an error command @@ -345,6 +347,8 @@ class MsnNotificationConnection : public MsnConnection bool initialized_; // Whether or not the connection has just been established bool isInitiatingConnection_; + // Whether the current session authenticated with legacy MSN MD5. + bool legacyMsnAuthentication_; // The last current media set. QString lastCurrentMedia_; // The last Personal Status Message set. diff --git a/src/network/msnsocketbase.cpp b/src/network/msnsocketbase.cpp index d79dbf5..580a712 100644 --- a/src/network/msnsocketbase.cpp +++ b/src/network/msnsocketbase.cpp @@ -20,9 +20,8 @@ #include #include -#include +#include #include -#include /** @@ -123,11 +122,9 @@ void MsnSocketBase::proxyAuthenticate( const QNetworkProxy &proxy, QAuthenticato KPasswordDialog::KPasswordDialogFlags flags = KPasswordDialog::ShowUsernameLine -#if KDE_IS_VERSION( 4, 1, 0 ) | KPasswordDialog::ShowDomainLine | KPasswordDialog::DomainReadOnly | KPasswordDialog::ShowAnonymousLoginCheckBox -#endif | KPasswordDialog::ShowKeepPassword; KPasswordDialog loginDialog( 0, flags ); diff --git a/src/network/msnsocketbase.h b/src/network/msnsocketbase.h index cb11d66..aaa79dc 100644 --- a/src/network/msnsocketbase.h +++ b/src/network/msnsocketbase.h @@ -18,6 +18,7 @@ #ifndef MSNSOCKETBASE_H #define MSNSOCKETBASE_H +#include #include // Forward declarations diff --git a/src/network/msnsockethttp.cpp b/src/network/msnsockethttp.cpp index 3d39638..9dba17e 100644 --- a/src/network/msnsockethttp.cpp +++ b/src/network/msnsockethttp.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include @@ -41,7 +41,7 @@ * This define holds the default address which KMess uses to send HTTP * messages. The port is usually 80. */ -#define DEFAULT_GATEWAY_ADDRESS "gateway.messenger.hotmail.com" +#define DEFAULT_GATEWAY_ADDRESS "ds.escargot.nina.chat" #define DEFAULT_GATEWAY_PORT 80 @@ -158,13 +158,11 @@ void MsnSocketHttp::connectToServer( const QString& server, const quint16 port ) desiredAddress = server; } -#ifdef KMESSTEST - // Redirect to a local socket if started with --usetestserver - if( static_cast( kapp )->getUseTestServer() ) + // Redirect to another gateway if started with --server. + if( static_cast(QApplication::instance())->getUseTestServer() ) { - desiredAddress = static_cast( kapp )->getTestServer() + ":8008"; + desiredAddress = static_cast(QApplication::instance())->getTestServer(); } -#endif #ifdef KMESSDEBUG_CONNECTION_SOCKET_HTTP kmDebug() << "Connecting to server at " << desiredAddress << ":" << DEFAULT_GATEWAY_PORT << "."; diff --git a/src/network/msnsockettcp.cpp b/src/network/msnsockettcp.cpp index 84d22e2..d98f10d 100644 --- a/src/network/msnsockettcp.cpp +++ b/src/network/msnsockettcp.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include "../utils/kmessshared.h" #include "../currentaccount.h" @@ -47,7 +47,7 @@ #define LOGIN_TIMER_CONNECTION 5000 -#define MSN_TCP_HOST "messenger.hotmail.com" +#define MSN_TCP_HOST "ds.escargot.nina.chat" #define MSN_TCP_PORT 1863 @@ -154,9 +154,9 @@ void MsnSocketTcp::connectToServer( const QString& server, const quint16 port ) } // Redirect to another server if started with --server - if( static_cast( kapp )->getUseTestServer() ) + if( static_cast(QApplication::instance())->getUseTestServer() ) { - desiredServer = static_cast( kapp )->getTestServer(); + desiredServer = static_cast(QApplication::instance())->getTestServer(); } #ifdef KMESSTEST diff --git a/src/network/msnswitchboardconnection.cpp b/src/network/msnswitchboardconnection.cpp index 8560b88..22a8c06 100644 --- a/src/network/msnswitchboardconnection.cpp +++ b/src/network/msnswitchboardconnection.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include #include @@ -166,7 +166,7 @@ void MsnSwitchboardConnection::activity() #ifdef KMESSDEBUG_SWITCHBOARD_KEEPALIVE kmDebug() << ( backgroundConnection_ ? "Background" : "Chatting" ) - << "keepalive session restarted." << endl; + << "keepalive session restarted." << Qt::endl; #endif } @@ -186,7 +186,7 @@ void MsnSwitchboardConnection::cleanUnackedMessages() uint mapCount = unAckedMessages_.count(); #endif - uint minTime = QDateTime::currentDateTime().toTime_t() - ( 5 * 60 ); + uint minTime = QDateTime::currentDateTime().toSecsSinceEpoch() - ( 5 * 60 ); // Find find the entries, then delete. QList removeAcks; @@ -227,7 +227,7 @@ void MsnSwitchboardConnection::cleanUnackedMessages() #ifdef KMESSDEBUG_SWITCHBOARD_ACKS kmDebug() << "removed " << ( mapCount - unAckedMessages_.size() ) << " messages, " - << "kept " << unAckedMessages_.size() << " messages until those expire." << endl; + << "kept " << unAckedMessages_.size() << " messages until those expire." << Qt::endl; #endif } @@ -385,7 +385,7 @@ void MsnSwitchboardConnection::contactJoined( const QString& handle, const QStri if( keepAliveTimer_ && contactsInChat_.count() > 1 ) { #ifdef KMESSDEBUG_SWITCHBOARD_KEEPALIVE - kmDebug() << "Starting group chat: stopping keepalive session." << endl; + kmDebug() << "Starting group chat: stopping keepalive session." << Qt::endl; #endif keepAliveTimer_->stop(); delete keepAliveTimer_; @@ -934,7 +934,7 @@ bool MsnSwitchboardConnection::isExclusiveChatWithContact(const QString& handle) { #ifdef KMESSDEBUG_SWITCHBOARD_CONTACTS kmDebug() << "Checking if chat is exclusive with " << handle - << " (contacts=" << contactsInChat_.join(",") << ", lastContact=" << lastContact_ << ")" << endl; + << " (contacts=" << contactsInChat_.join(",") << ", lastContact=" << lastContact_ << ")" << Qt::endl; #endif // Also check for last contact, contact can be re-invited to resume the session. @@ -1076,8 +1076,8 @@ void MsnSwitchboardConnection::parseChatMessage( const QString &contactHandle, c void MsnSwitchboardConnection::parseClientCapsMessage( const QString &contactHandle, const MimeMessage &message ) { #ifdef KMESSDEBUG_SWITCHBOARD_GENERAL - kmDebug() << "Got third-party client info message. (message dump follows)" << endl - << message.getMessage().data() << endl; + kmDebug() << "Got third-party client info message. (message dump follows)" << Qt::endl + << message.getMessage().data() << Qt::endl; #endif // Example message @@ -1208,7 +1208,7 @@ void MsnSwitchboardConnection::parseEmoticonMessage( const QString &contactHandl if( it == msnObjects.end() ) { kmWarning() << "Emoticon message has an unexpected format: odd number of fields! " - << "(ignoring msnobject, contact=" << contactHandle << ")." << endl; + << "(ignoring msnobject, contact=" << contactHandle << ")." << Qt::endl; break; } @@ -1218,7 +1218,7 @@ void MsnSwitchboardConnection::parseEmoticonMessage( const QString &contactHandl if( msnObjectData.length() < 20 ) { kmWarning() << "Emoticon message has an unexpected format " - << "(ignoring msnobject, contact=" << contactHandle << ", message='" << msnObjectData << "')." << endl; + << "(ignoring msnobject, contact=" << contactHandle << ", message='" << msnObjectData << "')." << Qt::endl; continue; } @@ -1433,7 +1433,7 @@ void MsnSwitchboardConnection::parseP2PMessage( const QString &contactHandle, co // P2P dest is empty if we produce an error when a session is not initiated yet (MSNSLP header also has To: set) // Also seen with amsn 0.97 once. kmWarning() << "Unable to handle P2P message, P2P-Dest field is empty " - "(contact=" << contactHandle << ")." << endl; + "(contact=" << contactHandle << ")." << Qt::endl; return; } else if( p2pDest != currentAccount_->getHandle() ) @@ -1506,7 +1506,7 @@ void MsnSwitchboardConnection::sendApplicationMessage( const MimeMessage &messag } else { - kmWarning() << "unknown message type '" << contentType << "', can't send message!" << endl; + kmWarning() << "unknown message type '" << contentType << "', can't send message!" << Qt::endl; return; } @@ -1595,7 +1595,7 @@ void MsnSwitchboardConnection::sendChatMessage( const QString& text ) #ifdef KMESSDEBUG_SWITCHBOARD_EMOTICONS kmDebug() << "Found custom emoticon '" << code << "' which file is '" - << ( emoticonThemePath + pictureFile ) << "'." << endl; + << ( emoticonThemePath + pictureFile ) << "'." << Qt::endl; #endif QFile iFile( emoticonThemePath + pictureFile ); @@ -1611,7 +1611,7 @@ void MsnSwitchboardConnection::sendChatMessage( const QString& text ) // Read the file and create an MSNObject of the emoticon const QByteArray data( iFile.readAll() ); iFile.close(); - MsnObject test( currentAccount_->getHandle(), pictureFile, QString::null, MsnObject::EMOTICON, data ); + MsnObject test( currentAccount_->getHandle(), pictureFile, QString(), MsnObject::EMOTICON, data ); // Only divide items between each other if( ! emoticonObjects.isEmpty() ) @@ -2389,7 +2389,7 @@ void MsnSwitchboardConnection::start( const ChatInformation &chatInfo ) { if( ! contactsInChat_.isEmpty() && ! isExclusiveChatWithContact(chatInfo.getContactHandle())) { - kmWarning() << "already connected, can't start new chat with '" << chatInfo.getContactHandle() << "'!" << endl; + kmWarning() << "already connected, can't start new chat with '" << chatInfo.getContactHandle() << "'!" << Qt::endl; return; } @@ -2449,7 +2449,7 @@ void MsnSwitchboardConnection::start( const ChatInformation &chatInfo ) #ifdef KMESSDEBUG_SWITCHBOARD_GENERAL kmDebug() << "Initializing connection with " << chatInfo.getContactHandle() - << ": Connecting to SB " << chatInfo.getIp() << ":" << chatInfo.getPort() << "." << endl; + << ": Connecting to SB " << chatInfo.getIp() << ":" << chatInfo.getPort() << "." << Qt::endl; #endif // Store information from the chatinfo object @@ -2493,7 +2493,7 @@ void MsnSwitchboardConnection::storeMessageForAcknowledgement(int ack, AckType a // Create a record of the unacked message UnAckedMessage* unAcked = new UnAckedMessage(); unAcked->ackType = ackType; - unAcked->time = QDateTime::currentDateTime().toTime_t(); + unAcked->time = QDateTime::currentDateTime().toSecsSinceEpoch(); unAcked->message = message; // no problem with data size, uses shared reference. // Add to QHash @@ -2502,7 +2502,7 @@ void MsnSwitchboardConnection::storeMessageForAcknowledgement(int ack, AckType a #ifdef KMESSDEBUG_SWITCHBOARD_ACKS kmDebug() << "Stored message for acknowledgement. " << "There are currently " << unAckedMessages_.count() << " messages kept, " - << acksPending_ << " need to be ACKed." << endl; + << acksPending_ << " need to be ACKed." << Qt::endl; #endif } diff --git a/src/network/multipacketmessage.cpp b/src/network/multipacketmessage.cpp index c7c0c37..4a616f4 100644 --- a/src/network/multipacketmessage.cpp +++ b/src/network/multipacketmessage.cpp @@ -128,7 +128,7 @@ void MultiPacketMessage::addChunk( const MimeMessage &message ) if( message.getValue("Chunk").toInt() != lastChunk_ ) { kmWarning() << "received message chunk " << message.getValue("Chunk").toInt() << - ", expecting chunk " << lastChunk_ << "!" << endl; + ", expecting chunk " << lastChunk_ << "!" << Qt::endl; return; } } diff --git a/src/network/soap/addressbookservice.cpp b/src/network/soap/addressbookservice.cpp index d7f85c5..dcc06d5 100644 --- a/src/network/soap/addressbookservice.cpp +++ b/src/network/soap/addressbookservice.cpp @@ -24,7 +24,7 @@ #include "../../kmessdebug.h" #include "soapmessage.h" -#include +#include #ifdef KMESSDEBUG_HTTPSOAPCONNECTION @@ -35,12 +35,12 @@ /** * @brief URL of the Address Book Service */ -#define SERVICE_URL_ADDRESSBOOK "https://omega.contacts.msn.com/abservice/abservice.asmx" +#define SERVICE_URL_ADDRESSBOOK "https://ds.escargot.nina.chat/abservice/abservice.asmx" /** * @brief URL of the Address Book Sharing Service */ -#define SERVICE_URL_ADDRESSBOOK_SHARING "https://omega.contacts.msn.com/abservice/SharingService.asmx" +#define SERVICE_URL_ADDRESSBOOK_SHARING "https://ds.escargot.nina.chat/abservice/SharingService.asmx" diff --git a/src/network/soap/httpsoapconnection.cpp b/src/network/soap/httpsoapconnection.cpp index dd381fe..ee818df 100644 --- a/src/network/soap/httpsoapconnection.cpp +++ b/src/network/soap/httpsoapconnection.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include #ifdef KMESSDEBUG_HTTPSOAPCONNECTION @@ -339,9 +339,9 @@ void HttpSoapConnection::sendNextRequest() #ifdef KMESSTEST // Redirect to another server if started with --server - if( static_cast( kapp )->getUseTestServer() ) + if( static_cast(QApplication::instance())->getUseTestServer() ) { - endpoint.setHost( static_cast( kapp )->getTestServer() ); + endpoint.setHost( static_cast(QApplication::instance())->getTestServer() ); endpoint.setPort( 4430 ); request.setUrl( endpoint ); } @@ -495,12 +495,12 @@ void HttpSoapConnection::slotRequestFinished( QNetworkReply *reply ) { if( currentResponse->getFaultCode() == "psf:Redirect" ) { - redirectUrl = XmlFunctions::getNodeValue( currentResponse->getFault(), "redirectUrl" ); + redirectUrl = QUrl( XmlFunctions::getNodeValue( currentResponse->getFault(), "redirectUrl" ) ); } // Verify if the server is redirecting us to another server if( ! redirectUrl.isEmpty() ) { - const QUrl& originalUrl = currentResponse->getEndPoint(); + const QUrl originalUrl( currentResponse->getEndPoint() ); const QString originalHost( originalUrl.host() ); const QString redirectHost( redirectUrl.host() ); @@ -638,7 +638,7 @@ void HttpSoapConnection::slotSslErrors( QNetworkReply *reply, const QListurl(); } - // It's needed to ignore SSL errors because rsi.hotmail.com uses an invalid certificate. + // Some revived MSN service hosts use compatibility certificates that old clients ignored. reply->ignoreSslErrors(); } diff --git a/src/network/soap/msnappdirectoryservice.cpp b/src/network/soap/msnappdirectoryservice.cpp index fbb0af6..f5f519f 100644 --- a/src/network/soap/msnappdirectoryservice.cpp +++ b/src/network/soap/msnappdirectoryservice.cpp @@ -31,7 +31,7 @@ /** * @brief URL of the Application Directory Service */ -#define SERVICE_URL_APPDIRSERVICE "http://appdirectory.messenger.msn.com/AppDirectory/AppDirectory.asmx" +#define SERVICE_URL_APPDIRSERVICE "https://msnmsgr.escargot.chat/AppDirectory/AppDirectory.asmx" diff --git a/src/network/soap/offlineimservice.cpp b/src/network/soap/offlineimservice.cpp index 85df018..4158c86 100644 --- a/src/network/soap/offlineimservice.cpp +++ b/src/network/soap/offlineimservice.cpp @@ -27,9 +27,11 @@ #include "../msnchallengehandler.h" #include "soapmessage.h" +#include +#include +#include #include - -#include +#include #ifdef KMESSDEBUG_OFFLINE_IM @@ -41,12 +43,29 @@ /** * @brief URL of the Offline IM Receiving Service */ -#define SERVICE_URL_INCOMING_OFFLINE_IM_SERVICE "https://rsi.hotmail.com/rsi/rsi.asmx" +#define SERVICE_URL_INCOMING_OFFLINE_IM_SERVICE "https://ds.escargot.nina.chat/rsi/rsi.asmx" /** * @brief URL of the Offline IM Sending Service */ -#define SERVICE_URL_OUTGOING_OFFLINE_IM_SERVICE "https://ows.messenger.msn.com/OimWS/oim.asmx" +#define SERVICE_URL_OUTGOING_OFFLINE_IM_SERVICE "https://ds.escargot.nina.chat/OimWS/oim.asmx" + +static QDateTime parseOfflineMessageDate( const QString &value ) +{ + QDateTime date( QDateTime::fromString( value, Qt::RFC2822Date ) ); + if( date.isValid() ) + { + return date.toLocalTime(); + } + + date = QLocale::c().toDateTime( value, QStringLiteral( "ddd, dd MMM yyyy HH:mm:ss 'GMT'" ) ); + if( date.isValid() ) + { + date.setTimeZone( QTimeZone::UTC ); + } + + return date.toLocalTime(); +} @@ -422,12 +441,8 @@ void OfflineImService::processGetMessageResult( SoapMessage *message ) from = extractRFC822Address( from ); to = extractRFC822Address( to ); - // Convert the date from RFC 2822 format, e.g. "15 Nov 2005 14:24:27 -0800" - // NOTE: QDateTime ignores the timezone (and doesn't know about the RFC2822 format). - // Also, QDateTime only knows about UTC and local time: we'll be able to compare dates with - // precision only if we convert from KDateTime to local time or UTC! - // Of course, KDateTime::dateTime() takes care of this. - QDateTime date( KDateTime::fromString( dateString, KDateTime::RFCDate ).toClockTime().dateTime() ); + // Convert the date from RFC 2822 format, e.g. "15 Nov 2005 14:24:27 -0800". + QDateTime date( parseOfflineMessageDate( dateString ) ); // Also check for invalid dates if( ! date.isValid() ) @@ -531,7 +546,7 @@ void OfflineImService::storeMessage( const QString &to, const QString &message, // Get a copy of the message with Windows linefeeds QString messageCopy( message ); - messageCopy.replace( QRegExp("\r?\n"), windowsNewLine ); + messageCopy.replace( QRegularExpression( "\r?\n" ), QString::fromLatin1( windowsNewLine ) ); // Encode it to Base64 QByteArray contentBody( messageCopy.toUtf8() ); contentBody = contentBody.toBase64(); diff --git a/src/network/soap/passportloginservice.cpp b/src/network/soap/passportloginservice.cpp index dc1bb29..184ba08 100644 --- a/src/network/soap/passportloginservice.cpp +++ b/src/network/soap/passportloginservice.cpp @@ -25,14 +25,13 @@ #include -#include -#include +#include /** * @brief URL of the Request Security Token Service */ -#define SERVICE_URL_RST_SERVICE "https://login.live.com/RST.srf" +#define SERVICE_URL_RST_SERVICE "https://ds.escargot.nina.chat/RST.srf" // Static attributes initialization @@ -91,7 +90,7 @@ void PassportLoginService::login( const QString ¶meters ) // Store the account and login data authenticationParameters_ = parameters; - handle_ = currentAccount_->getHandle(); + handle_ = KMessShared::normalizeMsnHandle( currentAccount_->getHandle() ); // Get the right password if( password_.isEmpty() ) @@ -150,7 +149,7 @@ const QString PassportLoginService::createHotmailToken( const QString &passportT , "", ".-" ) ); // Create the token - QString token( "ct=" + QString::number( QDateTime::currentDateTime().toTime_t(), 10 ) + + QString token( "ct=" + QString::number( QDateTime::currentDateTime().toSecsSinceEpoch(), 10 ) + "&rru=" + QUrl::toPercentEncoding( folder ) + "&sru=" + QUrl::toPercentEncoding( folder ) + "&ru=" + QUrl::toPercentEncoding( folder ) + @@ -470,8 +469,8 @@ void PassportLoginService::parseSoapResult( SoapMessage *message ) const QString creationString ( XmlFunctions::getNodeValue( tokenResponse, "LifeTime/Created" ) ); const QString expirationString( XmlFunctions::getNodeValue( tokenResponse, "LifeTime/Expires" ) ); - const QDateTime &creationDate = QDateTime::fromString( creationString, Qt::ISODate ); - const QDateTime &expirationDate = QDateTime::fromString( expirationString, Qt::ISODate ); + const QDateTime creationDate = QDateTime::fromString( creationString, Qt::ISODate ); + const QDateTime expirationDate = QDateTime::fromString( expirationString, Qt::ISODate ); int ticketDuration; diff --git a/src/network/soap/roamingservice.cpp b/src/network/soap/roamingservice.cpp index 48e0fb3..efc7415 100644 --- a/src/network/soap/roamingservice.cpp +++ b/src/network/soap/roamingservice.cpp @@ -32,13 +32,17 @@ #include #include #include - -#include +#include /** * @brief URL of the Storage Service */ -#define SERVICE_URL_STORAGE_SERVICE "https://storage.msn.com/storageservice/SchematizedStore.asmx" +#define SERVICE_URL_STORAGE_SERVICE "https://ds.escargot.nina.chat/storageservice/SchematizedStore.asmx" + +static QDateTime parseServerIsoDate( const QString &value ) +{ + return QDateTime::fromString( value, Qt::ISODate ).toLocalTime(); +} // Constructor RoamingService::RoamingService( QObject *parent ) @@ -382,8 +386,8 @@ void RoamingService::processProfileResult( const QDomElement &body ) lastKnownFriendlyName_ = XmlFunctions::getNodeValue( expressionProfile, "DisplayName" ); // Fix encoding of the friendly name and personal message - lastKnownFriendlyName_ = QString::fromUtf8( lastKnownFriendlyName_.toAscii() ); - lastKnownPersonalMessage_ = QString::fromUtf8( lastKnownPersonalMessage_.toAscii() ); + lastKnownFriendlyName_ = QString::fromUtf8( lastKnownFriendlyName_.toLatin1() ); + lastKnownPersonalMessage_ = QString::fromUtf8( lastKnownPersonalMessage_.toLatin1() ); #ifdef KMESSDEBUG_ROAMINGSERVICE kmDebug() << "Got profile result:" << profileResourceId_; @@ -418,10 +422,10 @@ void RoamingService::processProfileResult( const QDomElement &body ) const QString displayPicturePath( currentAccount->getPicturePath( false /* don't fallback to the kmess default pic */ ) ); QFileInfo info( displayPicturePath ); - // KDateTime is used to process the timestamp from the server, - // because it also handles the timezone information + const QDateTime pictureModifiedDate( parseServerIsoDate( pictureLastModified ) ); + if( displayPicturePath.isEmpty() - || info.lastModified() < KDateTime::fromString( pictureLastModified, KDateTime::ISODate ).toClockTime().dateTime() ) + || info.lastModified() < pictureModifiedDate ) { #ifdef KMESSDEBUG_ROAMINGSERVICE kmDebug() << "Downloading display picture from storage"; @@ -438,7 +442,7 @@ void RoamingService::processProfileResult( const QDomElement &body ) { #ifdef KMESSDEBUG_ROAMINGSERVICE kmDebug() << "DP path:" << displayPicturePath << " Last modification date:" << info.lastModified() - << "vs. server dp's date:" << KDateTime::fromString( pictureLastModified, KDateTime::ISODate ).toClockTime().dateTime(); + << "vs. server dp's date:" << pictureModifiedDate; #endif } @@ -518,7 +522,7 @@ void RoamingService::receivedDisplayPicture( QNetworkReply *reply ) // Retrieve the picture's hash QString msnObjectHash( KMessShared::generateFileHash( tempPicturePath ).toBase64() ); - const QString safeMsnObjectHash( msnObjectHash.replace( QRegExp( "[^a-zA-Z0-9+=]"), "_" ) ); + const QString safeMsnObjectHash( msnObjectHash.replace( QRegularExpression( "[^a-zA-Z0-9+=]" ), "_" ) ); // Find out the image format QImageReader imageInfo( tempPicturePath ); diff --git a/src/network/soap/soapmessage.cpp b/src/network/soap/soapmessage.cpp index 1a7f9ad..bba32c7 100644 --- a/src/network/soap/soapmessage.cpp +++ b/src/network/soap/soapmessage.cpp @@ -20,6 +20,7 @@ #include "../../utils/xmlfunctions.h" #include "../../kmessdebug.h" +#include #include @@ -276,4 +277,3 @@ void SoapMessage::setMessage( const QString &message ) } - diff --git a/src/notification/addressbooknotifications.cpp b/src/notification/addressbooknotifications.cpp index d9a6ba5..0f71d24 100644 --- a/src/notification/addressbooknotifications.cpp +++ b/src/notification/addressbooknotifications.cpp @@ -21,7 +21,7 @@ #include "../network/soap/addressbookservice.h" -#include +#include #include // Class constructor diff --git a/src/notification/chatnotification.cpp b/src/notification/chatnotification.cpp index 5860f4e..21d67f2 100644 --- a/src/notification/chatnotification.cpp +++ b/src/notification/chatnotification.cpp @@ -28,10 +28,11 @@ #include "../currentaccount.h" #include "notificationmanager.h" +#include #include +#include #include -#include // How long a message can be without being cropped away @@ -107,7 +108,7 @@ void ChatNotification::notify( const ChatMessage &message, Chat *chat ) } // Verify if the chat is active, and if so don't notify anything - if( KWindowSystem::activeWindow() == chat->getChatWindow()->winId() + if( QApplication::activeWindow() == chat->getChatWindow() && chat == chat->getChatWindow()->getCurrentChat() ) { #ifdef KMESSDEBUG_CHATNOTIFICATION diff --git a/src/notification/contactstatusnotification.cpp b/src/notification/contactstatusnotification.cpp index efb6c26..20415d4 100644 --- a/src/notification/contactstatusnotification.cpp +++ b/src/notification/contactstatusnotification.cpp @@ -29,10 +29,9 @@ #include #include -#include -#include +#include +#include #include -#include @@ -147,26 +146,6 @@ void ContactStatusNotification::notify( Contact *contact, bool isNeeded ) text = getStatusString( status, friendlyName ); } -// TODO Fix custom contact sound, possibly using contexts and setComponentData() from KNotification -/* - // Play a sound - QString soundPath( contact->getExtension()->getContactSoundPath() ); - QFile soundFile( soundPath ); - - // If a custom audio file exists, play it - if ( soundFile.exists() ) - { -#ifdef KMESSDEBUG_CONTACTSTATUSNOTIFICATION - kmDebug() << "Play sound " << soundPath; -#endif - - // Play the custom sound instead of the generic sound - Phonon::MediaObject* media = Phonon::createPlayer( Phonon::NotificationCategory ); - media->setCurrentSource( soundPath ); - media->play(); - } -*/ - QString eventName; if( lastStatus == STATUS_OFFLINE ) { @@ -182,7 +161,7 @@ void ContactStatusNotification::notify( Contact *contact, bool isNeeded ) } // Associate the list events with the contact list window - const KMessApplication *kmessApp = static_cast( kapp ); + const KMessApplication *kmessApp = static_cast(QApplication::instance()); QWidget *mainWindow = kmessApp->getContactListWindow()->window(); NotificationManager::EventSettings settings; diff --git a/src/notification/macnotification.cpp b/src/notification/macnotification.cpp index 70a6942..ae51518 100644 --- a/src/notification/macnotification.cpp +++ b/src/notification/macnotification.cpp @@ -20,11 +20,10 @@ #include #include -#include -#include -#include +#include +#include -#include +#include #include "macnotification.h" @@ -171,14 +170,19 @@ void MacNotification::showGrowlBalloon( const QString &title, const QString &tex void MacNotification::playSound( const QString &name ) { - Phonon::MediaObject *obj = new Phonon::MediaObject(); - obj->setCurrentSource( Phonon::MediaSource("/tmp/" + name) ); - Phonon::AudioOutput *out = - new Phonon::AudioOutput(); - Phonon::createPath(obj, out); - obj->play(); - connect( obj, SIGNAL( finished() ), out, SLOT( deleteLater() ) ); - connect( obj, SIGNAL( finished() ), obj, SLOT( deleteLater() ) ); + QMediaPlayer *player = new QMediaPlayer(); + QAudioOutput *audio = new QAudioOutput( player ); + player->setAudioOutput( audio ); + player->setSource( QUrl::fromLocalFile( "/tmp/" + name ) ); + QObject::connect( player, &QMediaPlayer::playbackStateChanged, + player, [player]( QMediaPlayer::PlaybackState state ) + { + if( state == QMediaPlayer::StoppedState ) + { + player->deleteLater(); + } + } ); + player->play(); } /** diff --git a/src/notification/newemailnotification.cpp b/src/notification/newemailnotification.cpp index 3abfed8..14ee92c 100644 --- a/src/notification/newemailnotification.cpp +++ b/src/notification/newemailnotification.cpp @@ -24,7 +24,7 @@ #include -#include +#include #include @@ -90,8 +90,8 @@ void NewEmailNotification::notify( QString sender, QString subject, bool inInbox QString text( i18nc("%1 is the subject of the mail, %2 is the sender of the mail", "New email:
    '%1'
    by '%2'", - Qt::escape( subject ), - Qt::escape( sender ) ) ); + subject.toHtmlEscaped(), + sender.toHtmlEscaped() ) ); NotificationManager::EventSettings settings; settings.sender = this; diff --git a/src/notification/newsystemtraywidget.cpp b/src/notification/newsystemtraywidget.cpp index c7f31b1..3e71ed0 100644 --- a/src/notification/newsystemtraywidget.cpp +++ b/src/notification/newsystemtraywidget.cpp @@ -24,18 +24,17 @@ #include "../kmessdebug.h" #include "config-kmess.h" -#include #include #include #include #include -#include +#include #include -#include +#include +#include #include -#include -#include +#include @@ -103,7 +102,7 @@ void SystemTrayWidget::displayCloseMessage( QString /*fileMenu*/ ) // Make the icon to blink to help the user find it setStatus( KStatusNotifierItem::NeedsAttention ); - KMessageBox::information( kapp->activeWindow(), + KMessageBox::information( QApplication::activeWindow(), message, i18n( "Docking in System Tray" ), "hideOnCloseInfo" ); @@ -134,7 +133,7 @@ void SystemTrayWidget::enable() // Return the context menu -KMenu* SystemTrayWidget::menu() const +QMenu* SystemTrayWidget::menu() const { return contextMenu(); } diff --git a/src/notification/newsystemtraywidget.h b/src/notification/newsystemtraywidget.h index 1f58a99..428f9ec 100644 --- a/src/notification/newsystemtraywidget.h +++ b/src/notification/newsystemtraywidget.h @@ -18,18 +18,9 @@ #ifndef NEWSYSTEMTRAYWIDGET_H #define NEWSYSTEMTRAYWIDGET_H -#include +#include -#if KDE_IS_VERSION(4,3,70) - #include -#else - #include - using namespace Experimental; // KNotificationItem is in the Experimental namespace until 4.4 -#define KStatusNotifierItem KNotificationItem -#endif - -// Forward declarations -class KMenu; +class QMenu; @@ -57,7 +48,7 @@ class SystemTrayWidget : public KStatusNotifierItem // Enable the system tray icon void enable(); // Return the context menu - KMenu *menu() const; + QMenu *menu() const; public slots: // Change the icon when the user's status changes diff --git a/src/notification/notificationmanager.cpp b/src/notification/notificationmanager.cpp index ada467e..0184338 100644 --- a/src/notification/notificationmanager.cpp +++ b/src/notification/notificationmanager.cpp @@ -23,16 +23,17 @@ #include "../currentaccount.h" #include "../kmessdebug.h" -#include #include -#include +#include #ifndef Q_WS_MAC #include #else #include "macnotification.h" #endif -#include +#include +#include +#include #ifdef Q_WS_WIN #include @@ -146,7 +147,7 @@ QStringList NotificationManager::getButtonsLabels( int buttons ) // Return the current tray object -QSystemTrayIcon *NotificationManager::getTrayObject() +QObject *NotificationManager::getTrayObject() { return trayObject_; } @@ -183,11 +184,14 @@ void NotificationManager::notify( const QString &event, const QString &text, Eve #else bool isFullscreen = false; - #ifdef Q_WS_X11 + #if defined(Q_OS_UNIX) // Check if a full screen application is running by querying the window manager and asking // the state of the currently active window - KWindowInfo info = KWindowSystem::windowInfo( KWindowSystem::activeWindow(), NET::WMState | NET::FullScreen ); - isFullscreen = ( info.valid() && info.hasState( NET::FullScreen ) ); + if( KWindowSystem::isPlatformX11() ) + { + KWindowInfo info( KX11Extras::activeWindow(), NET::WMState ); + isFullscreen = ( info.valid() && info.hasState( NET::FullScreen ) ); + } #else #ifdef Q_WS_WIN // Windows version @@ -227,19 +231,9 @@ void NotificationManager::notify( const QString &event, const QString &text, Eve #ifdef KMESSDEBUG_NOTIFICATIONMANAGER kmDebug() << "Updating existing notification" << notification; #endif - notification->setText ( text ); - notification->setActions( getButtonsLabels( settings.buttons ) ); - // We can't update the event ID, crap. - - if( settings.contact != 0 ) - { - notification->setPixmap( QPixmap( settings.contact->getContactPicturePath() ).scaled( 96, 96 ) ); - } - - eventSettings_[ notification ] = settings; - - notification->update(); - return; + events_.remove( notification ); + eventSettings_.remove( notification ); + notification->close(); } // We have to send a new event @@ -256,11 +250,23 @@ void NotificationManager::notify( const QString &event, const QString &text, Eve eventSettings_.insert( notification, settings ); // Set it up - notification->setWidget( settings.widget ); notification->setText ( text ); - notification->setActions( getButtonsLabels( settings.buttons ) ); notification->setFlags ( KNotification::CloseOnTimeout - | KNotification::CloseWhenWidgetActivated ); + | KNotification::CloseWhenWindowActivated ); + if( settings.widget && settings.widget->windowHandle() ) + { + notification->setWindow( settings.widget->windowHandle() ); + } + + const QStringList actionLabels = getButtonsLabels( settings.buttons ); + for( int index = 0; index < actionLabels.count(); ++index ) + { + KNotificationAction *action = notification->addAction( actionLabels.at( index ) ); + connect( action, &KNotificationAction::activated, this, [this, settings, index]() + { + emit eventActivated( settings, getButtonFromAction( settings.buttons, index ) ); + } ); + } if( settings.contact != 0 ) { @@ -268,8 +274,6 @@ void NotificationManager::notify( const QString &event, const QString &text, Eve } // The slots will call the appropriate *Notification class - connect( notification, SIGNAL( activated(unsigned int) ), - this, SLOT ( relayActivation(unsigned int) ) ); connect( notification, SIGNAL( destroyed(QObject*) ), this, SLOT ( remove(QObject*) ) ); @@ -347,7 +351,7 @@ void NotificationManager::remove( QObject *object ) // Set the tray object that will be used -void NotificationManager::setTrayObject( QSystemTrayIcon *trayObject ) +void NotificationManager::setTrayObject( QObject *trayObject ) { trayObject_ = trayObject; } diff --git a/src/notification/notificationmanager.h b/src/notification/notificationmanager.h index b505cc3..9478ede 100644 --- a/src/notification/notificationmanager.h +++ b/src/notification/notificationmanager.h @@ -23,9 +23,6 @@ #include -// Forward declarations -class QSystemTrayIcon; - #ifndef Q_WS_MAC class KNotification; #endif @@ -81,9 +78,9 @@ class NotificationManager : public QObject // Insert a new popup in the stack if needed, or change an existing one void notify( const QString &event, const QString &text, EventSettings settings ); // Return the current tray widget object - QSystemTrayIcon *getTrayObject(); + QObject *getTrayObject(); // Set the tray widget object that will be used - void setTrayObject( QSystemTrayIcon *trayObject ); + void setTrayObject( QObject *trayObject ); public: // Public static methods // Return a singleton instance of the current account @@ -113,7 +110,7 @@ class NotificationManager : public QObject QHash eventSettings_; #endif // The System Tray widget to which the popups will refer - QSystemTrayIcon *trayObject_; + QObject *trayObject_; // The instance of the singleton manager static NotificationManager *instance_; diff --git a/src/notification/systemtraywidget.cpp b/src/notification/systemtraywidget.cpp index 775ecbf..6192840 100644 --- a/src/notification/systemtraywidget.cpp +++ b/src/notification/systemtraywidget.cpp @@ -23,15 +23,16 @@ #include "kmessdebug.h" #include "utils/kmessshared.h" -#include #include +#include #include #include +#include #include -#include +#include #include -#include +#include #include #ifdef Q_WS_WIN @@ -92,7 +93,7 @@ void SystemTrayWidget::displayCloseMessage( QString /*fileMenu*/ ) kmDebug() << "Displaying simple dialog with no screenshot."; #endif - KMessageBox::information( kapp->activeWindow(), message, + KMessageBox::information( QApplication::activeWindow(), message, i18n( "Docking in System Tray" ), "hideOnCloseInfo" ); return; @@ -105,7 +106,12 @@ void SystemTrayWidget::displayCloseMessage( QString /*fileMenu*/ ) // Get initial position of the tray icon and the the screen size QRect pictureArea( geometry() ); QRect pictureGeometry( geometry() ); - QRect desktopArea = kapp->desktop()->screenGeometry( geometry().topLeft() ); + QScreen *screen = QGuiApplication::screenAt( geometry().topLeft() ); + if( ! screen ) + { + screen = QGuiApplication::primaryScreen(); + } + QRect desktopArea = screen ? screen->geometry() : QRect(); // Compute the final size and position of the pixmap to grab const int xRadius = desktopArea.width() / 8; @@ -159,7 +165,7 @@ void SystemTrayWidget::displayCloseMessage( QString /*fileMenu*/ ) // Draw the circle with a dark shadow QPainter painter( &shot ); - painter.setPen( QPen(KApplication::palette().dark(), CIRCLE_WIDTH) ); + painter.setPen( QPen(QApplication::palette().dark(), CIRCLE_WIDTH) ); painter.drawArc( circleArea.adjusted( SHADOW_OFFSET, SHADOW_OFFSET, 0, 0 ), 0, 16*360 ); painter.setPen( QPen(Qt::red, CIRCLE_WIDTH) ); painter.drawArc( circleArea, 0, 16*360); @@ -170,7 +176,7 @@ void SystemTrayWidget::displayCloseMessage( QString /*fileMenu*/ ) // Then, we add a border around the image, to make it more visible QPixmap finalShot( pictureArea.size() ); - finalShot.fill( KApplication::palette().color( QPalette::Active, QPalette::Foreground ) ); + finalShot.fill( QApplication::palette().color( QPalette::Active, QPalette::Foreground ) ); painter.begin( &finalShot ); painter.drawPixmap( QRect( IMAGE_BORDER, IMAGE_BORDER, shot.width() - IMAGE_BORDER*2, shot.height() - IMAGE_BORDER*2 ), shot ); painter.end(); @@ -187,7 +193,7 @@ void SystemTrayWidget::displayCloseMessage( QString /*fileMenu*/ ) #endif // Show the dialog - KMessageBox::information(kapp->activeWindow(), + KMessageBox::information(QApplication::activeWindow(), "

    " + message + "

    activeWindow(), + KMessageBox::information(QApplication::activeWindow(), "

    " + message + "

    ", i18n("Docking in System Tray"), "hideOnCloseInfo"); } diff --git a/src/notification/systemtraywidget.h b/src/notification/systemtraywidget.h index b288bb2..b04a1b6 100644 --- a/src/notification/systemtraywidget.h +++ b/src/notification/systemtraywidget.h @@ -1,63 +1,6 @@ -/*************************************************************************** - systemtraywidget.h - description - ------------------- - begin : Sun Dec 29 2002 - copyright : (C) 2002 by Mike K. Bennett - email : mkb137b@hotmail.com - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - #ifndef SYSTEMTRAYWIDGET_H #define SYSTEMTRAYWIDGET_H -#include - - -// Forward declarations -class CurrentAccount; -class KMenu; - - - -/** - * @brief System tray event handling. - * - * The user's status is displayed in the system tray. - * It also gives access to some settings. - * This class handles the events fired by the KDE systemtray. - * - * @author Mike K. Bennett - * @ingroup Root - */ -class SystemTrayWidget : public KSystemTrayIcon -{ - Q_OBJECT - - public: - // The constructor - SystemTrayWidget( QWidget *parent=0 ); - // The destructor - virtual ~SystemTrayWidget(); - // Display a customized close window with a screenshot of the app's tray icon - void displayCloseMessage( QString fileMenu = QString::null ); - // Return the context menu - QMenu *menu() const; - - private: // private attributes - // Pointer to current account informations - CurrentAccount *currentAccount_; - - private slots: // Private slots - // Change the icon when the user's status changes - void statusChanged(); -}; +#include "newsystemtraywidget.h" #endif diff --git a/src/settings/accountpage.cpp b/src/settings/accountpage.cpp index 51e47e8..91e019c 100644 --- a/src/settings/accountpage.cpp +++ b/src/settings/accountpage.cpp @@ -27,16 +27,16 @@ #include #include +#include -#include +#include -#include -#include -#include -#include +#include +#include +#include +#include #include #include -#include @@ -71,18 +71,17 @@ AccountPage::AccountPage( QWidget* parent ) connect( rememberCheckbox_, SIGNAL( toggled(bool) ), this, SLOT( rememberMeToggled(bool) ) ); // Find the default picture - KStandardDirs *dirs = KGlobal::dirs(); - QString defaultPicture ( dirs->findResource( "data", "kmess/pics/kmesspic.png" ) ); + QString defaultPicture ( KMessShared::findResource( "data", "kmess/pics/kmesspic.png" ) ); // Load the picture in the X-Server: defaultPixmap_ = QPixmap(defaultPicture); customPixmap_ = defaultPixmap_; // Create the "Change..." button actions - KMenu *browsePopup = new KMenu( this ); - KAction *browseSimple = new KAction( KIcon("folder-open"), i18n("Browse..."), this ); - KAction *browseResize = new KAction( KIcon("edit-cut"), i18n("Browse and Crop Picture..."), this ); - KAction *setPrevious = new KAction( KIcon("edit-redo"), i18n("Set Previous Image..."), this ); + QMenu *browsePopup = new QMenu( this ); + QAction *browseSimple = new QAction( QIcon::fromTheme( "folder-open" ), i18n("Browse..."), this ); + QAction *browseResize = new QAction( QIcon::fromTheme( "edit-cut" ), i18n("Browse and Crop Picture..."), this ); + QAction *setPrevious = new QAction( QIcon::fromTheme( "edit-redo" ), i18n("Set Previous Image..."), this ); connect( browseSimple, SIGNAL(activated()), this, SLOT(pictureBrowseSimple() ) ); connect( browseResize, SIGNAL(activated()), this, SLOT(pictureBrowseResize() ) ); connect( setPrevious, SIGNAL(activated()), this, SLOT( pictureSetPrevious() ) ); @@ -217,7 +216,7 @@ void AccountPage::loadSettings( const Account *account, bool isCurrentAccount) handleEdit_ ->setEnabled( true ); // Only show the Register link when creating new accounts - bool hasInvalidHandle = ( account->getHandle() == i18n("you@hotmail.com") ); + bool hasInvalidHandle = ( account->getHandle() == i18n("you@escargot.chat") ); registerLabel_ ->setVisible( hasInvalidHandle ); registerButton_ ->setVisible( hasInvalidHandle ); } @@ -321,7 +320,7 @@ void AccountPage::saveSettings( Account *account ) { // Retrieve the picture's hash 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 pictureName = msnObjectHash + ".png"; @@ -420,9 +419,7 @@ void AccountPage::selectPicture( bool resize, QString picturePath ) { // This code is partially borrowed from Kopete. - KStandardDirs *dirs = KGlobal::dirs(); - bool isRemoteFile = false; - KUrl filePath; + QUrl filePath; QString localFilePath; QImage pictureData; @@ -441,12 +438,12 @@ void AccountPage::selectPicture( bool resize, QString picturePath ) // Search a resourcedir to use as default. // all pictures: dirs->findAllResources("data", "kdm/pics/users/*.png") - // default dir: dirs->findResource("data", "kdm/pics/users/"); + // default dir: KMessShared::findResource("data", "kdm/pics/users/"); // Get the resourcedir which contains the largest collection of pictures. // This fixes a problem with SuSE, where /etc/opt/kde/share is returned instead of /opt/kde3/share - const QStringList kdmDirs( dirs->findDirs( "data", "kdm/pics/users/" ) ); + const QStringList kdmDirs( KMessShared::findResourceDirs( "data", "kdm/pics/users/" ) ); QDir kdmDir; int fileCount = 0; @@ -463,11 +460,14 @@ void AccountPage::selectPicture( bool resize, QString picturePath ) } } - filePath = KFileDialog::getImageOpenUrl( startDir, this, i18n( "Display Picture" ) ); + filePath = QFileDialog::getOpenFileUrl( this, + i18n( "Display Picture" ), + QUrl::fromLocalFile( startDir ), + QStringLiteral( "Images (*.png *.jpg *.jpeg *.gif *.bmp *.webp);;All Files (*)" ) ); } else { - filePath = picturePath; + filePath = QUrl::fromUserInput( picturePath, QDir::currentPath(), QUrl::AssumeLocalFile ); } if( filePath.isEmpty() ) @@ -478,26 +478,15 @@ void AccountPage::selectPicture( bool resize, QString picturePath ) // Save location if the user selected the image. if( picturePath.isEmpty() ) { - originalPicturePath_ = filePath.pathOrUrl(); + originalPicturePath_ = filePath.toString( QUrl::PreferLocalFile ); } // Read the path. - if( filePath.isLocalFile() ) + QString temporaryFilePath; + if( ! KMessShared::downloadToLocalFile( filePath, localFilePath, &temporaryFilePath ) ) { - localFilePath = filePath.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(filePath, localFilePath, this ) ) - { - KMessageBox::sorry( this, i18n( "Downloading of display picture failed" ), i18n("KMess") ); - return; - } - - isRemoteFile = true; + KMessageBox::error( this, i18n( "Downloading of display picture failed" ), i18n("KMess") ); + return; } @@ -506,10 +495,7 @@ void AccountPage::selectPicture( bool resize, QString picturePath ) pictureData = QImage( localFilePath ); // Load picture data // Remove any temporary files - if( isRemoteFile ) - { - KIO::NetAccess::removeTempFile( localFilePath ); - } + KMessShared::removeDownloadedTempFile( temporaryFilePath ); // Allow the user to select a region of the picture if( resize ) @@ -551,7 +537,7 @@ void AccountPage::selectPicture( bool resize, QString picturePath ) } else { - 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" ) ); @@ -576,7 +562,7 @@ void AccountPage::showPictureToggled( bool noPicture ) void AccountPage::showRegisterPassport() { // Launch the browser for the given URL - KMessShared::openBrowser( KUrl( "https://accountservices.passport.net/reg.srf" ) ); + KMessShared::openBrowser( QUrl( "https://account.nina.chat/register/" ) ); } @@ -585,7 +571,7 @@ void AccountPage::showRegisterPassport() void AccountPage::showVerifyPassport() { // Launch the browser for the given URL - KMessShared::openBrowser( KUrl( "https://login.live.com/emailval.srf" ) ); + KMessShared::openBrowser( QUrl( "https://account.nina.chat/login/" ) ); } diff --git a/src/settings/accountpage.ui b/src/settings/accountpage.ui index 5bb56f6..7a3beb5 100644 --- a/src/settings/accountpage.ui +++ b/src/settings/accountpage.ui @@ -57,10 +57,10 @@ - Enter the email address of your MSN Passport account. You can register a new account at http://register.passport.com/ + Enter the username of your NINA/Escargot account. You can register a new account at https://account.nina.chat/register/ - &Email address: + &Username: false @@ -76,7 +76,7 @@ - Enter the password of your MSN Passport account. You can register a new account at http://register.passport.com/ + Enter the password of your NINA/Escargot account. You can register a new account at https://account.nina.chat/register/ &Password: @@ -222,7 +222,7 @@ - + 0 @@ -372,10 +372,10 @@ It is recommended to enable this option, unless you are using KMess as guest or - You need to connect to the Passport site to confirm that your email address exists. + You need to connect to account.nina.chat to manage your account. - You cannot change your friendly name because your Passport email address is not verified. + You cannot change your friendly name because your NINA/Escargot account is not verified. Qt::AlignVCenter @@ -424,7 +424,7 @@ It is recommended to enable this option, unless you are using KMess as guest or - Go to accountservices.passport.net + Go to account.nina.chat true @@ -443,10 +443,10 @@ It is recommended to enable this option, unless you are using KMess as guest or - <html>You need a Passport account to connect to the Live Messenger network. You can register your current email address at register.passport.com or use a Live Mail account to connect.</html> + <html>You need a NINA/Escargot account to connect to the Escargot MSN service. You can register a new account at account.nina.chat.</html> - To connect to the Live Messenger service, you will need to register an email address as Passport account. + To connect to the Escargot MSN service, you will need to register a NINA/Escargot account. Qt::AlignVCenter @@ -495,7 +495,7 @@ It is recommended to enable this option, unless you are using KMess as guest or - Go to register.passport.com + Go to account.nina.chat true @@ -671,20 +671,15 @@ It is recommended to enable this option, unless you are using KMess as guest or - - KPushButton - QPushButton -
    kpushbutton.h
    -
    KLineEdit QLineEdit -
    klineedit.h
    +
    KLineEdit
    KUrlLabel QLabel -
    kurllabel.h
    +
    KUrlLabel
    diff --git a/src/settings/accountsettingsdialog.cpp b/src/settings/accountsettingsdialog.cpp index 08a83e7..d2e27ee 100644 --- a/src/settings/accountsettingsdialog.cpp +++ b/src/settings/accountsettingsdialog.cpp @@ -35,6 +35,8 @@ #include #include +#include +#include #include @@ -46,7 +48,7 @@ AccountSettingsDialog* AccountSettingsDialog::instance_(0); // The constructor AccountSettingsDialog::AccountSettingsDialog( QWidget *parent ) -: KPageDialog( parent ) +: KMessPageDialog( parent ) , account_(0) , initialPage_( PageAccount ) { @@ -78,30 +80,30 @@ AccountSettingsDialog::AccountSettingsDialog( QWidget *parent ) page = addPage( accountPage_, i18n("Account") ); page->setHeader( i18n( "My Account" ) ); - page->setIcon( KIcon( "user-identity" ) ); + page->setIcon( QIcon::fromTheme( "user-identity" ) ); pageWidgets_.insert( PageAccount, page ); pageWidgets_.insert( PageAccountStatus, page ); page = addPage( contactListPage_, i18n("Contact List") ); page->setHeader( i18n( "Contact List" ) ); - page->setIcon( KIcon( "view-list-details" ) ); + page->setIcon( QIcon::fromTheme( "view-list-details" ) ); pageWidgets_.insert( PageContactList, page ); page = addPage( emoticonPage_, i18n("Emoticons") ); page->setHeader( i18n( "Emoticons" ) ); - page->setIcon( KIcon( "emoticons" ) ); + page->setIcon( QIcon::fromTheme( "emoticons" ) ); pageWidgets_.insert( PageEmoticons, page ); pageWidgets_.insert( PageEmoticonsTabCustom, page ); page = addPage( chattingPage_, i18n("Chatting") ); page->setHeader( i18n( "Chatting" ) ); - page->setIcon( KIcon( "format-stroke-color" ) ); // preferences-desktop-color, insert-text? + page->setIcon( QIcon::fromTheme( "format-stroke-color" ) ); // preferences-desktop-color, insert-text? pageWidgets_.insert( PageChatStyle, page ); pageWidgets_.insert( PageChatStyleTabText, page ); page = addPage( chatLoggingPage_, i18n("Chat Logging") ); page->setHeader( i18n( "Chat Logging" ) ); - page->setIcon( KIcon( "document-save-as" ) ); + page->setIcon( QIcon::fromTheme( "document-save-as" ) ); pageWidgets_.insert( PageChatLogging, page ); } @@ -144,13 +146,13 @@ void AccountSettingsDialog::loadSettings( Account *account, bool isCurrentAccoun // Disable the "remove account" button for guest accounts and for // the current account - KMessApplication *kmessApp = static_cast( kapp ); + KMessApplication *kmessApp = static_cast(QApplication::instance()); if( account->isGuestAccount() || ( CurrentAccount::instance()->getHandle() == account->getHandle() && kmessApp->getContactListWindow()->isConnected() ) ) { - enableButton( KDialog::User1, false ); - setButtonToolTip( KDialog::User1, + enableButton( KMessPageDialog::User1, false ); + setButtonToolTip( KMessPageDialog::User1, i18nc( "Button tooltip text", "Click here to delete this account from the " "list of registered accounts.\nYou cannot delete " @@ -201,10 +203,10 @@ bool AccountSettingsDialog::saveAccountSettings() QString oldFriendlyName ( account_->getFriendlyName( STRING_ORIGINAL ) ); // Make sure the account handle was changed off the default - if( newHandle.isEmpty() || ! Account::isValidEmail( newHandle ) - || newHandle == i18n( "you@hotmail.com" ) ) + if( newHandle.isEmpty() || ! Account::isValidHandle( newHandle ) + || newHandle == i18n( "you@escargot.chat" ) ) { - KMessageBox::error( 0, i18n( "The email address you have entered is not valid, and cannot be used as an account: '%1'", newHandle ) ); + KMessageBox::error( 0, i18n( "The username you have entered is not valid, and cannot be used as an account: '%1'", newHandle ) ); return false; } @@ -212,7 +214,7 @@ bool AccountSettingsDialog::saveAccountSettings() if( oldHandle != newHandle && AccountsManager::instance()->getAccountByHandle( newHandle ) != 0 ) { - KMessageBox::error( 0, i18n( "The email address you have entered is already in use: '%1'", newHandle ) ); + KMessageBox::error( 0, i18n( "The username you have entered is already in use: '%1'", newHandle ) ); return false; } @@ -287,7 +289,7 @@ void AccountSettingsDialog::slotButtonClicked( int button ) { switch( button ) { - case KDialog::Ok: + case KMessPageDialog::Ok: if( ! saveAccountSettings() ) { return; @@ -296,21 +298,25 @@ void AccountSettingsDialog::slotButtonClicked( int button ) accept(); break; - case KDialog::Apply: + case KMessPageDialog::Apply: saveAccountSettings(); // Do not delete the dialog, we still need it return; break; - case KDialog::Cancel: - case KDialog::Close: + case KMessPageDialog::Cancel: + case KMessPageDialog::Close: reject(); break; - case KDialog::User1: + case KMessPageDialog::User1: // Delete the account, but first ask the user for confirmation - if( KMessageBox::warningYesNo( this, i18n("Are you sure you want to delete this account?") ) == KMessageBox::Yes ) + if( KMessageBox::warningTwoActions( this, + i18n("Are you sure you want to delete this account?"), + i18n( "Delete Account" ), + KGuiItem( i18n( "Yes" ) ), + KGuiItem( i18n( "No" ) ) ) == KMessageBox::PrimaryAction ) { emit deleteAccount( account_ ); reject(); @@ -323,7 +329,7 @@ void AccountSettingsDialog::slotButtonClicked( int button ) break; default: - KDialog::slotButtonClicked( button ); + KMessPageDialog::slotButtonClicked( button ); break; } diff --git a/src/settings/accountsettingsdialog.h b/src/settings/accountsettingsdialog.h index debd47f..b075437 100644 --- a/src/settings/accountsettingsdialog.h +++ b/src/settings/accountsettingsdialog.h @@ -20,7 +20,8 @@ //#include -#include +#include "../utils/kmesspagedialog.h" +#include // Forward declarations @@ -42,7 +43,7 @@ class EmoticonsPage; * @author Mike K. Bennett * @ingroup Settings */ -class AccountSettingsDialog : public KPageDialog +class AccountSettingsDialog : public KMessPageDialog { Q_OBJECT diff --git a/src/settings/accountsmanagerpage.cpp b/src/settings/accountsmanagerpage.cpp index 5e50928..ec6dd71 100644 --- a/src/settings/accountsmanagerpage.cpp +++ b/src/settings/accountsmanagerpage.cpp @@ -27,6 +27,7 @@ #include +#include #include @@ -88,7 +89,7 @@ void AccountsManagerPage::accountSelected() // Disallow removal of the currently connected account. if( hasSelection ) { - const KMessApplication *kmessApp = static_cast( kapp ); + const KMessApplication *kmessApp = static_cast(QApplication::instance()); const QListWidgetItem *selection = accountsList_->selectedItems().first(); const QString handle( selection->data( Qt::UserRole ).toString() ); @@ -141,7 +142,7 @@ void AccountsManagerPage::deleteAccount() const QString handle( selection->data( Qt::UserRole ).toString() ); // Prevent deletion of the currently connected account - const KMessApplication *kmessApp = static_cast( kapp ); + const KMessApplication *kmessApp = static_cast(QApplication::instance()); if( kmessApp->getContactListWindow()->isConnected() && CurrentAccount::instance()->getHandle() == handle ) { @@ -155,12 +156,15 @@ void AccountsManagerPage::deleteAccount() return; } - int result = KMessageBox::warningYesNo( + int result = KMessageBox::warningTwoActions( this, i18n("Are you sure you want to delete the account '%1' ?
    " "All settings of this account will be lost.", - handle ) ); - if( result != KMessageBox::Yes ) + handle ), + i18n( "Delete Account" ), + KGuiItem( i18n( "Yes" ) ), + KGuiItem( i18n( "No" ) ) ); + if( result != KMessageBox::PrimaryAction ) { return; } diff --git a/src/settings/accountsmanagerpage.ui b/src/settings/accountsmanagerpage.ui index eee7834..1e71d86 100644 --- a/src/settings/accountsmanagerpage.ui +++ b/src/settings/accountsmanagerpage.ui @@ -31,7 +31,7 @@
    - + true @@ -121,13 +121,6 @@ qPixmapFromMimeSource - - - KListWidget - QListWidget -
    klistwidget.h
    -
    -
    diff --git a/src/settings/chatloggingpage.cpp b/src/settings/chatloggingpage.cpp index 5d98b63..1fb35fa 100644 --- a/src/settings/chatloggingpage.cpp +++ b/src/settings/chatloggingpage.cpp @@ -19,7 +19,7 @@ #include "../account.h" -#include +#include @@ -50,7 +50,7 @@ ChatLoggingPage::ChatLoggingPage( QWidget *parent ) void ChatLoggingPage::chooseDirectory() { // Let the user choose a folder, starting from the previously set path (if any) - const QString dir( KFileDialog::getExistingDirectory( chatSavePathEdit_->text() ) ); + const QString dir( QFileDialog::getExistingDirectory( this, QString(), chatSavePathEdit_->text() ) ); if( ! dir.isEmpty() ) { diff --git a/src/settings/chatstylepage.cpp b/src/settings/chatstylepage.cpp index 32fabcc..ea4f89b 100644 --- a/src/settings/chatstylepage.cpp +++ b/src/settings/chatstylepage.cpp @@ -21,13 +21,13 @@ #include "../chat/chatmessageview.h" #include "../currentaccount.h" #include "../kmessdebug.h" +#include "../utils/kmessshared.h" #include -#include -#include -#include -#include +#include +#include +#include @@ -40,18 +40,17 @@ ChatStylePage::ChatStylePage( QWidget *parent ) { setupUi( this ); - newStylesButton_->setIcon( KIcon( "get-hot-new-stuff" ) ); + newStylesButton_->setIcon( QIcon::fromTheme( "get-hot-new-stuff" ) ); QPixmap pixmap; const QString& emoticonDir = CurrentAccount::instance()->getEmoticonStyle(); - KStandardDirs *dirs = KGlobal::dirs(); // Set up the emoticons which explain what the graphics elements in chat are - pixmap.load( dirs->findResource( "emoticons", emoticonDir + "/teeth.png" ) ); + pixmap.load( KMessShared::findResource( "emoticons", emoticonDir + "/teeth.png" ) ); pixmapLabel1_->setPixmap( pixmap ); - pixmap.load( dirs->findResource( "emoticons", emoticonDir + "/rainbow.png" ) ); + pixmap.load( KMessShared::findResource( "emoticons", emoticonDir + "/rainbow.png" ) ); pixmapLabel2_->setPixmap( pixmap ); - pixmap.load( dirs->findResource( "emoticons", emoticonDir + "/dog.png" ) ); + pixmap.load( KMessShared::findResource( "emoticons", emoticonDir + "/dog.png" ) ); pixmapLabel3_->setPixmap( pixmap ); // Connect our signals @@ -120,7 +119,7 @@ void ChatStylePage::loadStyleList() chatStyle_->clear(); // Get all available chat styles for the "chatting" widget, avoiding duplicate entries - const QStringList stylesDirectories( KGlobal::dirs()->findDirs( "data", "kmess/styles" ) ); + const QStringList stylesDirectories( KMessShared::findResourceDirs( "data", "kmess/styles" ) ); foreach( const QString &dir, stylesDirectories ) { @@ -197,11 +196,9 @@ void ChatStylePage::fontClicked() bool ChatStylePage::getFont( QFont &font ) const { bool accepted; - int result; QFont selection = font; - result = KFontDialog::getFont( selection ); - accepted = ( result == KFontDialog::Accepted ); + selection = QFontDialog::getFont( &accepted, selection ); if ( accepted ) { @@ -414,10 +411,6 @@ void ChatStylePage::useContactFontToggled( bool checked ) // Open a dialog for KDE New Stuff Chat Themes void ChatStylePage::getNewThemes() { - KNS::Engine engine( this ); - engine.init( "kmesschatstyles.knsrc" ); - KNS::Entry::List entries = engine.downloadDialogModal( this ); - loadStyleList(); } diff --git a/src/settings/chatstylepage.ui b/src/settings/chatstylepage.ui index 9ce67cf..6290692 100644 --- a/src/settings/chatstylepage.ui +++ b/src/settings/chatstylepage.ui @@ -59,7 +59,7 @@
    - + Get &New Styles... @@ -697,15 +697,10 @@ - - KPushButton - QPushButton -
    kpushbutton.h
    -
    KColorButton QPushButton -
    kcolorbutton.h
    +
    KColorButton
    diff --git a/src/settings/emoticonspage.cpp b/src/settings/emoticonspage.cpp index 4cff278..7a264e0 100644 --- a/src/settings/emoticonspage.cpp +++ b/src/settings/emoticonspage.cpp @@ -21,13 +21,14 @@ #include "../currentaccount.h" #include "../emoticonmanager.h" #include "../kmessdebug.h" +#include "../utils/kmessshared.h" #include #include #include +#include #include -#include #ifdef KMESSDEBUG_EMOTICONS @@ -194,10 +195,12 @@ void EmoticonsPage::removeCustomEmoticon() const QListWidgetItem *item = selectedItems.first(); // Request confirmation - int result = KMessageBox::questionYesNo( this, + int result = KMessageBox::questionTwoActions( this, i18n( "Are you sure you want to delete the emoticon \"%1\" ?", item->text() ), - i18nc( "Dialog box title", "Delete Emoticon" ) ); - if( result != KMessageBox::Yes ) + i18nc( "Dialog box title", "Delete Emoticon" ), + KGuiItem( i18n( "Yes" ) ), + KGuiItem( i18n( "No" ) ) ); + if( result != KMessageBox::PrimaryAction ) { return; } @@ -334,7 +337,7 @@ void EmoticonsPage::updateThemesList() emoticonThemesList_->clear(); // Browse all emoticon dirs, to get all emoticons - const QStringList themesDirs( KGlobal::dirs()->findDirs("emoticons", "") ); + const QStringList themesDirs( KMessShared::findResourceDirs("emoticons", "") ); #ifdef KMESSDEBUG_EMOTICONS_SETTINGS kmDebug() << "Theme dirs: " << themesDirs; diff --git a/src/settings/emoticonspage.ui b/src/settings/emoticonspage.ui index 01b5f9c..dcd2254 100644 --- a/src/settings/emoticonspage.ui +++ b/src/settings/emoticonspage.ui @@ -41,7 +41,7 @@
    - + true @@ -268,13 +268,6 @@ qPixmapFromMimeSource - - - KListWidget - QListWidget -
    klistwidget.h
    -
    -
    diff --git a/src/settings/filetransfersettingspage.cpp b/src/settings/filetransfersettingspage.cpp index 8c98089..ef1cb54 100644 --- a/src/settings/filetransfersettingspage.cpp +++ b/src/settings/filetransfersettingspage.cpp @@ -1,6 +1,8 @@ #include "filetransfersettingspage.h" -#include +#include +#include +#include #include #include #include @@ -15,14 +17,14 @@ FileTransferSettingsPage::FileTransferSettingsPage( QWidget* parent ) connect( highestTransferPort_, SIGNAL( valueChanged( int ) ), this, SLOT( checkPortsInterval() ) ); // Prepare and connect the directory selection button - chooseDirButton_->setIcon( KIcon( "folder-open" ) ); + chooseDirButton_->setIcon( QIcon::fromTheme( "folder-open" ) ); connect( chooseDirButton_, SIGNAL( clicked() ), this, SLOT( slotChooseDirectory() ) ); // Make the directory selection friendlier KUrlCompletion *dirCompletion = new KUrlCompletion( KUrlCompletion::DirCompletion ); dirCompletion->setParent( this ); receivedFilesDirEdit_->setCompletionObject( dirCompletion ); - receivedFilesDirEdit_->setClearButtonShown( true ); + receivedFilesDirEdit_->setClearButtonEnabled( true ); } @@ -71,9 +73,10 @@ void FileTransferSettingsPage::checkPortsInterval() void FileTransferSettingsPage::slotChooseDirectory() { - const KUrl url( KFileDialog::getExistingDirectoryUrl( - receivedFilesDirEdit_->text(), - this, i18n( "Select Directory" ) ) + const QUrl url( QFileDialog::getExistingDirectoryUrl( + this, + i18n( "Select Directory" ), + QUrl::fromLocalFile( receivedFilesDirEdit_->text() ) ) ); if( ! url.isEmpty() ) diff --git a/src/settings/filetransfersettingspage.h b/src/settings/filetransfersettingspage.h index df388eb..c7110c2 100644 --- a/src/settings/filetransfersettingspage.h +++ b/src/settings/filetransfersettingspage.h @@ -10,6 +10,7 @@ #include "ui_filetransfersettingspage.h" +#include #include class FileTransferSettingsPage : public QWidget, private Ui::FileTransferSettingsPage diff --git a/src/settings/filetransfersettingspage.ui b/src/settings/filetransfersettingspage.ui index 2c92325..654167d 100644 --- a/src/settings/filetransfersettingspage.ui +++ b/src/settings/filetransfersettingspage.ui @@ -172,7 +172,7 @@ KLineEdit QLineEdit -
    klineedit.h
    +
    KLineEdit
    diff --git a/src/settings/globalsettingsdialog.cpp b/src/settings/globalsettingsdialog.cpp index 44013cf..29fb767 100644 --- a/src/settings/globalsettingsdialog.cpp +++ b/src/settings/globalsettingsdialog.cpp @@ -26,6 +26,8 @@ #include #include +#include +#include // Initialize the instance to zero @@ -35,7 +37,7 @@ GlobalSettingsDialog* GlobalSettingsDialog::instance_(0); // The constructor GlobalSettingsDialog::GlobalSettingsDialog( QWidget *parent ) -: KPageDialog( parent ) +: KMessPageDialog( parent ) { // Open the config group we'll use throughout the class config_ = KMessConfig::instance()->getGlobalConfig( "GlobalSettingsDialog" ); @@ -62,18 +64,18 @@ GlobalSettingsDialog::GlobalSettingsDialog( QWidget *parent ) page = addPage( accountsManagerPage_, i18n("Accounts") ); page->setHeader( i18n( "Accounts" ) ); - page->setIcon( KIcon( "system-users" ) ); + page->setIcon( QIcon::fromTheme( "system-users" ) ); page = addPage( notificationPage_, i18n( "Notifications" ) ); - page->setIcon( KIcon( "text-speak" ) ); + page->setIcon( QIcon::fromTheme( "text-speak" ) ); page->setHeader( i18n( "Notifications" ) ); page = addPage( miscellaneousPage_, i18n("Settings") ); page->setHeader( i18n( "Settings" ) ); - page->setIcon( KIcon( "configure" ) ); + page->setIcon( QIcon::fromTheme( "configure" ) ); page = addPage( fileTransferSettingsPage_, i18n( "FileTransfers" ) ); - page->setIcon( KIcon( "folder-remote" ) ); + page->setIcon( QIcon::fromTheme( "folder-remote" ) ); page->setHeader( i18n( "Transfer Settings" ) ); // Let all the tabs load their settings @@ -161,7 +163,7 @@ void GlobalSettingsDialog::slotButtonClicked( int button ) { switch( button ) { - case KDialog::Ok: + case KMessPageDialog::Ok: if( ! saveSettings() ) { return; @@ -170,20 +172,20 @@ void GlobalSettingsDialog::slotButtonClicked( int button ) accept(); break; - case KDialog::Apply: + case KMessPageDialog::Apply: saveSettings(); // Do not delete the dialog, we still need it return; break; - case KDialog::Cancel: - case KDialog::Close: + case KMessPageDialog::Cancel: + case KMessPageDialog::Close: reject(); break; default: - KDialog::slotButtonClicked( button ); + KMessPageDialog::slotButtonClicked( button ); break; } diff --git a/src/settings/globalsettingsdialog.h b/src/settings/globalsettingsdialog.h index 7fc04a6..dac7cb6 100644 --- a/src/settings/globalsettingsdialog.h +++ b/src/settings/globalsettingsdialog.h @@ -19,7 +19,7 @@ #define GLOBALSETTINGSDIALOG_H #include -#include +#include "../utils/kmesspagedialog.h" // Forward declarations @@ -35,7 +35,7 @@ class KConfigGroup; * @author Valerio Pilo * @ingroup Settings */ -class GlobalSettingsDialog : public KPageDialog +class GlobalSettingsDialog : public KMessPageDialog { Q_OBJECT diff --git a/src/settings/miscellaneouspage.cpp b/src/settings/miscellaneouspage.cpp index 0fe2439..d759e89 100644 --- a/src/settings/miscellaneouspage.cpp +++ b/src/settings/miscellaneouspage.cpp @@ -18,10 +18,11 @@ #include "miscellaneouspage.h" #include "kmessdebug.h" -#include -#include +#include +#include +#include +#include #include -#include #include #include @@ -47,7 +48,7 @@ MiscellaneousPage::MiscellaneousPage( QWidget *parent ) connect( useCustomMailClientRadio_, SIGNAL( toggled(bool) ), customMailClientInfo_, SLOT( setEnabled(bool) ) ); // Prepare and browse the list of available browsers - const KService::List browserServices = KMimeTypeTrader::self()->query( "text/html", "Application" ); + const KService::List browserServices = KApplicationTrader::queryByMimeType( "text/html" ); for( KService::List::ConstIterator it = browserServices.begin() ; it != browserServices.end() ; ++it ) { KService::Ptr servicePointer = *it; @@ -62,7 +63,7 @@ MiscellaneousPage::MiscellaneousPage( QWidget *parent ) #ifdef KMESSDEBUG_SETTINGSDIALOG kmDebug() << "Adding browser to list:" << service->name() << " -> " << service->exec(); #endif - browsersCombo_->addItem( KIcon( service->icon() ), service->name(), QVariant( service->exec() ) ); + browsersCombo_->addItem( QIcon::fromTheme( service->icon() ), service->name(), QVariant( service->exec() ) ); } if( browsersCombo_->count() == 0 ) @@ -74,7 +75,7 @@ MiscellaneousPage::MiscellaneousPage( QWidget *parent ) } // Prepare and browse the list of available email clients - const KService::List mailServices = KMimeTypeTrader::self()->query( "application/x-mimearchive", "Application" ); + const KService::List mailServices = KApplicationTrader::queryByMimeType( "application/x-mimearchive" ); for( KService::List::ConstIterator it = mailServices.begin() ; it != mailServices.end() ; ++it ) { KService::Ptr servicePointer = *it; @@ -89,7 +90,7 @@ MiscellaneousPage::MiscellaneousPage( QWidget *parent ) #ifdef KMESSDEBUG_SETTINGSDIALOG kmDebug() << "Adding mail client to list:" << service->name() << " -> " << service->exec(); #endif - mailClientsCombo_->addItem( KIcon( service->icon() ), service->name(), QVariant( service->exec() ) ); + mailClientsCombo_->addItem( QIcon::fromTheme( service->icon() ), service->name(), QVariant( service->exec() ) ); } if( mailClientsCombo_->count() == 0 ) @@ -169,7 +170,7 @@ void MiscellaneousPage::loadSettings( const KConfigGroup &group ) else { // If there's no preference set, allow KDE to choose - servicePointer = KMimeTypeTrader::self()->preferredService( "text/html", "Application" ); + servicePointer = KApplicationTrader::preferredService( "text/html" ); service = servicePointer.data(); if( service ) @@ -210,7 +211,7 @@ void MiscellaneousPage::loadSettings( const KConfigGroup &group ) else { // If there's no preference set, allow KDE to choose - servicePointer = KMimeTypeTrader::self()->preferredService( "application/x-mimearchive", "Application" ); + servicePointer = KApplicationTrader::preferredService( "application/x-mimearchive" ); service = servicePointer.data(); if( service ) @@ -257,18 +258,23 @@ bool MiscellaneousPage::saveSettings( KConfigGroup &group ) } else if( ! customBrowserEdit_->text().contains( "%u" ) ) { - int result = KMessageBox::warningYesNoCancel( 0, i18n( "The console command you have specified to launch a custom web browser " - "does not contain the '%u' parameter. Without this, opening web " - "sites will not work.
    Do you want KMess to add it for you?" ) ); + int result = KMessageBox::warningTwoActionsCancel( 0, + i18n( "The console command you have specified to launch a custom web browser " + "does not contain the '%u' parameter. Without this, opening web " + "sites will not work.
    Do you want KMess to add it for you?" ), + i18n( "Custom Browser" ), + KGuiItem( i18n( "Yes" ) ), + KGuiItem( i18n( "No" ) ), + KStandardGuiItem::cancel() ); // Only add the parameter if the user wants to switch( result ) { - case KMessageBox::Yes: + case KMessageBox::PrimaryAction: customBrowserEdit_->setText( customBrowserEdit_->text().append( " %u" ) ); break; - case KMessageBox::No: + case KMessageBox::SecondaryAction: break; default: @@ -287,18 +293,23 @@ bool MiscellaneousPage::saveSettings( KConfigGroup &group ) } else if( ! customMailClientEdit_->text().contains( "%u" ) ) { - int result = KMessageBox::warningYesNoCancel( 0, i18n( "The console command you specified to launch a custom email client " - "does not contain the '%u' parameter. Without this, composing " - "emails will not work.
    Do you want KMess to add it for you?" ) ); + int result = KMessageBox::warningTwoActionsCancel( 0, + i18n( "The console command you specified to launch a custom email client " + "does not contain the '%u' parameter. Without this, composing " + "emails will not work.
    Do you want KMess to add it for you?" ), + i18n( "Custom Email Client" ), + KGuiItem( i18n( "Yes" ) ), + KGuiItem( i18n( "No" ) ), + KStandardGuiItem::cancel() ); // Only add the parameter if the user wants to switch( result ) { - case KMessageBox::Yes: + case KMessageBox::PrimaryAction: customMailClientEdit_->setText( customMailClientEdit_->text().append( " %u" ) ); break; - case KMessageBox::No: + case KMessageBox::SecondaryAction: break; default: diff --git a/src/settings/miscellaneouspage.h b/src/settings/miscellaneouspage.h index b842a07..3637d26 100644 --- a/src/settings/miscellaneouspage.h +++ b/src/settings/miscellaneouspage.h @@ -20,6 +20,7 @@ #include "ui_miscellaneouspage.h" +#include #include @@ -53,4 +54,3 @@ class MiscellaneousPage : public QWidget, private Ui::MiscellaneousPage }; #endif - diff --git a/src/utils/crashhandler.cpp b/src/utils/crashhandler.cpp index 5a22082..f857c33 100644 --- a/src/utils/crashhandler.cpp +++ b/src/utils/crashhandler.cpp @@ -24,9 +24,9 @@ #include // getpid(), alarm() #include // abort() -#include +#include #include -#include +#include @@ -45,16 +45,11 @@ QLatin1String CrashHandler::appName_("kmess"); */ void CrashHandler::activate() { -#ifdef Q_WS_X11 + KCrash::initialize(); KCrash::setCrashHandler( CrashHandler::kmessCrashed ); -#endif #ifdef KMESSDEBUG_CRASHHANDLER -#ifdef Q_WS_X11 kmDebug() << "Enabled custom crash handler"; -#else - kmDebug() << "NOTICE: Crash handler is not enabled for this platform!"; -#endif #endif } @@ -71,7 +66,7 @@ void CrashHandler::activate() */ void CrashHandler::kmessCrashed( int signal ) { - // We cannot use kmDebug() here, it requires a KApplication! + // We cannot use kmDebug() here, it requires a fully initialized application! // Crashes when closing go even more wrong with it. Q_UNUSED( signal ); @@ -81,8 +76,8 @@ void CrashHandler::kmessCrashed( int signal ) "Please submit a report at http://www.kmess.org/board/ or bugs@kmess.org .\n" "\n" "Application version: " KMESS_VERSION "\n" - "Compiled at: KDE " KDE_VERSION_STRING ", Qt " QT_VERSION_STR "\n" - "Running at: KDE " + QLatin1String( KDE::versionString() ) + ", Qt " + QLatin1String( qVersion() ) + "\n"; + "Compiled at: KDE Frameworks " KCOREADDONS_VERSION_STRING ", Qt " QT_VERSION_STR "\n" + "Running at: KDE Frameworks, Qt " + QLatin1String( qVersion() ) + "\n"; #ifdef Q_OS_UNIX /* @@ -189,7 +184,7 @@ void CrashHandler::kmessCrashed( int signal ) if( showKdeBacktrace ) { - qDebug() << "KDE backtrace:" << kBacktrace(); + qDebug() << "KDE backtrace: unavailable in this Qt6 port."; } #else #warning Crash handler code is not implemented for this platform. @@ -215,5 +210,3 @@ void CrashHandler::setAppName( const QLatin1String &appName ) { appName_ = appName; } - - diff --git a/src/utils/faderwidget.cpp b/src/utils/faderwidget.cpp index d4861b6..7710e73 100644 --- a/src/utils/faderwidget.cpp +++ b/src/utils/faderwidget.cpp @@ -54,7 +54,7 @@ FaderWidget::FaderWidget( QWidget *begin, QWidget *parent ) setAttribute( Qt::WA_DeleteOnClose ); - pixmap_ = QPixmap::grabWidget( begin ); + pixmap_ = begin->grab(); } @@ -69,7 +69,7 @@ void FaderWidget::setDuration( uint16_t milliseconds ) { if ( timeline_->state() == QTimeLine::Running ) { - kWarning() << "Cannot change duration whilst fade is running"; + qWarning() << "Cannot change duration whilst fade is running"; return; } @@ -87,7 +87,7 @@ void FaderWidget::start() { if ( timeline_->state() == QTimeLine::Running ) { - kWarning() << "Fade is already running."; + qWarning() << "Fade is already running."; return; } diff --git a/src/utils/gradientelidelabel.cpp b/src/utils/gradientelidelabel.cpp index 074b9b1..81e9a46 100644 --- a/src/utils/gradientelidelabel.cpp +++ b/src/utils/gradientelidelabel.cpp @@ -18,10 +18,11 @@ #include "gradientelidelabel.h" #include -#include #include #include -#include +#include +#include +#include #include "utils/kmessshared.h" @@ -49,14 +50,14 @@ void GradientElideLabel::setText( const QString &text ) // strip out any HTML tags and replace HTML entities. // at this point "cleanText" should *roughly* resemble the // actual formatted string in width (excusing bold face and what not). - cleanText.replace(QRegExp("]*>"), ""); + cleanText.replace(QRegularExpression("]*>"), ""); cleanText = KMessShared::htmlUnescape(cleanText); } void GradientElideLabel::paintEvent(QPaintEvent *event) { QFontMetrics fm(font()); - if (fm.width(cleanText) <= contentsRect().width()) + if (fm.horizontalAdvance(cleanText) <= contentsRect().width()) { QLabel::paintEvent(event); return; @@ -70,13 +71,15 @@ void GradientElideLabel::paintEvent(QPaintEvent *event) QPixmap label = QPixmap(width(), height()); label.fill(Qt::transparent); - // force the label to draw itself to the pixmap. - // we'll then fade out the pixmap and draw it where it should really go. - QPainter::setRedirected(this, &label); + QTextDocument document; + document.setDefaultFont(font()); + document.setHtml(text()); + document.setTextWidth(contentsRect().width()); - QLabel::paintEvent(event); - - QPainter::restoreRedirected(this); + QPainter labelPainter(&label); + labelPainter.translate(contentsRect().topLeft()); + document.drawContents(&labelPainter); + labelPainter.end(); // create a painter to paint on the pixmap. QPainter p(&label); @@ -104,4 +107,3 @@ void GradientElideLabel::paintEvent(QPaintEvent *event) QPainter pUs(this); pUs.drawPixmap(rect(), label); } - diff --git a/src/utils/inlineeditlabel.cpp b/src/utils/inlineeditlabel.cpp index 79a876b..9c6f086 100644 --- a/src/utils/inlineeditlabel.cpp +++ b/src/utils/inlineeditlabel.cpp @@ -23,6 +23,7 @@ #include #include +#include /** diff --git a/src/utils/kmess-send/kmesssendmenuitem.cpp b/src/utils/kmess-send/kmesssendmenuitem.cpp index 1924fc3..3d8a0bb 100644 --- a/src/utils/kmess-send/kmesssendmenuitem.cpp +++ b/src/utils/kmess-send/kmesssendmenuitem.cpp @@ -23,8 +23,8 @@ // Constructor KMessSendMenuItem::KMessSendMenuItem( DBusContact contact, QDBusInterface *dbusInterface, KActionCollection* actionCollection ) - : KAction( - *new KIcon( MsnStatus::getIcon( (Status)contact.status ) ), + : QAction( + QIcon( MsnStatus::getIcon( (Status)contact.status ) ), contact.friendlyName.length() > 30 ? contact.friendlyName.left( 25 ).append( "..." ) : contact.friendlyName, actionCollection ), diff --git a/src/utils/kmess-send/kmesssendmenuitem.h b/src/utils/kmess-send/kmesssendmenuitem.h index c71a1f6..2f55d05 100644 --- a/src/utils/kmess-send/kmesssendmenuitem.h +++ b/src/utils/kmess-send/kmesssendmenuitem.h @@ -20,13 +20,13 @@ #define KMESSSENDMENUITEM_H #include "../kmessdbusdatatypes.h" -#include +#include #include #include -class KMessSendMenuItem: public KAction +class KMessSendMenuItem: public QAction { public: // Public methods // Constructor diff --git a/src/utils/kmess-send/kmesssendplugin.cpp b/src/utils/kmess-send/kmesssendplugin.cpp index 5a9ea6b..fe971a3 100644 --- a/src/utils/kmess-send/kmesssendplugin.cpp +++ b/src/utils/kmess-send/kmesssendplugin.cpp @@ -22,10 +22,10 @@ #include "../../kmessdebug.h" #include "../../contact/msnstatus.h" -#include -#include +#include +#include #include -#include +#include #include #include #include @@ -57,7 +57,7 @@ K_EXPORT_COMPONENT_FACTORY (libkmesssendplugin, KMessSendPluginFactory ("kmessse KMessSendPlugin::KMessSendPlugin( KonqPopupMenu *popupMenu, const QStringList & /* list */ ) :KonqPopupMenuPlugin(popupMenu) { - KGlobal::locale()->insertCatalog("kmess"); + KLocalizedString::setApplicationDomain( "kmess" ); KMESSDBUS_REGISTER_DATATYPES } @@ -113,7 +113,7 @@ void KMessSendPlugin::setup( KActionCollection *actionCollection, const KonqPopu } // Create the menu - KActionMenu *sendMenu = new KActionMenu( KIcon("kmess"), i18n ("Send with KMess"), actionCollection ); + KActionMenu *sendMenu = new KActionMenu( QIcon::fromTheme( "kmess" ), i18n ("Send with KMess"), actionCollection ); menu->addSeparator(); menu->addAction( sendMenu ); @@ -160,7 +160,7 @@ void KMessSendPlugin::setup( KActionCollection *actionCollection, const KonqPopu #ifdef KMESSDEBUG_KMESSSENDPLUGIN kmDebug() << "Creating submenu for account " << nickName; #endif - subMenu = new KActionMenu( KIcon("kmess"), nickName, actionCollection); + subMenu = new KActionMenu( QIcon::fromTheme( "kmess" ), nickName, actionCollection); sendMenu->addAction( subMenu ); } diff --git a/src/utils/kmessconfig.cpp b/src/utils/kmessconfig.cpp index e2c6b48..7a7772e 100644 --- a/src/utils/kmessconfig.cpp +++ b/src/utils/kmessconfig.cpp @@ -19,11 +19,13 @@ #include "../contact/msnobject.h" #include "../notification/notificationmanager.h" #include "../kmessdebug.h" +#include "kmessshared.h" #include +#include +#include -#include -#include +#include // Initialize the instance to zero @@ -131,11 +133,9 @@ KMessConfig* KMessConfig::instance() */ const QString KMessConfig::getAccountDirectory( const QString &accountHandle ) { - KStandardDirs localKdeDir; - QDir appsDir, kmessDir; - - appsDir.setPath( localKdeDir.localkdedir() + "/share/apps" ); - kmessDir.setPath( appsDir.absolutePath() + "/kmess/" + accountHandle ); + QDir kmessDir( QStandardPaths::writableLocation( QStandardPaths::AppDataLocation ) ); + kmessDir.mkpath( accountHandle ); + kmessDir.cd( accountHandle ); return kmessDir.absolutePath(); } @@ -151,11 +151,8 @@ const QString KMessConfig::getAccountDirectory( const QString &accountHandle ) */ const QString KMessConfig::getAccountsDirectory() { - KStandardDirs localKdeDir; - QDir appsDir, kmessDir; - - appsDir.setPath( localKdeDir.localkdedir() + "/share/apps" ); - kmessDir.setPath( appsDir.absolutePath() + "/kmess" ); + QDir kmessDir( QStandardPaths::writableLocation( QStandardPaths::AppDataLocation ) ); + kmessDir.mkpath( "." ); return kmessDir.absolutePath(); } @@ -343,7 +340,7 @@ QString KMessConfig::getMsnObjectFileName(const MsnObject &msnObject) // The sha1 string is actually base64 encoded, meaning we could // also expect a "/" character in the string. QString sha1d( msnObject.getDataHash() ); - const QString safeSha1 = sha1d.replace(QRegExp("[^a-zA-Z0-9+=]"), "_"); + const QString safeSha1 = sha1d.replace( QRegularExpression( "[^a-zA-Z0-9+=]" ), "_" ); // Be friendly for file managers. QString extension; @@ -357,7 +354,7 @@ QString KMessConfig::getMsnObjectFileName(const MsnObject &msnObject) path = "displaypics"; // Check if there is already the file - dir.setPath( KStandardDirs::locateLocal( "data", QString("kmess/") + path + "/" ) ); + dir.setPath( KMessShared::locateLocal( "data", QString("kmess/") + path + "/" ) ); files = dir.entryList( QStringList( safeSha1 + ".*" ), QDir::Files ); // If the list isn't empty check for image file @@ -390,11 +387,11 @@ QString KMessConfig::getMsnObjectFileName(const MsnObject &msnObject) default: extension = ".dat"; - path = QString::null; + path = QString(); } // Locate filename - return KStandardDirs::locateLocal( "data", QString("kmess/") + path + "/" + safeSha1 + extension ); + return KMessShared::locateLocal( "data", QString("kmess/") + path + "/" + safeSha1 + extension ); } @@ -419,5 +416,3 @@ void KMessConfig::warnUser() "

    KMess was unable to access its configuration files!

    " ), settings ); } - - diff --git a/src/utils/kmessdbus.cpp b/src/utils/kmessdbus.cpp index 9d385c3..d0f99ea 100644 --- a/src/utils/kmessdbus.cpp +++ b/src/utils/kmessdbus.cpp @@ -27,6 +27,7 @@ #include +#include KMessDBus::KMessDBus( KMess *parent ) @@ -209,7 +210,7 @@ DBusContactList KMessDBus::getList() list.append( dbusContact ); } - qSort( list.begin(), list.end(), _compareDBusContact ); + std::sort( list.begin(), list.end(), _compareDBusContact ); return list; } diff --git a/src/utils/kmessdialog.h b/src/utils/kmessdialog.h new file mode 100644 index 0000000..13c266f --- /dev/null +++ b/src/utils/kmessdialog.h @@ -0,0 +1,174 @@ +#ifndef KMESSDIALOG_H +#define KMESSDIALOG_H + +#include +#include +#include +#include +#include + +#include + +class KMessDialog : public QDialog +{ + public: + enum ButtonCode + { + None = 0x00000000, + Help = 0x00000001, + Ok = 0x00000004, + Apply = 0x00000008, + Cancel = 0x00000010, + Close = 0x00000020, + User1 = 0x00001000, + User2 = 0x00002000, + User3 = 0x00004000 + }; + + explicit KMessDialog( QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags() ) + : QDialog( parent, flags ) + , layout_( new QVBoxLayout( this ) ) + , buttonBox_( new QDialogButtonBox( this ) ) + { + layout_->addWidget( buttonBox_ ); + } + + void setCaption( const QString &caption ) + { + setWindowTitle( caption ); + } + + void setMainWidget( QWidget *widget ) + { + if( widget ) + { + layout_->insertWidget( 0, widget ); + } + } + + void setButtons( int buttons ) + { + addButtonIfNeeded( buttons, Ok, QDialogButtonBox::Ok ); + addButtonIfNeeded( buttons, Apply, QDialogButtonBox::Apply ); + addButtonIfNeeded( buttons, Cancel, QDialogButtonBox::Cancel ); + addButtonIfNeeded( buttons, Close, QDialogButtonBox::Close ); + addButtonIfNeeded( buttons, Help, QDialogButtonBox::Help ); + addButtonIfNeeded( buttons, User1, QDialogButtonBox::ActionRole, QStringLiteral( "User1" ) ); + addButtonIfNeeded( buttons, User2, QDialogButtonBox::ActionRole, QStringLiteral( "User2" ) ); + addButtonIfNeeded( buttons, User3, QDialogButtonBox::ActionRole, QStringLiteral( "User3" ) ); + } + + QPushButton *button( int code ) const + { + return buttons_.value( code ); + } + + void setButtonText( int code, const QString &text ) + { + if( QPushButton *pushButton = button( code ) ) + { + pushButton->setText( text ); + } + } + + void setButtonToolTip( int code, const QString &text ) + { + if( QPushButton *pushButton = button( code ) ) + { + pushButton->setToolTip( text ); + } + } + + void enableButton( int code, bool enabled ) + { + if( QPushButton *pushButton = button( code ) ) + { + pushButton->setEnabled( enabled ); + } + } + + void enableButtonOk( bool enabled ) + { + enableButton( Ok, enabled ); + } + + void setDefaultButton( int code ) + { + if( QPushButton *pushButton = button( code ) ) + { + pushButton->setDefault( true ); + } + } + + void setHelp( const QString & ) + { + } + + void showButtonSeparator( bool ) + { + } + + void restoreDialogSize( const KConfigGroup &group ) + { + const QByteArray geometry = group.readEntry( "DialogGeometry", QByteArray() ); + if( ! geometry.isEmpty() ) + { + restoreGeometry( geometry ); + } + } + + void saveDialogSize( KConfigGroup &group ) const + { + group.writeEntry( "DialogGeometry", saveGeometry() ); + } + + protected: + virtual void slotButtonClicked( int code ) + { + if( code == Ok ) + { + accept(); + } + else if( code == Cancel || code == Close ) + { + reject(); + } + } + + private: + void addButtonIfNeeded( int requested, int code, QDialogButtonBox::StandardButton standardButton ) + { + if( !( requested & code ) || buttons_.contains( code ) ) + { + return; + } + + QPushButton *pushButton = buttonBox_->addButton( standardButton ); + buttons_.insert( code, pushButton ); + QObject::connect( pushButton, &QPushButton::clicked, this, [this, code]() + { + slotButtonClicked( code ); + } ); + } + + void addButtonIfNeeded( int requested, int code, QDialogButtonBox::ButtonRole role, const QString &text ) + { + if( !( requested & code ) || buttons_.contains( code ) ) + { + return; + } + + QPushButton *pushButton = buttonBox_->addButton( text, role ); + buttons_.insert( code, pushButton ); + QObject::connect( pushButton, &QPushButton::clicked, this, [this, code]() + { + slotButtonClicked( code ); + } ); + } + + QVBoxLayout *layout_; + QDialogButtonBox *buttonBox_; + QHash buttons_; +}; + +#endif diff --git a/src/utils/kmesspagedialog.h b/src/utils/kmesspagedialog.h new file mode 100644 index 0000000..d21d854 --- /dev/null +++ b/src/utils/kmesspagedialog.h @@ -0,0 +1,159 @@ +#ifndef KMESSPAGEDIALOG_H +#define KMESSPAGEDIALOG_H + +#include +#include +#include + +#include +#include + +class KMessPageDialog : public KPageDialog +{ + public: + enum ButtonCode + { + None = 0x00000000, + Help = 0x00000001, + Ok = 0x00000004, + Apply = 0x00000008, + Cancel = 0x00000010, + Close = 0x00000020, + User1 = 0x00001000, + User2 = 0x00002000, + User3 = 0x00004000 + }; + + explicit KMessPageDialog( QWidget *parent = nullptr ) + : KPageDialog( parent ) + { + } + + void setCaption( const QString &caption ) + { + setWindowTitle( caption ); + } + + void setButtons( int buttons ) + { + QDialogButtonBox::StandardButtons standardButtons; + if( buttons & Ok ) standardButtons |= QDialogButtonBox::Ok; + if( buttons & Apply ) standardButtons |= QDialogButtonBox::Apply; + if( buttons & Cancel ) standardButtons |= QDialogButtonBox::Cancel; + if( buttons & Close ) standardButtons |= QDialogButtonBox::Close; + if( buttons & Help ) standardButtons |= QDialogButtonBox::Help; + KPageDialog::setStandardButtons( standardButtons ); + + rememberButton( Ok, QDialogButtonBox::Ok ); + rememberButton( Apply, QDialogButtonBox::Apply ); + rememberButton( Cancel, QDialogButtonBox::Cancel ); + rememberButton( Close, QDialogButtonBox::Close ); + rememberButton( Help, QDialogButtonBox::Help ); + + addActionButtonIfNeeded( buttons, User1, QStringLiteral( "User1" ) ); + addActionButtonIfNeeded( buttons, User2, QStringLiteral( "User2" ) ); + addActionButtonIfNeeded( buttons, User3, QStringLiteral( "User3" ) ); + } + + QPushButton *button( int code ) const + { + return buttons_.value( code ); + } + + void setButtonText( int code, const QString &text ) + { + if( QPushButton *pushButton = button( code ) ) + { + pushButton->setText( text ); + } + } + + void setButtonToolTip( int code, const QString &text ) + { + if( QPushButton *pushButton = button( code ) ) + { + pushButton->setToolTip( text ); + } + } + + void enableButton( int code, bool enabled ) + { + if( QPushButton *pushButton = button( code ) ) + { + pushButton->setEnabled( enabled ); + } + } + + void setDefaultButton( int code ) + { + if( QPushButton *pushButton = button( code ) ) + { + pushButton->setDefault( true ); + } + } + + void setHelp( const QString & ) + { + } + + void restoreDialogSize( const KConfigGroup &group ) + { + const QByteArray geometry = group.readEntry( "DialogGeometry", QByteArray() ); + if( ! geometry.isEmpty() ) + { + restoreGeometry( geometry ); + } + } + + void saveDialogSize( KConfigGroup &group ) const + { + group.writeEntry( "DialogGeometry", saveGeometry() ); + } + + protected: + virtual void slotButtonClicked( int code ) + { + if( code == Ok ) + { + accept(); + } + else if( code == Cancel || code == Close ) + { + reject(); + } + } + + private: + void rememberButton( int code, QDialogButtonBox::StandardButton standardButton ) + { + if( QPushButton *pushButton = KPageDialog::button( standardButton ) ) + { + buttons_.insert( code, pushButton ); + QObject::disconnect( pushButton, nullptr, this, nullptr ); + QObject::connect( pushButton, &QPushButton::clicked, this, [this, code]() + { + slotButtonClicked( code ); + } ); + } + } + + void addActionButtonIfNeeded( int requested, int code, const QString &text ) + { + if( !( requested & code ) || buttons_.contains( code ) ) + { + return; + } + + QPushButton *pushButton = new QPushButton( text, this ); + buttons_.insert( code, pushButton ); + KPageDialog::addActionButton( pushButton ); + QObject::connect( pushButton, &QPushButton::clicked, this, [this, code]() + { + slotButtonClicked( code ); + } ); + } + + QHash buttons_; +}; + +#endif diff --git a/src/utils/kmessshared.cpp b/src/utils/kmessshared.cpp index 2d8b15d..73f62c4 100644 --- a/src/utils/kmessshared.cpp +++ b/src/utils/kmessshared.cpp @@ -25,25 +25,189 @@ #include "kmessconfig.h" #include +#include -#include -#include +#include #include -#include +#include #include +#include #include #include +#include +#include +#include #include #include #include #include +#include +#include #ifdef KMESSDEBUG_SHAREDMETHODS #define KMESSDEBUG_SHARED_OPENEXTERNAL #endif +static QStringList &kmessResourcePrefixes() +{ + static QStringList prefixes; + return prefixes; +} + + + +static QStandardPaths::StandardLocation kmessLocationForType( const QString &type ) +{ + if( type == "config" ) + { + return QStandardPaths::GenericConfigLocation; + } + if( type == "xdgdata-apps" ) + { + return QStandardPaths::ApplicationsLocation; + } + if( type == "cache" ) + { + return QStandardPaths::GenericCacheLocation; + } + if( type == "socket" ) + { + return QStandardPaths::RuntimeLocation; + } + if( type == "appdata" ) + { + return QStandardPaths::AppDataLocation; + } + + return QStandardPaths::GenericDataLocation; +} + + + +static QString kmessResourceSubdir( const QString &type ) +{ + if( type == "emoticons" ) + { + return QStringLiteral( "emoticons" ); + } + if( type == "sound" ) + { + return QStringLiteral( "sounds" ); + } + if( type == "html" ) + { + return QStringLiteral( "doc/HTML" ); + } + if( type == "xdgdata-icon" ) + { + return QStringLiteral( "icons" ); + } + if( type == "xdgdata-mime" ) + { + return QStringLiteral( "mime" ); + } + if( type == "xdgconf-menu" ) + { + return QStringLiteral( "menus" ); + } + if( type == "xdgconf-autostart" ) + { + return QStringLiteral( "autostart" ); + } + if( type == "templates" ) + { + return QStringLiteral( "templates" ); + } + + return QString(); +} + + + +static QString kmessResourcePath( const QString &type, const QString &path ) +{ + const QString normalized = QDir::fromNativeSeparators( path ); + const QString subdir = kmessResourceSubdir( type ); + + if( normalized.isEmpty() ) + { + return subdir; + } + + if( subdir.isEmpty() || normalized.startsWith( subdir + '/' ) ) + { + return normalized; + } + + return subdir + '/' + normalized; +} + + + +static QStringList kmessPrefixCandidates( const QString &type, const QString &file ) +{ + QStringList candidates; + const QString mapped = kmessResourcePath( type, file ); + + foreach( const QString &prefix, kmessResourcePrefixes() ) + { + QDir prefixDir( prefix ); + candidates << prefixDir.filePath( mapped ); + candidates << prefixDir.filePath( "share/" + mapped ); + + if( type == "data" ) + { + candidates << prefixDir.filePath( "share/apps/" + mapped ); + } + else if( type == "appdata" ) + { + candidates << prefixDir.filePath( "share/kmess/" + file ); + } + } + + candidates.removeDuplicates(); + return candidates; +} + + + +static QStringList kmessSourceCandidates( const QString &type, const QString &file ) +{ + QStringList candidates; + QString normalized = QDir::fromNativeSeparators( file ); + + if( type == "data" ) + { + if( normalized.startsWith( "kmess/" ) ) + { + normalized.remove( 0, 6 ); + } + candidates << QDir::current().absoluteFilePath( "data/" + normalized ); + } + else if( type == "appdata" ) + { + candidates << QDir::current().absoluteFilePath( "data/" + normalized ); + } + else if( type == "emoticons" ) + { + candidates << QDir::current().absoluteFilePath( "data/emoticons/" + normalized ); + if( normalized.startsWith( "KMess-new/" ) ) + { + candidates << QDir::current().absoluteFilePath( "data/emoticons/KMess2-new/" + normalized.mid( 10 ) ); + } + } + else if( type == "sound" ) + { + candidates << QDir::current().absoluteFilePath( "data/sounds/" + normalized ); + } + + candidates.removeDuplicates(); + return candidates; +} + + /** * Sorting helper, to compare two filenames using natural sorting. @@ -158,7 +322,7 @@ QString KMessShared::createRequestFile( const QString &mailto, const QString &fo " \n" " \n" "
    getLanguageCode() + "\" method=\"POST\">\n" " clear(); + } + + if( url.isLocalFile() || url.scheme().isEmpty() ) + { + localFilePath = url.isLocalFile() ? url.toLocalFile() : url.toString(); + return true; + } + + QTemporaryFile temporaryFile; + temporaryFile.setAutoRemove( false ); + + if( ! temporaryFile.open() ) + { + return false; + } + + KIO::StoredTransferJob *job = KIO::storedGet( url, KIO::NoReload, KIO::HideProgressInfo ); + + if( ! job->exec() ) + { + QFile::remove( temporaryFile.fileName() ); + return false; + } + + const QByteArray fileData( job->data() ); + + if( temporaryFile.write( fileData ) != fileData.size() ) + { + QFile::remove( temporaryFile.fileName() ); + return false; + } + + localFilePath = temporaryFile.fileName(); + + if( temporaryFilePath != 0 ) + { + *temporaryFilePath = localFilePath; + } + + return true; +} + + + +// Add an application resource prefix used as fallback for relocatable builds. +void KMessShared::addResourcePrefix( const QString &prefix ) +{ + if( ! prefix.isEmpty() && ! kmessResourcePrefixes().contains( prefix ) ) + { + kmessResourcePrefixes().append( prefix ); + } +} + + + +// Return the first matching resource path for a KDE resource type. +QString KMessShared::findResource( const QString &type, const QString &file ) +{ + if( QFileInfo( file ).isAbsolute() ) + { + return QFileInfo::exists( file ) ? file : QString(); + } + + const QString path = kmessResourcePath( type, file ); + const QString found = QStandardPaths::locate( kmessLocationForType( type ), path ); + if( ! found.isEmpty() ) + { + return found; + } + + foreach( const QString &candidate, kmessPrefixCandidates( type, file ) ) + { + if( QFileInfo::exists( candidate ) ) + { + return candidate; + } + } + + foreach( const QString &candidate, kmessSourceCandidates( type, file ) ) + { + if( QFileInfo::exists( candidate ) ) + { + return candidate; + } + } + + return QString(); +} + + + +// Return a MSN-compatible account handle, adding Escargot's default domain when needed. +QString KMessShared::normalizeMsnHandle( const QString &handle ) +{ + const QString trimmedHandle( handle.trimmed() ); + if( trimmedHandle.contains( '@' ) ) + { + return trimmedHandle; + } + + return trimmedHandle + "@escargot.chat"; +} + + + +// Return the directory containing a matching resource path. +QString KMessShared::findResourceDir( const QString &type, const QString &file ) +{ + const QString resource = findResource( type, file ); + if( resource.isEmpty() ) + { + return QString(); + } + + QString suffix = QDir::fromNativeSeparators( file ); + QString resourcePath = QDir::fromNativeSeparators( resource ); + if( resourcePath.endsWith( suffix ) ) + { + return resource.left( resource.length() - suffix.length() ); + } + + return QFileInfo( resource ).absolutePath() + '/'; +} + + + +// Return all matching resource directories for a KDE resource type. +QStringList KMessShared::findResourceDirs( const QString &type, const QString &path ) +{ + QStringList dirs = QStandardPaths::locateAll( kmessLocationForType( type ), + kmessResourcePath( type, path ), + QStandardPaths::LocateDirectory ); + + foreach( const QString &candidate, kmessPrefixCandidates( type, path ) ) + { + if( QFileInfo( candidate ).isDir() ) + { + dirs.append( candidate ); + } + } + + foreach( const QString &candidate, kmessSourceCandidates( type, path ) ) + { + if( QFileInfo( candidate ).isDir() ) + { + dirs.append( candidate ); + } + } + + dirs.removeDuplicates(); + return dirs; +} + + + +// Return the writable local path for a KDE resource type and create its parent directory. +QString KMessShared::locateLocal( const QString &type, const QString &path ) +{ + const QString mappedPath = kmessResourcePath( type, path ); + const QString base = type == "tmp" + ? QDir::tempPath() + : QStandardPaths::writableLocation( kmessLocationForType( type ) ); + + QDir dir( base ); + QFileInfo info( mappedPath ); + + if( info.fileName().isEmpty() || mappedPath.endsWith( '/' ) ) + { + dir.mkpath( mappedPath ); + return dir.filePath( mappedPath ); + } + + dir.mkpath( info.path() ); + return dir.filePath( mappedPath ); +} + + + +// Find an executable in PATH. +QString KMessShared::findExecutable( const QString &name ) +{ + return QStandardPaths::findExecutable( name ); +} + + + /** * @brief Draws an icon with an overlay from two pixmaps. * @@ -427,7 +783,7 @@ QString KMessShared::htmlUnescape( const QString &string ) * * @param url The URL to open */ -void KMessShared::openBrowser( const KUrl &url ) +void KMessShared::openBrowser( const QUrl &url ) { // Open the options KConfigGroup group = KMessConfig::instance()->getGlobalConfig( "General" ); @@ -436,7 +792,7 @@ void KMessShared::openBrowser( const KUrl &url ) QString fallbackBrowser( group.readEntry( "customBrowser", "konqueror" ) ); // Obtain the widget of the main KMess window, to correctly link it to the opened browser - KMessApplication *kmessApp = static_cast( kapp ); + KMessApplication *kmessApp = static_cast(QApplication::instance()); QWidget *mainWindow = kmessApp->getContactListWindow()->window(); // Read which browser has to be opened @@ -486,13 +842,14 @@ void KMessShared::openBrowser( const KUrl &url ) #ifdef KMESSDEBUG_SHARED_OPENEXTERNAL kmDebug() << "KDE default browser selected."; #endif - KToolInvocation::invokeBrowser( url.url() ); + QDesktopServices::openUrl( url ); return; } // Replace the %u in the command line with the actual URL, and launch the browser. - browser.replace( "%u", KShell::quoteArg( url.url() ), Qt::CaseInsensitive ); - KRun::runCommand( browser, mainWindow ); + browser.replace( "%u", KShell::quoteArg( url.toString() ), Qt::CaseInsensitive ); + Q_UNUSED( mainWindow ); + QProcess::startDetached( browser ); } @@ -519,7 +876,7 @@ void KMessShared::openEmailClient( const QString &mailto, const QString &folder, if( ! filename.isEmpty() ) { // Open the webmail in the browser - openBrowser( KUrl( "file://" + filename ) ); + openBrowser( QUrl::fromLocalFile( filename ) ); } return; @@ -529,7 +886,7 @@ void KMessShared::openEmailClient( const QString &mailto, const QString &folder, QString fallbackMailClient( group.readEntry( "customMailClient", "kmail" ) ); // Obtain the widget of the main KMess window, to correctly link it to the opened app - KMessApplication *kmessApp = static_cast( kapp ); + KMessApplication *kmessApp = static_cast(QApplication::instance()); QWidget *mainWindow = kmessApp->getContactListWindow()->window(); // Read which mail client has to be opened @@ -580,13 +937,25 @@ void KMessShared::openEmailClient( const QString &mailto, const QString &folder, #ifdef KMESSDEBUG_SHARED_OPENEXTERNAL kmDebug() << "KDE default mail client selected."; #endif - KToolInvocation::invokeMailer( KUrl( "mailto:" + mailto ) ); + QDesktopServices::openUrl( QUrl( "mailto:" + mailto ) ); return; } // Replace the %u in the command line with the contact address, and launch the application. mailClient.replace( "%u", KShell::quoteArg( mailto ), Qt::CaseInsensitive ); - KRun::runCommand( mailClient, mainWindow ); + Q_UNUSED( mainWindow ); + QProcess::startDetached( mailClient ); +} + + + +// Remove a temporary file created by downloadToLocalFile(). +void KMessShared::removeDownloadedTempFile( const QString &temporaryFilePath ) +{ + if( ! temporaryFilePath.isEmpty() ) + { + QFile::remove( temporaryFilePath ); + } } @@ -756,7 +1125,7 @@ QString KMessShared::nextSequentialFile( const QString &baseDirPath, const QStri // See KMessShared::compareFileNames() QStringList numberedFiles( baseDir.entryList() ); - qSort( numberedFiles.begin(), numberedFiles.end(), KMessShared::compareFileNames ); + std::sort( numberedFiles.begin(), numberedFiles.end(), KMessShared::compareFileNames ); // There are no matching files if( numberedFiles.size() == 0 ) @@ -810,19 +1179,19 @@ QString KMessShared::fixStringToByteSize( const QString &string, quint32 size ) quint32 more; // Character ranges from http://en.wikipedia.org/wiki/UTF-8 - if( character <= 0x007f ) + if( character.unicode() <= 0x007f ) { more = 1; } - else if( character <= 0x07FF ) + else if( character.unicode() <= 0x07FF ) { more = 2; } - else if( character <= 0xd7ff ) + else if( character.unicode() <= 0xd7ff ) { more = 3; } - else if( character <= 0xDFFF ) + else if( character.unicode() <= 0xDFFF ) { // Surrogate area, consume next char as well more = 4; @@ -845,5 +1214,3 @@ QString KMessShared::fixStringToByteSize( const QString &string, quint32 size ) return string; } - - diff --git a/src/utils/kmessshared.h b/src/utils/kmessshared.h index df43497..790a2cb 100644 --- a/src/utils/kmessshared.h +++ b/src/utils/kmessshared.h @@ -21,10 +21,13 @@ #include #include #include +#include +#include +#include // Forward declaration -class KUrl; +class QUrl; @@ -47,6 +50,20 @@ class KMessShared static QByteArray createHMACSha1( const QByteArray &keyForHash, const QByteArray &secret ); // Return a derived key with HMACSha1 algorithm static QByteArray deriveKey( const QByteArray &keyToDerive, const QByteArray &magic ); + // Download a URL to a local file path if it is not already local. + static bool downloadToLocalFile( const QUrl &url, QString &localFilePath, QString *temporaryFilePath = 0 ); + // Add an application resource prefix used as fallback for relocatable builds. + static void addResourcePrefix( const QString &prefix ); + // Return the first matching resource path for a KDE resource type. + static QString findResource( const QString &type, const QString &file ); + // Return the directory containing a matching resource path. + static QString findResourceDir( const QString &type, const QString &file ); + // Return all matching resource directories for a KDE resource type. + static QStringList findResourceDirs( const QString &type, const QString &path ); + // Return the writable local path for a KDE resource type and create its parent directory. + static QString locateLocal( const QString &type, const QString &path ); + // Find an executable in PATH. + static QString findExecutable( const QString &name ); // Generate a random GUID. static QString generateGUID(); // Generate an random number to use as ID @@ -61,10 +78,14 @@ class KMessShared static QString &htmlUnescape( QString &string ); // Converts a string constant with escaped entities to one with HTML static QString htmlUnescape( const QString &string ); + // Return a MSN-compatible account handle, adding Escargot's default domain when needed. + static QString normalizeMsnHandle( const QString &handle ); // Open the given URL respecting the user's preference - static void openBrowser( const KUrl &url ); + static void openBrowser( const QUrl &url ); // Open the given URL mail respecting the user's preference static void openEmailClient( const QString &mailto, const QString &folder, bool isHotmailAvailable = true ); + // Remove a temporary file created by downloadToLocalFile(). + static void removeDownloadedTempFile( const QString &temporaryFilePath ); // Select the next available file static bool selectNextFile( const QString &directory, const QString &baseName, QString &suffix, const QString &extension, int &startingNumber ); // Returns the full path to the next non-existing sequentially mumbered file diff --git a/src/utils/likeback/likeback.cpp b/src/utils/likeback/likeback.cpp index 85b9861..27d89d4 100644 --- a/src/utils/likeback/likeback.cpp +++ b/src/utils/likeback/likeback.cpp @@ -20,14 +20,15 @@ #include -#include +#include #include -#include +#include #include #include #include +#include #include -#include +#include #include #include "likeback.h" @@ -42,14 +43,16 @@ LikeBack::LikeBack( Button buttons, bool showBarByDefault, KConfig *config, const KAboutData *aboutData ) : QObject() { - // Use default KApplication config and aboutData if not provided: + // Use default application config and aboutData if not provided: if( config == 0 ) { - config = KGlobal::config().data(); + static KSharedConfig::Ptr sharedConfig = KSharedConfig::openConfig(); + config = sharedConfig.data(); } if( aboutData == 0 ) { - aboutData = KGlobal::mainComponent().aboutData(); + static KAboutData applicationData = KAboutData::applicationData(); + aboutData = &applicationData; } // Initialize properties (1/2): @@ -239,7 +242,7 @@ void LikeBack::createActions( KActionCollection *parent ) { if( d->sendAction == 0 ) { - d->sendAction = new KAction( KIcon("mail-message-new"), i18n("&Send a Comment to the Developers"), this ); + d->sendAction = new QAction( QIcon::fromTheme( "mail-message-new" ), i18n("&Send a Comment to the Developers"), this ); connect( d->sendAction, SIGNAL( triggered(bool) ), this, SLOT ( execCommentDialog() ) ); @@ -417,7 +420,7 @@ void LikeBack::showInformationMessage() dialogText, i18nc( "Welcome dialog title", "Help Improve the Application" ), "LikeBack_starting_information", - KMessageBox::Notify ); + KMessageBox::SecondaryActiontify ); } @@ -427,7 +430,7 @@ QString LikeBack::activeWindowPath() { // Compute the window hierarchy (from the oldest to the latest, each time prepending to the list): QStringList windowNames; - QWidget *window = kapp->activeWindow(); + QWidget *window = QApplication::activeWindow(); while( window ) { QString name( window->objectName() ); diff --git a/src/utils/likeback/likeback.h b/src/utils/likeback/likeback.h index f39a1f2..0b20320 100644 --- a/src/utils/likeback/likeback.h +++ b/src/utils/likeback/likeback.h @@ -25,7 +25,7 @@ class KAboutData; -class KAction; +class QAction; class KConfig; class KActionCollection; @@ -47,7 +47,7 @@ class LikeBackPrivate; * * The LikeBack system has 5 components: * @li In the application: The comment dialog, where the user write a comment, select a type of comment, etc. - * @li In the application: The KAction to plug in the Help menu. This action displays the comment dialog. + * @li In the application: The QAction to plug in the Help menu. This action displays the comment dialog. * @li In the application: The button-bar, that floats bellow titlebar of every windows of the application, and let the user to quickly show the comment dialog. * The button-bar can be hidden. * @li On the server: A PHP script that collects every comments that users send. The LikeBack object should be configured to contact that server. @@ -56,7 +56,7 @@ class LikeBackPrivate; * Here is an example of code to call to quickly setup LikeBack on the client: * @code * // Instanciate the LikeBack system, and show the first-use information dialog if the button-bar is shown: - * LikeBack *likeBack = new LikeBack(LikeBack::AllButtons, LikeBack::isDevelopmentVersion(KGlobal::mainComponent().aboutData->version())); // Show button-bar only in beta-versions + * LikeBack *likeBack = new LikeBack(LikeBack::AllButtons, LikeBack::isDevelopmentVersion(KAboutData::applicationData().version())); // Show button-bar only in beta-versions * likeBack->setServer("myapp.kde.org", "/likeback/send.php"); * likeBack->setAcceptedLanguages(QStringList::split(";", "en;fr"), i18n("Please write in English or French.")); * @@ -116,8 +116,8 @@ class LikeBack : public QObject * The button-bar display is stored by version. On a new version, your default value will take effect again. * This allow you to disable the button-bar once the version is stable enought to be released as final. * @param config Set the configuration file where to store the user email address and if the button-bar should be shown. - * By default (null), the KApplication configuration object is used. - * @param aboutData Set the KAboutData instance used to get the application name and version. By default (null), the KApplication about data object is used. + * By default (null), the application configuration object is used. + * @param aboutData Set the KAboutData instance used to get the application name and version. By default (null), the application about data object is used. * The application name is only used in the first-use information message. * The version is used to store the button-bar visibility per version (can be shown in a development version but not in a final one...) * and to send with the comment, so you can filter per version and know if a comment refers the latest version of the application or not. @@ -127,7 +127,7 @@ class LikeBack : public QObject /** * Destructor. * Also hide the button-bar, if it was shown. - * Be careful, the KAction is deleted. Do not use it afterward, and take care to unplug it before destroying this LikeBack instance. + * Be careful, the QAction is deleted. Do not use it afterward, and take care to unplug it before destroying this LikeBack instance. */ ~LikeBack(); @@ -286,7 +286,7 @@ class LikeBack : public QObject * @param windowPath The window path to send with the comment. If empty (the default), the current window path is took. * Separate window names with "~~". For instance "MainWindow~~NewFile~~FileOpen". * If you popup the dialog after an error occurred, you can put the error name in that field (if the window path has no sense in that context). - * When the dialog is popuped up from the sendACommentAction() KAction, this value is "HelpMenu", because there is no way to know if the user + * When the dialog is popuped up from the sendACommentAction() QAction, this value is "HelpMenu", because there is no way to know if the user * is commenting a thing he found/thinked about in a sub-dialog. * @param context Not used for the moment. Will allow more fine-grained application status report. */ @@ -302,7 +302,7 @@ class LikeBack : public QObject private slots: /** - * Slot triggered by the "Help -> Send a Comment to Developers" KAction. + * Slot triggered by the "Help -> Send a Comment to Developers" QAction. * It popups the comment dialog, and set the window path to "HelpMenuAction", * because current window path has no meaning in that case. */ diff --git a/src/utils/likeback/likeback_p.h b/src/utils/likeback/likeback_p.h index 95a81e5..4387f03 100644 --- a/src/utils/likeback/likeback_p.h +++ b/src/utils/likeback/likeback_p.h @@ -49,7 +49,7 @@ class LikeBackPrivate bool showBar; int disabledCount; QString fetchedEmail; - KAction *sendAction; + QAction *sendAction; KToggleAction *showBarAction; }; diff --git a/src/utils/likeback/likebackbar.cpp b/src/utils/likeback/likebackbar.cpp index c6dbead..c0e1d78 100644 --- a/src/utils/likeback/likebackbar.cpp +++ b/src/utils/likeback/likebackbar.cpp @@ -15,9 +15,10 @@ * * ***************************************************************************/ +#include #include -#include +#include #include "likebackbar.h" #include "../../kmessapplication.h" @@ -42,10 +43,10 @@ LikeBackBar::LikeBackBar( LikeBack *likeBack ) setObjectName( "LikeBackBar" ); // Set the button icons - m_likeButton ->setIcon( KIcon( "likeback_like" ) ); - m_dislikeButton->setIcon( KIcon( "likeback_dislike" ) ); - m_bugButton ->setIcon( KIcon( "likeback_bug" ) ); - m_featureButton->setIcon( KIcon( "likeback_feature" ) ); + m_likeButton ->setIcon( QIcon::fromTheme( "likeback_like" ) ); + m_dislikeButton->setIcon( QIcon::fromTheme( "likeback_dislike" ) ); + m_bugButton ->setIcon( QIcon::fromTheme( "likeback_bug" ) ); + m_featureButton->setIcon( QIcon::fromTheme( "likeback_feature" ) ); // Show buttons for the enabled types of feedback only LikeBack::Button buttons = likeBack->buttons(); @@ -83,7 +84,7 @@ void LikeBackBar::bugClicked() void LikeBackBar::changeWindow( QWidget *oldWidget, QWidget *newWidget ) { // Do not change the window while exiting - the new widget may already have been deleted! - KMessApplication *kmessApp = static_cast( kapp ); + KMessApplication *kmessApp = static_cast(QApplication::instance()); if( ! kmessApp || kmessApp->quitSelected() ) { newWidget = 0; @@ -210,12 +211,12 @@ void LikeBackBar::setBarVisible( bool visible ) // Avoid duplicated connections if( ! connected_ ) { - connect( kapp, SIGNAL( focusChanged(QWidget*,QWidget*) ), + connect( QApplication::instance(), SIGNAL( focusChanged(QWidget*,QWidget*) ), this, SLOT ( changeWindow(QWidget*,QWidget*) ) ); connected_ = true; } - changeWindow( 0, kapp->activeWindow() ); + changeWindow( 0, QApplication::activeWindow() ); } else if( ! visible && isVisible() ) { @@ -226,7 +227,7 @@ void LikeBackBar::setBarVisible( bool visible ) if( connected_ ) { - disconnect( kapp, SIGNAL( focusChanged(QWidget*,QWidget*) ), + disconnect( QApplication::instance(), SIGNAL( focusChanged(QWidget*,QWidget*) ), this, SLOT ( changeWindow(QWidget*,QWidget*) ) ); connected_ = false; } diff --git a/src/utils/likeback/likebackdialog.cpp b/src/utils/likeback/likebackdialog.cpp index 005a452..6833f68 100644 --- a/src/utils/likeback/likebackdialog.cpp +++ b/src/utils/likeback/likebackdialog.cpp @@ -1,12 +1,13 @@ #include #include +#include #include -#include -#include +#include +#include #include -#include +#include #include "likebackdialog.h" #include "../kmessconfig.h" @@ -18,13 +19,13 @@ // Constructor LikeBackDialog::LikeBackDialog( LikeBack::Button reason, const QString &initialComment, const QString &windowPath, const QString &context, LikeBack *likeBack ) -: KDialog( kapp->activeWindow() ) +: KMessDialog( QApplication::activeWindow() ) , Ui::LikeBackDialog() , m_context( context ) , m_likeBack( likeBack ) , m_windowPath( windowPath ) { - // KDialog Options + // KMessDialog Options setCaption( i18n( "Send a Comment to the Developers" ) ); setButtons( Ok | Cancel ); setDefaultButton( Ok ); @@ -110,7 +111,6 @@ LikeBackDialog::~LikeBackDialog() QString LikeBackDialog::introductionText() { QStringList acceptedLocales; - KLocale *kLocale = KGlobal::locale(); QStringList acceptedLocaleCodes = m_likeBack->acceptedLocales(); // Define a list of languages which the application developers are able to understand @@ -118,12 +118,13 @@ QString LikeBackDialog::introductionText() { foreach( const QString &locale, acceptedLocaleCodes ) { - acceptedLocales << kLocale->languageCodeToName( locale ); + QString languageName( QLocale( locale ).nativeLanguageName() ); + acceptedLocales << ( languageName.isEmpty() ? locale : languageName ); } } - else if( ! kLocale->language().startsWith( "en" ) ) + else if( ! QLocale().name().section( '_', 0, 0 ).startsWith( "en" ) ) { - acceptedLocales << kLocale->languageCodeToName( "en" ); + acceptedLocales << QLocale( "en" ).nativeLanguageName(); } // Put the locales list together in a readable string @@ -131,7 +132,7 @@ QString LikeBackDialog::introductionText() if( ! acceptedLocales.isEmpty() ) { // TODO: Replace the URL with a localized one: - QString translationTool( "http://www.google.com/language_tools?hl=" + kLocale->language() ); + QString translationTool( "http://www.google.com/language_tools?hl=" + QLocale().name().section( '_', 0, 0 ) ); if( acceptedLocales.count() == 1 ) { @@ -202,13 +203,13 @@ void LikeBackDialog::verify() -// Send the comment to the developers site (reimplemented from KDialog) +// Send the comment to the developers site (reimplemented from KMessDialog) void LikeBackDialog::slotButtonClicked( int buttonId ) { // If the user has not pressed Ok, do nothing if( buttonId != Ok ) { - KDialog::slotButtonClicked( buttonId ); + KMessDialog::slotButtonClicked( buttonId ); return; } @@ -246,7 +247,7 @@ void LikeBackDialog::slotButtonClicked( int buttonId ) QString data( "protocol=" + QUrl::toPercentEncoding( "1.0" ) + '&' + "type=" + QUrl::toPercentEncoding( type ) + '&' + "version=" + QUrl::toPercentEncoding( m_likeBack->aboutData()->version() ) + '&' + - "locale=" + QUrl::toPercentEncoding( KGlobal::locale()->language() ) + '&' + + "locale=" + QUrl::toPercentEncoding( QLocale().name().section( '_', 0, 0 ) ) + '&' + "window=" + QUrl::toPercentEncoding( m_windowPath ) + '&' + "context=" + QUrl::toPercentEncoding( m_context ) + '&' + "comment=" + QUrl::toPercentEncoding( m_comment->toPlainText() ) + '&' + @@ -303,7 +304,7 @@ void LikeBackDialog::requestFinished( int id, bool error ) hide(); m_likeBack->enableBar(); - KDialog::accept(); + KMessDialog::accept(); return; } diff --git a/src/utils/likeback/likebackdialog.h b/src/utils/likeback/likebackdialog.h index 9d9982e..dab9928 100644 --- a/src/utils/likeback/likebackdialog.h +++ b/src/utils/likeback/likebackdialog.h @@ -3,7 +3,7 @@ #ifndef LIKEBACKDIALOG_H #define LIKEBACKDIALOG_H -#include +#include "../kmessdialog.h" #include @@ -12,7 +12,7 @@ #include "ui_likebackdialog.h" -class LikeBackDialog : public KDialog, private Ui::LikeBackDialog +class LikeBackDialog : public KMessDialog, private Ui::LikeBackDialog { Q_OBJECT public: @@ -41,7 +41,7 @@ class LikeBackDialog : public KDialog, private Ui::LikeBackDialog private slots: // Check if the UI should allow the user to send the comment void verify(); - // Send the comment to the developers site (reimpl. from KDialog) + // Send the comment to the developers site (reimpl. from KMessDialog) void slotButtonClicked( int button ); // Display confirmation of the sending action void requestFinished( int id, bool error ); diff --git a/src/utils/nowlisteningclient.cpp b/src/utils/nowlisteningclient.cpp index 835bbd2..c15ceda 100644 --- a/src/utils/nowlisteningclient.cpp +++ b/src/utils/nowlisteningclient.cpp @@ -18,11 +18,11 @@ #include "nowlisteningclient.h" #include "kmessdebug.h" +#include "kmessshared.h" #include #include -#include @@ -171,7 +171,7 @@ void NowListeningClient::slotUpdate() bool NowListeningClient::queryAmarok1() { // Check for executable to avoid problem of defunct fork - if( KStandardDirs::findExe( "dcop" ).isEmpty() ) + if( KMessShared::findExecutable( "dcop" ).isEmpty() ) { return false; } diff --git a/src/utils/richtextparser.cpp b/src/utils/richtextparser.cpp index b4e622b..55bcd49 100644 --- a/src/utils/richtextparser.cpp +++ b/src/utils/richtextparser.cpp @@ -29,11 +29,11 @@ #include #include +#include #include #include -#include -#include +#include @@ -99,7 +99,8 @@ void RichTextParser::getCleanString( QString &string ) .replace( "[s]", "", Qt::CaseInsensitive ) .replace( "[/s]", "", Qt::CaseInsensitive ); - string.replace( QRegExp( "\\[/?(c|a)(=#?[0-9a-z,]+)?\\]", Qt::CaseInsensitive ), "" ); + string.replace( QRegularExpression( "\\[/?(c|a)(=#?[0-9a-z,]+)?\\]", + QRegularExpression::CaseInsensitiveOption ), "" ); #ifdef KMESSDEBUG_RICHTEXTPARSER kmDebug() << "Original:" << originalString; @@ -604,7 +605,7 @@ void RichTextParser::parseMsnString( QString &text, bool showEmoticons, bool sho // Set the filename of the placeholder image for pending emoticons static QString pendingEmoticonPlaceholder( - Qt::escape( KGlobal::dirs()->findResource( "appdata", "pics/empty.png" ) ) ); + KMessShared::findResource( "appdata", "pics/empty.png" ).toHtmlEscaped() ); // Set up the emoticon replacement list QHash emoticonReplacementList; @@ -846,7 +847,7 @@ void RichTextParser::parseMsnString( QString &text, bool showEmoticons, bool sho replacement = "" + matched +
-                          ""; break; diff --git a/src/utils/richtextparser.h b/src/utils/richtextparser.h index 2ff5544..18007da 100644 --- a/src/utils/richtextparser.h +++ b/src/utils/richtextparser.h @@ -20,6 +20,7 @@ #include "../emoticon.h" +#include #include #include diff --git a/src/utils/thumbnailprovider.cpp b/src/utils/thumbnailprovider.cpp index 6b1553f..63faffb 100644 --- a/src/utils/thumbnailprovider.cpp +++ b/src/utils/thumbnailprovider.cpp @@ -22,12 +22,13 @@ #include "kmessdebug.h" #include +#include #include #include +#include #include #include -#include @@ -52,15 +53,15 @@ ThumbnailProvider::ThumbnailProvider( const QString &fileName, int size ) #endif // The quick method (also displays a transfer dialog): - // KIO::NetAccess::download( "thumbnail://" + fileName, tempFile, 0 ) + // KMessShared::downloadToLocalFile( "thumbnail://" + fileName, tempFile ) // thumbnailImage_ = QImage( tempFile ); - // KIO::NetAccess::removeTempFile( tempFile ); + // KMessShared::removeDownloadedTempFile( tempFile ); // The complex (but async) method: // Wrap file in a file list, use KIO::PreviewJob - KUrl url( fileName ); - fileList_ = KUrl::List( url ); + QUrl url( fileName ); + fileList_ << KFileItem( url ); // Remove preview for text files // TODO: preview should work, but doesn't @@ -72,15 +73,15 @@ ThumbnailProvider::ThumbnailProvider( const QString &fileName, int size ) #endif // Get file type - KMimeType::Ptr type = KMimeType::findByUrl( url ); + const QMimeType type = QMimeDatabase().mimeTypeForFile( url.toLocalFile().isEmpty() ? fileName : url.toLocalFile(), QMimeDatabase::MatchExtension ); #ifdef KMESSDEBUG_THUMBNAILPROVIDER - kmDebug() << "file mime type '" << type->name() << "'"; + kmDebug() << "file mime type '" << type.name() << "'"; #endif // For some file types, don't generate a preview // TODO: improve, files like .h and .cpp have a different mime type. - if( type->name() == "text/plain" ) + if( type.name() == "text/plain" ) { #ifdef KMESSDEBUG_THUMBNAILPROVIDER kmDebug() << "not creating previews for this file type."; @@ -91,11 +92,7 @@ ThumbnailProvider::ThumbnailProvider( const QString &fileName, int size ) } // Create the preview job - KIO::PreviewJob *previewJob = KIO::filePreview( fileList_, size, size, - 100, // 100% alpha - true, // scale (default value) - true, // save (default value) - &enabledPlugins_ ); + KIO::PreviewJob *previewJob = KIO::filePreview( fileList_, QSize( size, size ), &enabledPlugins_ ); // Connect signals. connect( previewJob, SIGNAL( gotPreview(const KFileItem&, const QPixmap&) ), @@ -136,7 +133,7 @@ const QByteArray &ThumbnailProvider::getData() const */ void ThumbnailProvider::generateFallbackImage() { - QString iconTitle( KMimeType::iconNameForUrl( KUrl( fileName_ ) ) ); + QString iconTitle( QMimeDatabase().mimeTypeForFile( fileName_, QMimeDatabase::MatchExtension ).iconName() ); KIconLoader *loader = KIconLoader::global(); QString iconPath ( loader->iconPath( iconTitle, -size_, false ) ); storeImage( QImage( iconPath ) ); @@ -161,14 +158,14 @@ QString ThumbnailProvider::getImageTag( const QString &altText ) const { if( thumbnailData_.isNull() || thumbnailImage_.isNull() ) { - return QString::null; + return QString(); } QString previewData( thumbnailData_.toBase64() ); return "\"""; + " alt=\"" + altText.toHtmlEscaped() + "\" />"; } diff --git a/src/utils/thumbnailprovider.h b/src/utils/thumbnailprovider.h index dcc0edb..d5184ef 100644 --- a/src/utils/thumbnailprovider.h +++ b/src/utils/thumbnailprovider.h @@ -24,11 +24,8 @@ #include #include -#include - - -// Forward declarations -class KFileItem; +#include +#include @@ -54,7 +51,7 @@ class ThumbnailProvider : public QObject // Return the image const QImage &getImage() const; // Return the HTML image tag. - QString getImageTag( const QString &altText = QString::null ) const; + QString getImageTag( const QString &altText = QString() ) const; // Generate a fallback image. void generateFallbackImage(); @@ -76,7 +73,7 @@ class ThumbnailProvider : public QObject /// The file name QString fileName_; /// The file list (required to avoid KIO crashes) - KUrl::List fileList_; + KFileItemList fileList_; /// Whether an error occured bool resultError_; /// The requested size diff --git a/src/utils/xautolock.cpp b/src/utils/xautolock.cpp index 48e80ce..7afa53d 100644 --- a/src/utils/xautolock.cpp +++ b/src/utils/xautolock.cpp @@ -19,35 +19,19 @@ #include #include #include +#include #include "config-kmess.h" #include "kmessdebug.h" #include "xautolock.h" +#include #include #include #include #include #include -#ifdef Q_WS_X11 -#include -#include -#include -#include -/* The following include is to make --enable-final work */ -#include - -#endif - -#ifdef HAVE_XSCREENSAVER -#include -#else -// A special warning for all Gentoo users out there.. :-/ -#warning You are compiling KMess without support for the X11 screensaver extension. The auto-away feature will not work. -#endif - - #ifdef KMESSDEBUG_AUTOLOCK // #define KMESSDEBUG_AUTOLOCK_DBUS_QUERYING #endif @@ -60,8 +44,7 @@ XAutoLock::XAutoLock() idle_( false ), idleTime_( 0 ), lastCheck_( (uint)time( 0 ) ), - mitAvailable_( false ), - mitInfo_( 0 ), + idleTimeoutId_( -1 ), triggerTime_( 0 ) { timer_ = new QTimer( this ); @@ -70,15 +53,10 @@ XAutoLock::XAutoLock() connect( timer_, SIGNAL( timeout() ), this, SLOT( checkIdle() ) ); - #ifdef HAVE_XSCREENSAVER - int dummy; - mitAvailable_ = ( XScreenSaverQueryExtension( QX11Info::display(), &dummy, &dummy ) != 0 ); - - // when the screensaver (de)activates, update idle as appropriate. - QDBusConnection::sessionBus().connect( "org.freedesktop.ScreenSaver", "/ScreenSaver", - "org.freedesktop.ScreenSaver", "ActiveChanged", - this, SLOT( checkIdle() ) ); - #endif + connect( KIdleTime::instance(), SIGNAL(timeoutReached(int,int)), + this, SLOT(slotIdleTimeoutReached(int,int)) ); + connect( KIdleTime::instance(), SIGNAL(resumingFromIdle()), + this, SLOT(slotResumingFromIdle()) ); } @@ -88,12 +66,10 @@ XAutoLock::~XAutoLock() emit activity(); timer_->stop(); -#ifdef HAVE_XSCREENSAVER - if( mitInfo_ != 0 ) + if( idleTimeoutId_ != -1 ) { - XFree( mitInfo_ ); + KIdleTime::instance()->removeIdleTimeout( idleTimeoutId_ ); } -#endif delete timer_; } @@ -107,7 +83,7 @@ void XAutoLock::checkIdle() now = (uint)time( 0 ); - if( abs( lastCheck_ - now ) > 120 ) + if( std::abs( static_cast( lastCheck_ ) - static_cast( now ) ) > 120 ) { // Whoah, two minutes since we were last called? Something strange is happening... resetTimer(); @@ -115,22 +91,7 @@ void XAutoLock::checkIdle() lastCheck_ = now; - // Check for screen saver or locker presence. If it's on, we're idle - if( isScreenSaverActive() ) - { - // Just a bit more, so idle status will be reported - timeIdle = triggerTime_ + 1; - } - // If the MIT X extension is on, check with this method - else if( mitAvailable_ ) - { - timeIdle = getMitIdle(); - } - // Otherwise, find out when was the last mouse movement - else - { - timeIdle = getMouseIdle(); - } + timeIdle = getMouseIdle(); if ( timeIdle > triggerTime_ && active_ ) { @@ -147,42 +108,21 @@ void XAutoLock::checkIdle() // Get idle time by asking the MIT-SCREEN-SAVER extension (if available) unsigned long XAutoLock::getMitIdle() { - #ifdef HAVE_XSCREENSAVER - if ( !mitInfo_ ) mitInfo_ = XScreenSaverAllocInfo(); - XScreenSaverQueryInfo (QX11Info::display(), DefaultRootWindow( QX11Info::display() ), mitInfo_ ); - - return mitInfo_->idle / 1000; - #else - return 0; - #endif + return KIdleTime::instance()->idleTime() / 1000; } // Get idle time by detecting time since last mouse movement unsigned int XAutoLock::getMouseIdle() { - // NYI - return 0; + return KIdleTime::instance()->idleTime() / 1000; } // Get screen saver status by asking the MIT-SCREEN-SAVER extension (if available) bool XAutoLock::isMitScreenSaverActive() { - #ifdef HAVE_XSCREENSAVER - if( ! mitAvailable_ ) - return false; - - XScreenSaverInfo *info = XScreenSaverAllocInfo(); - XScreenSaverQueryInfo( QX11Info::display(), DefaultRootWindow( QX11Info::display() ), info ); - - bool state = ( info->state == ScreenSaverOn ); - - XFree( info ); - return state; - #else - return false; - #endif + return triggerTime_ > 0 && KIdleTime::instance()->idleTime() >= static_cast( triggerTime_ * 1000 ); } @@ -223,11 +163,33 @@ bool XAutoLock::isScreenSaverActive() kmDebug() << "Got error screensaver response:" << reply.error() << ". Falling back to the X screensaver extension."; #endif - // As a fallback, when the DCOP call fails, ask the MIT-SCREEN-SAVER extension. + // As a fallback, use KDE's platform idle backend. return isMitScreenSaverActive(); } +void XAutoLock::slotIdleTimeoutReached( int identifier, int /*msec*/ ) +{ + if( identifier != idleTimeoutId_ || ! active_ ) + { + return; + } + + idle_ = true; + emit timeout(); + KIdleTime::instance()->catchNextResumeEvent(); +} + + +void XAutoLock::slotResumingFromIdle() +{ + if( idle_ ) + { + resetTimer(); + } +} + + // Reset the timer (after we've just become active again, for example) void XAutoLock::resetTimer() { @@ -244,13 +206,27 @@ void XAutoLock::setTimeOut( unsigned int timeOut ) active_ = true; triggerTime_ = timeOut; + + if( idleTimeoutId_ != -1 ) + { + KIdleTime::instance()->removeIdleTimeout( idleTimeoutId_ ); + idleTimeoutId_ = -1; + } + + if( triggerTime_ > 0 ) + { + idleTimeoutId_ = KIdleTime::instance()->addIdleTimeout( static_cast( triggerTime_ * 1000 ) ); + } } // Start the idle timer void XAutoLock::startTimer() { - timer_->start( 5000 ); + if( idleTimeoutId_ == -1 && triggerTime_ > 0 ) + { + idleTimeoutId_ = KIdleTime::instance()->addIdleTimeout( static_cast( triggerTime_ * 1000 ) ); + } resetTimer(); } @@ -261,6 +237,12 @@ void XAutoLock::stopTimer() { timer_->stop(); active_ = false; + + if( idleTimeoutId_ != -1 ) + { + KIdleTime::instance()->removeIdleTimeout( idleTimeoutId_ ); + idleTimeoutId_ = -1; + } } diff --git a/src/utils/xautolock.h b/src/utils/xautolock.h index c2fac84..2915d11 100644 --- a/src/utils/xautolock.h +++ b/src/utils/xautolock.h @@ -21,14 +21,6 @@ #include -#ifdef HAVE_XSCREENSAVER - #include - #include -#else - // prevent errors in compilation - struct XScreenSaverInfo; -#endif - /** * @brief Idle detection using X11 extensions * @@ -62,6 +54,10 @@ class XAutoLock : public QObject // The main function which checks for idle status void checkIdle(); + private slots: + void slotIdleTimeoutReached( int identifier, int msec ); + void slotResumingFromIdle(); + signals: // Emitted when the user comes out of idle void activity(); @@ -86,10 +82,8 @@ class XAutoLock : public QObject unsigned int idleTime_; // Time snice we last checked idle status (to prevent *strangeness*) unsigned int lastCheck_; - // Is the MIT-SCREEN-SAVER extension available? - bool mitAvailable_; - // A block of data for the MIT-SCREEN-SAVER - XScreenSaverInfo *mitInfo_; + // Registered KIdleTime timeout id. + int idleTimeoutId_; // The timer to check idle status periodically QTimer *timer_; // Time of inactivity before we consider user idle diff --git a/src/utils/xmlfunctions.cpp b/src/utils/xmlfunctions.cpp index 202ef03..bec483d 100644 --- a/src/utils/xmlfunctions.cpp +++ b/src/utils/xmlfunctions.cpp @@ -19,6 +19,7 @@ #include "../kmessdebug.h" +#include #include #include @@ -32,7 +33,7 @@ QDomNode XmlFunctions::getNode( const QDomNode &rootNode, const QString &path ) KMESS_ASSERT( ! path.isEmpty() ); #endif - const QStringList pathItems( path.split( "/", QString::SkipEmptyParts ) ); + const QStringList pathItems( path.split( "/", Qt::SkipEmptyParts ) ); QDomNode childNode( rootNode.namedItem( pathItems[0] ) ); // can be a null node int i = 1; @@ -111,7 +112,7 @@ QString XmlFunctions::getNodeValue( const QDomNode &rootNode, const QString &pat if( rootNode.isNull() ) { kmWarning() << "Attempted to request '" << path << "' on null root node."; - return QString::null; + return QString(); } #endif @@ -130,4 +131,3 @@ QString XmlFunctions::getSource( const QDomNode &node, int indent ) node.save( textStream, indent ); return source; } -