From e82ccabc1386b2dbcc711e4d5361a1d3c1b22fe9 Mon Sep 17 00:00:00 2001 From: Boris Pek Date: Thu, 14 Mar 2024 21:20:07 +0300 Subject: [PATCH] Current version of Psi+ is 1.5.1662 It is based on: * psi: 4feb01d8 * plugins: 45e2354 * psimedia: 9fd3307 * resources: 2ef1865 --- src/chatview_webkit.cpp | 2 +- src/filecache.cpp | 2 +- src/filesharinghttpproxy.cpp | 2 +- src/filesharingmanager.cpp | 4 +- src/filesharingnamproxy.cpp | 2 +- .../tools/spellchecker/hunspellchecker.cpp | 53 ++++++++++--------- .../tools/spellchecker/hunspellchecker.h | 11 +++- src/rtparse.cpp | 4 +- src/textutil.cpp | 6 +-- src/textutil.h | 4 +- src/widgets/emojiregistry.cpp | 8 +-- src/widgets/emojiregistry.h | 4 +- src/widgets/psirichtext.cpp | 24 ++++----- src/widgets/psirichtext.h | 2 +- src/widgets/psitextview.cpp | 6 +-- version | 2 +- 16 files changed, 73 insertions(+), 63 deletions(-) diff --git a/src/chatview_webkit.cpp b/src/chatview_webkit.cpp index ece7a84af..afc388ee3 100644 --- a/src/chatview_webkit.cpp +++ b/src/chatview_webkit.cpp @@ -108,7 +108,7 @@ class ChatViewPrivate { auto match = it.next(); auto idStr = match.captured(1); auto text = match.captured(2); - auto id = XMPP::Hash::from(QStringRef(&idStr)); + auto id = XMPP::Hash::from(idStr); auto item = account_->psi()->fileSharingManager()->item(id); ret.append(QStringView{msg}.mid(post, match.capturedStart(0) - post)); diff --git a/src/filecache.cpp b/src/filecache.cpp index 09027c3bc..473e55620 100644 --- a/src/filecache.cpp +++ b/src/filecache.cpp @@ -152,7 +152,7 @@ FileCache::FileCache(const QString &cacheDir, QObject *parent) : if (id.isEmpty()) continue; auto hAlgo = _registry->getOption(prefix + ".ha", QString()).toString(); - auto hash = XMPP::Hash(QStringRef(&hAlgo)); + auto hash = XMPP::Hash(hAlgo); if (!hash.isValid()) { needCleanup = true; continue; diff --git a/src/filesharinghttpproxy.cpp b/src/filesharinghttpproxy.cpp index 05a938d47..72d37bf90 100644 --- a/src/filesharinghttpproxy.cpp +++ b/src/filesharinghttpproxy.cpp @@ -37,7 +37,7 @@ FileSharingHttpProxy::FileSharingHttpProxy(PsiAccount *acc, const QString &sourceIdHex, qhttp::server::QHttpRequest *req, qhttp::server::QHttpResponse *res) : QObject(res), - item(acc->psi()->fileSharingManager()->item(XMPP::Hash::from(QStringRef(&sourceIdHex)))), acc(acc), request(req), + item(acc->psi()->fileSharingManager()->item(XMPP::Hash::from(sourceIdHex))), acc(acc), request(req), response(res) { auto baseUrl = acc->psi()->webServer()->serverUrl().toString(); diff --git a/src/filesharingmanager.cpp b/src/filesharingmanager.cpp index 39a8236b5..d60e72c53 100644 --- a/src/filesharingmanager.cpp +++ b/src/filesharingmanager.cpp @@ -313,7 +313,7 @@ XMPP::Hash FileSharingDeviceOpener::urlToSourceId(const QUrl &url) return XMPP::Hash(); QString path = url.path(); - QStringRef sourceId(&path); + auto sourceId = QStringView{path}; if (sourceId.startsWith('/')) sourceId = sourceId.mid(1); return XMPP::Hash::from(sourceId); @@ -389,5 +389,5 @@ QVariant FileSharingDeviceOpener::metadata(const QUrl &url) FileSharingItem *FileSharingDeviceOpener::sharedItem(const QString &id) { - return acc->psi()->fileSharingManager()->item(XMPP::Hash::from(QStringRef(&id))); + return acc->psi()->fileSharingManager()->item(XMPP::Hash::from(id)); } diff --git a/src/filesharingnamproxy.cpp b/src/filesharingnamproxy.cpp index 3fc564c2b..2f8669160 100644 --- a/src/filesharingnamproxy.cpp +++ b/src/filesharingnamproxy.cpp @@ -29,7 +29,7 @@ #include FileSharingNAMReply::FileSharingNAMReply(PsiAccount *acc, const QString &sourceIdHex, const QNetworkRequest &req) : - item(acc->psi()->fileSharingManager()->item(XMPP::Hash::from(QStringRef(&sourceIdHex)))), acc(acc) + item(acc->psi()->fileSharingManager()->item(XMPP::Hash::from(sourceIdHex))), acc(acc) { setRequest(req); setOperation(QNetworkAccessManager::GetOperation); // TODO rewrite when we have others diff --git a/src/libpsi/tools/spellchecker/hunspellchecker.cpp b/src/libpsi/tools/spellchecker/hunspellchecker.cpp index 42bd8d758..5b679b8c8 100644 --- a/src/libpsi/tools/spellchecker/hunspellchecker.cpp +++ b/src/libpsi/tools/spellchecker/hunspellchecker.cpp @@ -39,14 +39,17 @@ #include #include #include -#include +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) +# include +#endif #include -#ifdef H_DEPRECATED -#define NEW_HUNSPELL -#define HS_STRING(text) li.codec->fromUnicode(text).toStdString() +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) +# define HS_STRING(text) li.codec->fromUnicode(text).toStdString() +# define QT_STRING(text) QString(li.codec->toUnicode(item.c_str())) #else -#define HS_STRING(text) li.codec->fromUnicode(text) +# define HS_STRING(text) QByteArray(li.encoder(text)).toStdString() +# define QT_STRING(text) li.decoder(QByteArray::fromStdString(item)) #endif HunspellChecker::HunspellChecker() @@ -137,19 +140,26 @@ void HunspellChecker::addLanguage(const LanguageManager::LangId &langId) QFileInfo aff, dic; if (scanDictPaths(language, aff, dic)) { LangItem li; + // TODO on windows it makes sense to use "\\\\?\\" prefix to paths li.hunspell_ - = HunspellPtr(new Hunspell(aff.absoluteFilePath().toLocal8Bit(), dic.absoluteFilePath().toLocal8Bit())); + = HunspellPtr(new Hunspell(aff.absoluteFilePath().toUtf8(), dic.absoluteFilePath().toLocal8Bit())); QByteArray codecName(li.hunspell_->get_dic_encoding()); if (codecName.startsWith("microsoft-cp125")) { codecName.replace(0, sizeof("microsoft-cp") - 1, "Windows-"); } else if (codecName.startsWith("TIS620-2533")) { codecName.resize(sizeof("TIS620") - 1); } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) li.codec = QTextCodec::codecForName(codecName); if (li.codec) { +#else + li.encoder = QStringEncoder(codecName.data()); + li.decoder = QStringDecoder(codecName.data()); + if (li.encoder.isValid()) { +#endif li.info.langId = langId; li.info.filename = dic.filePath(); - languages_.append(li); + languages_.push_back(std::move(li)); } else { qDebug("Unsupported myspell dict encoding: \"%s\" for %s", codecName.data(), qPrintable(dic.fileName())); } @@ -159,29 +169,20 @@ void HunspellChecker::addLanguage(const LanguageManager::LangId &langId) QList HunspellChecker::suggestions(const QString &word) { QStringList qtResult; - for (const LangItem &li : std::as_const(languages_)) { -#ifdef NEW_HUNSPELL + for (LangItem &li : languages_) { std::vector result = li.hunspell_->suggest(HS_STRING(word)); if (!result.empty()) { for (const std::string &item : result) { - qtResult << QString(li.codec->toUnicode(item.c_str())); + qtResult << QT_STRING(item); // QString(li.codec->toUnicode(item.c_str())); } } -#else - char **result; - int sugNum = li.hunspell_->suggest(&result, HS_STRING(word)); - for (int i = 0; i < sugNum; i++) { - qtResult << li.codec->toUnicode(result[i]); - } - li.hunspell_->free_list(&result, sugNum); -#endif } return std::move(qtResult); } bool HunspellChecker::isCorrect(const QString &word) { - for (const LangItem &li : std::as_const(languages_)) { + for (LangItem &li : languages_) { if (li.hunspell_->spell(HS_STRING(word)) != 0) { return true; } @@ -192,7 +193,7 @@ bool HunspellChecker::add(const QString &word) { if (!word.isEmpty()) { QString trimmed_word = word.trimmed(); - for (const LangItem &li : std::as_const(languages_)) { + for (LangItem &li : languages_) { if (li.hunspell_->add(HS_STRING(trimmed_word)) != 0) { return true; } @@ -213,12 +214,12 @@ bool HunspellChecker::writable() const { return false; } void HunspellChecker::unloadLanguage(const LanguageManager::LangId &langId) { - QMutableListIterator it(languages_); - while (it.hasNext()) { - LangItem item = it.next(); - if (item.info.langId == langId) { - it.remove(); - } + for (auto it = languages_.begin(); it != languages_.end();) + { + if ((*it).info.langId == langId) + it = languages_.erase(it); + else + ++it; } } diff --git a/src/libpsi/tools/spellchecker/hunspellchecker.h b/src/libpsi/tools/spellchecker/hunspellchecker.h index 93dc05e96..91fcded97 100644 --- a/src/libpsi/tools/spellchecker/hunspellchecker.h +++ b/src/libpsi/tools/spellchecker/hunspellchecker.h @@ -34,6 +34,10 @@ #include #include #include +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) +# include +# include +#endif class Hunspell; class QTextCodec; @@ -60,7 +64,12 @@ class HunspellChecker : public SpellChecker { struct LangItem { HunspellPtr hunspell_; DictInfo info; +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) QTextCodec *codec; +#else + QStringEncoder encoder; + QStringDecoder decoder; +#endif }; void getSupportedLanguages(); void addLanguage(const LanguageManager::LangId &langId); @@ -69,7 +78,7 @@ class HunspellChecker : public SpellChecker { void unloadLanguage(const LanguageManager::LangId &langId); private: - QList languages_; + std::list languages_; QStringList dictPaths_; QSet supportedLangs_; }; diff --git a/src/rtparse.cpp b/src/rtparse.cpp index d146f8217..e3baec0dc 100644 --- a/src/rtparse.cpp +++ b/src/rtparse.cpp @@ -44,7 +44,7 @@ QString RTParse::next() // if we're at a tag, append it to the output if (in.at(v_at) == '<') { - QStringRef s; + QStringView s; int n = in.indexOf('>', v_at); if (n == -1) { s = QStringView{in}.mid(v_at); @@ -57,7 +57,7 @@ QString RTParse::next() } // now find the next tag, and grab the text in between - QStringRef s; + QStringView s; int x = in.indexOf('<', v_at); if (x == -1) { s = QStringView{in}.mid(v_at); diff --git a/src/textutil.cpp b/src/textutil.cpp index da7b99295..a7c023bff 100644 --- a/src/textutil.cpp +++ b/src/textutil.cpp @@ -192,7 +192,7 @@ QString TextUtil::rich2plain(const QString &in, bool collapseSpaces) return out; } -QString TextUtil::resolveEntities(const QStringRef &in) +QString TextUtil::resolveEntities(const QStringView &in) { QString out; @@ -203,7 +203,7 @@ QString TextUtil::resolveEntities(const QStringRef &in) int n = in.indexOf(';', i); if (n == -1) break; - QStringRef type = in.mid(i, (n - i)); + auto type = in.mid(i, (n - i)); i = n; // should be n+1, but we'll let the loop increment do it @@ -290,7 +290,7 @@ static void emojiconifyPlainText(RTParse &p, const QString &in) const auto ® = EmojiRegistry::instance(); int idx = 0; int emojisStartIdx = -1; - QStringRef ref; + QStringView ref; auto dump_emoji = [&p, &emojisStartIdx, &in, &idx]() { #if defined(WEBKIT) || defined(WEBENGINE) diff --git a/src/textutil.h b/src/textutil.h index 00130aa30..96702420b 100644 --- a/src/textutil.h +++ b/src/textutil.h @@ -4,7 +4,7 @@ #include class QString; -class QStringRef; +class QStringView; namespace TextUtil { @@ -14,7 +14,7 @@ QString unescape(const QString &escaped); QString quote(const QString &, int width = 60, bool quoteEmpty = false); QString plain2rich(const QString &); QString rich2plain(const QString &, bool collapseSpaces = true); -QString resolveEntities(const QStringRef &); +QString resolveEntities(const QStringView &); QString linkify(const QString &); QString legacyFormat(const QString &); QString emoticonify(const QString &in); diff --git a/src/widgets/emojiregistry.cpp b/src/widgets/emojiregistry.cpp index 218f5ffba..2dd3f6ea9 100644 --- a/src/widgets/emojiregistry.cpp +++ b/src/widgets/emojiregistry.cpp @@ -35,7 +35,7 @@ bool EmojiRegistry::isEmoji(const QString &code) const // TODO check the whole code is emoji. not just start } -EmojiRegistry::Category EmojiRegistry::startCategory(QStringRef in) const +EmojiRegistry::Category EmojiRegistry::startCategory(QStringView in) const { if (in.isEmpty()) return Category::None; @@ -85,7 +85,7 @@ int EmojiRegistry::count() const return count; } -QStringRef EmojiRegistry::findEmoji(const QString &in, int idx) const +QStringView EmojiRegistry::findEmoji(const QString &in, int idx) const { int emojiStart = -1; @@ -93,7 +93,7 @@ QStringRef EmojiRegistry::findEmoji(const QString &in, int idx) const bool gotSkin = false; bool gotFQ = false; for (; idx < in.size(); idx++) { - auto category = startCategory(QStringRef(&in, idx, in.size() - idx)); + auto category = startCategory(QStringView{in}.mid(idx, in.size() - idx)); if (gotEmoji && category != Category::None) { if (category == Category::ZWJ) { // zero-width joiner gotEmoji = false; @@ -130,7 +130,7 @@ QStringRef EmojiRegistry::findEmoji(const QString &in, int idx) const if (in[idx].isHighSurrogate()) idx++; } - return emojiStart == -1 ? QStringRef() : QStringRef(&in, emojiStart, idx - emojiStart); + return emojiStart == -1 ? QStringView() : QStringView{in}.mid(emojiStart, idx - emojiStart); } EmojiRegistry::EmojiRegistry() : groups(std::move(db)), ranges_(std::move(ranges)) { } diff --git a/src/widgets/emojiregistry.h b/src/widgets/emojiregistry.h index 3f1d991f8..2232805c9 100644 --- a/src/widgets/emojiregistry.h +++ b/src/widgets/emojiregistry.h @@ -52,14 +52,14 @@ class EmojiRegistry { bool isEmoji(const QString &code) const; /// Find emoji in a string starting from the specified position - QStringRef findEmoji(const QString &in, int startPos = 0) const; + QStringView findEmoji(const QString &in, int startPos = 0) const; /*! * \brief startCategory returns category of what the string starts with if the sequence looks valida for emoji * \param in * \return category */ - Category startCategory(QStringRef in) const; + Category startCategory(QStringView in) const; int count() const; struct iterator { diff --git a/src/widgets/psirichtext.cpp b/src/widgets/psirichtext.cpp index 75f9d7c02..6e9717202 100644 --- a/src/widgets/psirichtext.cpp +++ b/src/widgets/psirichtext.cpp @@ -258,7 +258,7 @@ typedef QQueue TextCharFormatQueue; * Adds null format to queue for all ObjectReplacementCharacters that were * already in the text. Returns passed \param text to save some code. */ -static QStringRef preserveOriginalObjectReplacementCharacters(const QStringRef &text, TextCharFormatQueue *queue) +static QStringView preserveOriginalObjectReplacementCharacters(const QStringView &text, TextCharFormatQueue *queue) { int objReplChars = 0; objReplChars += text.count(QChar::ObjectReplacementCharacter); @@ -267,7 +267,7 @@ static QStringRef preserveOriginalObjectReplacementCharacters(const QStringRef & // But we must be careful if some other character instead of // 0x20 is used immediately after tag opening, this could // create a hole. ejabberd protects us from it though. - objReplChars += text.count("enqueue(nullptr); } @@ -280,19 +280,19 @@ static QStringRef preserveOriginalObjectReplacementCharacters(const QStringRef & * adds appropriate format to the \param queue. Returns processed * \param text. */ -static QString convertIconsToObjectReplacementCharacters(const QStringRef &text, TextCharFormatQueue *queue, +static QString convertIconsToObjectReplacementCharacters(const QStringView &text, TextCharFormatQueue *queue, int insertedAfter, const PsiRichText::ParsersMap &parsers) { QString result; - QStringRef work(text); + QStringView work(text); int start = -1; forever { - start = work.indexOf("<", start + 1); + start = work.indexOf(QLatin1Char('<'), start + 1); if (start == -1) break; - if (work.mid(start + 1, 4) == "icon") { + if (work.mid(start + 1, 4) == QLatin1StringView{"icon"}) { // Format: static QRegularExpression rxName("name=\"([^\"]+)\""); static QRegularExpression rxText("text=\"([^\"]+)\""); @@ -300,10 +300,10 @@ static QString convertIconsToObjectReplacementCharacters(const QStringRef &text, result += preserveOriginalObjectReplacementCharacters(work.left(start), queue); - int end = work.indexOf(">", start); + int end = work.indexOf(QLatin1Char{'>'}, start); Q_ASSERT(end != -1); - QStringRef fragment = work.mid(start, end - start); + QStringView fragment = work.mid(start, end - start); auto matchName = rxName.match(fragment); if (matchName.hasMatch()) { #ifndef WIDGET_PLUGIN @@ -341,17 +341,17 @@ static QString convertIconsToObjectReplacementCharacters(const QStringRef &text, // if parsers key matches with html element name result += preserveOriginalObjectReplacementCharacters(work.left(start), queue); - int end = work.indexOf(">", start); + int end = work.indexOf(QLatin1Char{'>'}, start); Q_ASSERT(end != -1); // take attributes part of the tag - QStringRef fragment = work.mid(start + it.key().length() + 1, end - start - it.key().length() - 1); + auto fragment = work.mid(start + it.key().length() + 1, end - start - it.key().length() - 1); QString replaceHtml; QTextCharFormat charFormat; std::tie(charFormat, replaceHtml) = it.value()(fragment, insertedAfter); if (replaceHtml.size()) { - result += convertIconsToObjectReplacementCharacters(QStringRef(&replaceHtml), queue, + result += convertIconsToObjectReplacementCharacters(replaceHtml, queue, insertedAfter, parsers); } if (charFormat.isValid()) { @@ -464,7 +464,7 @@ static void appendTextHelper(QTextDocument *doc, QString text, QTextCursor &curs } cursor.insertFragment(QTextDocumentFragment::fromHtml( - convertIconsToObjectReplacementCharacters(QStringRef(&text), &queue, cursor.position(), parsers))); + convertIconsToObjectReplacementCharacters(text, &queue, cursor.position(), parsers))); cursor.setPosition(initialpos); applyFormatToIcons(doc, &queue, cursor); diff --git a/src/widgets/psirichtext.h b/src/widgets/psirichtext.h index d44a62291..1f9583395 100644 --- a/src/widgets/psirichtext.h +++ b/src/widgets/psirichtext.h @@ -28,7 +28,7 @@ class ITEMediaOpener; class PsiRichText { public: using ParserRet = std::pair; - using Parser = std::function; + using Parser = std::function; using ParsersMap = QMap; static void install(QTextDocument *doc); diff --git a/src/widgets/psitextview.cpp b/src/widgets/psitextview.cpp index d4a0e60e6..b7ce13eaa 100644 --- a/src/widgets/psitextview.cpp +++ b/src/widgets/psitextview.cpp @@ -55,7 +55,7 @@ class PsiTextView::Private : public QObject { // handler function accepts everything after tag name upto but exluding final ">" PsiRichText::ParsersMap objectParsers; - QMap parseHtmlAttrs(const QStringRef &html) + QMap parseHtmlAttrs(const QStringView &html) { static QRegularExpression attrStart("([a-zA-Z0-9]+)=([\"'])((.(?!\\2))*.)\\2"); // static QRegularExpression attrStart("([a-zA-Z0-9]+)=([\"'])([^\"']*)\\2"); @@ -108,7 +108,7 @@ span.emojis { d->objectParsers = PsiRichText::ParsersMap { { "share", - [this](const QStringRef &html, int insertAfter) -> PsiRichText::ParserRet { + [this](const QStringView &html, int insertAfter) -> PsiRichText::ParserRet { if (!d->mediaOpener) return { QTextCharFormat(), "" }; auto attrs = d->parseHtmlAttrs(html); @@ -199,7 +199,7 @@ span.emojis { return { QTextCharFormat(), "" }; } }, { "marker", - [this](const QStringRef &html, int) -> PsiRichText::ParserRet { + [this](const QStringView &html, int) -> PsiRichText::ParserRet { auto attrs = d->parseHtmlAttrs(html); auto id = attrs.value("id"); return { PsiRichText::markerFormat(id), QString() }; diff --git a/version b/version index 238807a2e..d75bce7ca 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.5.1661 (2024-03-14, 9c74f6cb) +1.5.1662 (2024-03-14, 4feb01d8)