Copy adjusted color values to editor.

This commit is contained in:
John Preston 2019-09-08 21:00:31 +03:00
parent a770b5d4cd
commit bb7018424a
4 changed files with 124 additions and 103 deletions

View File

@ -493,6 +493,7 @@ ChatBackground::AdjustableColor::AdjustableColor(style::color data)
, original(data->c) {
}
// They're duplicated in window_theme_editor_box.cpp:ReplaceAdjustableColors.
ChatBackground::ChatBackground() : _adjustableColors({
st::msgServiceBg,
st::msgServiceBgSelected,

View File

@ -148,52 +148,6 @@ bool isValidColorValue(QLatin1String value) {
return true;
}
QByteArray replaceValueInContent(const QByteArray &content, const QByteArray &name, const QByteArray &value) {
auto validNames = OrderedSet<QLatin1String>();
auto start = content.constBegin(), data = start, end = data + content.size();
auto lastValidValueStart = end, lastValidValueEnd = end;
while (data != end) {
skipWhitespacesAndComments(data, end);
if (data == end) break;
auto foundName = base::parse::readName(data, end);
skipWhitespacesAndComments(data, end);
if (data == end || *data != ':') {
return "error";
}
++data;
skipWhitespacesAndComments(data, end);
auto valueStart = data;
auto value = readValue(data, end);
auto valueEnd = data;
if (value.size() == 0) {
return "error";
}
auto validValue = validNames.contains(value) || isValidColorValue(value);
if (validValue) {
validNames.insert(foundName);
if (foundName == name) {
lastValidValueStart = valueStart;
lastValidValueEnd = valueEnd;
}
}
skipWhitespacesAndComments(data, end);
if (data == end || *data != ';') {
return "error";
}
++data;
}
if (lastValidValueStart != end) {
auto result = QByteArray();
result.reserve((lastValidValueStart - start) + value.size() + (end - lastValidValueEnd));
result.append(start, lastValidValueStart - start);
result.append(value);
if (end - lastValidValueEnd > 0) result.append(lastValidValueEnd, end - lastValidValueEnd);
return result;
}
return QByteArray();
}
[[nodiscard]] QByteArray ColorizeInContent(
QByteArray content,
const Colorizer &colorizer) {
@ -302,6 +256,79 @@ private:
};
QByteArray ColorHexString(const QColor &color) {
auto result = QByteArray();
result.reserve(9);
result.append('#');
const auto addHex = [&](int code) {
if (code >= 0 && code < 10) {
result.append('0' + code);
} else if (code >= 10 && code < 16) {
result.append('a' + (code - 10));
}
};
const auto addValue = [&](int code) {
addHex(code / 16);
addHex(code % 16);
};
addValue(color.red());
addValue(color.green());
addValue(color.blue());
if (color.alpha() != 255) {
addValue(color.alpha());
}
return result;
}
QByteArray ReplaceValueInPaletteContent(
const QByteArray &content,
const QByteArray &name,
const QByteArray &value) {
auto validNames = OrderedSet<QLatin1String>();
auto start = content.constBegin(), data = start, end = data + content.size();
auto lastValidValueStart = end, lastValidValueEnd = end;
while (data != end) {
skipWhitespacesAndComments(data, end);
if (data == end) break;
auto foundName = base::parse::readName(data, end);
skipWhitespacesAndComments(data, end);
if (data == end || *data != ':') {
return "error";
}
++data;
skipWhitespacesAndComments(data, end);
auto valueStart = data;
auto value = readValue(data, end);
auto valueEnd = data;
if (value.size() == 0) {
return "error";
}
auto validValue = validNames.contains(value) || isValidColorValue(value);
if (validValue) {
validNames.insert(foundName);
if (foundName == name) {
lastValidValueStart = valueStart;
lastValidValueEnd = valueEnd;
}
}
skipWhitespacesAndComments(data, end);
if (data == end || *data != ';') {
return "error";
}
++data;
}
if (lastValidValueStart != end) {
auto result = QByteArray();
result.reserve((lastValidValueStart - start) + value.size() + (end - lastValidValueEnd));
result.append(start, lastValidValueStart - start);
result.append(value);
if (end - lastValidValueEnd > 0) result.append(lastValidValueEnd, end - lastValidValueEnd);
return result;
}
return QByteArray();
}
[[nodiscard]] QByteArray WriteCloudToText(const Data::CloudTheme &cloud) {
auto result = QByteArray();
const auto add = [&](const QByteArray &key, const QString &value) {
@ -543,36 +570,12 @@ bool Editor::Inner::feedExistingRow(const QString &name, QLatin1String value) {
return true;
}
QString colorString(QColor color) {
auto result = QString();
result.reserve(9);
result.append('#');
const auto addHex = [&](int code) {
if (code >= 0 && code < 10) {
result.append('0' + code);
} else if (code >= 10 && code < 16) {
result.append('a' + (code - 10));
}
};
const auto addValue = [&](int code) {
addHex(code / 16);
addHex(code % 16);
};
addValue(color.red());
addValue(color.green());
addValue(color.blue());
if (color.alpha() != 255) {
addValue(color.alpha());
}
return result;
}
void Editor::Inner::applyEditing(const QString &name, const QString &copyOf, QColor value) {
auto plainName = name.toLatin1();
auto plainValue = (copyOf.isEmpty() ? colorString(value) : copyOf).toLatin1();
auto newContent = replaceValueInContent(_paletteContent, plainName, plainValue);
auto plainValue = copyOf.isEmpty() ? ColorHexString(value) : copyOf.toLatin1();
auto newContent = ReplaceValueInPaletteContent(_paletteContent, plainName, plainValue);
if (newContent == "error") {
LOG(("Theme Error: could not replace '%1: %2' in content").arg(name).arg(copyOf.isEmpty() ? colorString(value) : copyOf));
LOG(("Theme Error: could not replace '%1: %2' in content").arg(name).arg(copyOf.isEmpty() ? QString::fromLatin1(ColorHexString(value)) : copyOf));
error();
return;
}

View File

@ -32,6 +32,11 @@ struct ParsedTheme {
bool tiled = false;
};
[[nodiscard]] QByteArray ColorHexString(const QColor &color);
[[nodiscard]] QByteArray ReplaceValueInPaletteContent(
const QByteArray &content,
const QByteArray &name,
const QByteArray &value);
[[nodiscard]] QByteArray WriteCloudToText(const Data::CloudTheme &cloud);
[[nodiscard]] Data::CloudTheme ReadCloudFromText(const QByteArray &text);

View File

@ -247,6 +247,37 @@ void ImportFromFile(
return QString::fromUtf8(string.data(), string.size());
}
// They're duplicated in window_theme.cpp:ChatBackground::ChatBackground.
[[nodiscard]] QByteArray ReplaceAdjustableColors(QByteArray data) {
const auto &themeObject = Background()->themeObject();
const auto &paper = Background()->paper();
const auto usingDefaultTheme = themeObject.pathAbsolute.isEmpty();
const auto usingThemeBackground = usingDefaultTheme
? Data::IsDefaultWallPaper(paper)
: Data::IsThemeWallPaper(paper);
if (usingThemeBackground) {
return data;
}
const auto adjustables = base::flat_map<QByteArray, style::color>{
{ qba(qstr("msgServiceBg")), st::msgServiceBg },
{ qba(qstr("msgServiceBgSelected")), st::msgServiceBgSelected },
{ qba(qstr("historyScrollBg")), st::historyScrollBg },
{ qba(qstr("historyScrollBgOver")), st::historyScrollBgOver },
{ qba(qstr("historyScrollBarBg")), st::historyScrollBarBg },
{ qba(qstr("historyScrollBarBgOver")), st::historyScrollBarBgOver }
};
for (const auto &[name, color] : adjustables) {
data = ReplaceValueInPaletteContent(
data,
name,
ColorHexString(color->c));
}
return data;
}
// Only is valid for current theme, pass Local::ReadThemeContent() here.
[[nodiscard]] ParsedTheme ParseTheme(
const Object &theme,
bool onlyPalette = false) {
@ -258,6 +289,7 @@ void ImportFromFile(
std::move(raw.palette),
colorizer);
}
raw.palette = ReplaceAdjustableColors(std::move(raw.palette));
return raw;
};
@ -310,29 +342,6 @@ void ImportFromFile(
return result();
}
[[nodiscard]] bool CopyColorsToPalette(
const QString &destination,
const Object &theme,
const Data::CloudTheme &cloud) {
auto parsed = ParseTheme(theme, true);
if (parsed.palette.isEmpty()) {
return false;
}
QFile f(destination);
if (!f.open(QIODevice::WriteOnly)) {
LOG(("Theme Error: could not open file for write '%1'").arg(destination));
return false;
}
const auto content = WriteCloudToText(cloud) + parsed.palette;
if (f.write(content) != content.size()) {
LOG(("Theme Error: could not write palette to '%1'").arg(destination));
return false;
}
return true;
}
QByteArray GenerateDefaultPalette() {
auto result = QByteArray();
const auto rows = style::main_palette::data();
@ -355,8 +364,9 @@ QByteArray GenerateDefaultPalette() {
return result;
}
bool WriteDefaultPalette(
bool CopyColorsToPalette(
const QString &path,
const QByteArray &palette,
const Data::CloudTheme &cloud) {
QFile f(path);
if (!f.open(QIODevice::WriteOnly)) {
@ -364,8 +374,9 @@ bool WriteDefaultPalette(
return false;
}
const auto content = WriteCloudToText(cloud) + GenerateDefaultPalette();
if (f.write(content) != content.size()) {
const auto prefix = WriteCloudToText(cloud);
if (f.write(prefix) != prefix.size()
|| f.write(palette) != palette.size()) {
LOG(("Theme Error: could not write palette to '%1'").arg(path));
return false;
}
@ -688,10 +699,11 @@ void StartEditor(
const Data::CloudTheme &cloud) {
const auto path = EditingPalettePath();
auto object = Local::ReadThemeContent();
const auto written = object.content.isEmpty()
? WriteDefaultPalette(path, cloud)
: CopyColorsToPalette(path, object, cloud);
if (!written) {
const auto palette = object.content.isEmpty()
? GenerateDefaultPalette()
: ParseTheme(object, true).palette;
if (palette.isEmpty() || !CopyColorsToPalette(path, palette, cloud)) {
window->show(Box<InformBox>(tr::lng_theme_editor_error(tr::now)));
return;
}