mirror of https://github.com/procxx/kepka.git
Check palette changes on editor cancel.
This commit is contained in:
parent
95da2dbc34
commit
cedb2d31af
|
@ -34,7 +34,6 @@ namespace Theme {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kThemeFileSizeLimit = 5 * 1024 * 1024;
|
constexpr auto kThemeFileSizeLimit = 5 * 1024 * 1024;
|
||||||
constexpr auto kThemeBackgroundSizeLimit = 4 * 1024 * 1024;
|
|
||||||
constexpr auto kBackgroundSizeLimit = 25 * 1024 * 1024;
|
constexpr auto kBackgroundSizeLimit = 25 * 1024 * 1024;
|
||||||
constexpr auto kNightThemeFile = str_const(":/gui/night.tdesktop-theme");
|
constexpr auto kNightThemeFile = str_const(":/gui/night.tdesktop-theme");
|
||||||
constexpr auto kMinimumTiledSize = 512;
|
constexpr auto kMinimumTiledSize = 512;
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Window {
|
||||||
namespace Theme {
|
namespace Theme {
|
||||||
|
|
||||||
inline constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
|
inline constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
|
||||||
|
inline constexpr auto kThemeBackgroundSizeLimit = 4 * 1024 * 1024;
|
||||||
|
|
||||||
[[nodiscard]] bool IsEmbeddedTheme(const QString &path);
|
[[nodiscard]] bool IsEmbeddedTheme(const QString &path);
|
||||||
|
|
||||||
|
|
|
@ -665,18 +665,7 @@ Editor::Editor(
|
||||||
_scroll->scrollToY(top, bottom);
|
_scroll->scrollToY(top, bottom);
|
||||||
});
|
});
|
||||||
_close->setClickedCallback([=] {
|
_close->setClickedCallback([=] {
|
||||||
const auto box = std::make_shared<QPointer<BoxContent>>();
|
closeWithConfirmation();
|
||||||
const auto close = crl::guard(this, [=] {
|
|
||||||
Background()->clearEditingTheme(ClearEditing::RevertChanges);
|
|
||||||
closeEditor();
|
|
||||||
if (*box) {
|
|
||||||
(*box)->closeBox();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*box = _window->show(Box<ConfirmBox>(
|
|
||||||
tr::lng_theme_editor_sure_close(tr::now),
|
|
||||||
tr::lng_close(tr::now),
|
|
||||||
close));
|
|
||||||
});
|
});
|
||||||
_close->show(anim::type::instant);
|
_close->show(anim::type::instant);
|
||||||
|
|
||||||
|
@ -791,6 +780,26 @@ void Editor::paintEvent(QPaintEvent *e) {
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
void Editor::closeWithConfirmation() {
|
||||||
|
if (!PaletteChanged(_inner->paletteContent(), _cloud)) {
|
||||||
|
Background()->clearEditingTheme(ClearEditing::KeepChanges);
|
||||||
|
closeEditor();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto box = std::make_shared<QPointer<BoxContent>>();
|
||||||
|
const auto close = crl::guard(this, [=] {
|
||||||
|
Background()->clearEditingTheme(ClearEditing::RevertChanges);
|
||||||
|
closeEditor();
|
||||||
|
if (*box) {
|
||||||
|
(*box)->closeBox();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*box = _window->show(Box<ConfirmBox>(
|
||||||
|
tr::lng_theme_editor_sure_close(tr::now),
|
||||||
|
tr::lng_close(tr::now),
|
||||||
|
close));
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::closeEditor() {
|
void Editor::closeEditor() {
|
||||||
if (const auto window = App::wnd()) {
|
if (const auto window = App::wnd()) {
|
||||||
window->showRightColumn(nullptr);
|
window->showRightColumn(nullptr);
|
||||||
|
|
|
@ -49,6 +49,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void save();
|
void save();
|
||||||
void closeEditor();
|
void closeEditor();
|
||||||
|
void closeWithConfirmation();
|
||||||
|
|
||||||
const not_null<Window::Controller*> _window;
|
const not_null<Window::Controller*> _window;
|
||||||
const Data::CloudTheme _cloud;
|
const Data::CloudTheme _cloud;
|
||||||
|
|
|
@ -56,12 +56,29 @@ enum class SaveErrorType {
|
||||||
Link,
|
Link,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ParsedTheme {
|
||||||
|
QByteArray palette;
|
||||||
|
QByteArray background;
|
||||||
|
bool isPng = false;
|
||||||
|
bool tiled = false;
|
||||||
|
};
|
||||||
|
|
||||||
struct PreparedBackground {
|
struct PreparedBackground {
|
||||||
QByteArray content;
|
QByteArray content;
|
||||||
bool tile = false;
|
bool tile = false;
|
||||||
bool isPng = false;
|
bool isPng = false;
|
||||||
|
bool changed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <size_t Size>
|
||||||
|
QByteArray qba(const char(&string)[Size]) {
|
||||||
|
return QByteArray::fromRawData(string, Size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray qba(QLatin1String string) {
|
||||||
|
return QByteArray::fromRawData(string.data(), string.size());
|
||||||
|
}
|
||||||
|
|
||||||
class BackgroundSelector : public Ui::RpWidget {
|
class BackgroundSelector : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
BackgroundSelector(
|
BackgroundSelector(
|
||||||
|
@ -86,6 +103,7 @@ private:
|
||||||
QImage _background;
|
QImage _background;
|
||||||
QByteArray _backgroundContent;
|
QByteArray _backgroundContent;
|
||||||
bool _isPng = false;
|
bool _isPng = false;
|
||||||
|
bool _changed = false;
|
||||||
QString _imageText;
|
QString _imageText;
|
||||||
int _thumbnailSize = 0;
|
int _thumbnailSize = 0;
|
||||||
QPixmap _thumbnail;
|
QPixmap _thumbnail;
|
||||||
|
@ -185,6 +203,7 @@ void BackgroundSelector::chooseBackgroundFromFile() {
|
||||||
_background = image;
|
_background = image;
|
||||||
_backgroundContent = content;
|
_backgroundContent = content;
|
||||||
_isPng = (format == "png");
|
_isPng = (format == "png");
|
||||||
|
_changed = true;
|
||||||
const auto phrase = _isPng
|
const auto phrase = _isPng
|
||||||
? tr::lng_theme_editor_read_from_png
|
? tr::lng_theme_editor_read_from_png
|
||||||
: tr::lng_theme_editor_read_from_jpg;
|
: tr::lng_theme_editor_read_from_jpg;
|
||||||
|
@ -209,6 +228,7 @@ PreparedBackground BackgroundSelector::result() const {
|
||||||
_backgroundContent,
|
_backgroundContent,
|
||||||
_tileBackground->checked(),
|
_tileBackground->checked(),
|
||||||
_isPng,
|
_isPng,
|
||||||
|
_changed,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,27 +259,69 @@ void ImportFromFile(
|
||||||
return QString::fromUtf8(string.data(), string.size());
|
return QString::fromUtf8(string.data(), string.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool CopyColorsToPalette(
|
[[nodiscard]] ParsedTheme ParseTheme(
|
||||||
const QString &destination,
|
|
||||||
const QString &themePath,
|
|
||||||
const QByteArray &themeContent,
|
const QByteArray &themeContent,
|
||||||
const Data::CloudTheme &cloud) {
|
bool onlyPalette) {
|
||||||
auto paletteContent = themeContent;
|
auto result = ParsedTheme();
|
||||||
|
result.palette = themeContent;
|
||||||
|
|
||||||
zlib::FileToRead file(themeContent);
|
zlib::FileToRead file(themeContent);
|
||||||
|
|
||||||
unz_global_info globalInfo = { 0 };
|
unz_global_info globalInfo = { 0 };
|
||||||
file.getGlobalInfo(&globalInfo);
|
file.getGlobalInfo(&globalInfo);
|
||||||
if (file.error() == UNZ_OK) {
|
if (file.error() != UNZ_OK) {
|
||||||
paletteContent = file.readFileContent("colors.tdesktop-theme", zlib::kCaseInsensitive, kThemeSchemeSizeLimit);
|
return result;
|
||||||
if (file.error() == UNZ_END_OF_LIST_OF_FILE) {
|
}
|
||||||
|
result.palette = file.readFileContent("colors.tdesktop-theme", zlib::kCaseInsensitive, kThemeSchemeSizeLimit);
|
||||||
|
if (file.error() == UNZ_END_OF_LIST_OF_FILE) {
|
||||||
|
file.clearError();
|
||||||
|
result.palette = file.readFileContent("colors.tdesktop-palette", zlib::kCaseInsensitive, kThemeSchemeSizeLimit);
|
||||||
|
}
|
||||||
|
if (file.error() != UNZ_OK) {
|
||||||
|
LOG(("Theme Error: could not read 'colors.tdesktop-theme' or 'colors.tdesktop-palette' in the theme file."));
|
||||||
|
return ParsedTheme();
|
||||||
|
} else if (onlyPalette) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto fromFile = [&](const char *filename) {
|
||||||
|
result.background = file.readFileContent(filename, zlib::kCaseInsensitive, kThemeBackgroundSizeLimit);
|
||||||
|
if (file.error() == UNZ_OK) {
|
||||||
|
return true;
|
||||||
|
} else if (file.error() == UNZ_END_OF_LIST_OF_FILE) {
|
||||||
file.clearError();
|
file.clearError();
|
||||||
paletteContent = file.readFileContent("colors.tdesktop-palette", zlib::kCaseInsensitive, kThemeSchemeSizeLimit);
|
return true;
|
||||||
}
|
|
||||||
if (file.error() != UNZ_OK) {
|
|
||||||
LOG(("Theme Error: could not read 'colors.tdesktop-theme' or 'colors.tdesktop-palette' in the theme file, while copying to '%1'.").arg(destination));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
LOG(("Theme Error: could not read '%1' in the theme file.").arg(filename));
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!fromFile("background.jpg") || !result.background.isEmpty()) {
|
||||||
|
return result.background.isEmpty() ? ParsedTheme() : result;
|
||||||
|
}
|
||||||
|
result.isPng = true;
|
||||||
|
if (!fromFile("background.png") || !result.background.isEmpty()) {
|
||||||
|
return result.background.isEmpty() ? ParsedTheme() : result;
|
||||||
|
}
|
||||||
|
result.tiled = true;
|
||||||
|
if (!fromFile("tiled.png") || !result.background.isEmpty()) {
|
||||||
|
return result.background.isEmpty() ? ParsedTheme() : result;
|
||||||
|
}
|
||||||
|
result.isPng = false;
|
||||||
|
if (!fromFile("background.jpg") || !result.background.isEmpty()) {
|
||||||
|
return result.background.isEmpty() ? ParsedTheme() : result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool CopyColorsToPalette(
|
||||||
|
const QString &destination,
|
||||||
|
const QString &themePath,
|
||||||
|
const QByteArray &themeContent,
|
||||||
|
const Data::CloudTheme &cloud) {
|
||||||
|
auto parsed = ParseTheme(themeContent, true);
|
||||||
|
if (parsed.palette.isEmpty()) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFile f(destination);
|
QFile f(destination);
|
||||||
|
@ -269,18 +331,40 @@ void ImportFromFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto colorizer = ColorizerForTheme(themePath)) {
|
if (const auto colorizer = ColorizerForTheme(themePath)) {
|
||||||
paletteContent = Editor::ColorizeInContent(
|
parsed.palette = Editor::ColorizeInContent(
|
||||||
std::move(paletteContent),
|
std::move(parsed.palette),
|
||||||
colorizer);
|
colorizer);
|
||||||
}
|
}
|
||||||
paletteContent = WriteCloudToText(cloud) + paletteContent;
|
const auto content = WriteCloudToText(cloud) + parsed.palette;
|
||||||
if (f.write(paletteContent) != paletteContent.size()) {
|
if (f.write(content) != content.size()) {
|
||||||
LOG(("Theme Error: could not write palette to '%1'").arg(destination));
|
LOG(("Theme Error: could not write palette to '%1'").arg(destination));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray GenerateDefaultPalette() {
|
||||||
|
auto result = QByteArray();
|
||||||
|
const auto rows = style::main_palette::data();
|
||||||
|
for (const auto &row : std::as_const(rows)) {
|
||||||
|
result.append(qba(row.name)
|
||||||
|
).append(": "
|
||||||
|
).append(qba(row.value)
|
||||||
|
).append("; // "
|
||||||
|
).append(
|
||||||
|
qba(
|
||||||
|
row.description
|
||||||
|
).replace(
|
||||||
|
'\n',
|
||||||
|
' '
|
||||||
|
).replace(
|
||||||
|
'\r',
|
||||||
|
' ')
|
||||||
|
).append('\n');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool WriteDefaultPalette(
|
bool WriteDefaultPalette(
|
||||||
const QString &path,
|
const QString &path,
|
||||||
const Data::CloudTheme &cloud) {
|
const Data::CloudTheme &cloud) {
|
||||||
|
@ -290,27 +374,10 @@ bool WriteDefaultPalette(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextStream stream(&f);
|
const auto content = WriteCloudToText(cloud) + GenerateDefaultPalette();
|
||||||
stream.setCodec("UTF-8");
|
if (f.write(content) != content.size()) {
|
||||||
|
LOG(("Theme Error: could not write palette to '%1'").arg(path));
|
||||||
stream << QString::fromLatin1(WriteCloudToText(cloud));
|
return false;
|
||||||
|
|
||||||
auto rows = style::main_palette::data();
|
|
||||||
for (const auto &row : std::as_const(rows)) {
|
|
||||||
stream
|
|
||||||
<< BytesToUTF8(row.name)
|
|
||||||
<< ": "
|
|
||||||
<< BytesToUTF8(row.value)
|
|
||||||
<< "; // "
|
|
||||||
<< BytesToUTF8(
|
|
||||||
row.description
|
|
||||||
).replace(
|
|
||||||
'\n',
|
|
||||||
' '
|
|
||||||
).replace(
|
|
||||||
'\r',
|
|
||||||
' ')
|
|
||||||
<< "\n";
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -623,7 +690,11 @@ void StartEditor(
|
||||||
auto object = Local::ReadThemeContent();
|
auto object = Local::ReadThemeContent();
|
||||||
const auto written = object.content.isEmpty()
|
const auto written = object.content.isEmpty()
|
||||||
? WriteDefaultPalette(path, cloud)
|
? WriteDefaultPalette(path, cloud)
|
||||||
: CopyColorsToPalette(path, object.pathAbsolute, object.content, cloud);
|
: CopyColorsToPalette(
|
||||||
|
path,
|
||||||
|
object.pathAbsolute,
|
||||||
|
object.content,
|
||||||
|
cloud);
|
||||||
if (!written) {
|
if (!written) {
|
||||||
window->show(Box<InformBox>(tr::lng_theme_editor_error(tr::now)));
|
window->show(Box<InformBox>(tr::lng_theme_editor_error(tr::now)));
|
||||||
return;
|
return;
|
||||||
|
@ -730,7 +801,11 @@ void SaveThemeBox(
|
||||||
const QByteArray &palette) {
|
const QByteArray &palette) {
|
||||||
Expects(window->account().sessionExists());
|
Expects(window->account().sessionExists());
|
||||||
|
|
||||||
|
//Local::ReadThemeContent()
|
||||||
const auto background = Background()->createCurrentImage();
|
const auto background = Background()->createCurrentImage();
|
||||||
|
//if (Data::IsThemeWallPaper(Background()->paper())) {
|
||||||
|
|
||||||
|
//}
|
||||||
auto backgroundContent = QByteArray();
|
auto backgroundContent = QByteArray();
|
||||||
const auto tiled = Background()->tile();
|
const auto tiled = Background()->tile();
|
||||||
{
|
{
|
||||||
|
@ -854,5 +929,15 @@ void SaveThemeBox(
|
||||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PaletteChanged(
|
||||||
|
const QByteArray &editorPalette,
|
||||||
|
const Data::CloudTheme &cloud) {
|
||||||
|
auto object = Local::ReadThemeContent();
|
||||||
|
const auto real = object.content.isEmpty()
|
||||||
|
? GenerateDefaultPalette()
|
||||||
|
: ParseTheme(object.content, true).palette;
|
||||||
|
return (editorPalette != WriteCloudToText(cloud) + real);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Theme
|
} // namespace Theme
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
|
@ -40,5 +40,9 @@ void SaveThemeBox(
|
||||||
const Data::CloudTheme &cloud,
|
const Data::CloudTheme &cloud,
|
||||||
const QByteArray &palette);
|
const QByteArray &palette);
|
||||||
|
|
||||||
|
[[nodiscard]] bool PaletteChanged(
|
||||||
|
const QByteArray &editorPalette,
|
||||||
|
const Data::CloudTheme &cloud);
|
||||||
|
|
||||||
} // namespace Theme
|
} // namespace Theme
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
Loading…
Reference in New Issue