Applying color theme without restarting the application.

This commit is contained in:
John Preston 2016-11-01 23:59:51 +03:00
parent c932f3d9df
commit af9edc17d2
17 changed files with 275 additions and 177 deletions

View File

@ -277,7 +277,6 @@ boxScroll: flatScroll(solidScroll) {
boxScrollSkip: 6px; boxScrollSkip: 6px;
boxScrollShadowBg: #00000012; boxScrollShadowBg: #00000012;
titleBg: #6389a8;
titleHeight: 39px; titleHeight: 39px;
titleFont: font(17px); titleFont: font(17px);
titlePos: point(44px, 29px); titlePos: point(44px, 29px);

View File

@ -29,6 +29,8 @@ windowSubTextFgOver: #7c99b2; // gray over light blue: fallback for subtext over
windowActiveTextFg: #1485c2; // online blue: fallback for active color windowActiveTextFg: #1485c2; // online blue: fallback for active color
windowShadowFg: #000000; // black: fallback for shadow color windowShadowFg: #000000; // black: fallback for shadow color
titleBg: #6389a8;
imageBg: #000000; imageBg: #000000;
imageBgTransparent: #ffffff; imageBgTransparent: #ffffff;
@ -124,6 +126,10 @@ historyCaptionOutFg: historyTextOutFg;
historyFileNameInFg: historyTextInFg; historyFileNameInFg: historyTextInFg;
historyFileNameOutFg: historyTextOutFg; historyFileNameOutFg: historyTextOutFg;
historySystemBg: #89a0b47f;
historySystemBgSelected: #bbc8d4a2;
historySystemFg: #ffffff;
// mediaview // mediaview
mediaviewFileBg: windowBg; mediaviewFileBg: windowBg;
mediaviewFileNameFg: windowTextFg; mediaviewFileNameFg: windowTextFg;

View File

@ -29,6 +29,7 @@ windowOverBg: #edf2f5;
windowSubTextFgOver: #7c99b2; windowSubTextFgOver: #7c99b2;
windowActiveTextFg: #1485c2; windowActiveTextFg: #1485c2;
windowShadowFg: #000000; windowShadowFg: #000000;
titleBg: #6389a8;
imageBg: #000000; imageBg: #000000;
imageBgTransparent: #ffffff; imageBgTransparent: #ffffff;
trayCounterBg: #f23c34; trayCounterBg: #f23c34;
@ -97,6 +98,9 @@ historyCaptionInFg: historyTextInFg;
historyCaptionOutFg: historyTextOutFg; historyCaptionOutFg: historyTextOutFg;
historyFileNameInFg: historyTextInFg; historyFileNameInFg: historyTextInFg;
historyFileNameOutFg: historyTextOutFg; historyFileNameOutFg: historyTextOutFg;
historySystemBg: #89a0b47f;
historySystemBgSelected: #bbc8d4a2;
historySystemFg: #ffffff;
mediaviewFileBg: windowBg; mediaviewFileBg: windowBg;
mediaviewFileNameFg: windowTextFg; mediaviewFileNameFg: windowTextFg;
mediaviewFileSizeFg: windowSubTextFg; mediaviewFileSizeFg: windowSubTextFg;

View File

@ -2774,37 +2774,6 @@ namespace {
roundRect(p, x, y, w, h, bg, i.value(), 0); roundRect(p, x, y, w, h, bg, i.value(), 0);
} }
void initBackground(int32 id, const QImage &p, bool nowrite) {
if (Local::readBackground()) return;
QImage img(p);
bool remove = (id == Window::Theme::kThemeBackground);
if (p.isNull()) {
if (id == Window::Theme::kDefaultBackground) {
img.load(qsl(":/gui/art/bg.jpg"));
} else {
img.load(qsl(":/gui/art/bg_old.png"));
if (cRetina()) {
img = img.scaledToWidth(img.width() * 2, Qt::SmoothTransformation);
} else if (cScale() != dbisOne) {
img = img.scaledToWidth(convertScale(img.width()), Qt::SmoothTransformation);
}
id = Window::Theme::kOldBackground;
}
remove = true;
}
if (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied && img.format() != QImage::Format_RGB32) {
img = img.convertToFormat(QImage::Format_RGB32);
}
img.setDevicePixelRatio(cRetinaFactor());
if (!nowrite) {
Local::writeBackground(id, remove ? QImage() : img);
}
initColorsFromBackground(img);
}
void initColorsFromBackground(const QImage &img) { void initColorsFromBackground(const QImage &img) {
uint64 components[3] = { 0 }, componentsScroll[3] = { 0 }; uint64 components[3] = { 0 }, componentsScroll[3] = { 0 };
auto w = img.width(); auto w = img.width();
@ -2889,10 +2858,10 @@ namespace {
prepareCorners(StickerSelectedCorners, st::dateRadius, _msgServiceSelectBg); prepareCorners(StickerSelectedCorners, st::dateRadius, _msgServiceSelectBg);
uchar rScroll = uchar(componentsScroll[0]), gScroll = uchar(componentsScroll[1]), bScroll = uchar(componentsScroll[2]); uchar rScroll = uchar(componentsScroll[0]), gScroll = uchar(componentsScroll[1]), bScroll = uchar(componentsScroll[2]);
_historyScrollBarColor = style::color(rScroll, gScroll, bScroll, qRound(st::historyScroll.barColor->c.alphaF() * 0xFF)); _historyScrollBarColor = style::color(rScroll, gScroll, bScroll, st::historyScroll.barColor->c.alpha());
_historyScrollBgColor = style::color(rScroll, gScroll, bScroll, qRound(st::historyScroll.bgColor->c.alphaF() * 0xFF)); _historyScrollBgColor = style::color(rScroll, gScroll, bScroll, st::historyScroll.bgColor->c.alpha());
_historyScrollBarOverColor = style::color(rScroll, gScroll, bScroll, qRound(st::historyScroll.barOverColor->c.alphaF() * 0xFF)); _historyScrollBarOverColor = style::color(rScroll, gScroll, bScroll, st::historyScroll.barOverColor->c.alpha());
_historyScrollBgOverColor = style::color(rScroll, gScroll, bScroll, qRound(st::historyScroll.bgOverColor->c.alphaF() * 0xFF)); _historyScrollBgOverColor = style::color(rScroll, gScroll, bScroll, st::historyScroll.bgOverColor->c.alpha());
if (App::main()) { if (App::main()) {
App::main()->updateScrollColors(); App::main()->updateScrollColors();

View File

@ -294,7 +294,6 @@ namespace App {
} }
void initColorsFromBackground(const QImage &image); void initColorsFromBackground(const QImage &image);
void initBackground(int32 id, const QImage &p = QImage(), bool nowrite = false);
const style::color &msgServiceBg(); const style::color &msgServiceBg();
const style::color &msgServiceSelectBg(); const style::color &msgServiceSelectBg();

View File

@ -435,6 +435,9 @@ bool Generator::writePaletteDefinition() {
header_->stream() << "\ header_->stream() << "\
class palette {\n\ class palette {\n\
public:\n\ public:\n\
palette() = default;\n\
palette(const palette &other) = delete;\n\
\n\
QByteArray save() const;\n\ QByteArray save() const;\n\
bool load(const QByteArray &cache);\n\ bool load(const QByteArray &cache);\n\
bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\ bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\
@ -451,29 +454,90 @@ public:\n\
return false; return false;
} }
auto type = typeToString(variable.value.type());
auto index = (indexInPalette++); auto index = (indexInPalette++);
header_->stream() << "\tinline const " << type << " &" << name << "() const { return _colors[" << index << "]; };\n"; header_->stream() << "\tinline const color &" << name << "() const { return _colors[" << index << "]; };\n";
return true; return true;
})) return false; })) return false;
auto count = indexInPalette; auto count = indexInPalette;
auto type = typeToString({ structure::TypeTag::Color });
header_->stream() << "\ header_->stream() << "\
\n\
palette &operator=(const palette &other) {\n\
auto wasReady = _ready;\n\
for (int i = 0; i != " << count << "; ++i) {\n\
if (other._status[i] == Status::Loaded) {\n\
if (_status[i] == Status::Initial) {\n\
new (data(i)) internal::ColorData(*other.data(i));\n\
} else {\n\
*data(i) = *other.data(i);\n\
}\n\
} else if (_status[i] != Status::Initial) {\n\
data(i)->~ColorData();\n\
_status[i] = Status::Initial;\n\
_ready = false;\n\
}\n\
}\n\
if (wasReady && !_ready) {\n\
finalize();\n\
}\n\
return *this;\n\
}\n\
\n\ \n\
static int32 Checksum();\n\ static int32 Checksum();\n\
\n\
~palette() {\n\
for (int i = 0; i != " << count << "; ++i) {\n\
if (_status[i] != Status::Initial) {\n\
data(i)->~ColorData();\n\
}\n\
}\n\
}\n\
\n\ \n\
private:\n\ private:\n\
struct TempColorData { uchar r, g, b, a; };\n\ struct TempColorData { uchar r, g, b, a; };\n\
void compute(int index, int fallbackIndex, TempColorData data);\n\ void compute(int index, int fallbackIndex, TempColorData value) {\n\
if (_status[index] == Status::Initial) {\n\
if (fallbackIndex >= 0 && _status[fallbackIndex] != Status::Initial) {\n\
_status[index] = Status::Loaded;\n\
new (data(index)) internal::ColorData(*data(fallbackIndex));\n\
} else {\n\
_status[index] = Status::Created;\n\
new (data(index)) internal::ColorData(value.r, value.g, value.b, value.a);\n\
}\n\
}\n\
}\n\
\n\
internal::ColorData *data(int index) {\n\
return reinterpret_cast<internal::ColorData*>(_data) + index;\n\
}\n\
\n\
const internal::ColorData *data(int index) const {\n\
return reinterpret_cast<const internal::ColorData*>(_data) + index;\n\
}\n\
\n\
void setData(int index, const internal::ColorData &value) {\n\
if (_status[index] == Status::Initial) {\n\
new (data(index)) internal::ColorData(value);\n\
} else {\n\
*data(index) = value;\n\
}\n\
_status[index] = Status::Loaded;\n\
}\n\
\n\ \n\
enum class Status {\n\ enum class Status {\n\
Initial,\n\ Initial,\n\
Created,\n\
Loaded,\n\ Loaded,\n\
Fallback,\n\
};\n\ };\n\
\n\ \n\
" << type << " _colors[" << count << "] = { Qt::Uninitialized };\n\ alignas(alignof(internal::ColorData)) char _data[sizeof(internal::ColorData) * " << count << "];\n\
\n\
color _colors[" << count << "] = {\n";
for (int i = 0; i != count; ++i) {
header_->stream() << "\t\tdata(" << i << "),\n";
}
header_->stream() << "\
};\n\
Status _status[" << count << "] = { Status::Initial };\n\ Status _status[" << count << "] = { Status::Initial };\n\
bool _ready = false;\n\ bool _ready = false;\n\
\n\ \n\
@ -485,9 +549,9 @@ QByteArray save();\n\
bool load(const QByteArray &cache);\n\ bool load(const QByteArray &cache);\n\
bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\ bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\
bool setColor(QLatin1String name, QLatin1String from);\n\ bool setColor(QLatin1String name, QLatin1String from);\n\
void apply(const palette &other);\n\
\n\ \n\
} // namespace main_palette\n\ } // namespace main_palette\n";
\n";
header_->newline(); header_->newline();
@ -648,17 +712,6 @@ void palette::finalize() {\n\
\n\ \n\
int32 palette::Checksum() {\n\ int32 palette::Checksum() {\n\
return " << checksum << ";\n\ return " << checksum << ";\n\
}\n\
\n\
void palette::compute(int index, int fallbackIndex, TempColorData data) {\n\
if (_status[index] == Status::Initial) {\n\
if (fallbackIndex >= 0 && _status[fallbackIndex] != Status::Initial) {\n\
_status[index] = Status::Fallback;\n\
_colors[index] = _colors[fallbackIndex];\n\
} else {\n\
_colors[index] = { data.r, data.g, data.b, data.a };\n\
}\n\
}\n\
}\n"; }\n";
source_->newline().pushNamespace().newline(); source_->newline().pushNamespace().newline();
@ -731,10 +784,10 @@ QByteArray palette::save() const {\n\
\n\ \n\
auto result = QByteArray(" << (count * 4) << ", Qt::Uninitialized);\n\ auto result = QByteArray(" << (count * 4) << ", Qt::Uninitialized);\n\
for (auto i = 0, index = 0; i != " << count << "; ++i) {\n\ for (auto i = 0, index = 0; i != " << count << "; ++i) {\n\
result[index++] = static_cast<uchar>(_colors[i]->c.red());\n\ result[index++] = static_cast<uchar>(data(i)->c.red());\n\
result[index++] = static_cast<uchar>(_colors[i]->c.green());\n\ result[index++] = static_cast<uchar>(data(i)->c.green());\n\
result[index++] = static_cast<uchar>(_colors[i]->c.blue());\n\ result[index++] = static_cast<uchar>(data(i)->c.blue());\n\
result[index++] = static_cast<uchar>(_colors[i]->c.alpha());\n\ result[index++] = static_cast<uchar>(data(i)->c.alpha());\n\
}\n\ }\n\
return result;\n\ return result;\n\
}\n\ }\n\
@ -744,8 +797,7 @@ bool palette::load(const QByteArray &cache) {\n\
\n\ \n\
auto p = reinterpret_cast<const uchar*>(cache.constData());\n\ auto p = reinterpret_cast<const uchar*>(cache.constData());\n\
for (auto i = 0; i != " << count << "; ++i) {\n\ for (auto i = 0; i != " << count << "; ++i) {\n\
_colors[i] = { p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3] };\n\ setData(i, { p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3] });\n\
_status[i] = Status::Loaded;\n\
}\n\ }\n\
return true;\n\ return true;\n\
}\n\ }\n\
@ -753,8 +805,7 @@ bool palette::load(const QByteArray &cache) {\n\
bool palette::setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) {\n\ bool palette::setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) {\n\
auto index = getPaletteIndex(name);\n\ auto index = getPaletteIndex(name);\n\
if (index >= 0) {\n\ if (index >= 0) {\n\
_colors[index] = { r, g, b, a };\n\ setData(index, { r, g, b, a });\n\
_status[index] = Status::Loaded;\n\
return true;\n\ return true;\n\
}\n\ }\n\
return false;\n\ return false;\n\
@ -764,8 +815,7 @@ bool palette::setColor(QLatin1String name, QLatin1String from) {\n\
auto nameIndex = getPaletteIndex(name);\n\ auto nameIndex = getPaletteIndex(name);\n\
auto fromIndex = getPaletteIndex(from);\n\ auto fromIndex = getPaletteIndex(from);\n\
if (nameIndex >= 0 && fromIndex >= 0 && _status[fromIndex] == Status::Loaded) {\n\ if (nameIndex >= 0 && fromIndex >= 0 && _status[fromIndex] == Status::Loaded) {\n\
_colors[nameIndex] = _colors[fromIndex];\n\ setData(nameIndex, *data(fromIndex));\n\
_status[nameIndex] = Status::Loaded;\n\
return true;\n\ return true;\n\
}\n\ }\n\
return false;\n\ return false;\n\
@ -789,6 +839,11 @@ bool setColor(QLatin1String name, QLatin1String from) {\n\
return _palette.setColor(name, from);\n\ return _palette.setColor(name, from);\n\
}\n\ }\n\
\n\ \n\
void apply(const palette &other) {\n\
_palette = other;\n\
style::internal::resetIcons();\n\
}\n\
\n\
} // namespace main_palette\n\ } // namespace main_palette\n\
\n"; \n";

View File

@ -667,8 +667,6 @@ struct Data {
base::Observable<HistoryItem*> ItemRemoved; base::Observable<HistoryItem*> ItemRemoved;
bool ApplyingTheme = false;
}; };
} // namespace internal } // namespace internal
@ -784,6 +782,4 @@ DefineRefVar(Global, base::Observable<void>, LocalPasscodeChanged);
DefineRefVar(Global, base::Observable<HistoryItem*>, ItemRemoved); DefineRefVar(Global, base::Observable<HistoryItem*>, ItemRemoved);
DefineVar(Global, bool, ApplyingTheme);
} // namespace Global } // namespace Global

View File

@ -356,8 +356,6 @@ DeclareRefVar(base::Observable<void>, LocalPasscodeChanged);
DeclareRefVar(base::Observable<HistoryItem*>, ItemRemoved); DeclareRefVar(base::Observable<HistoryItem*>, ItemRemoved);
DeclareVar(bool, ApplyingTheme);
} // namespace Global } // namespace Global
namespace Adaptive { namespace Adaptive {

View File

@ -598,7 +598,7 @@ FileKey _backgroundKey = 0;
bool _backgroundWasRead = false; bool _backgroundWasRead = false;
bool _backgroundCanWrite = true; bool _backgroundCanWrite = true;
FileKey _themeKey = 0, _applyingThemeKey = 0; FileKey _themeKey = 0;
bool _readingUserSettings = false; bool _readingUserSettings = false;
FileKey _userSettingsKey = 0; FileKey _userSettingsKey = 0;
@ -1066,12 +1066,11 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version) {
} break; } break;
case dbiTheme: { case dbiTheme: {
quint64 themeKey = 0, applyingThemeKey = 0; quint64 themeKey = 0;
stream >> themeKey >> applyingThemeKey; stream >> themeKey;
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
_themeKey = themeKey; _themeKey = themeKey;
_applyingThemeKey = applyingThemeKey;
} break; } break;
case dbiTryIPv6: { case dbiTryIPv6: {
@ -2232,7 +2231,7 @@ void writeSettings() {
auto &proxy = Global::ConnectionProxy(); auto &proxy = Global::ConnectionProxy();
size += Serialize::stringSize(proxy.host) + sizeof(qint32) + Serialize::stringSize(proxy.user) + Serialize::stringSize(proxy.password); size += Serialize::stringSize(proxy.host) + sizeof(qint32) + Serialize::stringSize(proxy.user) + Serialize::stringSize(proxy.password);
} }
if (_themeKey || _applyingThemeKey) { if (_themeKey) {
size += sizeof(quint32) + 2 * sizeof(quint64); size += sizeof(quint32) + 2 * sizeof(quint64);
} }
size += sizeof(quint32) + sizeof(qint32) * 7; size += sizeof(quint32) + sizeof(qint32) * 7;
@ -2264,8 +2263,8 @@ void writeSettings() {
data.stream << proxy.host << qint32(proxy.port) << proxy.user << proxy.password; data.stream << proxy.host << qint32(proxy.port) << proxy.user << proxy.password;
} }
data.stream << quint32(dbiTryIPv6) << qint32(Global::TryIPv6()); data.stream << quint32(dbiTryIPv6) << qint32(Global::TryIPv6());
if (_themeKey || _applyingThemeKey) { if (_themeKey) {
data.stream << quint32(dbiTheme) << quint64(_themeKey) << quint64(_applyingThemeKey); data.stream << quint32(dbiTheme) << quint64(_themeKey);
} }
TWindowPos pos(cWindowPos()); TWindowPos pos(cWindowPos());
@ -3639,7 +3638,7 @@ void writeBackground(int32 id, const QImage &img) {
} }
bool readBackground() { bool readBackground() {
if (_backgroundWasRead || Global::ApplyingTheme()) { if (_backgroundWasRead) {
return false; return false;
} }
_backgroundWasRead = true; _backgroundWasRead = true;
@ -3729,9 +3728,8 @@ bool readThemeUsingKey(FileKey key) {
} }
void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache) { void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache) {
auto key = _applyingThemeKey ? _applyingThemeKey : _themeKey; if (!_themeKey) {
if (!key) { _themeKey = genKey();
key = _themeKey = genKey();
writeSettings(); writeSettings();
} }
@ -3744,21 +3742,12 @@ void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const
data.stream << pathRelative << pathAbsolute; data.stream << pathRelative << pathAbsolute;
data.stream << cache.paletteChecksum << cache.contentChecksum << cache.colors << cache.background << backgroundTiled; data.stream << cache.paletteChecksum << cache.contentChecksum << cache.colors << cache.background << backgroundTiled;
FileWriteDescriptor file(key, FileOption::Safe); FileWriteDescriptor file(_themeKey, FileOption::Safe);
file.writeEncrypted(data, _settingsKey); file.writeEncrypted(data, _settingsKey);
} }
void readTheme() { void readTheme() {
if (_applyingThemeKey) { if (_themeKey && !readThemeUsingKey(_themeKey)) {
if (readThemeUsingKey(_applyingThemeKey)) {
Global::SetApplyingTheme(true);
} else {
clearKey(_applyingThemeKey);
_applyingThemeKey = 0;
writeSettings();
readTheme();
}
} else if (_themeKey && !readThemeUsingKey(_themeKey)) {
clearKey(_themeKey); clearKey(_themeKey);
_themeKey = 0; _themeKey = 0;
writeSettings(); writeSettings();

View File

@ -1905,7 +1905,6 @@ void MainWidget::backgroundParams(const QRect &forRect, QRect &to, QRect &from)
void MainWidget::updateScrollColors() { void MainWidget::updateScrollColors() {
_history->updateScrollColors(); _history->updateScrollColors();
if (_overview) _overview->updateScrollColors();
} }
void MainWidget::setChatBackground(const App::WallPaper &wp) { void MainWidget::setChatBackground(const App::WallPaper &wp) {

View File

@ -1874,7 +1874,7 @@ OverviewInner::~OverviewInner() {
} }
OverviewWidget::OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type) : TWidget(parent) OverviewWidget::OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type) : TWidget(parent)
, _scroll(this, st::historyScroll, false) , _scroll(this, st::setScroll, false)
, _inner(this, &_scroll, peer, type) , _inner(this, &_scroll, peer, type)
, _a_show(animation(this, &OverviewWidget::step_show)) , _a_show(animation(this, &OverviewWidget::step_show))
, _topShadow(this, st::shadowColor) { , _topShadow(this, st::shadowColor) {
@ -1883,8 +1883,6 @@ OverviewWidget::OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewTyp
_scroll.move(0, 0); _scroll.move(0, 0);
_inner.move(0, 0); _inner.move(0, 0);
updateScrollColors();
_scroll.show(); _scroll.show();
connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
@ -2195,11 +2193,6 @@ void OverviewWidget::fillSelectedItems(SelectedItemSet &sel, bool forDelete) {
_inner.fillSelectedItems(sel, forDelete); _inner.fillSelectedItems(sel, forDelete);
} }
void OverviewWidget::updateScrollColors() {
if (!App::historyScrollBarColor()) return;
_scroll.updateColors(App::historyScrollBarColor(), App::historyScrollBgColor(), App::historyScrollBarOverColor(), App::historyScrollBgOverColor());
}
void OverviewWidget::updateAfterDrag() { void OverviewWidget::updateAfterDrag() {
_inner.dragActionUpdate(QCursor::pos()); _inner.dragActionUpdate(QCursor::pos());
} }

View File

@ -315,8 +315,6 @@ public:
void fillSelectedItems(SelectedItemSet &sel, bool forDelete); void fillSelectedItems(SelectedItemSet &sel, bool forDelete);
void updateScrollColors();
void updateAfterDrag(); void updateAfterDrag();
void grabStart() override { void grabStart() override {

View File

@ -239,7 +239,7 @@ void BackgroundWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &upd
if (!theme.cached.background.isEmpty()) { if (!theme.cached.background.isEmpty()) {
Local::writeBackground(Window::Theme::kThemeBackground, QImage()); Local::writeBackground(Window::Theme::kThemeBackground, QImage());
} }
App::restart(); style::main_palette::apply(theme.palette);
} }
return; return;
} }

View File

@ -41,30 +41,25 @@ void destroyColors() {
colorsMap.clear(); colorsMap.clear();
} }
Color::Color(const Color &c) : ptr(c.owner ? new ColorData(*c.ptr) : c.ptr), owner(c.owner) { Color::Color(const Color &c) : ptr(c.ptr) {
} }
Color::Color(QColor c) : owner(false) { Color::Color(ColorData *data) : ptr(data) {
init(c.red(), c.green(), c.blue(), c.alpha());
} }
Color::Color(uchar r, uchar g, uchar b, uchar a) : owner(false) { Color::Color(uchar r, uchar g, uchar b, uchar a) {
init(r, g, b, a); init(r, g, b, a);
} }
Color &Color::operator=(const Color &c) { void Color::set(uchar r, uchar g, uchar b, uchar a) const {
if (this != &c) { ptr->set(r, g, b, a);
if (owner) {
delete ptr;
}
ptr = c.owner ? new ColorData(*c.ptr) : c.ptr;
owner = c.owner;
}
return *this;
} }
void Color::init(uchar r, uchar g, uchar b, uchar a) { void Color::init(uchar r, uchar g, uchar b, uchar a) {
uint32 key = colorKey(r, g, b, a); if (ptr) {
return set(r, g, b, a);
}
auto key = colorKey(r, g, b, a);
auto i = colorsMap.constFind(key); auto i = colorsMap.constFind(key);
if (i == colorsMap.cend()) { if (i == colorsMap.cend()) {
i = colorsMap.insert(key, new ColorData(r, g, b, a)); i = colorsMap.insert(key, new ColorData(r, g, b, a));
@ -72,19 +67,16 @@ void Color::init(uchar r, uchar g, uchar b, uchar a) {
ptr = i.value(); ptr = i.value();
} }
Color::~Color() { ColorData::ColorData() : p(Qt::NoPen), b(Qt::NoBrush) {
if (owner) {
delete ptr;
}
} }
ColorData::ColorData(uchar r, uchar g, uchar b, uchar a) : c(int(r), int(g), int(b), int(a)), p(c), b(c) { ColorData::ColorData(uchar r, uchar g, uchar b, uchar a) : c(int(r), int(g), int(b), int(a)), p(c), b(c) {
} }
void ColorData::set(QColor color) { void ColorData::set(uchar r, uchar g, uchar b, uchar a) {
c = color; this->c = QColor(r, g, b, a);
p = QPen(color); this->p = QPen(c);
b = QBrush(color); this->b = QBrush(c);
} }
} // namespace internal } // namespace internal

View File

@ -21,6 +21,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once #pragma once
namespace style { namespace style {
class palette;
namespace internal { namespace internal {
void destroyColors(); void destroyColors();
@ -31,13 +34,9 @@ public:
Color(Qt::Initialization = Qt::Uninitialized) { Color(Qt::Initialization = Qt::Uninitialized) {
} }
Color(const Color &c); Color(const Color &c);
explicit Color(QColor c); Color(uchar r, uchar g, uchar b, uchar a);
Color(uchar r, uchar g, uchar b, uchar a = 255);
Color &operator=(const Color &c);
~Color();
void set(QColor newv); void set(uchar r, uchar g, uchar b, uchar a) const;
void set(uchar r, uchar g, uchar b, uchar a = 255);
operator const QBrush &() const; operator const QBrush &() const;
operator const QPen &() const; operator const QPen &() const;
@ -54,16 +53,12 @@ public:
} }
private: private:
ColorData *ptr = nullptr; Color(ColorData *data);
bool owner = false;
void init(uchar r, uchar g, uchar b, uchar a); void init(uchar r, uchar g, uchar b, uchar a);
friend void startManager(); ColorData *ptr = nullptr;
Color(ColorData *p) : ptr(p) { friend class style::palette;
}
friend class ColorData;
}; };
@ -78,10 +73,12 @@ public:
} }
private: private:
ColorData();
ColorData(uchar r, uchar g, uchar b, uchar a); ColorData(uchar r, uchar g, uchar b, uchar a);
void set(QColor c); void set(uchar r, uchar g, uchar b, uchar a);
friend class Color; friend class Color;
friend class style::palette;
}; };

View File

@ -31,8 +31,10 @@ uint32 colorKey(QColor c) {
using IconMasks = QMap<const IconMask*, QImage>; using IconMasks = QMap<const IconMask*, QImage>;
using IconPixmaps = QMap<QPair<const IconMask*, uint32>, QPixmap>; using IconPixmaps = QMap<QPair<const IconMask*, uint32>, QPixmap>;
using IconDatas = OrderedSet<IconData*>;
NeverFreedPointer<IconMasks> iconMasks; NeverFreedPointer<IconMasks> iconMasks;
NeverFreedPointer<IconPixmaps> iconPixmaps; NeverFreedPointer<IconPixmaps> iconPixmaps;
NeverFreedPointer<IconDatas> iconData;
inline int pxAdjust(int value, int scale) { inline int pxAdjust(int value, int scale) {
if (value < 0) { if (value < 0) {
@ -82,6 +84,11 @@ MonoIcon::MonoIcon(const IconMask *mask, const Color &color, QPoint offset)
, _offset(offset) { , _offset(offset) {
} }
void MonoIcon::reset() const {
_pixmap = QPixmap();
_size = QSize();
}
int MonoIcon::width() const { int MonoIcon::width() const {
ensureLoaded(); ensureLoaded();
return _size.width(); return _size.width();
@ -151,8 +158,13 @@ void MonoIcon::ensureLoaded() const {
if (_size.isValid()) { if (_size.isValid()) {
return; return;
} }
const uchar *data = _mask->data(); if (!_maskImage.isNull()) {
int size = _mask->size(); createCachedPixmap();
return;
}
auto data = _mask->data();
auto size = _mask->size();
auto generateTag = qstr("GENERATE:"); auto generateTag = qstr("GENERATE:");
if (size > generateTag.size() && !memcmp(data, generateTag.data(), generateTag.size())) { if (size > generateTag.size() && !memcmp(data, generateTag.data(), generateTag.size())) {
@ -190,6 +202,11 @@ void MonoIcon::ensureLoaded() const {
} }
_maskImage = i.value(); _maskImage = i.value();
createCachedPixmap();
}
}
void MonoIcon::createCachedPixmap() const {
iconPixmaps.createIfNull(); iconPixmaps.createIfNull();
auto key = qMakePair(_mask, colorKey(_color->c)); auto key = qMakePair(_mask, colorKey(_color->c));
auto j = iconPixmaps->constFind(key); auto j = iconPixmaps->constFind(key);
@ -199,9 +216,13 @@ void MonoIcon::ensureLoaded() const {
_pixmap = j.value(); _pixmap = j.value();
_size = _pixmap.size() / cIntRetinaFactor(); _size = _pixmap.size() / cIntRetinaFactor();
} }
void IconData::created() {
iconData.createIfNull();
iconData->insert(this);
} }
void Icon::fill(QPainter &p, const QRect &rect) const { void IconData::fill(QPainter &p, const QRect &rect) const {
if (_parts.isEmpty()) return; if (_parts.isEmpty()) return;
auto partSize = _parts.at(0).size(); auto partSize = _parts.at(0).size();
@ -212,7 +233,7 @@ void Icon::fill(QPainter &p, const QRect &rect) const {
} }
} }
void Icon::fill(QPainter &p, const QRect &rect, QColor colorOverride) const { void IconData::fill(QPainter &p, const QRect &rect, QColor colorOverride) const {
if (_parts.isEmpty()) return; if (_parts.isEmpty()) return;
auto partSize = _parts.at(0).size(); auto partSize = _parts.at(0).size();
@ -223,7 +244,7 @@ void Icon::fill(QPainter &p, const QRect &rect, QColor colorOverride) const {
} }
} }
int Icon::width() const { int IconData::width() const {
if (_width < 0) { if (_width < 0) {
_width = 0; _width = 0;
for_const (auto &part, _parts) { for_const (auto &part, _parts) {
@ -233,7 +254,7 @@ int Icon::width() const {
return _width; return _width;
} }
int Icon::height() const { int IconData::height() const {
if (_height < 0) { if (_height < 0) {
_height = 0; _height = 0;
for_const (auto &part, _parts) { for_const (auto &part, _parts) {
@ -243,7 +264,17 @@ int Icon::height() const {
return _height; return _height;
} }
void resetIcons() {
iconPixmaps.clear();
if (iconData) {
for (auto data : *iconData) {
data->reset();
}
}
}
void destroyIcons() { void destroyIcons() {
iconData.clear();
iconPixmaps.clear(); iconPixmaps.clear();
iconMasks.clear(); iconMasks.clear();
} }

View File

@ -50,6 +50,7 @@ public:
MonoIcon() = default; MonoIcon() = default;
MonoIcon(const IconMask *mask, const Color &color, QPoint offset); MonoIcon(const IconMask *mask, const Color &color, QPoint offset);
void reset() const;
int width() const; int width() const;
int height() const; int height() const;
QSize size() const; QSize size() const;
@ -66,6 +67,7 @@ public:
private: private:
void ensureLoaded() const; void ensureLoaded() const;
void createCachedPixmap() const;
const IconMask *_mask = nullptr; const IconMask *_mask = nullptr;
Color _color; Color _color;
@ -76,17 +78,20 @@ private:
}; };
class Icon { class IconData {
public: public:
Icon(Qt::Initialization) {
}
template <typename ...MonoIcons> template <typename ...MonoIcons>
Icon(const MonoIcons&... icons) { IconData(const MonoIcons &...icons) {
created();
_parts.reserve(sizeof...(MonoIcons)); _parts.reserve(sizeof...(MonoIcons));
addIcons(icons...); addIcons(icons...);
} }
void reset() {
for_const (auto &part, _parts) {
part.reset();
}
}
bool empty() const { bool empty() const {
return _parts.empty(); return _parts.empty();
} }
@ -96,12 +101,6 @@ public:
part.paint(p, pos, outerw); part.paint(p, pos, outerw);
} }
} }
void paint(QPainter &p, int x, int y, int outerw) const {
paint(p, QPoint(x, y), outerw);
}
void paintInCenter(QPainter &p, const QRect &outer) const {
paint(p, outer.x() + (outer.width() - width()) / 2, outer.y() + (outer.height() - height()) / 2, outer.x() * 2 + outer.width());
}
void fill(QPainter &p, const QRect &rect) const; void fill(QPainter &p, const QRect &rect) const;
void paint(QPainter &p, const QPoint &pos, int outerw, QColor colorOverride) const { void paint(QPainter &p, const QPoint &pos, int outerw, QColor colorOverride) const {
@ -109,24 +108,18 @@ public:
part.paint(p, pos, outerw, colorOverride); part.paint(p, pos, outerw, colorOverride);
} }
} }
void paint(QPainter &p, int x, int y, int outerw, QColor colorOverride) const {
paint(p, QPoint(x, y), outerw, colorOverride);
}
void paintInCenter(QPainter &p, const QRect &outer, QColor colorOverride) const {
paint(p, outer.x() + (outer.width() - width()) / 2, outer.y() + (outer.height() - height()) / 2, outer.x() * 2 + outer.width(), colorOverride);
}
void fill(QPainter &p, const QRect &rect, QColor colorOverride) const; void fill(QPainter &p, const QRect &rect, QColor colorOverride) const;
int width() const; int width() const;
int height() const; int height() const;
QSize size() const {
return QSize(width(), height());
}
private: private:
void created();
template <typename ... MonoIcons> template <typename ... MonoIcons>
void addIcons() { void addIcons() {
} }
template <typename ... MonoIcons> template <typename ... MonoIcons>
void addIcons(const MonoIcon &icon, const MonoIcons&... icons) { void addIcons(const MonoIcon &icon, const MonoIcons&... icons) {
_parts.push_back(icon); _parts.push_back(icon);
@ -139,6 +132,86 @@ private:
}; };
class Icon {
public:
Icon(Qt::Initialization) {
}
template <typename ... MonoIcons>
Icon(const MonoIcons&... icons) : _data(new IconData(icons...)), _owner(true) {
}
Icon(const Icon &other) : _data(other._data) {
}
Icon(Icon &&other) : _data(base::take(other._data)), _owner(base::take(_owner)) {
}
Icon &operator=(const Icon &other) {
t_assert(!_owner);
_data = other._data;
_owner = false;
return *this;
}
Icon &operator=(Icon &&other) {
t_assert(!_owner);
_data = base::take(other._data);
_owner = base::take(other._owner);
return *this;
}
bool empty() const {
return _data->empty();
}
void paint(QPainter &p, const QPoint &pos, int outerw) const {
return _data->paint(p, pos, outerw);
}
void paint(QPainter &p, int x, int y, int outerw) const {
return _data->paint(p, QPoint(x, y), outerw);
}
void paintInCenter(QPainter &p, const QRect &outer) const {
return _data->paint(p, QPoint(outer.x() + (outer.width() - width()) / 2, outer.y() + (outer.height() - height()) / 2), outer.x() * 2 + outer.width());
}
void fill(QPainter &p, const QRect &rect) const {
return _data->fill(p, rect);
}
void paint(QPainter &p, const QPoint &pos, int outerw, QColor colorOverride) const {
return _data->paint(p, pos, outerw, colorOverride);
}
void paint(QPainter &p, int x, int y, int outerw, QColor colorOverride) const {
return _data->paint(p, QPoint(x, y), outerw, colorOverride);
}
void paintInCenter(QPainter &p, const QRect &outer, QColor colorOverride) const {
return _data->paint(p, QPoint(outer.x() + (outer.width() - width()) / 2, outer.y() + (outer.height() - height()) / 2), outer.x() * 2 + outer.width(), colorOverride);
}
void fill(QPainter &p, const QRect &rect, QColor colorOverride) const {
return _data->fill(p, rect, colorOverride);
}
int width() const {
return _data->width();
}
int height() const {
return _data->height();
}
QSize size() const {
return QSize(width(), height());
}
~Icon() {
if (auto data = base::take(_data)) {
if (_owner) {
delete data;
}
}
}
private:
IconData *_data = nullptr;
bool _owner = false;
};
void resetIcons();
void destroyIcons(); void destroyIcons();
} // namespace internal } // namespace internal