1
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-04-01 23:00:58 +00:00

First version of the new Settings page is finished.

Added LocalStorageBox for watching info and clearing local storage.
Local passcode and cloud password state display and editing done.
Temporary download location clearing link added.
Crash fixed in local storage clear + app close, now waiting for the
clearing thread to quit. Some design improvements and testing.
This commit is contained in:
John Preston 2016-08-28 13:16:23 -06:00
parent afab21372b
commit b520cf0f78
37 changed files with 751 additions and 188 deletions

View File

@ -306,6 +306,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_settings_section_privacy" = "Privacy and Security";
"lng_local_storage_title" = "Local storage";
"lng_settings_no_data_cached" = "No cached data found!";
"lng_settings_images_cached" = "{count:_not_used_|# image|# images}, {size}";
"lng_settings_audios_cached" = "{count:_not_used_|# voice message|# voice messages}, {size}";

View File

@ -188,8 +188,9 @@ namespace App {
namespace {
bool loggedOut() {
if (cHasPasscode()) {
cSetHasPasscode(false);
if (Global::LocalPasscode()) {
Global::SetLocalPasscode(false);
Global::RefLocalPasscodeChanged().notify();
}
if (audioPlayer()) {
audioPlayer()->stopAndClear();

View File

@ -339,7 +339,9 @@ void Application::closeApplication() {
_updateReply = 0;
if (_updateChecker) _updateChecker->deleteLater();
_updateChecker = 0;
if (_updateThread) _updateThread->quit();
if (_updateThread) {
_updateThread->quit();
}
_updateThread = 0;
#endif
@ -738,7 +740,8 @@ AppClass::AppClass() : QObject()
Local::ReadMapState state = Local::readMap(QByteArray());
if (state == Local::ReadMapPassNeeded) {
cSetHasPasscode(true);
Global::SetLocalPasscode(true);
Global::RefLocalPasscodeChanged().notify();
DEBUG_LOG(("Application Info: passcode needed..."));
} else {
DEBUG_LOG(("Application Info: local map read..."));

View File

@ -66,11 +66,11 @@ private:
bool checkReadyUpdate();
#else
#else // TDESKTOP_DISABLE_AUTOUPDATE
class UpdateChecker : public QObject {
Q_OBJECT
};
#endif
#endif // TDESKTOP_DISABLE_AUTOUPDATE
QString countBetaVersionSignature(uint64 version);

View File

@ -41,7 +41,7 @@ _close(this, lang(lng_box_ok), st::defaultBoxButton) {
_options.reserve(cnt);
for (int32 i = 0; i < cnt; ++i) {
int32 v = opts[i];
_options.push_back(new Radiobutton(this, qsl("autolock"), v, (v % 3600) ? lng_passcode_autolock_minutes(lt_count, v / 60) : lng_passcode_autolock_hours(lt_count, v / 3600), (cAutoLock() == v), st::langsButton));
_options.push_back(new Radiobutton(this, qsl("autolock"), v, (v % 3600) ? lng_passcode_autolock_minutes(lt_count, v / 60) : lng_passcode_autolock_hours(lt_count, v / 3600), (Global::AutoLock() == v), st::langsButton));
_options.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _options.back()->height() + st::boxOptionListPadding.top();
connect(_options.back(), SIGNAL(changed()), this, SLOT(onChange()));
@ -73,8 +73,9 @@ void AutoLockBox::onChange() {
for (int32 i = 0, l = _options.size(); i < l; ++i) {
int32 v = _options[i]->val();
if (_options[i]->checked()) {
cSetAutoLock(v);
Global::SetAutoLock(v);
Local::writeUserSettings();
Global::RefLocalPasscodeChanged().notify();
}
}
App::wnd()->checkAutoLock();

View File

@ -85,3 +85,5 @@ aboutRevokePublicLabel: flatLabel(labelDefFlat) {
width: 320px;
textFg: windowTextFg;
}
localStorageBoxSkip: 10px;

View File

@ -0,0 +1,131 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "boxes/localstoragebox.h"
#include "localstorage.h"
#include "ui/flatbutton.h"
#include "lang.h"
#include "styles/style_boxes.h"
#include "mainwindow.h"
LocalStorageBox::LocalStorageBox() : AbstractBox()
, _clear(this, lang(lng_local_storage_clear), st::defaultBoxLinkButton)
, _close(this, lang(lng_box_ok), st::defaultBoxButton) {
connect(_clear, SIGNAL(clicked()), this, SLOT(onClear()));
connect(_close, SIGNAL(clicked()), this, SLOT(onClose()));
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int)));
connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int)));
checkLocalStoredCounts();
prepare();
}
void LocalStorageBox::updateControls() {
int rowsHeight = 0;
if (_imagesCount > 0 && _audiosCount > 0) {
rowsHeight = 2 * (st::linkFont->height + st::localStorageBoxSkip);
} else {
rowsHeight = st::linkFont->height + st::localStorageBoxSkip;
}
_clear->setVisible(_imagesCount > 0 || _audiosCount > 0);
setMaxHeight(st::boxTitleHeight + st::localStorageBoxSkip + rowsHeight + _clear->height() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom());
_clear->moveToLeft(st::boxPadding.left(), st::boxTitleHeight + st::localStorageBoxSkip + rowsHeight);
_close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height());
update();
}
void LocalStorageBox::showAll() {
showChildren();
_clear->setVisible(_imagesCount > 0 || _audiosCount > 0);
}
void LocalStorageBox::checkLocalStoredCounts() {
int imagesCount = Local::hasImages() + Local::hasStickers() + Local::hasWebFiles();
int audiosCount = Local::hasAudios();
if (imagesCount != _imagesCount || audiosCount != _audiosCount) {
_imagesCount = imagesCount;
_audiosCount = audiosCount;
if (_imagesCount > 0 || _audiosCount > 0) {
_state = State::Normal;
}
updateControls();
}
}
void LocalStorageBox::paintEvent(QPaintEvent *e) {
Painter p(this);
if (paint(p)) return;
paintTitle(p, lang(lng_local_storage_title));
p.setFont(st::boxTextFont);
p.setPen(st::windowTextFg);
checkLocalStoredCounts();
int top = st::boxTitleHeight + st::localStorageBoxSkip;
if (_imagesCount > 0) {
auto text = lng_settings_images_cached(lt_count, _imagesCount, lt_size, formatSizeText(Local::storageImagesSize() + Local::storageStickersSize() + Local::storageWebFilesSize()));
p.drawTextLeft(st::boxPadding.left(), top, width(), text);
top += st::boxTextFont->height + st::localStorageBoxSkip;
}
if (_audiosCount > 0) {
auto text = lng_settings_audios_cached(lt_count, _audiosCount, lt_size, formatSizeText(Local::storageAudiosSize()));
p.drawTextLeft(st::boxPadding.left(), top, width(), text);
top += st::boxTextFont->height + st::localStorageBoxSkip;
} else if (_imagesCount <= 0) {
p.drawTextLeft(st::boxPadding.left(), top, width(), lang(lng_settings_no_data_cached));
top += st::boxTextFont->height + st::localStorageBoxSkip;
}
auto text = ([this]() -> QString {
switch (_state) {
case State::Clearing: return lang(lng_local_storage_clearing);
case State::Cleared: return lang(lng_local_storage_cleared);
case State::ClearFailed: return lang(lng_local_storage_clear_failed);
}
return QString();
})();
if (!text.isEmpty()) {
p.drawTextLeft(st::boxPadding.left(), top, width(), text);
top += st::boxTextFont->height + st::localStorageBoxSkip;
}
}
void LocalStorageBox::onClear() {
App::wnd()->tempDirDelete(Local::ClearManagerStorage);
_state = State::Clearing;
updateControls();
}
void LocalStorageBox::onTempDirCleared(int task) {
if (task & Local::ClearManagerStorage) {
_state = State::Cleared;
}
updateControls();
}
void LocalStorageBox::onTempDirClearFailed(int task) {
if (task & Local::ClearManagerStorage) {
_state = State::ClearFailed;
}
updateControls();
}

View File

@ -0,0 +1,62 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "abstractbox.h"
class BoxButton;
class LinkButton;
class LocalStorageBox : public AbstractBox {
Q_OBJECT
public:
LocalStorageBox();
private slots:
void onClear();
void onTempDirCleared(int task);
void onTempDirClearFailed(int task);
protected:
void paintEvent(QPaintEvent *e) override;
void showAll() override;
private:
void updateControls();
void checkLocalStoredCounts();
enum class State {
Normal,
Clearing,
Cleared,
ClearFailed,
};
State _state = State::Normal;
ChildWidget<LinkButton> _clear;
ChildWidget<BoxButton> _close;
int _imagesCount = -1;
int _audiosCount = -1;
};

View File

@ -39,7 +39,7 @@ PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth)
, _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton)
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
, _oldPasscode(this, st::defaultInputField, lang(lng_passcode_enter_old))
, _newPasscode(this, st::defaultInputField, lang(cHasPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
, _newPasscode(this, st::defaultInputField, lang(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
, _reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new))
, _passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint))
, _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email))
@ -86,7 +86,7 @@ void PasscodeBox::init() {
_boxTitle = lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove);
setMaxHeight(st::boxTitleHeight + st::passcodePadding.top() + _oldPasscode.height() + st::passcodeSkip + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeSkip : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton.height() + st::boxButtonPadding.bottom());
} else {
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
if (has) {
_oldPasscode.show();
_boxTitle = lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change);
@ -117,7 +117,7 @@ void PasscodeBox::init() {
}
void PasscodeBox::showAll() {
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
if (_turningOff) {
_oldPasscode.show();
if (_cloudPwd && _hasRecovery) {
@ -125,9 +125,10 @@ void PasscodeBox::showAll() {
} else {
_recover.hide();
}
_passwordHint.hide();
_newPasscode.hide();
_reenterPasscode.hide();
_passwordHint.hide();
_recoverEmail.hide();
} else {
if (has) {
_oldPasscode.show();
@ -159,7 +160,7 @@ void PasscodeBox::showAll() {
}
void PasscodeBox::onSubmit() {
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
if (_oldPasscode.hasFocus()) {
if (_turningOff) {
onSave();
@ -230,7 +231,7 @@ void PasscodeBox::paintEvent(QPaintEvent *e) {
}
void PasscodeBox::resizeEvent(QResizeEvent *e) {
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
int32 w = st::boxWidth - st::boxPadding.left() - st::boxPadding.right();
_oldPasscode.resize(w, _oldPasscode.height());
_oldPasscode.moveToLeft(st::boxPadding.left(), st::boxTitleHeight + st::passcodePadding.top());
@ -323,7 +324,7 @@ void PasscodeBox::onSave(bool force) {
if (_setRequest) return;
QString old = _oldPasscode.text(), pwd = _newPasscode.text(), conf = _reenterPasscode.text();
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
if (!_cloudPwd && (_turningOff || has)) {
if (!passcodeCanTry()) {
_oldError = lang(lng_flood_error);

View File

@ -653,6 +653,10 @@ struct Data {
base::Observable<void> ChooseCustomLang;
int AutoLock = 3600;
bool LocalPasscode = false;
base::Observable<void> LocalPasscodeChanged;
};
} // namespace internal
@ -757,4 +761,8 @@ DefineRefVar(Global, base::Observable<void>, ConnectionTypeChanged);
DefineRefVar(Global, base::Observable<void>, ChooseCustomLang);
DefineVar(Global, int, AutoLock);
DefineVar(Global, bool, LocalPasscode);
DefineRefVar(Global, base::Observable<void>, LocalPasscodeChanged);
} // namespace Global

View File

@ -318,6 +318,10 @@ DeclareRefVar(base::Observable<void>, ConnectionTypeChanged);
DeclareRefVar(base::Observable<void>, ChooseCustomLang);
DeclareVar(int, AutoLock);
DeclareVar(bool, LocalPasscode);
DeclareRefVar(base::Observable<void>, LocalPasscodeChanged);
} // namespace Global
namespace Adaptive {

View File

@ -1165,7 +1165,8 @@ namespace {
stream >> v;
if (!_checkStreamStatus(stream)) return false;
cSetAutoLock(v);
Global::SetAutoLock(v);
Global::RefLocalPasscodeChanged().notify();
} break;
case dbiReplaceEmojis: {
@ -1569,7 +1570,7 @@ namespace {
data.stream << quint32(dbiSendKey) << qint32(cCtrlEnter() ? dbiskCtrlEnter : dbiskEnter);
data.stream << quint32(dbiTileBackground) << qint32(Window::chatBackground()->tile() ? 1 : 0);
data.stream << quint32(dbiAdaptiveForWide) << qint32(Global::AdaptiveForWide() ? 1 : 0);
data.stream << quint32(dbiAutoLock) << qint32(cAutoLock());
data.stream << quint32(dbiAutoLock) << qint32(Global::AutoLock());
data.stream << quint32(dbiReplaceEmojis) << qint32(cReplaceEmojis() ? 1 : 0);
data.stream << quint32(dbiDefaultAttach) << qint32(cDefaultAttach());
data.stream << quint32(dbiSoundNotify) << qint32(Global::SoundNotify());
@ -2298,7 +2299,8 @@ namespace Local {
_mapChanged = true;
_writeMap(WriteMapNow);
cSetHasPasscode(!passcode.isEmpty());
Global::SetLocalPasscode(!passcode.isEmpty());
Global::RefLocalPasscodeChanged().notify();
}
ReadMapState readMap(const QByteArray &pass) {
@ -4167,11 +4169,22 @@ namespace Local {
void ClearManager::start() {
moveToThread(data->thread);
connect(data->thread, SIGNAL(started()), this, SLOT(onStart()));
connect(data->thread, SIGNAL(finished()), data->thread, SLOT(deleteLater()));
connect(data->thread, SIGNAL(finished()), this, SLOT(deleteLater()));
data->thread->start();
}
void ClearManager::stop() {
{
QMutexLocker lock(&data->mutex);
data->tasks.clear();
}
auto thread = data->thread;
thread->quit();
thread->wait();
}
ClearManager::~ClearManager() {
data->thread->deleteLater();
delete data;
}
@ -4231,11 +4244,11 @@ namespace Local {
}
{
QMutexLocker lock(&data->mutex);
if (data->tasks.at(0) == task) {
if (!data->tasks.isEmpty() && data->tasks.at(0) == task) {
data->tasks.pop_front();
if (data->tasks.isEmpty()) {
data->working = false;
}
}
if (data->tasks.isEmpty()) {
data->working = false;
}
if (result) {
emit succeed(task, data->working ? 0 : this);

View File

@ -81,16 +81,18 @@ namespace Local {
bool addTask(int task);
bool hasTask(ClearManagerTask task);
void start();
~ClearManager();
public slots:
void onStart();
void stop();
signals:
void succeed(int task, void *manager);
void failed(int task, void *manager);
private slots:
void onStart();
private:
~ClearManager();
ClearManagerData *data;
};

View File

@ -588,10 +588,10 @@ void MainWindow::checkAutoLockIn(int msec) {
}
void MainWindow::checkAutoLock() {
if (!cHasPasscode() || App::passcoded()) return;
if (!Global::LocalPasscode() || App::passcoded()) return;
App::app()->checkLocalTime();
uint64 ms = getms(true), idle = psIdleTime(), should = cAutoLock() * 1000ULL;
uint64 ms = getms(true), idle = psIdleTime(), should = Global::AutoLock() * 1000ULL;
if (idle >= should || (_shouldLockAt > 0 && ms > _shouldLockAt + 3000ULL)) {
setupPasscode(true);
} else {
@ -608,6 +608,7 @@ void MainWindow::setupIntro(bool anim) {
if (_mediaView) {
_mediaView->clearData();
}
Ui::hideSettingsAndLayer(true);
QPixmap bg = anim ? grabInner() : QPixmap();
@ -1350,8 +1351,8 @@ void MainWindow::tempDirDelete(int task) {
if (_clearManager->addTask(task)) {
return;
} else {
_clearManager->deleteLater();
_clearManager = 0;
_clearManager->stop();
_clearManager = nullptr;
}
}
_clearManager = new Local::ClearManager();
@ -1363,16 +1364,16 @@ void MainWindow::tempDirDelete(int task) {
void MainWindow::onClearFinished(int task, void *manager) {
if (manager && manager == _clearManager) {
_clearManager->deleteLater();
_clearManager = 0;
_clearManager->stop();
_clearManager = nullptr;
}
emit tempDirCleared(task);
}
void MainWindow::onClearFailed(int task, void *manager) {
if (manager && manager == _clearManager) {
_clearManager->deleteLater();
_clearManager = 0;
_clearManager->stop();
_clearManager = nullptr;
}
emit tempDirClearFailed(task);
}
@ -1918,7 +1919,10 @@ void MainWindow::updateIsActive(int timeout) {
MainWindow::~MainWindow() {
notifyClearFast();
delete _clearManager;
if (_clearManager) {
_clearManager->stop();
_clearManager = nullptr;
}
delete _connecting;
delete _mediaView;
delete trayIcon;

View File

@ -75,9 +75,6 @@ bool gCompressPastedImage = true;
QString gTimeFormat = qsl("hh:mm");
int32 gAutoLock = 3600;
bool gHasPasscode = false;
bool gHasAudioPlayer = true;
bool gHasAudioCapture = true;

View File

@ -121,9 +121,6 @@ DeclareSetting(DBIScale, ConfigScale);
DeclareSetting(bool, CompressPastedImage);
DeclareSetting(QString, TimeFormat);
DeclareSetting(int32, AutoLock);
DeclareSetting(bool, HasPasscode);
DeclareSetting(bool, HasAudioPlayer);
DeclareSetting(bool, HasAudioCapture);

View File

@ -104,22 +104,25 @@ settingsBlocksTop: 7px;
settingsBlocksBottom: 20px;
settingsBlockMarginTop: 14px;
settingsBlockMarginRight: 10px;
settingsBlockMarginBottom: 16px;
settingsBlockMarginBottom: 10px;
settingsBlockTitleHeight: 31px;
settingsBlockTitleFont: font(14px semibold);
settingsBlockTitleFont: font(15px semibold);
settingsBlockTitleFg: #333333;
settingsBlockTitleTop: 0px;
settingsBlockLabel: flatLabel(labelDefFlat) {
settingsPrimaryLabel: flatLabel(labelDefFlat) {
font: boxTextFont;
}
settingsBlockLabel: flatLabel(settingsPrimaryLabel) {
textFg: windowSubTextFg;
}
settingsBlockOneLineTextPart: flatLabel(labelDefFlat) {
settingsBlockOneLineTextPart: flatLabel(settingsPrimaryLabel) {
width: 0px; // No need to set minWidth in one-line text.
margin: margins(5px, 5px, 5px, 5px);
maxHeight: 20px;
}
settingsSubSkip: 4px;
settingsSmallSkip: 10px;
settingsSkip: 15px;
settingsSkip: 14px;
settingsLargeSkip: 23px;
settingsActionPadding: margins(0px, 4px, 0px, 5px);

View File

@ -26,6 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/connectionbox.h"
#include "boxes/confirmbox.h"
#include "boxes/aboutbox.h"
#include "boxes/localstoragebox.h"
#include "mainwindow.h"
namespace Settings {
@ -43,14 +44,22 @@ void AdvancedWidget::createControls() {
style::margins marginSmall(0, 0, 0, st::settingsSmallSkip);
style::margins marginLarge(0, 0, 0, st::settingsLargeSkip);
if (self()) {
addChildRow(_manageLocalStorage, marginSmall, lang(lng_settings_manage_local_storage), SLOT(onManageLocalStorage()));
}
style::margins marginLocalStorage = ([&marginSmall, &marginLarge]() {
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY
addChildRow(_connectionType, marginLarge, lang(lng_connection_type), lang(lng_connection_auto_connecting));
connectionTypeUpdated();
connect(_connectionType->link(), SIGNAL(clicked()), this, SLOT(onConnectionType()));
return marginSmall;
#else // TDESKTOP_DISABLE_NETWORK_PROXY
return marginLarge;
#endif // TDESKTOP_DISABLE_NETWORK_PROXY
})();
if (self()) {
addChildRow(_manageLocalStorage, marginLocalStorage, lang(lng_settings_manage_local_storage), SLOT(onManageLocalStorage()));
}
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY
addChildRow(_connectionType, marginLarge, lang(lng_connection_type), lang(lng_connection_auto_connecting), LabeledLink::Type::Primary, SLOT(onConnectionType()));
connectionTypeUpdated();
#endif // TDESKTOP_DISABLE_NETWORK_PROXY
if (self()) {
addChildRow(_askQuestion, marginSmall, lang(lng_settings_ask_question), SLOT(onAskQuestion()));
}
@ -61,7 +70,7 @@ void AdvancedWidget::createControls() {
}
void AdvancedWidget::onManageLocalStorage() {
Ui::showLayer(new LocalStorageBox());
}
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY

View File

@ -33,8 +33,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Settings {
BackgroundRow::BackgroundRow(QWidget *parent) : TWidget(parent)
, _chooseFromGallery(this, lang(lng_settings_bg_from_gallery))
, _chooseFromFile(this, lang(lng_settings_bg_from_file))
, _chooseFromGallery(this, lang(lng_settings_bg_from_gallery), st::defaultBoxLinkButton)
, _chooseFromFile(this, lang(lng_settings_bg_from_file), st::defaultBoxLinkButton)
, _radial(animation(this, &BackgroundRow::step_radial)) {
Window::chatBackground()->initIfEmpty();
@ -87,8 +87,8 @@ int BackgroundRow::resizeGetHeight(int newWidth) {
_chooseFromGallery->resizeToWidth(qMin(linkWidth, _chooseFromGallery->naturalWidth()));
_chooseFromFile->resizeToWidth(qMin(linkWidth, _chooseFromFile->naturalWidth()));
_chooseFromGallery->moveToLeft(linkLeft, 0);
_chooseFromFile->moveToLeft(linkLeft, _chooseFromGallery->height() + st::settingsSmallSkip);
_chooseFromGallery->moveToLeft(linkLeft, 0, newWidth);
_chooseFromFile->moveToLeft(linkLeft, _chooseFromGallery->height() + st::settingsSmallSkip, newWidth);
return st::settingsBackgroundSize;
}

View File

@ -43,10 +43,10 @@ int BlockWidget::resizeGetHeight(int newWidth) {
int x = contentLeft(), result = contentTop();
int availw = newWidth - x;
for_const (auto &row, _rows) {
row.child->moveToLeft(x + row.margin.left(), result + row.margin.top());
auto availRowWidth = availw - row.margin.left() - row.margin.right();
row.child->moveToLeft(x + row.margin.left(), result + row.margin.top(), newWidth);
auto availRowWidth = availw - row.margin.left() - row.margin.right() - x;
auto natural = row.child->naturalWidth();
auto rowWidth = (natural < 0) ? (availRowWidth - x) : qMin(natural, availRowWidth);
auto rowWidth = (natural < 0) ? availRowWidth : qMin(natural, availRowWidth);
if (row.child->width() != rowWidth) {
row.child->resizeToWidth(rowWidth);
}
@ -85,17 +85,17 @@ void BlockWidget::rowHeightUpdated() {
}
void BlockWidget::createChildRow(ChildWidget<Checkbox> &child, style::margins &margin, const QString &text, const char *slot, bool checked) {
child = new Checkbox(this, text, checked);
child = new Checkbox(this, text, checked, st::defaultBoxCheckbox);
connect(child, SIGNAL(changed()), this, slot);
}
void BlockWidget::createChildRow(ChildWidget<Radiobutton> &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked) {
child = new Radiobutton(this, group, value, text, checked);
child = new Radiobutton(this, group, value, text, checked, st::defaultRadiobutton);
connect(child, SIGNAL(changed()), this, slot);
}
void BlockWidget::createChildRow(ChildWidget<LinkButton> &child, style::margins &margin, const QString &text, const char *slot) {
child = new LinkButton(this, text);
void BlockWidget::createChildRow(ChildWidget<LinkButton> &child, style::margins &margin, const QString &text, const char *slot, const style::linkButton &st) {
child = new LinkButton(this, text, st);
connect(child, SIGNAL(clicked()), this, slot);
}

View File

@ -89,7 +89,7 @@ private:
}
void createChildRow(ChildWidget<Checkbox> &child, style::margins &margin, const QString &text, const char *slot, bool checked);
void createChildRow(ChildWidget<Radiobutton> &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked);
void createChildRow(ChildWidget<LinkButton> &child, style::margins &margin, const QString &text, const char *slot);
void createChildRow(ChildWidget<LinkButton> &child, style::margins &margin, const QString &text, const char *slot, const style::linkButton &st = st::defaultBoxLinkButton);
void addCreatedRow(TWidget *child, const style::margins &margin);
void rowHeightUpdated();

View File

@ -27,59 +27,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/flatlabel.h"
#include "localstorage.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "boxes/emojibox.h"
#include "boxes/stickersetbox.h"
#include "boxes/downloadpathbox.h"
#include "boxes/connectionbox.h"
#include "boxes/confirmbox.h"
namespace Settings {
ChatSettingsWidget::ChatSettingsWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_chat_settings)) {
createControls();
subscribe(Global::RefDownloadPathChanged(), [this]() {
_downloadPath->entity()->link()->setText(downloadPathText());
resizeToWidth(width());
});
}
QString ChatSettingsWidget::downloadPathText() const {
if (Global::DownloadPath().isEmpty()) {
return lang(lng_download_path_default);
} else if (Global::DownloadPath() == qsl("tmp")) {
return lang(lng_download_path_temp);
}
return QDir::toNativeSeparators(Global::DownloadPath());
};
void ChatSettingsWidget::createControls() {
style::margins marginSmall(0, 0, 0, st::settingsSmallSkip);
style::margins marginSkip(0, 0, 0, st::settingsSkip);
style::margins marginSub(0, 0, 0, st::settingsSubSkip);
style::margins slidedPadding(0, marginSub.bottom() / 2, 0, marginSub.bottom() - (marginSub.bottom() / 2));
addChildRow(_replaceEmoji, marginSub, lang(lng_settings_replace_emojis), SLOT(onReplaceEmoji()), cReplaceEmojis());
style::margins marginList(st::defaultCheckbox.textPosition.x(), 0, 0, st::settingsSkip);
addChildRow(_viewList, marginList, slidedPadding, lang(lng_settings_view_emojis), SLOT(onViewList()));
addChildRow(_dontAskDownloadPath, marginSub, lang(lng_download_path_dont_ask), SLOT(onDontAskDownloadPath()), !Global::AskDownloadPath());
style::margins marginPath(st::defaultCheckbox.textPosition.x(), 0, 0, st::settingsSkip);
addChildRow(_downloadPath, marginPath, slidedPadding, lang(lng_download_path_label), downloadPathText());
connect(_downloadPath->entity()->link(), SIGNAL(clicked()), this, SLOT(onDownloadPath()));
if (Global::AskDownloadPath()) {
_downloadPath->hideFast();
}
addChildRow(_sendByEnter, marginSmall, qsl("send_key"), 0, lang(lng_settings_send_enter), SLOT(onSendByEnter()), !cCtrlEnter());
addChildRow(_sendByCtrlEnter, marginSkip, qsl("send_key"), 1, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), SLOT(onSendByCtrlEnter()), cCtrlEnter());
addChildRow(_automaticMediaDownloadSettings, marginSmall, lang(lng_media_auto_settings), SLOT(onAutomaticMediaDownloadSettings()));
addChildRow(_manageStickerSets, marginSmall, lang(lng_stickers_you_have), SLOT(onManageStickerSets()));
}
LabeledLink::LabeledLink(QWidget *parent, const QString &label, const QString &text) : TWidget(parent)
, _label(this, label, FlatLabel::InitType::Simple)
, _link(this, text) {
LabeledLink::LabeledLink(QWidget *parent, const QString &label, const QString &text, Type type, const char *slot) : TWidget(parent)
, _label(this, label, FlatLabel::InitType::Simple, (type == Type::Primary) ? st::settingsPrimaryLabel : st::labelDefFlat)
, _link(this, text, (type == Type::Primary) ? st::defaultBoxLinkButton : st::btnDefLink) {
connect(_link, SIGNAL(clicked()), parent, slot);
}
void LabeledLink::setLink(const QString &text) {
@ -92,12 +52,130 @@ int LabeledLink::naturalWidth() const {
}
int LabeledLink::resizeGetHeight(int newWidth) {
_label->moveToLeft(0, 0);
_label->moveToLeft(0, 0, newWidth);
_link->resizeToWidth(newWidth - st::normalFont->spacew - _label->width());
_link->moveToLeft(_label->width() + st::normalFont->spacew, 0);
_link->moveToLeft(_label->width() + st::normalFont->spacew, 0, newWidth);
return _label->height();
}
DownloadPathState::DownloadPathState(QWidget *parent) : TWidget(parent)
, _path(this, lang(lng_download_path_label), downloadPathText(), LabeledLink::Type::Secondary, SLOT(onDownloadPath()))
, _clear(this, lang(lng_download_path_clear)) {
connect(_clear, SIGNAL(clicked()), this, SLOT(onClear()));
connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int)));
connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int)));
subscribe(Global::RefDownloadPathChanged(), [this]() {
_path->link()->setText(downloadPathText());
resizeToWidth(width());
});
switch (App::wnd()->tempDirState()) {
case MainWindow::TempDirEmpty: _state = State::Empty; break;
case MainWindow::TempDirExists: _state = State::Exists; break;
case MainWindow::TempDirRemoving: _state = State::Clearing; break;
}
updateControls();
}
int DownloadPathState::resizeGetHeight(int newWidth) {
_path->resizeToWidth(qMin(newWidth, _path->naturalWidth()));
_path->moveToLeft(0, 0, newWidth);
_clear->moveToRight(0, 0, newWidth);
return _path->height();
}
void DownloadPathState::paintEvent(QPaintEvent *e) {
Painter p(this);
auto text = ([this]() -> QString {
switch (_state) {
case State::Clearing: return lang(lng_download_path_clearing);
case State::Cleared: return lang(lng_download_path_cleared);
case State::ClearFailed: return lang(lng_download_path_clear_failed);
}
return QString();
})();
if (!text.isEmpty()) {
p.setFont(st::linkFont);
p.setPen(st::windowTextFg);
p.drawTextRight(0, 0, width(), text);
}
}
void DownloadPathState::updateControls() {
_clear->setVisible(_state == State::Exists);
update();
}
QString DownloadPathState::downloadPathText() const {
if (Global::DownloadPath().isEmpty()) {
return lang(lng_download_path_default);
} else if (Global::DownloadPath() == qsl("tmp")) {
return lang(lng_download_path_temp);
}
return QDir::toNativeSeparators(Global::DownloadPath());
};
void DownloadPathState::onDownloadPath() {
Ui::showLayer(new DownloadPathBox());
}
void DownloadPathState::onClear() {
ConfirmBox *box = new ConfirmBox(lang(lng_sure_clear_downloads));
connect(box, SIGNAL(confirmed()), this, SLOT(onClearSure()));
Ui::showLayer(box);
}
void DownloadPathState::onClearSure() {
Ui::hideLayer();
App::wnd()->tempDirDelete(Local::ClearManagerDownloads);
_state = State::Clearing;
updateControls();
}
void DownloadPathState::onTempDirCleared(int task) {
if (task & Local::ClearManagerDownloads) {
_state = State::Cleared;
}
updateControls();
}
void DownloadPathState::onTempDirClearFailed(int task) {
if (task & Local::ClearManagerDownloads) {
_state = State::ClearFailed;
}
updateControls();
}
ChatSettingsWidget::ChatSettingsWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_chat_settings)) {
createControls();
}
void ChatSettingsWidget::createControls() {
style::margins marginSmall(0, 0, 0, st::settingsSmallSkip);
style::margins marginSkip(0, 0, 0, st::settingsSkip);
style::margins marginSub(0, 0, 0, st::settingsSubSkip);
style::margins slidedPadding(0, marginSub.bottom() / 2, 0, marginSub.bottom() - (marginSub.bottom() / 2));
addChildRow(_replaceEmoji, marginSub, lang(lng_settings_replace_emojis), SLOT(onReplaceEmoji()), cReplaceEmojis());
style::margins marginList(st::defaultBoxCheckbox.textPosition.x(), 0, 0, st::settingsSkip);
addChildRow(_viewList, marginList, slidedPadding, lang(lng_settings_view_emojis), SLOT(onViewList()), st::btnDefLink);
if (!cReplaceEmojis()) {
_viewList->hideFast();
}
addChildRow(_dontAskDownloadPath, marginSub, lang(lng_download_path_dont_ask), SLOT(onDontAskDownloadPath()), !Global::AskDownloadPath());
style::margins marginPath(st::defaultBoxCheckbox.textPosition.x(), 0, 0, st::settingsSkip);
addChildRow(_downloadPath, marginPath, slidedPadding);
if (Global::AskDownloadPath()) {
_downloadPath->hideFast();
}
addChildRow(_sendByEnter, marginSmall, qsl("send_key"), 0, lang(lng_settings_send_enter), SLOT(onSendByEnter()), !cCtrlEnter());
addChildRow(_sendByCtrlEnter, marginSkip, qsl("send_key"), 1, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), SLOT(onSendByCtrlEnter()), cCtrlEnter());
addChildRow(_automaticMediaDownloadSettings, marginSmall, lang(lng_media_auto_settings), SLOT(onAutomaticMediaDownloadSettings()));
addChildRow(_manageStickerSets, marginSmall, lang(lng_stickers_you_have), SLOT(onManageStickerSets()));
}
void ChatSettingsWidget::onReplaceEmoji() {
cSetReplaceEmojis(_replaceEmoji->checked());
Local::writeUserSettings();
@ -123,10 +201,6 @@ void ChatSettingsWidget::onDontAskDownloadPath() {
}
}
void ChatSettingsWidget::onDownloadPath() {
Ui::showLayer(new DownloadPathBox());
}
void ChatSettingsWidget::onSendByEnter() {
if (_sendByEnter->checked()) {
cSetCtrlEnter(false);

View File

@ -28,7 +28,11 @@ namespace Settings {
class LabeledLink : public TWidget {
public:
LabeledLink(QWidget *parent, const QString &label, const QString &text);
enum class Type {
Primary,
Secondary,
};
LabeledLink(QWidget *parent, const QString &label, const QString &text, Type type, const char *slot);
void setLink(const QString &text);
@ -47,6 +51,42 @@ private:
};
class DownloadPathState : public TWidget, public base::Subscriber {
Q_OBJECT
public:
DownloadPathState(QWidget *parent);
protected:
int resizeGetHeight(int newWidth) override;
void paintEvent(QPaintEvent *e) override;
private slots:
void onDownloadPath();
void onClear();
void onClearSure();
void onTempDirCleared(int task);
void onTempDirClearFailed(int task);
private:
QString downloadPathText() const;
void updateControls();
enum class State {
Empty,
Exists,
Clearing,
Cleared,
ClearFailed,
};
State _state = State::Empty;
ChildWidget<LabeledLink> _path;
ChildWidget<LinkButton> _clear;
};
class ChatSettingsWidget : public BlockWidget {
Q_OBJECT
@ -57,7 +97,6 @@ private slots:
void onReplaceEmoji();
void onViewList();
void onDontAskDownloadPath();
void onDownloadPath();
void onSendByEnter();
void onSendByCtrlEnter();
void onAutomaticMediaDownloadSettings();
@ -65,12 +104,11 @@ private slots:
private:
void createControls();
QString downloadPathText() const;
ChildWidget<Checkbox> _replaceEmoji = { nullptr };
ChildWidget<Ui::WidgetSlideWrap<LinkButton>> _viewList = { nullptr };
ChildWidget<Checkbox> _dontAskDownloadPath = { nullptr };
ChildWidget<Ui::WidgetSlideWrap<LabeledLink>> _downloadPath = { nullptr };
ChildWidget<Ui::WidgetSlideWrap<DownloadPathState>> _downloadPath = { nullptr };
ChildWidget<Radiobutton> _sendByEnter = { nullptr };
ChildWidget<Radiobutton> _sendByCtrlEnter = { nullptr };
ChildWidget<LinkButton> _automaticMediaDownloadSettings = { nullptr };

View File

@ -97,19 +97,19 @@ int CoverWidget::resizeGetHeight(int newWidth) {
newHeight += st::settingsMarginTop;
_userpicButton->moveToLeft(contentLeft() + st::settingsPhotoLeft, newHeight);
_userpicButton->moveToLeft(contentLeft() + st::settingsPhotoLeft, newHeight, newWidth);
int infoLeft = _userpicButton->x() + _userpicButton->width();
_statusPosition = QPoint(infoLeft + st::settingsStatusLeft, _userpicButton->y() + st::settingsStatusTop);
if (_cancelPhotoUpload) {
_cancelPhotoUpload->moveToLeft(_statusPosition.x() + st::settingsStatusFont->width(_statusText) + st::settingsStatusFont->spacew, _statusPosition.y());
_cancelPhotoUpload->moveToLeft(_statusPosition.x() + st::settingsStatusFont->width(_statusText) + st::settingsStatusFont->spacew, _statusPosition.y(), newWidth);
}
int buttonLeft = _userpicButton->x() + _userpicButton->width() + st::settingsButtonLeft;
int buttonsRight = newWidth - st::settingsButtonSkip;
_setPhoto->moveToLeft(buttonLeft, _userpicButton->y() + st::settingsButtonTop);
_setPhoto->moveToLeft(buttonLeft, _userpicButton->y() + st::settingsButtonTop, newWidth);
buttonLeft += _setPhoto->width() + st::settingsButtonSkip;
_editName->moveToLeft(buttonLeft, _setPhoto->y());
_editName->moveToLeft(buttonLeft, _setPhoto->y(), newWidth);
_editNameVisible = (buttonLeft + _editName->width() + st::settingsButtonSkip <= newWidth);
_editName->setVisible(_editNameVisible);
@ -139,9 +139,9 @@ void CoverWidget::refreshNameGeometry(int newWidth) {
int marginsAdd = st::settingsNameLabel.margin.left() + st::settingsNameLabel.margin.right();
_name->resizeToWidth(qMin(nameWidth - marginsAdd, _name->naturalWidth()) + marginsAdd);
_name->moveToLeft(nameLeft, nameTop);
_name->moveToLeft(nameLeft, nameTop, newWidth);
_editNameInline->moveToLeft(nameLeft + _name->width(), nameTop);
_editNameInline->moveToLeft(nameLeft + _name->width(), nameTop, newWidth);
_editNameInline->setVisible(editNameInlineVisible);
}

View File

@ -45,7 +45,7 @@ QString currentVersion() {
result += " alpha";
}
if (cBetaVersion()) {
result += qsl(" beta %1").arg(cBetaVersion());
result += qsl(" beta %1").arg(cBetaVersion() % 1000);
}
return result;
}
@ -83,10 +83,10 @@ int UpdateStateRow::resizeGetHeight(int newWidth) {
auto restartLeft = labelWidth(lang(lng_settings_update_ready));
_check->resizeToWidth(qMin(newWidth, _check->naturalWidth()));
_check->moveToLeft(checkLeft, 0);
_check->moveToLeft(checkLeft, 0, newWidth);
_restart->resizeToWidth(qMin(newWidth, _restart->naturalWidth()));
_restart->moveToLeft(restartLeft, 0);
_restart->moveToLeft(restartLeft, 0, newWidth);
return _check->height();
}
@ -112,6 +112,7 @@ void UpdateStateRow::paintEvent(QPaintEvent *e) {
void UpdateStateRow::onCheck() {
if (!cAutoUpdate()) return;
setState(State::Check);
cSetLastUpdateCheck(0);
Sandbox::startUpdateCheck();
}
@ -120,11 +121,11 @@ void UpdateStateRow::setState(State state, bool force) {
if (_state != state || force) {
_state = state;
switch (state) {
case State::None:
case State::Latest: _check->show(); _restart->hide(); break;
case State::None: _check->show(); _restart->hide(); break;
case State::Ready: _check->hide(); _restart->show(); break;
case State::Check:
case State::Download:
case State::Latest:
case State::Fail: _check->hide(); _restart->hide(); break;
}
resizeToWidth(width());
@ -167,7 +168,7 @@ void UpdateStateRow::onFailed() {
#endif // TDESKTOP_DISABLE_AUTOUPDATE
GeneralWidget::GeneralWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_general))
, _changeLanguage(this, lang(lng_settings_change_lang)) {
, _changeLanguage(this, lang(lng_settings_change_lang), st::defaultBoxLinkButton) {
connect(_changeLanguage, SIGNAL(clicked()), this, SLOT(onChangeLanguage()));
subscribe(Global::RefChooseCustomLang(), [this]() { chooseCustomLang(); });
FileDialog::registerObserver(this, &GeneralWidget::notifyFileQueryUpdated);
@ -175,7 +176,7 @@ GeneralWidget::GeneralWidget(QWidget *parent, UserData *self) : BlockWidget(pare
}
int GeneralWidget::resizeGetHeight(int newWidth) {
_changeLanguage->moveToRight(contentLeft(), st::settingsBlockMarginTop + st::settingsBlockTitleTop + st::settingsBlockTitleFont->ascent - st::btnDefLink.font->ascent);
_changeLanguage->moveToRight(contentLeft(), st::settingsBlockMarginTop + st::settingsBlockTitleTop + st::settingsBlockTitleFont->ascent - st::btnDefLink.font->ascent, newWidth);
return BlockWidget::resizeGetHeight(newWidth);
}
@ -187,7 +188,7 @@ void GeneralWidget::refreshControls() {
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
addChildRow(_updateAutomatically, marginSub, lng_settings_update_automatically(lt_version, currentVersion()), SLOT(onUpdateAutomatically()), cAutoUpdate());
style::margins marginLink(st::defaultCheckbox.textPosition.x(), 0, 0, st::settingsSkip);
style::margins marginLink(st::defaultBoxCheckbox.textPosition.x(), 0, 0, st::settingsSkip);
addChildRow(_updateRow, marginLink, slidedPadding);
connect(_updateRow->entity(), SIGNAL(restart()), this, SLOT(onRestart()));
#endif // TDESKTOP_DISABLE_AUTOUPDATE

View File

@ -45,6 +45,9 @@ void InfoWidget::createControls() {
addChildRow(_mobileNumber, margin, slidedPadding);
addChildRow(_username, margin, slidedPadding);
addChildRow(_link, margin, slidedPadding);
if (self()->username.isEmpty()) {
_link->hideFast();
}
refreshControls();
}
@ -75,7 +78,7 @@ void InfoWidget::refreshUsername() {
usernameText.text = '@' + self()->username;
copyText = lang(lng_context_copy_mention);
}
usernameText.entities.push_back(EntityInText(EntityInTextCustomUrl, 0, usernameText.text.size()));
usernameText.entities.push_back(EntityInText(EntityInTextCustomUrl, 0, usernameText.text.size(), qsl("https://telegram.me/") + self()->username));
setLabeledText(_username, lang(lng_profile_username), usernameText, TextWithEntities(), copyText);
if (auto text = _username->entity()->textLabel()) {
text->setClickHandlerHook(func(this, &InfoWidget::usernameClickHandlerHook));
@ -106,10 +109,6 @@ bool InfoWidget::usernameClickHandlerHook(const ClickHandlerPtr &handler, Qt::Mo
return false;
}
InfoWidget::LabeledWidget::LabeledWidget(QWidget *parent) : TWidget(parent) {
resize(width(), st::labelDefFlat.font->height);
}
void InfoWidget::setLabeledText(ChildWidget<LabeledWrap> &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString &copyText) {
if (textWithEntities.text.isEmpty()) {
row->slideUp();
@ -119,6 +118,9 @@ void InfoWidget::setLabeledText(ChildWidget<LabeledWrap> &row, const QString &la
}
}
InfoWidget::LabeledWidget::LabeledWidget(QWidget *parent) : TWidget(parent) {
}
void InfoWidget::LabeledWidget::setLabeledText(const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString &copyText) {
_label.destroy();
_text.destroy();
@ -129,6 +131,7 @@ void InfoWidget::LabeledWidget::setLabeledText(const QString &label, const TextW
_label->show();
setLabelText(_text, textWithEntities, copyText);
setLabelText(_shortText, shortTextWithEntities, copyText);
resizeToWidth(width());
}
void InfoWidget::LabeledWidget::setLabelText(ChildWidget<FlatLabel> &text, const TextWithEntities &textWithEntities, const QString &copyText) {
@ -161,7 +164,7 @@ void InfoWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
int InfoWidget::LabeledWidget::naturalWidth() const {
if (!_text) return -1;
return _label->naturalWidth() + st::normalFont->spacew + (_shortText ? _shortText : _text)->naturalWidth();
return _label->naturalWidth() + st::normalFont->spacew + _text->naturalWidth();
}
int InfoWidget::LabeledWidget::resizeGetHeight(int newWidth) {
@ -170,7 +173,7 @@ int InfoWidget::LabeledWidget::resizeGetHeight(int newWidth) {
if (!_label) return 0;
_label->moveToLeft(0, st::settingsBlockOneLineTextPart.margin.top());
_label->moveToLeft(0, st::settingsBlockOneLineTextPart.margin.top(), newWidth);
auto labelNatural = _label->naturalWidth();
t_assert(labelNatural >= 0);
@ -186,10 +189,10 @@ int InfoWidget::LabeledWidget::resizeGetHeight(int newWidth) {
textWidth = -(marginLeft + marginRight);
}
_text->resizeToWidth(textWidth + marginLeft + marginRight);
_text->moveToLeft(textLeft - marginLeft, 0);
_text->moveToLeft(textLeft - marginLeft, 0, newWidth);
if (_shortText) {
_shortText->resizeToWidth(textWidth + marginLeft + marginRight);
_shortText->moveToLeft(textLeft - marginLeft, 0);
_shortText->moveToLeft(textLeft - marginLeft, 0, newWidth);
if (doesNotFit) {
_shortText->show();
_text->hide();

View File

@ -102,25 +102,25 @@ int InnerWidget::resizeGetHeight(int newWidth) {
block->resizeToWidth(newWidth);
}
int result = refreshBlocksPositions();
int result = refreshBlocksPositions(newWidth);
return result;
}
int InnerWidget::refreshBlocksPositions() {
int InnerWidget::refreshBlocksPositions(int newWidth) {
int result = (_cover ? _cover->height() : 0) + st::settingsBlocksTop;
for_const (auto block, _blocks) {
if (block->isHidden()) {
continue;
}
block->moveToLeft(0, result);
block->moveToLeft(0, result, newWidth);
result += block->height();
}
return result;
}
void InnerWidget::onBlockHeightUpdated() {
int newHeight = refreshBlocksPositions();
int newHeight = refreshBlocksPositions(width());
if (newHeight != height()) {
resize(width(), newHeight);
emit heightUpdated();

View File

@ -57,7 +57,7 @@ private:
void refreshBlocks();
// Returns the new height value.
int refreshBlocksPositions();
int refreshBlocksPositions(int newWidth);
ChildWidget<CoverWidget> _cover = { nullptr };
QList<BlockWidget*> _blocks;

View File

@ -45,7 +45,7 @@ NotificationsWidget::NotificationsWidget(QWidget *parent, UserData *self) : Bloc
}
void NotificationsWidget::createControls() {
style::margins margin(0, 0, 0, st::settingsSmallSkip);
style::margins margin(0, 0, 0, st::settingsSkip);
style::margins slidedPadding(0, margin.bottom() / 2, 0, margin.bottom() - (margin.bottom() / 2));
addChildRow(_desktopNotifications, margin, lang(lng_settings_desktop_notify), SLOT(onDesktopNotifications()), Global::DesktopNotify());
addChildRow(_showSenderName, margin, slidedPadding, lang(lng_settings_show_name), SLOT(onShowSenderName()), Global::NotifyView() <= dbinvShowName);

View File

@ -21,32 +21,181 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "settings/settings_privacy_widget.h"
#include "ui/widgets/widget_slide_wrap.h"
#include "styles/style_settings.h"
#include "lang.h"
#include "application.h"
#include "boxes/sessionsbox.h"
#include "boxes/passcodebox.h"
#include "boxes/autolockbox.h"
#include "pspecific.h"
namespace Settings {
PrivacyWidget::PrivacyWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_privacy)) {
refreshControls();
LocalPasscodeState::LocalPasscodeState(QWidget *parent) : TWidget(parent)
, _edit(this, lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on), st::defaultBoxLinkButton)
, _turnOff(this, lang(lng_passcode_turn_off), st::defaultBoxLinkButton) {
updateControls();
connect(_edit, SIGNAL(clicked()), this, SLOT(onEdit()));
connect(_turnOff, SIGNAL(clicked()), this, SLOT(onTurnOff()));
subscribe(Global::RefLocalPasscodeChanged(), [this]() { updateControls(); });
}
void PrivacyWidget::refreshControls() {
int LocalPasscodeState::resizeGetHeight(int newWidth) {
_edit->moveToLeft(0, 0, newWidth);
_turnOff->moveToRight(0, 0, newWidth);
return _edit->height();
}
void LocalPasscodeState::onEdit() {
Ui::showLayer(new PasscodeBox());
}
void LocalPasscodeState::onTurnOff() {
Ui::showLayer(new PasscodeBox(true));
}
void LocalPasscodeState::updateControls() {
_edit->setText(lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on));
_edit->moveToLeft(0, 0);
_turnOff->setVisible(Global::LocalPasscode());
}
CloudPasswordState::CloudPasswordState(QWidget *parent) : TWidget(parent)
, _edit(this, lang(lng_cloud_password_set), st::defaultBoxLinkButton)
, _turnOff(this, lang(lng_passcode_turn_off), st::defaultBoxLinkButton) {
_turnOff->hide();
connect(_edit, SIGNAL(clicked()), this, SLOT(onEdit()));
connect(_turnOff, SIGNAL(clicked()), this, SLOT(onTurnOff()));
Sandbox::connect(SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(onReloadPassword(Qt::ApplicationState)));
onReloadPassword();
}
int CloudPasswordState::resizeGetHeight(int newWidth) {
_edit->moveToLeft(0, 0, newWidth);
_turnOff->moveToRight(0, 0, newWidth);
return _edit->height();
}
void CloudPasswordState::onEdit() {
PasscodeBox *box = new PasscodeBox(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint);
connect(box, SIGNAL(reloadPassword()), this, SLOT(onReloadPassword()));
Ui::showLayer(box);
}
void CloudPasswordState::onTurnOff() {
if (_curPasswordSalt.isEmpty()) {
_turnOff->hide();
MTPDaccount_passwordInputSettings::Flags flags = MTPDaccount_passwordInputSettings::Flag::f_email;
MTPaccount_PasswordInputSettings settings(MTP_account_passwordInputSettings(MTP_flags(flags), MTP_bytes(QByteArray()), MTP_bytes(QByteArray()), MTP_string(QString()), MTP_string(QString())));
MTP::send(MTPaccount_UpdatePasswordSettings(MTP_bytes(QByteArray()), settings), rpcDone(&CloudPasswordState::offPasswordDone), rpcFail(&CloudPasswordState::offPasswordFail));
} else {
PasscodeBox *box = new PasscodeBox(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint, true);
connect(box, SIGNAL(reloadPassword()), this, SLOT(onReloadPassword()));
Ui::showLayer(box);
}
}
void CloudPasswordState::onReloadPassword(Qt::ApplicationState state) {
if (state == Qt::ApplicationActive) {
MTP::send(MTPaccount_GetPassword(), rpcDone(&CloudPasswordState::getPasswordDone));
}
}
void CloudPasswordState::getPasswordDone(const MTPaccount_Password &result) {
_waitingConfirm = QString();
switch (result.type()) {
case mtpc_account_noPassword: {
auto &d = result.c_account_noPassword();
_curPasswordSalt = QByteArray();
_hasPasswordRecovery = false;
_curPasswordHint = QString();
_newPasswordSalt = qba(d.vnew_salt);
auto pattern = qs(d.vemail_unconfirmed_pattern);
if (!pattern.isEmpty()) {
_waitingConfirm = lng_cloud_password_waiting(lt_email, pattern);
}
} break;
case mtpc_account_password: {
auto &d = result.c_account_password();
_curPasswordSalt = qba(d.vcurrent_salt);
_hasPasswordRecovery = mtpIsTrue(d.vhas_recovery);
_curPasswordHint = qs(d.vhint);
_newPasswordSalt = qba(d.vnew_salt);
auto pattern = qs(d.vemail_unconfirmed_pattern);
if (!pattern.isEmpty()) {
_waitingConfirm = lng_cloud_password_waiting(lt_email, pattern);
}
} break;
}
_edit->setText(lang(_curPasswordSalt.isEmpty() ? lng_cloud_password_set : lng_cloud_password_edit));
_edit->setVisible(_waitingConfirm.isEmpty());
_turnOff->setVisible(!_waitingConfirm.isEmpty() || !_curPasswordSalt.isEmpty());
update();
_newPasswordSalt.resize(_newPasswordSalt.size() + 8);
memset_rand(_newPasswordSalt.data() + _newPasswordSalt.size() - 8, 8);
}
void CloudPasswordState::paintEvent(QPaintEvent *e) {
Painter p(this);
auto text = st::linkFont->elided(_waitingConfirm, width() - _turnOff->width());
if (!text.isEmpty()) {
p.setPen(st::windowTextFg);
p.setFont(st::boxTextFont);
p.drawTextLeft(0, 0, width(), text);
}
}
void CloudPasswordState::offPasswordDone(const MTPBool &result) {
onReloadPassword();
}
bool CloudPasswordState::offPasswordFail(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
onReloadPassword();
return true;
}
PrivacyWidget::PrivacyWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_privacy)) {
createControls();
subscribe(Global::RefLocalPasscodeChanged(), [this]() { autoLockUpdated(); });
}
void PrivacyWidget::createControls() {
style::margins marginSmall(0, 0, 0, st::settingsSmallSkip);
style::margins marginSkip(0, 0, 0, st::settingsSkip);
style::margins slidedPadding(0, marginSmall.bottom() / 2, 0, marginSmall.bottom() - (marginSmall.bottom() / 2));
addChildRow(_editPasscode, marginSmall, lang(lng_passcode_turn_on), SLOT(onEditPasscode()));
addChildRow(_editPassword, marginSmall, lang(lng_cloud_password_set), SLOT(onEditPassword()));
addChildRow(_localPasscodeState, marginSmall);
auto label = lang(psIdleSupported() ? lng_passcode_autolock_away : lng_passcode_autolock_inactive);
auto value = (Global::AutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, Global::AutoLock() / 60) : lng_passcode_autolock_hours(lt_count, Global::AutoLock() / 3600);
addChildRow(_autoLock, marginSmall, slidedPadding, label, value, LabeledLink::Type::Primary, SLOT(onAutoLock()));
if (!Global::LocalPasscode()) {
_autoLock->hideFast();
}
addChildRow(_cloudPasswordState, marginSmall);
addChildRow(_showAllSessions, marginSmall, lang(lng_settings_show_sessions), SLOT(onShowSessions()));
}
void PrivacyWidget::onEditPasscode() {
void PrivacyWidget::autoLockUpdated() {
if (Global::LocalPasscode()) {
auto value = (Global::AutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, Global::AutoLock() / 60) : lng_passcode_autolock_hours(lt_count, Global::AutoLock() / 3600);
_autoLock->entity()->link()->setText(value);
resizeToWidth(width());
_autoLock->slideDown();
} else {
_autoLock->slideUp();
}
}
void PrivacyWidget::onEditPassword() {
void PrivacyWidget::onAutoLock() {
Ui::showLayer(new AutoLockBox());
}
void PrivacyWidget::onShowSessions() {

View File

@ -21,13 +21,61 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once
#include "settings/settings_block_widget.h"
#include "settings/settings_chat_settings_widget.h"
namespace Settings {
class LocalPasscodeState : public TWidget {
class LocalPasscodeState : public TWidget, public base::Subscriber {
Q_OBJECT
public:
LocalPasscodeState(QWidget *parent);
protected:
int resizeGetHeight(int newWidth) override;
private slots:
void onEdit();
void onTurnOff();
private:
void updateControls();
ChildWidget<LinkButton> _edit;
ChildWidget<LinkButton> _turnOff;
};
class CloudPasswordState : public TWidget {
class CloudPasswordState : public TWidget, private base::Subscriber, public RPCSender {
Q_OBJECT
public:
CloudPasswordState(QWidget *parent);
protected:
int resizeGetHeight(int newWidth) override;
void paintEvent(QPaintEvent *e) override;
private slots:
void onEdit();
void onTurnOff();
void onReloadPassword(Qt::ApplicationState state = Qt::ApplicationActive);
private:
void getPasswordDone(const MTPaccount_Password &result);
void offPasswordDone(const MTPBool &result);
bool offPasswordFail(const RPCError &error);
ChildWidget<LinkButton> _edit;
ChildWidget<LinkButton> _turnOff;
QString _waitingConfirm;
QByteArray _curPasswordSalt;
bool _hasPasswordRecovery = false;
QString _curPasswordHint;
QByteArray _newPasswordSalt;
};
class PrivacyWidget : public BlockWidget {
@ -37,18 +85,16 @@ public:
PrivacyWidget(QWidget *parent, UserData *self);
private slots:
void onEditPasscode();
void onEditPassword();
void onAutoLock();
void onShowSessions();
private:
void refreshControls();
void createControls();
void autoLockUpdated();
//ChildWidget<LocalPasscodeState> _localPasscodeState = { nullptr };
//ChildWidget<Ui::WidgetSlideWrap<LabeledLink>> _autoLock = { nullptr };
//ChildWidget<CloudPasswordState> _cloudPasswordState = { nullptr };
ChildWidget<LinkButton> _editPasscode = { nullptr };
ChildWidget<LinkButton> _editPassword = { nullptr };
ChildWidget<LocalPasscodeState> _localPasscodeState = { nullptr };
ChildWidget<Ui::WidgetSlideWrap<LabeledLink>> _autoLock = { nullptr };
ChildWidget<CloudPasswordState> _cloudPasswordState = { nullptr };
ChildWidget<LinkButton> _showAllSessions = { nullptr };
};

View File

@ -191,9 +191,9 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
, _radial(animation(this, &SettingsInner::step_radial))
// advanced
, _passcodeEdit(this, lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on))
, _passcodeEdit(this, lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on))
, _passcodeTurnOff(this, lang(lng_passcode_turn_off))
, _autoLock(this, (cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600))
, _autoLock(this, /*(cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600)*/"")
, _autoLockText(lang(psIdleSupported() ? lng_passcode_autolock_away : lng_passcode_autolock_inactive) + ' ')
, _autoLockWidth(st::linkFont->width(_autoLockText))
, _passwordEdit(this, lang(lng_cloud_password_set))
@ -665,7 +665,7 @@ void SettingsInner::paintEvent(QPaintEvent *e) {
p.setPen(st::black->p);
if (self()) {
top += _passcodeEdit.height() + st::setLittleSkip;
if (cHasPasscode()) {
if (Global::LocalPasscode()) {
p.drawText(_left, top + st::linkFont->ascent, _autoLockText);
top += _autoLock.height() + st::setLittleSkip;
}
@ -782,7 +782,7 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
if (self()) {
_passcodeEdit.move(_left, top);
_passcodeTurnOff.move(_left + st::setWidth - _passcodeTurnOff.width(), top); top += _passcodeTurnOff.height() + st::setLittleSkip;
if (cHasPasscode()) {
if (Global::LocalPasscode()) {
_autoLock.move(_left + _autoLockWidth, top); top += _autoLock.height() + st::setLittleSkip;
}
_passwordEdit.move(_left, top);
@ -953,8 +953,8 @@ void SettingsInner::updateConnectionType() {
void SettingsInner::passcodeChanged() {
resizeEvent(0);
_passcodeEdit.setText(lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on));
_autoLock.setText((cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600));
//_passcodeEdit.setText(lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on));
//_autoLock.setText((cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600));
// _passwordEdit.setText()
showAll();
}
@ -1165,7 +1165,7 @@ void SettingsInner::showAll() {
// advanced
if (self()) {
_passcodeEdit.show();
if (cHasPasscode()) {
if (Global::LocalPasscode()) {
_autoLock.show();
_passcodeTurnOff.show();
} else {

View File

@ -35,7 +35,7 @@ bool lock_telegram() {
if (App::passcoded()) {
w->passcodeWidget()->onSubmit();
return true;
} else if (cHasPasscode()) {
} else if (Global::LocalPasscode()) {
w->setupPasscode(true);
return true;
}

View File

@ -73,7 +73,7 @@ TitleWidget::TitleWidget(MainWindow *window) : TWidget(window)
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
Sandbox::updatingState() == Application::UpdatingReady ||
#endif
cHasPasscode()
Global::LocalPasscode()
) {
showUpdateBtn();
}
@ -309,7 +309,7 @@ void TitleWidget::showUpdateBtn() {
_close.hide();
return;
}
if (cHasPasscode()) {
if (Global::LocalPasscode()) {
_lock.show();
} else {
_lock.hide();

View File

@ -121,26 +121,36 @@ void FlatButton::paintEvent(QPaintEvent *e) {
p.drawText(r, _text, style::al_top);
}
LinkButton::LinkButton(QWidget *parent, const QString &text, const style::linkButton &st) : Button(parent), _text(text), _st(st) {
LinkButton::LinkButton(QWidget *parent, const QString &text, const style::linkButton &st) : Button(parent)
, _text(text)
, _textWidth(st.font->width(_text))
, _st(st) {
connect(this, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(onStateChange(int, ButtonStateChangeSource)));
resize(_st.font->width(_text), _st.font->height);
resize(_textWidth, _st.font->height);
setCursor(style::cur_pointer);
}
int LinkButton::naturalWidth() const {
return _st.font->width(_text);
return _textWidth;
}
void LinkButton::paintEvent(QPaintEvent *e) {
QPainter p(this);
p.setFont(((_state & StateOver) ? _st.overFont : _st.font)->f);
p.setPen(((_state & StateDown) ? _st.downColor : ((_state & StateOver) ? _st.overColor : _st.color))->p);
p.drawText(0, ((_state & StateOver) ? _st.overFont : _st.font)->ascent, _text);
Painter p(this);
auto &font = ((_state & StateOver) ? _st.overFont : _st.font);
auto &pen = ((_state & StateDown) ? _st.downColor : ((_state & StateOver) ? _st.overColor : _st.color));
p.setFont(font);
p.setPen(pen);
if (_textWidth > width()) {
p.drawText(0, font->ascent, font->elided(_text, width()));
} else {
p.drawText(0, font->ascent, _text);
}
}
void LinkButton::setText(const QString &text) {
_text = text;
resize(_st.font->width(_text), _st.font->height);
_textWidth = _st.font->width(_text);
resize(_textWidth, _st.font->height);
update();
}

View File

@ -82,6 +82,7 @@ public slots:
private:
QString _text;
int _textWidth = 0;
style::linkButton _st;
};

View File

@ -163,6 +163,8 @@
'<(src_loc)/boxes/emojibox.h',
'<(src_loc)/boxes/languagebox.cpp',
'<(src_loc)/boxes/languagebox.h',
'<(src_loc)/boxes/localstoragebox.cpp',
'<(src_loc)/boxes/localstoragebox.h',
'<(src_loc)/boxes/passcodebox.cpp',
'<(src_loc)/boxes/passcodebox.h',
'<(src_loc)/boxes/photocropbox.cpp',