Merge branch 'wizard_encodings' into 'master'

Do not use Qt streams with legacy encodings in the Wizard code

Closes #7165

See merge request OpenMW/openmw!2634
7220-lua-add-a-general-purpose-lexical-parser
psi29a 2 years ago
commit 1390c7ed7c

@ -5,7 +5,10 @@
#include <QRegularExpression> #include <QRegularExpression>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QTextStream>
#include <fstream>
#include <components/files/qtconversion.hpp>
Wizard::IniSettings::IniSettings() {} Wizard::IniSettings::IniSettings() {}
@ -25,7 +28,7 @@ QStringList Wizard::IniSettings::findKeys(const QString& text)
return result; return result;
} }
bool Wizard::IniSettings::readFile(QTextStream& stream) bool Wizard::IniSettings::readFile(std::ifstream& stream, ToUTF8::FromType encoding)
{ {
// Look for a square bracket, "'\\[" // Look for a square bracket, "'\\["
// that has one or more "not nothing" in it, "([^]]+)" // that has one or more "not nothing" in it, "([^]]+)"
@ -39,10 +42,20 @@ bool Wizard::IniSettings::readFile(QTextStream& stream)
QString currentSection; QString currentSection;
while (!stream.atEnd()) ToUTF8::Utf8Encoder encoder(encoding);
std::string legacyEncLine;
while (std::getline(stream, legacyEncLine))
{ {
const QString line(stream.readLine()); std::string_view lineBuffer = encoder.getUtf8(legacyEncLine);
// unify Unix-style and Windows file ending
if (!(lineBuffer.empty()) && (lineBuffer[lineBuffer.length() - 1]) == '\r')
{
lineBuffer = lineBuffer.substr(0, lineBuffer.length() - 1);
}
const QString line = QString::fromStdString(std::string(lineBuffer));
if (line.isEmpty() || line.startsWith(QLatin1Char(';'))) if (line.isEmpty() || line.startsWith(QLatin1Char(';')))
continue; continue;
@ -70,7 +83,7 @@ bool Wizard::IniSettings::readFile(QTextStream& stream)
return true; return true;
} }
bool Wizard::IniSettings::writeFile(const QString& path, QTextStream& stream) bool Wizard::IniSettings::writeFile(const QString& path, std::ifstream& stream, ToUTF8::FromType encoding)
{ {
// Look for a square bracket, "'\\[" // Look for a square bracket, "'\\["
// that has one or more "not nothing" in it, "([^]]+)" // that has one or more "not nothing" in it, "([^]]+)"
@ -87,10 +100,19 @@ bool Wizard::IniSettings::writeFile(const QString& path, QTextStream& stream)
QString currentSection; QString currentSection;
QString buffer; QString buffer;
while (!stream.atEnd()) ToUTF8::Utf8Encoder encoder(encoding);
std::string legacyEncLine;
while (std::getline(stream, legacyEncLine))
{ {
const QString line(stream.readLine()); std::string_view lineBuffer = encoder.getUtf8(legacyEncLine);
// unify Unix-style and Windows file ending
if (!(lineBuffer.empty()) && (lineBuffer[lineBuffer.length() - 1]) == '\r')
{
lineBuffer = lineBuffer.substr(0, lineBuffer.length() - 1);
}
const QString line = QString::fromStdString(std::string(lineBuffer));
if (line.isEmpty() || line.startsWith(QLatin1Char(';'))) if (line.isEmpty() || line.startsWith(QLatin1Char(';')))
{ {
buffer.append(line + QLatin1String("\n")); buffer.append(line + QLatin1String("\n"));
@ -158,27 +180,13 @@ bool Wizard::IniSettings::writeFile(const QString& path, QTextStream& stream)
} }
} }
// Now we reopen the file, this time we write const auto iniPath = Files::pathFromQString(path);
QFile file(path); std::ofstream file(iniPath, std::ios::out);
if (file.fail())
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text))
{
QTextStream in(&file);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
in.setCodec(stream.codec());
#else
in.setEncoding(stream.encoding());
#endif
// Write the updated buffer to an empty file
in << buffer;
file.flush();
file.close();
}
else
{
return false; return false;
}
file << encoder.getLegacyEnc(buffer.toStdString());
file.close();
return true; return true;
} }

@ -4,7 +4,7 @@
#include <QHash> #include <QHash>
#include <QVariant> #include <QVariant>
class QTextStream; #include <components/to_utf8/to_utf8.hpp>
namespace Wizard namespace Wizard
{ {
@ -30,8 +30,8 @@ namespace Wizard
QStringList findKeys(const QString& text); QStringList findKeys(const QString& text);
bool readFile(QTextStream& stream); bool readFile(std::ifstream& stream, ToUTF8::FromType encoding);
bool writeFile(const QString& path, QTextStream& stream); bool writeFile(const QString& path, std::ifstream& stream, ToUTF8::FromType encoding);
bool parseInx(const QString& path); bool parseInx(const QString& path);

@ -128,15 +128,15 @@ void Wizard::InstallationPage::startInstallation()
if (language == QLatin1String("Polish")) if (language == QLatin1String("Polish"))
{ {
mUnshield->setIniCodec(QTextCodec::codecForName("windows-1250")); mUnshield->setIniEncoding(ToUTF8::FromType::WINDOWS_1250);
} }
else if (language == QLatin1String("Russian")) else if (language == QLatin1String("Russian"))
{ {
mUnshield->setIniCodec(QTextCodec::codecForName("windows-1251")); mUnshield->setIniEncoding(ToUTF8::FromType::WINDOWS_1251);
} }
else else
{ {
mUnshield->setIniCodec(QTextCodec::codecForName("windows-1252")); mUnshield->setIniEncoding(ToUTF8::FromType::WINDOWS_1252);
} }
mThread->start(); mThread->start();

@ -6,8 +6,10 @@
#include <QFileInfo> #include <QFileInfo>
#include <QReadLocker> #include <QReadLocker>
#include <QStringList> #include <QStringList>
#include <QTextCodec>
#include <QTextStream> #include <fstream>
#include <components/files/qtconversion.hpp>
#include <apps/wizard/inisettings.hpp> #include <apps/wizard/inisettings.hpp>
@ -23,7 +25,7 @@ Wizard::UnshieldWorker::UnshieldWorker(qint64 expectedMorrowindBsaSize, QObject*
mDiskPath = QString(); mDiskPath = QString();
// Default to Latin encoding // Default to Latin encoding
mIniCodec = QTextCodec::codecForName("windows-1252"); mIniEncoding = ToUTF8::FromType::WINDOWS_1252;
mInstallMorrowind = false; mInstallMorrowind = false;
mInstallTribunal = false; mInstallTribunal = false;
@ -153,10 +155,10 @@ QString Wizard::UnshieldWorker::getDiskPath()
return mDiskPath; return mDiskPath;
} }
void Wizard::UnshieldWorker::setIniCodec(QTextCodec* codec) void Wizard::UnshieldWorker::setIniEncoding(ToUTF8::FromType encoding)
{ {
QWriteLocker writeLock(&mLock); QWriteLocker writeLock(&mLock);
mIniCodec = codec; mIniEncoding = encoding;
} }
void Wizard::UnshieldWorker::wakeAll() void Wizard::UnshieldWorker::wakeAll()
@ -170,19 +172,16 @@ bool Wizard::UnshieldWorker::setupSettings()
if (getIniPath().isEmpty()) if (getIniPath().isEmpty())
return false; return false;
QFile file(getIniPath()); const auto iniPath = Files::pathFromQString(getIniPath());
std::ifstream file(iniPath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) if (file.fail())
{ {
emit error(tr("Failed to open Morrowind configuration file!"), emit error(tr("Failed to open Morrowind configuration file!"),
tr("Opening %1 failed: %2.").arg(getIniPath(), file.errorString())); tr("Opening %1 failed: %2.").arg(getIniPath(), strerror(errno)));
return false; return false;
} }
QTextStream stream(&file); mIniSettings.readFile(file, mIniEncoding);
stream.setCodec(mIniCodec);
mIniSettings.readFile(stream);
return true; return true;
} }
@ -192,22 +191,19 @@ bool Wizard::UnshieldWorker::writeSettings()
if (getIniPath().isEmpty()) if (getIniPath().isEmpty())
return false; return false;
QFile file(getIniPath()); const auto iniPath = Files::pathFromQString(getIniPath());
std::ifstream file(iniPath);
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) if (file.fail())
{ {
emit error(tr("Failed to open Morrowind configuration file!"), emit error(tr("Failed to open Morrowind configuration file!"),
tr("Opening %1 failed: %2.").arg(getIniPath(), file.errorString())); tr("Opening %1 failed: %2.").arg(getIniPath(), strerror(errno)));
return false; return false;
} }
QTextStream stream(&file); if (!mIniSettings.writeFile(getIniPath(), file, mIniEncoding))
stream.setCodec(mIniCodec);
if (!mIniSettings.writeFile(getIniPath(), stream))
{ {
emit error(tr("Failed to write Morrowind configuration file!"), emit error(tr("Failed to write Morrowind configuration file!"),
tr("Writing to %1 failed: %2.").arg(getIniPath(), file.errorString())); tr("Writing to %1 failed: %2.").arg(getIniPath(), strerror(errno)));
return false; return false;
} }

@ -41,7 +41,7 @@ namespace Wizard
QString getPath(); QString getPath();
QString getIniPath(); QString getIniPath();
void setIniCodec(QTextCodec* codec); void setIniEncoding(ToUTF8::FromType encoding);
bool setupSettings(); bool setupSettings();
@ -104,7 +104,7 @@ namespace Wizard
IniSettings mIniSettings; IniSettings mIniSettings;
QTextCodec* mIniCodec; ToUTF8::FromType mIniEncoding;
QWaitCondition mWait; QWaitCondition mWait;

Loading…
Cancel
Save