mirror of
https://github.com/vale981/tdesktop
synced 2025-03-05 09:41:41 -05:00
Copy adjusted color values to editor.
This commit is contained in:
parent
a770b5d4cd
commit
bb7018424a
4 changed files with 124 additions and 103 deletions
|
@ -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,
|
||||
|
|
|
@ -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 ©Of, 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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue