/* * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "qt_utils/utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN #include #include #include #endif const QByteArray guessTextEncoding(const QByteArray& text){ bool allAscii; int ii; int size; const QByteArray& s=text; size = s.length(); if ( (size >= 3) && ((unsigned char)s[0]==0xEF) && ((unsigned char)s[1]==0xBB) && ((unsigned char)s[2]==0xBF)) { return ENCODING_UTF8_BOM; } allAscii = true; ii = 0; while (ii < size) { unsigned char ch = s[ii]; if (ch < 0x80 ) { ii++; // is an ascii char } else if (ch < 0xC0) { // value between 0x80 and 0xC0 is an invalid UTF-8 char return ENCODING_SYSTEM_DEFAULT; } else if (ch < 0xE0) { // should be an 2-byte UTF-8 char if (ii>=size-1) { return ENCODING_SYSTEM_DEFAULT; } unsigned char ch2=s[ii+1]; if ((ch2 & 0xC0) !=0x80) { return ENCODING_SYSTEM_DEFAULT; } allAscii = false; ii+=2; } else if (ch < 0xF0) { // should be an 3-byte UTF-8 char if (ii>=size-2) { return ENCODING_SYSTEM_DEFAULT; } unsigned char ch2=s[ii+1]; unsigned char ch3=s[ii+2]; if (((ch2 & 0xC0)!=0x80) || ((ch3 & 0xC0)!=0x80)) { return ENCODING_SYSTEM_DEFAULT; } allAscii = false; ii+=3; } else { // invalid UTF-8 char return ENCODING_SYSTEM_DEFAULT; } } if (allAscii) return ENCODING_ASCII; return ENCODING_UTF8; } bool isTextAllAscii(const QByteArray& text) { for (char c:text) { if (c<0) { return false; } } return true; } bool isTextAllAscii(const QString& text) { for (QChar c:text) { if (c.unicode()>127) { return false; } } return true; } bool isNonPrintableAsciiChar(char ch) { return (ch<=32) && (ch>=0); } QStringList textToLines(const QString &text) { QTextStream stream(&((QString&)text),QIODevice::ReadOnly); return readStreamToLines(&stream); } void textToLines(const QString &text, LineProcessFunc lineFunc) { QTextStream stream(&((QString&)text),QIODevice::ReadOnly); readStreamToLines(&stream,lineFunc); } QString linesToText(const QStringList &lines, const QString& lineBreak) { return lines.join(lineBreak); } QList splitByteArrayToLines(const QByteArray &content) { QList lines; const char* p =content.constData(); const char* end = p+content.length(); const char* lineStart = p; QByteArray line; while (p<=end) { char ch=*p; switch(ch) { case '\r': line = QByteArray(lineStart, p-lineStart); lines.append(line); p++; if (*p=='\n') p++; lineStart = p; break; case '\n': line = QByteArray(lineStart, p-lineStart); lines.append(line); p++; lineStart = p; break; default: p++; } } if (lineStart>end) { lines.append(""); } else { line = QByteArray(lineStart, end-lineStart+1); lines.append(line); } return lines; } QString trimRight(const QString &s) { if (s.isEmpty()) return s; int i = s.length()-1; // while ((i>=0) && ((s[i] == '\r') || (s[i]=='\n') || (s[i] == '\t') || (s[i]==' '))) { while ((i>=0) && (s[i]<=32)) { i--; }; if (i>=0) { return s.left(i+1); } else { return QString(); } } QString trimLeft(const QString &s) { if (s.isEmpty()) return s; int i=0; // while ((i32) break; n++; } return n; } bool stringIsBlank(const QString &s) { for (QChar ch:s) { if (ch != ' ' && ch != '\t') return false; } return true; } QByteArray toByteArray(const QString &s) { //return s.toLocal8Bit(); return s.toUtf8(); } QString fromByteArray(const QByteArray &s) { QTextCodec* codec = QTextCodec::codecForName(ENCODING_UTF8); QTextCodec::ConverterState state; if (!codec) return QString(s); QString tmp = codec->toUnicode(s,s.length(),&state); if (state.invalidChars>0) tmp = QString::fromLocal8Bit(s); return tmp; } QStringList readStreamToLines(QTextStream *stream) { QStringList list; QString s; while (stream->readLineInto(&s)) { list.append(s); } return list; } void readStreamToLines(QTextStream *stream, LineProcessFunc lineFunc) { QString s; while (stream->readLineInto(&s)) { lineFunc(s); } } QStringList readFileToLines(const QString& fileName, QTextCodec* codec) { QFile file(fileName); if (file.open(QFile::ReadOnly)) { QTextStream stream(&file); stream.setCodec(codec); stream.setAutoDetectUnicode(false); return readStreamToLines(&stream); } return QStringList(); } void readFileToLines(const QString &fileName, QTextCodec *codec, LineProcessFunc lineFunc) { QFile file(fileName); if (file.open(QFile::ReadOnly)) { QTextStream stream(&file); stream.setCodec(codec); stream.setAutoDetectUnicode(false); readStreamToLines(&stream, lineFunc); } } QStringList readFileToLines(const QString &fileName) { QFile file(fileName); if (file.size()<=0) return QStringList(); QTextCodec* codec = QTextCodec::codecForLocale(); QStringList result; QTextCodec::ConverterState state; bool ok = true; if (file.open(QFile::ReadOnly)) { while (!file.atEnd()) { QByteArray array = file.readLine(); QString s = codec->toUnicode(array,array.length(),&state); if (state.invalidChars>0) { ok=false; break; } if (s.endsWith("\r\n")) { s.remove(s.length()-2,2); } else if (s.endsWith("\r")) { s.remove(s.length()-1,1); } else if (s.endsWith("\n")){ s.remove(s.length()-1,1); } result.append(s); } if (!ok) { file.seek(0); result.clear(); codec = QTextCodec::codecForName("UTF-8"); while (!file.atEnd()) { QByteArray array = file.readLine(); QString s = codec->toUnicode(array,array.length(),&state); if (state.invalidChars>0) { result.clear(); break; } if (s.endsWith("\r\n")) { s.remove(s.length()-2,2); } else if (s.endsWith("\r")) { s.remove(s.length()-1,1); } else if (s.endsWith("\n")){ s.remove(s.length()-1,1); } result.append(s); } } } return result; } QByteArray readFileToByteArray(const QString &fileName) { QFile file(fileName); if (file.open(QFile::ReadOnly)) { return file.readAll(); } return QByteArray(); } void stringToFile(const QString &str, const QString &fileName) { QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QTextStream stream(&file); stream<= QT_VERSION_CHECK(5,15,0) <=0 && (path[pos]=='/' || path[pos]==QDir::separator())) pos--; return path.mid(0,pos+1); } QString changeFileExt(const QString& filename, QString ext) { QFileInfo fileInfo(filename); QString suffix = fileInfo.suffix(); QString name = fileInfo.fileName(); QString path; if (!ext.isEmpty() && !ext.startsWith(".")) { ext = "."+ext; } if (fileInfo.path() != ".") { path = includeTrailingPathDelimiter(fileInfo.path()); } if (suffix.isEmpty()) { return path+filename+ext; } else { return path+fileInfo.completeBaseName()+ext; } } QString extractRelativePath(const QString &base, const QString &dest) { QFileInfo baseInfo(base); QDir baseDir; if (baseInfo.isDir()) { baseDir = QDir(baseInfo.absoluteFilePath()); } else { baseDir = baseInfo.absoluteDir(); } return baseDir.relativeFilePath(dest); } QString localizePath(const QString &path) { QString result = path; result.replace("/",QDir::separator()); return result; } QString extractFileName(const QString &fileName) { QFileInfo fileInfo(fileName); return fileInfo.fileName(); } QString extractFileDir(const QString &fileName) { return extractFilePath(fileName); } QString extractFilePath(const QString &filePath) { QFileInfo info(filePath); return info.path(); } QString extractAbsoluteFilePath(const QString &filePath) { QFileInfo info(filePath); return info.absoluteFilePath(); } bool isReadOnly(const QString &filename) { return QFile(filename).isWritable(); } int compareFileModifiedTime(const QString &filename1, const QString &filename2) { QFileInfo fileInfo1(filename1); QFileInfo fileInfo2(filename2); qint64 time1=fileInfo1.lastModified().toMSecsSinceEpoch(); qint64 time2=fileInfo2.lastModified().toMSecsSinceEpoch(); if (time1 > time2) return 1; if (time1 < time2) return -1; return 0; } void inflateRect(QRect &rect, int delta) { inflateRect(rect,delta,delta); } void inflateRect(QRect &rect, int dx, int dy) { rect.setLeft(rect.left()-dx); rect.setRight(rect.right()+dx); rect.setTop(rect.top()-dy); rect.setBottom(rect.bottom()+dy); } static int defaultScreenDPI = -1; int screenDPI() { if (defaultScreenDPI<1) { defaultScreenDPI = qApp->primaryScreen()->logicalDotsPerInch(); } return defaultScreenDPI; } void setScreenDPI(int dpi) { defaultScreenDPI = dpi; } float pointToPixel(float point, float dpi) { return point * dpi / 72; } float pointToPixel(float point) { return pointToPixel(point,screenDPI()); } float pixelToPoint(float pixel) { return pixel * 72 / screenDPI(); }