Linux Qt 6 port (#490)

* initial Qt 6 port

* move arch linux package to Qt 6

* minor fix
This commit is contained in:
Cyano Hao 2024-09-29 20:01:14 +08:00 committed by GitHub
parent 2e8f043f3f
commit b9f36558ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 558 additions and 173 deletions

View File

@ -1,6 +1,6 @@
# General Development Notes # General Development Notes
Red Panda C++ need Qt 5.15 to build. Red Panda C++ need Qt 5.15 or 6.7+ to build.
Recommended development environments: Recommended development environments:
1. Visual Studio Code. 1. Visual Studio Code.

View File

@ -1,6 +1,6 @@
# 通用开发说明 # 通用开发说明
小熊猫C++ 需要 Qt 5.15。 小熊猫C++ 需要 Qt 5.15 或 6.7+
推荐开发环境: 推荐开发环境:
1. Visual Studio Code。 1. Visual Studio Code。

View File

@ -25,7 +25,6 @@
#include <QFileInfo> #include <QFileInfo>
#include <QProcess> #include <QProcess>
#include <QString> #include <QString>
#include <QTextCodec>
#include <QTime> #include <QTime>
#include <QApplication> #include <QApplication>
#include "../editor.h" #include "../editor.h"

View File

@ -18,7 +18,6 @@
#include "compilermanager.h" #include "compilermanager.h"
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QTextCodec>
StdinCompiler::StdinCompiler(const QString &filename,const QByteArray& encoding, const QString& content, bool onlyCheckSyntax): StdinCompiler::StdinCompiler(const QString &filename,const QByteArray& encoding, const QString& content, bool onlyCheckSyntax):
Compiler(filename, onlyCheckSyntax), Compiler(filename, onlyCheckSyntax),
@ -98,9 +97,9 @@ QByteArray StdinCompiler::pipedText()
if (mEncoding == ENCODING_ASCII) if (mEncoding == ENCODING_ASCII)
return mContent.toLatin1(); return mContent.toLatin1();
QTextCodec* codec = QTextCodec::codecForName(mEncoding); TextEncoder encoder(mEncoding);
if (codec) { if (encoder.isValid()) {
return codec->fromUnicode(mContent); return encoder.encodeUnchecked(mContent);
} else { } else {
return mContent.toLocal8Bit(); return mContent.toLocal8Bit();
} }

View File

@ -17,7 +17,6 @@
#include <QFile> #include <QFile>
#include <QMessageBox> #include <QMessageBox>
#include <QProgressDialog> #include <QProgressDialog>
#include <QTextCodec>
#include <qsynedit/document.h> #include <qsynedit/document.h>
#include "cpprefacter.h" #include "cpprefacter.h"
#include "mainwindow.h" #include "mainwindow.h"

View File

@ -2542,11 +2542,8 @@ QVariant MemoryModel::data(const QModelIndex &index, int role) const
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
if (col==line->datas.count()) { if (col==line->datas.count()) {
QString s; QString s;
foreach (unsigned char ch, line->datas) { for (char ch : line->datas) {
if (ch<' ' || ch>=128) s += isAsciiPrint(ch) ? ch : '.';
s+='.';
else
s+=ch;
} }
return s; return s;
} else } else

View File

@ -18,7 +18,6 @@
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QFont> #include <QFont>
#include <QTextCodec>
#include <QVariant> #include <QVariant>
#include <QWheelEvent> #include <QWheelEvent>
#include <QGuiApplication> #include <QGuiApplication>
@ -30,7 +29,6 @@
#include <QPrinter> #include <QPrinter>
#include <QPrintDialog> #include <QPrintDialog>
#include <QTextDocument> #include <QTextDocument>
#include <QTextCodec>
#include <QScrollBar> #include <QScrollBar>
#include <QScreen> #include <QScreen>
#include <memory> #include <memory>
@ -4230,7 +4228,7 @@ void Editor::updateFunctionTip(bool showTip)
return; return;
QChar ch=lastNonSpaceChar(currentLine,currentChar); QChar ch=lastNonSpaceChar(currentLine,currentChar);
if (ch!="(" && ch!=",") if (ch!='(' && ch!=',')
return; return;
QSynedit::PTokenAttribute attr; QSynedit::PTokenAttribute attr;

View File

@ -59,7 +59,11 @@ class WindowLogoutEventFilter : public QAbstractNativeEventFilter {
// QAbstractNativeEventFilter interface // QAbstractNativeEventFilter interface
public: public:
#if QT_VERSION_MAJOR >= 6
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
#else
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
#endif
}; };
#ifndef WM_DPICHANGED #ifndef WM_DPICHANGED
@ -124,7 +128,12 @@ HWND getPreviousInstance() {
return NULL; return NULL;
} }
bool WindowLogoutEventFilter::nativeEventFilter(const QByteArray & /*eventType*/, void *message, long *result){ #if QT_VERSION_MAJOR >= 6
bool WindowLogoutEventFilter::nativeEventFilter(const QByteArray & /*eventType*/, void *message, qintptr *result)
#else
bool WindowLogoutEventFilter::nativeEventFilter(const QByteArray & /*eventType*/, void *message, long *result)
#endif
{
MSG * pMsg = static_cast<MSG *>(message); MSG * pMsg = static_cast<MSG *>(message);
switch(pMsg->message) { switch(pMsg->message) {
case WM_QUERYENDSESSION: case WM_QUERYENDSESSION:

View File

@ -17,7 +17,6 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QClipboard> #include <QClipboard>
#include <QMessageBox> #include <QMessageBox>
#include <QTextCodec>
#include <QCloseEvent> #include <QCloseEvent>
#include <QComboBox> #include <QComboBox>
#include <QDesktopServices> #include <QDesktopServices>
@ -45,6 +44,7 @@
#include <QUuid> #include <QUuid>
#include <QScrollBar> #include <QScrollBar>
#include <QTextDocumentFragment> #include <QTextDocumentFragment>
#include <QActionGroup>
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
@ -1733,7 +1733,7 @@ Editor* MainWindow::openFile(QString filename, bool activate, QTabWidget* page)
} }
bool inProject = (mProject && unit); bool inProject = (mProject && unit);
QByteArray encoding = unit ? unit->encoding() : QByteArray encoding = unit ? unit->encoding() :
(pSettings->editor().autoDetectFileEncoding()? ENCODING_AUTO_DETECT : pSettings->editor().defaultEncoding()); (pSettings->editor().autoDetectFileEncoding() ? QByteArray(ENCODING_AUTO_DETECT) : pSettings->editor().defaultEncoding());
Project * pProject = (inProject?mProject.get():nullptr); Project * pProject = (inProject?mProject.get():nullptr);
if (pProject && encoding==ENCODING_PROJECT) if (pProject && encoding==ENCODING_PROJECT)
encoding=pProject->options().encoding; encoding=pProject->options().encoding;
@ -3449,7 +3449,7 @@ void MainWindow::loadLastOpens()
} }
bool inProject = (mProject && unit); bool inProject = (mProject && unit);
QByteArray encoding = unit ? unit->encoding() : QByteArray encoding = unit ? unit->encoding() :
(pSettings->editor().autoDetectFileEncoding()? ENCODING_AUTO_DETECT : pSettings->editor().defaultEncoding()); (pSettings->editor().autoDetectFileEncoding()? QByteArray(ENCODING_AUTO_DETECT) : pSettings->editor().defaultEncoding());
Project* pProject = (inProject?mProject.get():nullptr); Project* pProject = (inProject?mProject.get():nullptr);
if (pProject && encoding==ENCODING_PROJECT) if (pProject && encoding==ENCODING_PROJECT)
encoding=pProject->options().encoding; encoding=pProject->options().encoding;
@ -6349,7 +6349,7 @@ void MainWindow::on_actionConvert_to_ANSI_triggered()
return; return;
if (QMessageBox::warning(this,tr("Confirm Convertion"), if (QMessageBox::warning(this,tr("Confirm Convertion"),
tr("The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue?") tr("The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue?")
.arg(QString(QTextCodec::codecForLocale()->name())), .arg(QString(TextEncoder::encoderForSystem().name())),
QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes) QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes)
return; return;
editor->convertToEncoding(ENCODING_SYSTEM_DEFAULT); editor->convertToEncoding(ENCODING_SYSTEM_DEFAULT);

View File

@ -17,7 +17,6 @@
#include "cpppreprocessor.h" #include "cpppreprocessor.h"
#include <QFile> #include <QFile>
#include <QTextCodec>
#include <QDebug> #include <QDebug>
#include <QMessageBox> #include <QMessageBox>
#include "../utils.h" #include "../utils.h"

View File

@ -113,7 +113,7 @@ private:
} }
static bool isBlankChar(const QChar& ch) { static bool isBlankChar(const QChar& ch) {
return (ch<=32) && (ch>0); return (ch.unicode() <= 32) && (ch.unicode() > 0);
} }
// static bool isOperatorChar(const QChar& ch) { // static bool isOperatorChar(const QChar& ch) {

View File

@ -16,6 +16,7 @@
*/ */
#include "project.h" #include "project.h"
#include "editor.h" #include "editor.h"
#include "qt_utils/utils.h"
#include "utils.h" #include "utils.h"
#include "systemconsts.h" #include "systemconsts.h"
#include "editorlist.h" #include "editorlist.h"
@ -31,7 +32,6 @@
#include <QFileDialog> #include <QFileDialog>
#include <QFileInfo> #include <QFileInfo>
#include <QMessageBox> #include <QMessageBox>
#include <QTextCodec>
#include <QMessageBox> #include <QMessageBox>
#include <QDirIterator> #include <QDirIterator>
#include <QMimeDatabase> #include <QMimeDatabase>
@ -255,7 +255,7 @@ void Project::open()
if (newUnit->encoding()!=ENCODING_UTF16_BOM && if (newUnit->encoding()!=ENCODING_UTF16_BOM &&
newUnit->encoding()!=ENCODING_UTF8_BOM && newUnit->encoding()!=ENCODING_UTF8_BOM &&
newUnit->encoding()!=ENCODING_UTF32_BOM && newUnit->encoding()!=ENCODING_UTF32_BOM &&
QTextCodec::codecForName(newUnit->encoding())==nullptr) { !isEncodingAvailable(newUnit->encoding())) {
newUnit->setEncoding(ENCODING_PROJECT); newUnit->setEncoding(ENCODING_PROJECT);
} }
newUnit->setRealEncoding(ini.GetValue(groupName, "RealEncoding",ENCODING_ASCII)); newUnit->setRealEncoding(ini.GetValue(groupName, "RealEncoding",ENCODING_ASCII));
@ -944,11 +944,9 @@ bool Project::assignTemplate(const std::shared_ptr<ProjectTemplate> aTemplate, b
updateCompilerSetting(); updateCompilerSetting();
mOptions.icon = aTemplate->icon(); mOptions.icon = aTemplate->icon();
QTextCodec* codec=QTextCodec::codecForName(mOptions.encoding); if (!isEncodingAvailable(mOptions.encoding))
if (!codec)
mOptions.encoding=ENCODING_SYSTEM_DEFAULT; mOptions.encoding=ENCODING_SYSTEM_DEFAULT;
codec=QTextCodec::codecForName(mOptions.execEncoding); if (!isEncodingAvailable(mOptions.execEncoding))
if (!codec)
mOptions.execEncoding=ENCODING_SYSTEM_DEFAULT; mOptions.execEncoding=ENCODING_SYSTEM_DEFAULT;
// Copy icon to project directory // Copy icon to project directory
@ -2611,7 +2609,7 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const
if (p->isUnit) { if (p->isUnit) {
PProjectUnit unit = p->pUnit.lock(); PProjectUnit unit = p->pUnit.lock();
if (unit) if (unit)
icon = mIconProvider->icon(unit->fileName()); icon = mIconProvider->icon(QFileInfo(unit->fileName()));
} else { } else {
if (p == mProject->rootNode().get()) { if (p == mProject->rootNode().get()) {
#ifdef ENABLE_VCS #ifdef ENABLE_VCS

View File

@ -16,7 +16,6 @@
*/ */
#include "settings.h" #include "settings.h"
#include <QApplication> #include <QApplication>
#include <QTextCodec>
#include <algorithm> #include <algorithm>
#include "utils.h" #include "utils.h"
#include "utils/escape.h" #include "utils/escape.h"

View File

@ -28,7 +28,6 @@
#include <QImageWriter> #include <QImageWriter>
#include <QImageWriter> #include <QImageWriter>
#include <QMessageBox> #include <QMessageBox>
#include <QTextCodec>
ProjectGeneralWidget::ProjectGeneralWidget(const QString &name, const QString &group, QWidget *parent) : ProjectGeneralWidget::ProjectGeneralWidget(const QString &name, const QString &group, QWidget *parent) :
SettingsWidget(name,group,parent), SettingsWidget(name,group,parent),

View File

@ -20,7 +20,6 @@
#include <QSet> #include <QSet>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QTextCodec>
SystemConsts* pSystemConsts; SystemConsts* pSystemConsts;
@ -44,28 +43,7 @@ SystemConsts::SystemConsts(): mDefaultFileFilters()
mCodecNames.append(ENCODING_SYSTEM_DEFAULT); mCodecNames.append(ENCODING_SYSTEM_DEFAULT);
mCodecNames.append(ENCODING_UTF8); mCodecNames.append(ENCODING_UTF8);
mCodecNames.append(ENCODING_UTF8_BOM); mCodecNames.append(ENCODING_UTF8_BOM);
QStringList codecNames; mCodecNames.append(availableEncodings());
QSet<QByteArray> codecAlias;
codecAlias.insert("system");
codecAlias.insert("utf-8");
foreach (const QByteArray& name, QTextCodec::availableCodecs()){
QByteArray lname = name.toLower();
if (lname.startsWith("cp"))
continue;
if (codecAlias.contains(lname))
continue;
codecNames.append(lname);
codecAlias.insert(lname);
QTextCodec* codec = QTextCodec::codecForName(name);
if (codec) {
foreach (const QByteArray& alias, codec->aliases()) {
codecAlias.insert(alias.toLower());
}
}
}
std::sort(codecNames.begin(),codecNames.end());
mCodecNames.append(codecNames);
mDefaultFileNameFilters.append("*.c"); mDefaultFileNameFilters.append("*.c");
mDefaultFileNameFilters.append("*.cpp"); mDefaultFileNameFilters.append("*.cpp");

View File

@ -227,4 +227,12 @@ bool osSupportsUtf8Manifest();
bool applicationIsUtf8(const QString &path); bool applicationIsUtf8(const QString &path);
#endif #endif
#if QT_VERSION_MAJOR >= 6
// for xml.name() == "tag"
inline bool operator==(QStringView a, const char *b)
{
return a.compare(b);
}
#endif
#endif // UTILS_H #endif // UTILS_H

View File

@ -115,7 +115,11 @@ void ColorEdit::mouseReleaseEvent(QMouseEvent *)
} }
} }
#if QT_VERSION_MAJOR >= 6
void ColorEdit::enterEvent(QEnterEvent *)
#else
void ColorEdit::enterEvent(QEvent *) void ColorEdit::enterEvent(QEvent *)
#endif
{ {
setCursor(Qt::PointingHandCursor); setCursor(Qt::PointingHandCursor);
} }

View File

@ -37,7 +37,11 @@ public:
QSize sizeHint() const override; QSize sizeHint() const override;
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override;
#if QT_VERSION_MAJOR >= 6
void enterEvent(QEnterEvent *event) override;
#else
void enterEvent(QEvent *event) override; void enterEvent(QEvent *event) override;
#endif
void leaveEvent(QEvent *event) override; void leaveEvent(QEvent *event) override;
QSize minimumSizeHint() const override; QSize minimumSizeHint() const override;
}; };

View File

@ -19,6 +19,7 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QPushButton> #include <QPushButton>
#include <QDebug> #include <QDebug>
#include <qt_utils/utils.h>
FunctionTooltipWidget::FunctionTooltipWidget(QWidget *parent) : FunctionTooltipWidget::FunctionTooltipWidget(QWidget *parent) :
QFrame{parent, Qt::ToolTip | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus}, QFrame{parent, Qt::ToolTip | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus},

View File

@ -33,7 +33,11 @@ void LabelWithMenu::mousePressEvent(QMouseEvent *event)
event->accept(); event->accept();
} }
#if QT_VERSION_MAJOR >= 6
void LabelWithMenu::enterEvent(QEnterEvent *event)
#else
void LabelWithMenu::enterEvent(QEvent *event) void LabelWithMenu::enterEvent(QEvent *event)
#endif
{ {
mCursor = cursor(); mCursor = cursor();
setCursor(Qt::PointingHandCursor); setCursor(Qt::PointingHandCursor);

View File

@ -31,7 +31,11 @@ protected:
// QWidget interface // QWidget interface
protected: protected:
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void enterEvent(QEnterEvent *event) override;
#else
void enterEvent(QEvent *event) override; void enterEvent(QEvent *event) override;
#endif
void leaveEvent(QEvent *event) override; void leaveEvent(QEvent *event) override;
private: private:

View File

@ -51,6 +51,9 @@ struct RowColumn {
struct LineChar { struct LineChar {
int ch; int ch;
int line; int line;
LineChar() = default;
constexpr LineChar(qsizetype ch_, qsizetype line_) : ch(ch_), line(line_) {}
}; };
class QConsole; class QConsole;

View File

@ -35,6 +35,13 @@ protected:
QListView::resizeEvent(event); QListView::resizeEvent(event);
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void initViewItemOption(QStyleOptionViewItem *option) const override
{
QListView::initViewItemOption(option);
option->showDecorationSelected = true;
}
#else
QStyleOptionViewItem viewOptions() const override QStyleOptionViewItem viewOptions() const override
{ {
QStyleOptionViewItem option = QListView::viewOptions(); QStyleOptionViewItem option = QListView::viewOptions();
@ -43,6 +50,7 @@ protected:
// option.font = combo->font(); // option.font = combo->font();
return option; return option;
} }
#endif
void paintEvent(QPaintEvent *e) override void paintEvent(QPaintEvent *e) override
{ {
@ -59,7 +67,11 @@ protected:
menuOpt.checkType = QStyleOptionMenuItem::NotCheckable; menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
menuOpt.menuRect = e->rect(); menuOpt.menuRect = e->rect();
menuOpt.maxIconWidth = 0; menuOpt.maxIconWidth = 0;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
menuOpt.reservedShortcutWidth = 0;
#else
menuOpt.tabWidth = 0; menuOpt.tabWidth = 0;
#endif
QPainter p(viewport()); QPainter p(viewport());
combo->style()->drawControl(QStyle::CE_MenuEmptyArea, &menuOpt, &p, this); combo->style()->drawControl(QStyle::CE_MenuEmptyArea, &menuOpt, &p, this);
} }

View File

@ -3,7 +3,7 @@
## 传统 Unix 方式(`./configure``make``make install` ## 传统 Unix 方式(`./configure``make``make install`
- 安装支持 C++17 的 GCC≥ 7或 Clang≥ 6 - 安装支持 C++17 的 GCC≥ 7或 Clang≥ 6
- 安装 Qt 5.15 Base、SVG、Tools 模块,包括库和开发文件。 - 安装 Qt 5.15 或 6.7+ Base、SVG、Tools 模块,包括库和开发文件。
- 如果使用静态版本的 Qt 编译,还要安装 fcitx5-qt。 - 如果使用静态版本的 Qt 编译,还要安装 fcitx5-qt。
- 安装 astyle 以便在小熊猫 C++ 中对代码进行重新排版。 - 安装 astyle 以便在小熊猫 C++ 中对代码进行重新排版。

View File

@ -3,7 +3,7 @@
## Traditional Unix Way (`./configure``make``make install`) ## Traditional Unix Way (`./configure``make``make install`)
- Install recent version of GCC (≥ 7) or Clang (≥ 6) that supports C++17. - Install recent version of GCC (≥ 7) or Clang (≥ 6) that supports C++17.
- Install Qt 5.15 Base, SVG and Tools modules, including both libraries and development files. - Install Qt 5.15 or 6.7+ Base, SVG and Tools modules, including both libraries and development files.
- Optionally install fcitx5-qt for building with static Qt library. - Optionally install fcitx5-qt for building with static Qt library.
- Install astyle for code formatting in Red Panda C++. - Install astyle for code formatting in Red Panda C++.

View File

@ -18,12 +18,12 @@
#include "qt_utils/utils.h" #include "qt_utils/utils.h"
#include <QDataStream> #include <QDataStream>
#include <QFile> #include <QFile>
#include <QTextCodec>
#include <QTextStream> #include <QTextStream>
#include <QMutexLocker> #include <QMutexLocker>
#include <stdexcept> #include <stdexcept>
#include <QMessageBox> #include <QMessageBox>
#include <cmath> #include <cmath>
#include <optional>
#include "qt_utils/charsetinfo.h" #include "qt_utils/charsetinfo.h"
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
@ -498,12 +498,11 @@ void Document::insertLines(int index, int numLines)
bool Document::tryLoadFileByEncoding(QByteArray encodingName, QFile& file) { bool Document::tryLoadFileByEncoding(QByteArray encodingName, QFile& file) {
QTextCodec* codec = QTextCodec::codecForName(encodingName); TextDecoder decoder(encodingName);
if (!codec) if (!decoder.isValid())
return false; return false;
file.reset(); file.reset();
internalClear(); internalClear();
QTextCodec::ConverterState state;
while (true) { while (true) {
if (file.atEnd()){ if (file.atEnd()){
break; break;
@ -516,10 +515,9 @@ bool Document::tryLoadFileByEncoding(QByteArray encodingName, QFile& file) {
} else if (line.endsWith("\n")){ } else if (line.endsWith("\n")){
line.remove(line.length()-1,1); line.remove(line.length()-1,1);
} }
QString newLine = codec->toUnicode(line.constData(),line.length(),&state); auto [ok, newLine] = decoder.decode(line);
if (state.invalidChars>0) { if (!ok) {
return false; return false;
break;
} }
addItem(newLine); addItem(newLine);
} }
@ -528,46 +526,46 @@ bool Document::tryLoadFileByEncoding(QByteArray encodingName, QFile& file) {
void Document::loadUTF16BOMFile(QFile &file) void Document::loadUTF16BOMFile(QFile &file)
{ {
QTextCodec* codec=QTextCodec::codecForName(ENCODING_UTF16); TextDecoder decoder = TextDecoder::decoderForUtf16();
if (!codec) if (!decoder.isValid())
return; return;
file.reset(); file.reset();
internalClear(); internalClear();
QByteArray buf = file.readAll(); QByteArray buf = file.readAll();
if (buf.length()<2) if (buf.length()<2)
return; return;
QString text = codec->toUnicode(buf.mid(2)); QString text = decoder.decodeUnchecked(buf.mid(2));
this->setText(text); this->setText(text);
} }
void Document::loadUTF32BOMFile(QFile &file) void Document::loadUTF32BOMFile(QFile &file)
{ {
QTextCodec* codec=QTextCodec::codecForName(ENCODING_UTF32); TextDecoder decoder = TextDecoder::decoderForUtf32();
if (!codec) if (!decoder.isValid())
return; return;
file.reset(); file.reset();
internalClear(); internalClear();
QByteArray buf = file.readAll(); QByteArray buf = file.readAll();
if (buf.length()<4) if (buf.length()<4)
return; return;
QString text = codec->toUnicode(buf.mid(4)); QString text = decoder.decodeUnchecked(buf.mid(4));
this->setText(text); this->setText(text);
} }
void Document::saveUTF16File(QFile &file, QTextCodec* codec) void Document::saveUTF16File(QFile &file, TextEncoder &encoder)
{ {
if (!codec) if (!encoder.isValid())
return; return;
QString text=getTextStr(); QString text=getTextStr();
file.write(codec->fromUnicode(text)); file.write(encoder.encodeUnchecked(text));
} }
void Document::saveUTF32File(QFile &file, QTextCodec* codec) void Document::saveUTF32File(QFile &file, TextEncoder &encoder)
{ {
if (!codec) if (!encoder.isValid())
return; return;
QString text=getTextStr(); QString text=getTextStr();
file.write(codec->fromUnicode(text)); file.write(encoder.encodeUnchecked(text));
} }
void Document::setTabSize(int newTabSize) void Document::setTabSize(int newTabSize)
@ -606,15 +604,14 @@ void Document::loadFromFile(const QString& filename, const QByteArray& encoding,
return; return;
} }
QByteArray line = file.readLine(); QByteArray line = file.readLine();
QTextCodec* codec; std::optional<TextDecoder> decoder;
QTextCodec::ConverterState state;
bool needReread = false; bool needReread = false;
bool allAscii = true; bool allAscii = true;
//test for BOM //test for BOM
if ((line.length()>=3) && ((unsigned char)line[0]==0xEF) && ((unsigned char)line[1]==0xBB) && ((unsigned char)line[2]==0xBF) ) { if ((line.length()>=3) && ((unsigned char)line[0]==0xEF) && ((unsigned char)line[1]==0xBB) && ((unsigned char)line[2]==0xBF) ) {
realEncoding = ENCODING_UTF8_BOM; realEncoding = ENCODING_UTF8_BOM;
line = line.mid(3); line = line.mid(3);
codec = QTextCodec::codecForName(ENCODING_UTF8); decoder = TextDecoder::decoderForUtf8();
} else if ((line.length()>=4) && ((unsigned char)line[0]==0xFF) && ((unsigned char)line[1]==0xFE) } else if ((line.length()>=4) && ((unsigned char)line[0]==0xFF) && ((unsigned char)line[1]==0xFE)
&& ((unsigned char)line[2]==0x00) && ((unsigned char)line[2]==0x00)
&& ((unsigned char)line[3]==0x00)) { && ((unsigned char)line[3]==0x00)) {
@ -627,9 +624,9 @@ void Document::loadFromFile(const QString& filename, const QByteArray& encoding,
return; return;
} else { } else {
realEncoding = ENCODING_UTF8; realEncoding = ENCODING_UTF8;
codec = QTextCodec::codecForName(ENCODING_UTF8); decoder = TextDecoder::decoderForUtf8();
} }
if (!codec) if (!decoder.has_value())
throw FileError(tr("Can't load codec '%1'!").arg(QString(realEncoding))); throw FileError(tr("Can't load codec '%1'!").arg(QString(realEncoding)));
if (line.endsWith("\r\n")) { if (line.endsWith("\r\n")) {
mNewlineType = NewlineType::Windows; mNewlineType = NewlineType::Windows;
@ -656,8 +653,8 @@ void Document::loadFromFile(const QString& filename, const QByteArray& encoding,
if (allAscii) { if (allAscii) {
addItem(QString::fromLatin1(line)); addItem(QString::fromLatin1(line));
} else { } else {
QString newLine = codec->toUnicode(line.constData(),line.length(),&state); auto [ok, newLine] = decoder->decode(line);
if (state.invalidChars>0) { if (!ok) {
needReread = true; needReread = true;
break; break;
} }
@ -703,13 +700,16 @@ void Document::loadFromFile(const QString& filename, const QByteArray& encoding,
realEncoding = pCharsetInfoManager->getDefaultSystemEncoding(); realEncoding = pCharsetInfoManager->getDefaultSystemEncoding();
} }
file.reset(); file.reset();
QTextStream textStream(&file); QByteArray data = file.readAll();
QString text;
QTextStream textStream(&text);
if (realEncoding == ENCODING_UTF8_BOM) { if (realEncoding == ENCODING_UTF8_BOM) {
textStream.setAutoDetectUnicode(true); textStream.setAutoDetectUnicode(true);
textStream.setCodec(ENCODING_UTF8); text = QString::fromUtf8(data);
} else { } else {
textStream.setAutoDetectUnicode(false); textStream.setAutoDetectUnicode(false);
textStream.setCodec(realEncoding); TextDecoder decoder(realEncoding);
text = decoder.decodeUnchecked(data);
} }
QString line; QString line;
internalClear(); internalClear();
@ -731,28 +731,28 @@ void Document::saveToFile(QFile &file, const QByteArray& encoding,
const QByteArray& defaultEncoding, QByteArray& realEncoding) const QByteArray& defaultEncoding, QByteArray& realEncoding)
{ {
QMutexLocker locker(&mMutex); QMutexLocker locker(&mMutex);
QTextCodec* codec; std::optional<TextEncoder> encoder;
realEncoding = encoding; realEncoding = encoding;
QString codecName = realEncoding; QString codecName = realEncoding;
if (realEncoding == ENCODING_UTF16_BOM || realEncoding == ENCODING_UTF16) { if (realEncoding == ENCODING_UTF16_BOM || realEncoding == ENCODING_UTF16) {
codec = QTextCodec::codecForName(ENCODING_UTF16); encoder = TextEncoder::encoderForUtf16();
codecName = ENCODING_UTF16; codecName = ENCODING_UTF16;
} else if (realEncoding == ENCODING_UTF32_BOM || realEncoding == ENCODING_UTF32) { } else if (realEncoding == ENCODING_UTF32_BOM || realEncoding == ENCODING_UTF32) {
codec = QTextCodec::codecForName(ENCODING_UTF32); encoder = TextEncoder::encoderForUtf32();
codecName = ENCODING_UTF32; codecName = ENCODING_UTF32;
} else if (realEncoding == ENCODING_UTF8_BOM) { } else if (realEncoding == ENCODING_UTF8_BOM) {
codec = QTextCodec::codecForName(ENCODING_UTF8); encoder = TextEncoder::encoderForUtf8();
codecName = ENCODING_UTF8; codecName = ENCODING_UTF8;
} else if (realEncoding == ENCODING_SYSTEM_DEFAULT) { } else if (realEncoding == ENCODING_SYSTEM_DEFAULT) {
codec = QTextCodec::codecForLocale(); encoder = TextEncoder::encoderForSystem();
codecName = realEncoding; codecName = realEncoding;
} else if (realEncoding == ENCODING_AUTO_DETECT) { } else if (realEncoding == ENCODING_AUTO_DETECT) {
codec = QTextCodec::codecForName(defaultEncoding); encoder = TextEncoder(defaultEncoding);
codecName = defaultEncoding; codecName = defaultEncoding;
} else { } else {
codec = QTextCodec::codecForName(realEncoding); encoder = TextEncoder(realEncoding);
} }
if (!codec) if (!encoder.has_value() || !encoder->isValid())
throw FileError(tr("Can't load codec '%1'!").arg(codecName)); throw FileError(tr("Can't load codec '%1'!").arg(codecName));
if (!file.open(QFile::WriteOnly | QFile::Truncate)) if (!file.open(QFile::WriteOnly | QFile::Truncate))
@ -760,10 +760,10 @@ void Document::saveToFile(QFile &file, const QByteArray& encoding,
if (mLines.isEmpty()) if (mLines.isEmpty())
return; return;
if (realEncoding == ENCODING_UTF16) { if (realEncoding == ENCODING_UTF16) {
saveUTF16File(file,codec); saveUTF16File(file, encoder.value());
return; return;
} else if (realEncoding == ENCODING_UTF32) { } else if (realEncoding == ENCODING_UTF32) {
saveUTF32File(file,codec); saveUTF32File(file, encoder.value());
return; return;
} if (realEncoding == ENCODING_UTF8_BOM) { } if (realEncoding == ENCODING_UTF8_BOM) {
file.putChar(0xEF); file.putChar(0xEF);
@ -774,7 +774,7 @@ void Document::saveToFile(QFile &file, const QByteArray& encoding,
QByteArray data; QByteArray data;
for (PDocumentLine& line:mLines) { for (PDocumentLine& line:mLines) {
QString text = line->lineText()+lineBreak(); QString text = line->lineText()+lineBreak();
data = codec->fromUnicode(text); data = encoder->encodeUnchecked(text);
if (allAscii) { if (allAscii) {
allAscii = (data==text.toLatin1()); allAscii = (data==text.toLatin1());
} }
@ -784,10 +784,10 @@ void Document::saveToFile(QFile &file, const QByteArray& encoding,
if (allAscii) { if (allAscii) {
realEncoding = ENCODING_ASCII; realEncoding = ENCODING_ASCII;
} else if (realEncoding == ENCODING_SYSTEM_DEFAULT) { } else if (realEncoding == ENCODING_SYSTEM_DEFAULT) {
if (QString(codec->name()).compare("System",Qt::CaseInsensitive)==0) { if (encoder->name().compare("System",Qt::CaseInsensitive)==0) {
realEncoding = pCharsetInfoManager->getDefaultSystemEncoding(); realEncoding = pCharsetInfoManager->getDefaultSystemEncoding();
} else { } else {
realEncoding = codec->name(); realEncoding = encoder->name();
} }
} }
} }

View File

@ -647,8 +647,8 @@ private:
bool tryLoadFileByEncoding(QByteArray encodingName, QFile& file); bool tryLoadFileByEncoding(QByteArray encodingName, QFile& file);
void loadUTF16BOMFile(QFile& file); void loadUTF16BOMFile(QFile& file);
void loadUTF32BOMFile(QFile& file); void loadUTF32BOMFile(QFile& file);
void saveUTF16File(QFile& file, QTextCodec* codec); void saveUTF16File(QFile& file, TextEncoder &encoder);
void saveUTF32File(QFile& file, QTextCodec* codec); void saveUTF32File(QFile& file, TextEncoder &encoder);
private: private:
DocumentLines mLines; DocumentLines mLines;

View File

@ -21,7 +21,7 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QMimeData> #include <QMimeData>
#include <QPalette> #include <QPalette>
#include <QTextCodec> #include <qt_utils/utils.h>
namespace QSynedit { namespace QSynedit {
@ -131,8 +131,9 @@ void Exporter::saveToFile(const QString &filename)
void Exporter::writeToStream(QIODevice &stream) void Exporter::writeToStream(QIODevice &stream)
{ {
QTextCodec *codec=getCodec(); TextEncoder encoder = getEncoder();
if (stream.write(codec->fromUnicode(mText))<0) { auto [ok, encoded] = encoder.encode(mText);
if (ok && stream.write(encoded) < 0) {
throw FileError(QObject::tr("Failed to write data.")); throw FileError(QObject::tr("Failed to write data."));
} }
} }
@ -274,12 +275,14 @@ int Exporter::getBufferSize() const
return mText.size(); return mText.size();
} }
QTextCodec * Exporter::getCodec() const { TextEncoder Exporter::getEncoder() const {
QTextCodec* codec = QTextCodec::codecForName(mCharset); TextEncoder encoder(mCharset);
if (codec == nullptr) if (encoder.isValid())
codec = QTextCodec::codecForLocale(); return encoder;
return codec; else
return TextEncoder::encoderForSystem();
} }
void Exporter::insertData(int pos, const QString &text) void Exporter::insertData(int pos, const QString &text)
{ {
if (!text.isEmpty()) { if (!text.isEmpty()) {
@ -339,8 +342,9 @@ void Exporter::setTokenAttribute(PTokenAttribute attri)
QByteArray Exporter::buffer() const QByteArray Exporter::buffer() const
{ {
QTextCodec* codec = getCodec(); TextEncoder encoder = getEncoder();
return codec->fromUnicode(mText); auto [_, encoded] = encoder.encode(mText);
return encoded;
} }
const QString &Exporter::text() const const QString &Exporter::text() const

View File

@ -242,7 +242,7 @@ protected:
*/ */
virtual void setTokenAttribute(PTokenAttribute attri); virtual void setTokenAttribute(PTokenAttribute attri);
QTextCodec *getCodec() const; TextEncoder getEncoder() const;
private: private:
QString mText; QString mText;
bool mFirstAttribute; bool mFirstAttribute;

View File

@ -16,6 +16,7 @@
*/ */
#include "gutter.h" #include "gutter.h"
#include "algorithm" #include "algorithm"
#include <qt_utils/utils.h>
namespace QSynedit { namespace QSynedit {

View File

@ -30,9 +30,9 @@ EditKeyStroke::EditKeyStroke()
QKeySequence EditKeyStroke::keySequence() const QKeySequence EditKeyStroke::keySequence() const
{ {
if (mKey2 == 0) { if (mKey2 == 0) {
return QKeySequence(mKey + mKeyModifiers); return QKeySequence(mKey | mKeyModifiers);
} else { } else {
return QKeySequence(mKey + mKeyModifiers, mKey2+mKeyModifiers2); return QKeySequence(mKey | mKeyModifiers, mKey2 | mKeyModifiers2);
} }
} }

View File

@ -309,7 +309,7 @@ void ASMSyntaxer::SpaceProc()
mRun++; mRun++;
if (mLine[mRun] == 0 || mLine[mRun] == '\r' || mLine[mRun] == '\n') if (mLine[mRun] == 0 || mLine[mRun] == '\r' || mLine[mRun] == '\n')
break; break;
if (mLine[mRun] > 32) if (!isLexicalSpace(mLine[mRun]))
break; break;
} }
if (mRun>=mStringLen) if (mRun>=mStringLen)
@ -1696,7 +1696,7 @@ void ASMSyntaxer::next()
NumberProc(); NumberProc();
} else if (isIdentStartChar(mLine[mRun])) { } else if (isIdentStartChar(mLine[mRun])) {
IdentProc(IdentPrefix::None); IdentProc(IdentPrefix::None);
} else if (mLine[mRun]<=32) { } else if (isLexicalSpace(mLine[mRun])) {
SpaceProc(); SpaceProc();
} else { } else {
UnknownProc(); UnknownProc();

View File

@ -16,6 +16,7 @@
*/ */
#include "cpp.h" #include "cpp.h"
#include "../constants.h" #include "../constants.h"
#include "qt_utils/utils.h"
#include <QFont> #include <QFont>
#include <QDebug> #include <QDebug>
@ -1069,7 +1070,7 @@ void CppSyntaxer::procSpace()
{ {
mRun += 1; mRun += 1;
mTokenId = TokenId::Space; mTokenId = TokenId::Space;
while (mRun<mLineSize && mLine[mRun]>=1 && mLine[mRun]<=32) while (mRun < mLineSize && isLexicalSpace(mLine[mRun]))
mRun+=1; mRun+=1;
if (mRun>=mLineSize) { if (mRun>=mLineSize) {
mRange.hasTrailingSpaces = true; mRange.hasTrailingSpaces = true;

View File

@ -846,7 +846,7 @@ void GLSLSyntaxer::spaceProc()
{ {
mRun += 1; mRun += 1;
mTokenId = TokenId::Space; mTokenId = TokenId::Space;
while (mLine[mRun]>=1 && mLine[mRun]<=32) while (isLexicalSpace(mLine[mRun]))
mRun+=1; mRun+=1;
mRange.state = RangeState::rsUnknown; mRange.state = RangeState::rsUnknown;
if (mRun>=mLineSize) if (mRun>=mLineSize)

View File

@ -16,6 +16,7 @@
*/ */
#include "lua.h" #include "lua.h"
#include "../constants.h" #include "../constants.h"
#include "qt_utils/utils.h"
#include <QFont> #include <QFont>
#include <QDebug> #include <QDebug>
@ -587,7 +588,7 @@ void LuaSyntaxer::spaceProc()
{ {
mRun += 1; mRun += 1;
mTokenId = TokenId::Space; mTokenId = TokenId::Space;
while (mRun<mLineSize && mLine[mRun]>=1 && mLine[mRun]<=32) while (mRun<mLineSize && isLexicalSpace(mLine[mRun]))
mRun+=1; mRun+=1;
if (mRun>=mLineSize) { if (mRun>=mLineSize) {
mRange.hasTrailingSpaces = true; mRange.hasTrailingSpaces = true;

View File

@ -200,7 +200,7 @@ MakefileSyntaxer::MakefileSyntaxer()
void MakefileSyntaxer::procSpace() void MakefileSyntaxer::procSpace()
{ {
mTokenID = TokenId::Space; mTokenID = TokenId::Space;
while (mLine[mRun]!=0 && mLine[mRun]<=32) while (mLine[mRun]!=0 && mLine[mRun] <= ' ')
mRun++; mRun++;
if (mRun>=mStringLen) if (mRun>=mStringLen)
mHasTrailingSpaces = true; mHasTrailingSpaces = true;

View File

@ -46,6 +46,10 @@ enum class ProgrammingLanguage {
struct BufferCoord { struct BufferCoord {
int ch; int ch;
int line; int line;
BufferCoord() = default;
constexpr BufferCoord(qsizetype ch_, qsizetype line_) : ch(ch_), line(line_) {}
bool operator==(const BufferCoord& coord); bool operator==(const BufferCoord& coord);
bool operator>=(const BufferCoord& coord); bool operator>=(const BufferCoord& coord);
bool operator>(const BufferCoord& coord); bool operator>(const BufferCoord& coord);

View File

@ -21,8 +21,6 @@
#include <QSet> #include <QSet>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <windows.h> #include <windows.h>
#else
#include <langinfo.h>
#endif #endif
CharsetInfoManager* pCharsetInfoManager; CharsetInfoManager* pCharsetInfoManager;
@ -37,7 +35,7 @@ QByteArray CharsetInfoManager::getDefaultSystemEncoding()
} }
return "unknown"; return "unknown";
#else #else
return QByteArray(nl_langinfo(CODESET)); return "UTF-8";
#endif #endif
} }

View File

@ -23,7 +23,6 @@
#include <QProcess> #include <QProcess>
#include <QProcessEnvironment> #include <QProcessEnvironment>
#include <QString> #include <QString>
#include <QTextCodec>
#include <QtGlobal> #include <QtGlobal>
#include <QDebug> #include <QDebug>
#include <QStyleFactory> #include <QStyleFactory>
@ -33,6 +32,8 @@
#include <QScreen> #include <QScreen>
#include <QDirIterator> #include <QDirIterator>
#include <QTextEdit> #include <QTextEdit>
#include "charsetinfo.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <QDirIterator> #include <QDirIterator>
#include <QFont> #include <QFont>
@ -40,7 +41,12 @@
#include <QMimeDatabase> #include <QMimeDatabase>
#include <windows.h> #include <windows.h>
#endif #endif
#include "charsetinfo.h"
#if QT_VERSION_MAJOR >= 6
# include <QStringConverter>
#else
# include <QTextCodec>
#endif
BaseError::BaseError(const QString &reason): BaseError::BaseError(const QString &reason):
mReason(reason) mReason(reason)
@ -64,7 +70,7 @@ FileError::FileError(const QString &reason): BaseError(reason)
} }
const QByteArray guessTextEncoding(const QByteArray& text){ QString guessTextEncoding(const QByteArray& text){
bool allAscii; bool allAscii;
int ii; int ii;
int size; int size;
@ -253,14 +259,16 @@ QByteArray toByteArray(const QString &s)
QString fromByteArray(const QByteArray &s) QString fromByteArray(const QByteArray &s)
{ {
QTextCodec* codec = QTextCodec::codecForName(ENCODING_UTF8); #ifdef Q_OS_WIN
QTextCodec::ConverterState state; TextDecoder decoder = TextDecoder::decoderForUtf8();
if (!codec) auto [ok, result] = decoder.decode(s);
return QString(s); if (ok)
QString tmp = codec->toUnicode(s,s.length(),&state); return result;
if (state.invalidChars>0) else
tmp = QString::fromLocal8Bit(s); return QString::fromLocal8Bit(s);
return tmp; #else
return QString::fromUtf8(s);
#endif
} }
QStringList readStreamToLines(QTextStream *stream) QStringList readStreamToLines(QTextStream *stream)
@ -282,37 +290,13 @@ void readStreamToLines(QTextStream *stream,
} }
} }
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);
}
}
static QStringList tryLoadFileByEncoding(QByteArray encodingName, QFile& file, bool* isOk) { static QStringList tryLoadFileByEncoding(QByteArray encodingName, QFile& file, bool* isOk) {
QStringList result; QStringList result;
*isOk = false; *isOk = false;
QTextCodec* codec = QTextCodec::codecForName(encodingName); TextDecoder decoder(encodingName);
if (!codec) if (!decoder.isValid())
return result; return result;
file.reset(); file.reset();
QTextCodec::ConverterState state;
while (true) { while (true) {
if (file.atEnd()){ if (file.atEnd()){
break; break;
@ -325,8 +309,8 @@ static QStringList tryLoadFileByEncoding(QByteArray encodingName, QFile& file, b
} else if (line.endsWith("\n")){ } else if (line.endsWith("\n")){
line.remove(line.length()-1,1); line.remove(line.length()-1,1);
} }
QString newLine = codec->toUnicode(line.constData(),line.length(),&state); auto [ok, newLine] = decoder.decode(line);
if (state.invalidChars>0) { if (!ok) {
return QStringList(); return QStringList();
} }
result.append(newLine); result.append(newLine);
@ -355,12 +339,12 @@ QStringList readFileToLines(const QString &fileName)
} }
QList<PCharsetInfo> charsets = pCharsetInfoManager->findCharsetByLocale(pCharsetInfoManager->localeName()); QList<PCharsetInfo> charsets = pCharsetInfoManager->findCharsetByLocale(pCharsetInfoManager->localeName());
if (!charsets.isEmpty()) { if (!charsets.isEmpty()) {
QSet<QByteArray> encodingSet; QSet<QString> encodingSet;
for (int i=0;i<charsets.size();i++) { for (int i=0;i<charsets.size();i++) {
encodingSet.insert(charsets[i]->name); encodingSet.insert(charsets[i]->name);
} }
encodingSet.remove(realEncoding); encodingSet.remove(realEncoding);
foreach (const QByteArray& encodingName,encodingSet) { foreach (const QString& encodingName,encodingSet) {
if (encodingName == ENCODING_UTF8) if (encodingName == ENCODING_UTF8)
continue; continue;
result = tryLoadFileByEncoding("UTF-8",file,&ok); result = tryLoadFileByEncoding("UTF-8",file,&ok);
@ -765,3 +749,273 @@ const QChar *getNullTerminatedStringData(const QString &str)
} }
return result; return result;
} }
TextEncoder::TextEncoder(const char *name)
{
#if QT_VERSION_MAJOR >= 6
mEncoder = QStringEncoder(name, QStringConverter::Flag::Stateless);
#else
mCodec = QTextCodec::codecForName(name);
#endif
}
TextEncoder::TextEncoder(const QByteArray &name) :
TextEncoder(name.data())
{
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
TextEncoder::TextEncoder(QStringEncoder &&encoder)
{
mEncoder = std::move(encoder);
}
#endif
bool TextEncoder::isValid() const
{
#if QT_VERSION_MAJOR >= 6
return mEncoder.isValid();
#else
return mCodec != nullptr;
#endif
}
QByteArray TextEncoder::name() const
{
#if QT_VERSION_MAJOR >= 6
return mEncoder.name();
#else
return mCodec->name();
#endif
}
std::pair<bool, QByteArray> TextEncoder::encode(const QString &text)
{
if (!isValid())
return {false, QByteArray()};
QByteArray result;
#if QT_VERSION_MAJOR >= 6
result = mEncoder(text);
if (mEncoder.hasError()) {
mEncoder.resetState();
return {false, QByteArray()};
}
#else
QTextCodec::ConverterState state;
result = mCodec->fromUnicode(text.constData(), text.length(), &state);
if (state.invalidChars > 0)
return {false, QByteArray()};
#endif
return {true, result};
}
QByteArray TextEncoder::encodeUnchecked(const QString &text)
{
if (!isValid())
return QByteArray();
#if QT_VERSION_MAJOR >= 6
QByteArray result = mEncoder(text);
if (mEncoder.hasError())
mEncoder.resetState();
return result;
#else
return mCodec->fromUnicode(text);
#endif
}
TextEncoder TextEncoder::encoderForUtf8()
{
#if QT_VERSION_MAJOR >= 6
return QStringEncoder(QStringConverter::Utf8, QStringConverter::Flag::Stateless);
#else
return TextEncoder(ENCODING_UTF8);
#endif
}
TextEncoder TextEncoder::encoderForUtf16()
{
#if QT_VERSION_MAJOR >= 6
return QStringEncoder(QStringConverter::Utf16, QStringConverter::Flag::Stateless);
#else
return TextEncoder(ENCODING_UTF16);
#endif
}
TextEncoder TextEncoder::encoderForUtf32()
{
#if QT_VERSION_MAJOR >= 6
return QStringEncoder(QStringConverter::Utf32, QStringConverter::Flag::Stateless);
#else
return TextEncoder(ENCODING_UTF32);
#endif
}
TextEncoder TextEncoder::encoderForSystem()
{
#ifdef Q_OS_WIN
# if QT_VERSION_MAJOR >= 6
return QStringEncoder(QStringConverter::System, QStringConverter::Flag::Stateless);
# else
return TextEncoder(ENCODING_SYSTEM_DEFAULT);
# endif
#else
return encoderForUtf8();
#endif
}
TextDecoder::TextDecoder(const char *name)
{
#if QT_VERSION_MAJOR >= 6
mDecoder = QStringDecoder(name, QStringConverter::Flag::Stateless);
#else
mCodec = QTextCodec::codecForName(name);
#endif
}
TextDecoder::TextDecoder(const QByteArray &name) :
TextDecoder(name.data())
{
}
#if QT_VERSION_MAJOR >= 6
TextDecoder::TextDecoder(QStringDecoder &&decoder)
{
mDecoder = std::move(decoder);
}
#endif
bool TextDecoder::isValid() const
{
#if QT_VERSION_MAJOR >= 6
return mDecoder.isValid();
#else
return mCodec != nullptr;
#endif
}
QByteArray TextDecoder::name() const
{
#if QT_VERSION_MAJOR >= 6
return mDecoder.name();
#else
return mCodec->name();
#endif
}
std::pair<bool, QString> TextDecoder::decode(const QByteArray &text)
{
if (!isValid())
return {false, QString()};
QString result;
#if QT_VERSION_MAJOR >= 6
result = mDecoder(text);
if (mDecoder.hasError()) {
mDecoder.resetState();
return {false, QString()};
}
#else
QTextCodec::ConverterState state;
result = mCodec->toUnicode(text.constData(), text.length(), &state);
if (state.invalidChars > 0)
return {false, QString()};
#endif
return {true, result};
}
QString TextDecoder::decodeUnchecked(const QByteArray &text)
{
if (!isValid())
return QString();
#if QT_VERSION_MAJOR >= 6
QString result = mDecoder(text);
if (mDecoder.hasError())
mDecoder.resetState();
return result;
#else
return mCodec->toUnicode(text);
#endif
}
TextDecoder TextDecoder::decoderForUtf8()
{
#if QT_VERSION_MAJOR >= 6
return QStringDecoder(QStringConverter::Utf8, QStringConverter::Flag::Stateless);
#else
return TextDecoder(ENCODING_UTF8);
#endif
}
TextDecoder TextDecoder::decoderForUtf16()
{
#if QT_VERSION_MAJOR >= 6
return QStringDecoder(QStringConverter::Utf16, QStringConverter::Flag::Stateless);
#else
return TextDecoder(ENCODING_UTF16);
#endif
}
TextDecoder TextDecoder::decoderForUtf32()
{
#if QT_VERSION_MAJOR >= 6
return QStringDecoder(QStringConverter::Utf32, QStringConverter::Flag::Stateless);
#else
return TextDecoder(ENCODING_UTF32);
#endif
}
TextDecoder TextDecoder::decoderForSystem()
{
#ifdef Q_OS_WIN
# if QT_VERSION_MAJOR >= 6
return QStringDecoder(QStringConverter::System, QStringConverter::Flag::Stateless);
# else
return TextDecoder(ENCODING_SYSTEM_DEFAULT);
# endif
#else
return decoderForUtf8();
#endif
}
const QStringList &availableEncodings() {
static bool initialized = false;
static QStringList encodings;
if (initialized)
return encodings;
#if QT_VERSION_MAJOR >= 6
for (const QString &name : QStringConverter::availableCodecs()) {
QString lname = name.toLower();
if (lname.startsWith("cp"))
continue;
if (lname == "locale" || lname == "utf-8")
continue;
encodings.append(name);
}
#else
QSet<QByteArray> codecAlias = {"system", "utf-8"};
for (const QByteArray &name : QTextCodec::availableCodecs()) {
QByteArray lname = name.toLower();
if (lname.startsWith("cp"))
continue;
if (codecAlias.contains(lname))
continue;
encodings.append(name);
codecAlias.insert(lname);
QTextCodec *codec = QTextCodec::codecForName(name);
if (codec != nullptr) {
for (const QByteArray &alias : codec->aliases())
codecAlias.insert(alias.toLower());
}
}
#endif
std::sort(encodings.begin(), encodings.end());
initialized = true;
return encodings;
}
bool isEncodingAvailable(const QByteArray &encoding)
{
TextEncoder encoder(encoding);
return encoder.isValid();
}

View File

@ -26,9 +26,15 @@
#include <QThread> #include <QThread>
#include <QProcessEnvironment> #include <QProcessEnvironment>
#if QT_VERSION_MAJOR >= 6
# include <QStringEncoder>
# include <QStringDecoder>
#else
class QTextCodec;
#endif
class QByteArray; class QByteArray;
class QTextStream; class QTextStream;
class QTextCodec;
#define ENCODING_AUTO_DETECT "AUTO" #define ENCODING_AUTO_DETECT "AUTO"
#define ENCODING_UTF8 "UTF-8" #define ENCODING_UTF8 "UTF-8"
@ -67,7 +73,7 @@ public:
}; };
/* text processing utils */ /* text processing utils */
const QByteArray guessTextEncoding(const QByteArray& text); QString guessTextEncoding(const QByteArray& text);
const QChar *getNullTerminatedStringData(const QString& str); const QChar *getNullTerminatedStringData(const QString& str);
@ -109,9 +115,7 @@ void readStreamToLines(QTextStream* stream, LineProcessFunc lineFunc);
* @param codec * @param codec
* @return * @return
*/ */
QStringList readFileToLines(const QString& fileName, QTextCodec* codec);
QStringList readFileToLines(const QString& fileName); QStringList readFileToLines(const QString& fileName);
void readFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc);
QByteArray readFileToByteArray(const QString& fileName); QByteArray readFileToByteArray(const QString& fileName);
@ -204,4 +208,108 @@ finally(F&& f) noexcept
return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>( return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(
std::forward<F>(f)); std::forward<F>(f));
} }
class TextEncoder {
public:
explicit TextEncoder(const char *name);
explicit TextEncoder(const QByteArray &name);
TextEncoder(const TextEncoder &other) = delete;
TextEncoder(TextEncoder &&other) noexcept = default;
TextEncoder &operator=(const TextEncoder &other) = delete;
TextEncoder &operator=(TextEncoder &&other) noexcept = default;
~TextEncoder() = default;
#if QT_VERSION_MAJOR >= 6
private:
TextEncoder(QStringEncoder &&encoder);
#endif
public:
bool isValid() const;
QByteArray name() const;
std::pair<bool, QByteArray> encode(const QString &text);
QByteArray encodeUnchecked(const QString &text);
public:
static TextEncoder encoderForUtf8();
static TextEncoder encoderForUtf16();
static TextEncoder encoderForUtf32();
static TextEncoder encoderForSystem();
private:
#if QT_VERSION_MAJOR >= 6
QStringEncoder mEncoder;
#else
QTextCodec *mCodec;
#endif
};
class TextDecoder {
public:
explicit TextDecoder(const char *name);
explicit TextDecoder(const QByteArray &name);
TextDecoder(const TextDecoder &other) = delete;
TextDecoder(TextDecoder &&other) noexcept = default;
TextDecoder &operator=(const TextDecoder &other) = delete;
TextDecoder &operator=(TextDecoder &&other) noexcept = default;
~TextDecoder() = default;
#if QT_VERSION_MAJOR >= 6
private:
TextDecoder(QStringDecoder &&decoder);
#endif
public:
bool isValid() const;
QByteArray name() const;
std::pair<bool, QString> decode(const QByteArray &text);
QString decodeUnchecked(const QByteArray &text);
public:
static TextDecoder decoderForUtf8();
static TextDecoder decoderForUtf16();
static TextDecoder decoderForUtf32();
static TextDecoder decoderForSystem();
private:
#if QT_VERSION_MAJOR >= 6
QStringDecoder mDecoder;
#else
QTextCodec *mCodec;
#endif
};
const QStringList &availableEncodings();
bool isEncodingAvailable(const QByteArray &encoding);
#if QT_VERSION_MAJOR >= 6
namespace std {
constexpr inline int max(int a, qsizetype b) {
return max<int>(a, b);
}
constexpr inline int max(qsizetype a, int b) {
return max<int>(a, b);
}
constexpr inline int min(int a, qsizetype b) {
return min<int>(a, b);
}
constexpr inline int min(qsizetype a, int b) {
return min<int>(a, b);
}
}
#endif
inline bool isAsciiPrint(int c)
{
return c >= 32 && c <= 126;
}
inline bool isLexicalSpace(QChar c)
{
return c.unicode() >= 1 && c.unicode() <= 32;
}
#endif // UTILS_H #endif // UTILS_H

View File

@ -11,7 +11,7 @@ pacman -Syu --noconfirm --needed base-devel git
useradd -m builduser useradd -m builduser
echo 'builduser ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/builduser echo 'builduser ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/builduser
echo "MAKEFLAGS=-j$(($(nproc)+1))" >>/etc/makepkg.conf echo "MAKEFLAGS=-j$(($(nproc)+1))" >>/etc/makepkg.conf.d/jobs.conf
su builduser -c "git config --global --add safe.directory $PWD" su builduser -c "git config --global --add safe.directory $PWD"
su builduser -c ./packages/archlinux/buildpkg.sh su builduser -c ./packages/archlinux/buildpkg.sh

View File

@ -6,8 +6,8 @@ pkgdesc='A fast, lightweight, open source, and cross platform C++ IDE (developme
arch=('i686' 'pentium4' 'x86_64' 'arm' 'armv6h' 'armv7h' 'aarch64' 'riscv64') arch=('i686' 'pentium4' 'x86_64' 'arm' 'armv6h' 'armv7h' 'aarch64' 'riscv64')
url="https://github.com/royqh1979/$_pkgname" url="https://github.com/royqh1979/$_pkgname"
license=('GPL3') license=('GPL3')
depends=(qt5-base qt5-svg gcc gdb astyle) depends=(qt6-base qt6-svg gcc gdb astyle)
makedepends=(qt5-tools imagemagick librsvg) makedepends=(qt6-tools imagemagick librsvg)
optdepends=( optdepends=(
'clang: C/C++ compiler (alternative)' 'clang: C/C++ compiler (alternative)'
) )
@ -29,7 +29,7 @@ prepare() {
build() { build() {
mkdir redpanda-build mkdir redpanda-build
cd redpanda-build cd redpanda-build
qmake \ qmake6 \
PREFIX='/usr' \ PREFIX='/usr' \
LIBEXECDIR='/usr/lib' \ LIBEXECDIR='/usr/lib' \
"$srcdir/$_pkgname/Red_Panda_CPP.pro" "$srcdir/$_pkgname/Red_Panda_CPP.pro"