goldendict-ng/utils.hh

273 lines
5.9 KiB
C++
Raw Normal View History

/* Thin wrappers for retaining compatibility for both Qt6.x and Qt5.x */
#ifndef UTILS_HH
#define UTILS_HH
#include <QString>
#include <QAtomicInt>
#include <QTextDocument>
#include <QKeyEvent>
#include <QUrl>
#include <QUrlQuery>
#include <QJsonObject>
#include <QJsonDocument>
namespace Utils
{
/**
* remove right end space
*/
inline QString rstrip(const QString &str) {
int n = str.size() - 1;
for (; n >= 0; --n) {
if (!str.at(n).isSpace()) {
return str.left(n + 1);
}
}
return "";
}
/**
* remove punctuation , space, symbol
*
*
* " abc, '" should be "abc"
*/
inline QString trimNonChar( const QString & str )
{
QString remain;
int n = str.size() - 1;
for( ; n >= 0; --n )
{
auto c = str.at( n );
if( !c.isSpace() && !c.isSymbol() && !c.isNonCharacter() && !c.isPunct()&& !c.isNull() )
{
remain = str.left( n + 1 );
break;
}
}
n = 0;
for( ; n < remain.size(); n++ )
{
auto c = remain.at( n );
if( !c.isSpace() && !c.isSymbol() && !c.isNonCharacter() && !c.isPunct() )
{
return remain.mid( n );
}
}
return "";
}
/**
* str="abc\r\n\u0000" should be returned as "abc"
* @brief rstripnull
* @param str
* @return
*/
inline QString rstripnull(const QString &str) {
int n = str.size() - 1;
for (; n >= 0; --n) {
auto c = str.at(n);
if (!c.isSpace()&&!c.isNull()) {
return str.left(n + 1);
}
}
return "";
}
inline QString unescapeHtml(const QString &str) {
QTextDocument text;
text.setHtml(str);
return text.toPlainText();
}
inline bool isExternalLink(QUrl const &url) {
return url.scheme() == "http" || url.scheme() == "https" || url.scheme() == "ftp" || url.scheme() == "mailto" ||
url.scheme() == "file" || url.toString().startsWith( "//" );
}
inline bool isCssFontImage(QUrl const &url) {
auto fileName = url.fileName();
auto ext=fileName.mid(fileName.lastIndexOf("."));
QStringList extensions{".css",".woff",".woff2","ttf",".bmp" ,".jpg", ".png", ".tif",".wav", ".ogg", ".oga", ".mp3", ".mp4", ".aac", ".flac",".mid", ".wv ",".ape"} ;
return extensions.indexOf(ext)>-1;
}
inline QString escape( QString const & plain )
{
return plain.toHtmlEscaped();
}
// should ignore key event.
inline bool ignoreKeyEvent(QKeyEvent *keyEvent) {
if ( keyEvent->key() == Qt::Key_Space ||
keyEvent->key() == Qt::Key_Backspace ||
keyEvent->key() == Qt::Key_Tab ||
keyEvent->key() == Qt::Key_Backtab ||
keyEvent->key() == Qt::Key_Escape)
return true;
return false;
}
inline QString json2String( const QJsonObject & json )
{
return QString( QJsonDocument( json ).toJson( QJsonDocument::Compact ) );
}
inline QStringList repeat( const QString str, const int times )
{
QStringList list;
for( int i = 0; i < times; i++ )
{
list << str;
}
return list;
}
namespace AtomicInt
{
inline int loadAcquire( QAtomicInt const & ref )
{
return ref.loadAcquire();
}
}
namespace Url
{
// This wrapper is created due to behavior change of the setPath() method
// See: https://bugreports.qt-project.org/browse/QTBUG-27728
// https://codereview.qt-project.org/#change,38257
inline QString ensureLeadingSlash( const QString & path )
{
QLatin1Char slash( '/' );
if ( path.startsWith( slash ) )
return path;
return slash + path;
}
inline bool hasQueryItem( QUrl const & url, QString const & key )
{
return QUrlQuery( url ).hasQueryItem( key );
}
inline QString queryItemValue( QUrl const & url, QString const & item )
{
return QUrlQuery( url ).queryItemValue( item, QUrl::FullyDecoded );
}
2015-10-30 13:35:00 +00:00
inline QByteArray encodedQueryItemValue( QUrl const & url, QString const & item )
{
return QUrlQuery( url ).queryItemValue( item, QUrl::FullyEncoded ).toLatin1();
}
inline void addQueryItem( QUrl & url, QString const & key, QString const & value )
{
QUrlQuery urlQuery( url );
urlQuery.addQueryItem( key, value );
url.setQuery( urlQuery );
}
inline void removeQueryItem( QUrl & url, QString const & key )
{
QUrlQuery urlQuery( url );
urlQuery.removeQueryItem( key );
url.setQuery( urlQuery );
}
inline void setQueryItems( QUrl & url, QList< QPair< QString, QString > > const & query )
{
QUrlQuery urlQuery( url );
urlQuery.setQueryItems( query );
url.setQuery( urlQuery );
}
inline QString path( QUrl const & url )
{
return url.path( QUrl::FullyDecoded );
}
inline void setFragment( QUrl & url, const QString & fragment )
{
url.setFragment( fragment, QUrl::DecodedMode );
}
inline QString fragment( const QUrl & url )
{
return url.fragment( QUrl::FullyDecoded );
}
// get the query word of bword and gdlookup scheme.
// if the scheme is gdlookup or scheme ,the first value of pair is true,otherwise is false;
inline std::pair< bool, QString > getQueryWord( QUrl const & url )
2022-02-15 12:22:43 +00:00
{
QString word;
bool validScheme = false;
if( url.scheme().compare( "gdlookup" ) == 0 )
2022-02-15 12:22:43 +00:00
{
validScheme = true;
2022-02-15 12:22:43 +00:00
if( hasQueryItem( url, "word" ) )
{
word = queryItemValue( url, "word" );
}
else
{
word = url.path().mid( 1 );
}
}
if( url.scheme().compare( "bword" ) == 0 )
{
validScheme = true;
word = url.path().mid( 1 );
}
return std::make_pair( validScheme, word );
2022-02-15 12:22:43 +00:00
}
}
}
namespace
{
/// Uses some heuristics to chop off the first domain name from the host name,
/// but only if it's not too base. Returns the resulting host name.
inline QString getHostBase( QString const & host )
{
QStringList domains = host.split( '.' );
int left = domains.size();
// Skip last <=3-letter domain name
if ( left && domains[ left - 1 ].size() <= 3 )
--left;
// Skip another <=3-letter domain name
if ( left && domains[ left - 1 ].size() <= 3 )
--left;
if ( left > 1 )
{
// We've got something like www.foobar.co.uk -- we can chop off the first
// domain
return host.mid( domains[ 0 ].size() + 1 );
}
else
return host;
}
inline QString getHostBaseFromUrl( QUrl const & url )
{
QString host = url.host();
return getHostBase( host );
}
}
#endif // UTILS_HH