mirror of https://github.com/procxx/kepka.git
Copy adjusted color values to editor.
This commit is contained in:
parent
a770b5d4cd
commit
bb7018424a
|
@ -493,6 +493,7 @@ ChatBackground::AdjustableColor::AdjustableColor(style::color data)
|
||||||
, original(data->c) {
|
, original(data->c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// They're duplicated in window_theme_editor_box.cpp:ReplaceAdjustableColors.
|
||||||
ChatBackground::ChatBackground() : _adjustableColors({
|
ChatBackground::ChatBackground() : _adjustableColors({
|
||||||
st::msgServiceBg,
|
st::msgServiceBg,
|
||||||
st::msgServiceBgSelected,
|
st::msgServiceBgSelected,
|
||||||
|
|
|
@ -148,52 +148,6 @@ bool isValidColorValue(QLatin1String value) {
|
||||||
return true;
|
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(
|
[[nodiscard]] QByteArray ColorizeInContent(
|
||||||
QByteArray content,
|
QByteArray content,
|
||||||
const Colorizer &colorizer) {
|
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) {
|
[[nodiscard]] QByteArray WriteCloudToText(const Data::CloudTheme &cloud) {
|
||||||
auto result = QByteArray();
|
auto result = QByteArray();
|
||||||
const auto add = [&](const QByteArray &key, const QString &value) {
|
const auto add = [&](const QByteArray &key, const QString &value) {
|
||||||
|
@ -543,36 +570,12 @@ bool Editor::Inner::feedExistingRow(const QString &name, QLatin1String value) {
|
||||||
return true;
|
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) {
|
void Editor::Inner::applyEditing(const QString &name, const QString ©Of, QColor value) {
|
||||||
auto plainName = name.toLatin1();
|
auto plainName = name.toLatin1();
|
||||||
auto plainValue = (copyOf.isEmpty() ? colorString(value) : copyOf).toLatin1();
|
auto plainValue = copyOf.isEmpty() ? ColorHexString(value) : copyOf.toLatin1();
|
||||||
auto newContent = replaceValueInContent(_paletteContent, plainName, plainValue);
|
auto newContent = ReplaceValueInPaletteContent(_paletteContent, plainName, plainValue);
|
||||||
if (newContent == "error") {
|
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();
|
error();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,11 @@ struct ParsedTheme {
|
||||||
bool tiled = false;
|
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]] QByteArray WriteCloudToText(const Data::CloudTheme &cloud);
|
||||||
[[nodiscard]] Data::CloudTheme ReadCloudFromText(const QByteArray &text);
|
[[nodiscard]] Data::CloudTheme ReadCloudFromText(const QByteArray &text);
|
||||||
|
|
||||||
|
|
|
@ -247,6 +247,37 @@ void ImportFromFile(
|
||||||
return QString::fromUtf8(string.data(), string.size());
|
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(
|
[[nodiscard]] ParsedTheme ParseTheme(
|
||||||
const Object &theme,
|
const Object &theme,
|
||||||
bool onlyPalette = false) {
|
bool onlyPalette = false) {
|
||||||
|
@ -258,6 +289,7 @@ void ImportFromFile(
|
||||||
std::move(raw.palette),
|
std::move(raw.palette),
|
||||||
colorizer);
|
colorizer);
|
||||||
}
|
}
|
||||||
|
raw.palette = ReplaceAdjustableColors(std::move(raw.palette));
|
||||||
return raw;
|
return raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -310,29 +342,6 @@ void ImportFromFile(
|
||||||
return result();
|
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() {
|
QByteArray GenerateDefaultPalette() {
|
||||||
auto result = QByteArray();
|
auto result = QByteArray();
|
||||||
const auto rows = style::main_palette::data();
|
const auto rows = style::main_palette::data();
|
||||||
|
@ -355,8 +364,9 @@ QByteArray GenerateDefaultPalette() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteDefaultPalette(
|
bool CopyColorsToPalette(
|
||||||
const QString &path,
|
const QString &path,
|
||||||
|
const QByteArray &palette,
|
||||||
const Data::CloudTheme &cloud) {
|
const Data::CloudTheme &cloud) {
|
||||||
QFile f(path);
|
QFile f(path);
|
||||||
if (!f.open(QIODevice::WriteOnly)) {
|
if (!f.open(QIODevice::WriteOnly)) {
|
||||||
|
@ -364,8 +374,9 @@ bool WriteDefaultPalette(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto content = WriteCloudToText(cloud) + GenerateDefaultPalette();
|
const auto prefix = WriteCloudToText(cloud);
|
||||||
if (f.write(content) != content.size()) {
|
if (f.write(prefix) != prefix.size()
|
||||||
|
|| f.write(palette) != palette.size()) {
|
||||||
LOG(("Theme Error: could not write palette to '%1'").arg(path));
|
LOG(("Theme Error: could not write palette to '%1'").arg(path));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -688,10 +699,11 @@ void StartEditor(
|
||||||
const Data::CloudTheme &cloud) {
|
const Data::CloudTheme &cloud) {
|
||||||
const auto path = EditingPalettePath();
|
const auto path = EditingPalettePath();
|
||||||
auto object = Local::ReadThemeContent();
|
auto object = Local::ReadThemeContent();
|
||||||
const auto written = object.content.isEmpty()
|
|
||||||
? WriteDefaultPalette(path, cloud)
|
const auto palette = object.content.isEmpty()
|
||||||
: CopyColorsToPalette(path, object, cloud);
|
? GenerateDefaultPalette()
|
||||||
if (!written) {
|
: ParseTheme(object, true).palette;
|
||||||
|
if (palette.isEmpty() || !CopyColorsToPalette(path, palette, cloud)) {
|
||||||
window->show(Box<InformBox>(tr::lng_theme_editor_error(tr::now)));
|
window->show(Box<InformBox>(tr::lng_theme_editor_error(tr::now)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue