Port KMess to KF6 and Qt6
This commit is contained in:
+387
-20
@@ -25,25 +25,189 @@
|
||||
#include "kmessconfig.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
|
||||
#include <KRun>
|
||||
#include <KUrl>
|
||||
#include <QUrl>
|
||||
#include <KShell>
|
||||
#include <KToolInvocation>
|
||||
#include <KIO/StoredTransferJob>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QStandardPaths>
|
||||
#include <QUuid>
|
||||
#include <QPainter>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QTemporaryFile>
|
||||
#include <QUrl>
|
||||
|
||||
#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
|
||||
" <head></head>\n"
|
||||
" <body onload=\"document.pform.submit(); \">\n"
|
||||
" <form name=\"pform\""
|
||||
"action=\"https://login.live.com/ppsecure/sha1auth.srf?lc=" +
|
||||
"action=\"https://ds.escargot.nina.chat/ppsecure/sha1auth.srf?lc=" +
|
||||
currentAccount->getLanguageCode() +
|
||||
"\" method=\"POST\">\n"
|
||||
" <input type=\"hidden\" name=\"token\" value=\"" +
|
||||
@@ -219,6 +383,198 @@ QByteArray KMessShared::deriveKey ( const QByteArray &keyToDerive, const QByteAr
|
||||
|
||||
|
||||
|
||||
// Download a URL to a local file path if it is not already local.
|
||||
bool KMessShared::downloadToLocalFile( const QUrl &url, QString &localFilePath, QString *temporaryFilePath )
|
||||
{
|
||||
if( temporaryFilePath != 0 )
|
||||
{
|
||||
temporaryFilePath->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<KMessApplication*>( kapp );
|
||||
KMessApplication *kmessApp = static_cast<KMessApplication *>(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<KMessApplication*>( kapp );
|
||||
KMessApplication *kmessApp = static_cast<KMessApplication *>(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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user