21 #include "ui_profileform.h"
36 #include <QApplication>
40 #include <QFileDialog>
42 #include <QImageReader>
43 #include <QInputDialog>
48 #include <QMessageBox>
49 #include <QMouseEvent>
52 static const QMap<IProfileInfo::SetAvatarResult, QString> SET_AVATAR_ERROR = {
54 ProfileForm::tr(
"Unable to open this file.") },
56 ProfileForm::tr(
"Unable to read this image.") },
58 ProfileForm::tr(
"The supplied image is too large.\nPlease use another image.") },
60 ProfileForm::tr(
"Empty path is unavaliable") },
63 static const QMap<IProfileInfo::RenameResult, QPair<QString, QString>> RENAME_ERROR = {
65 { ProfileForm::tr(
"Failed to rename"),
66 ProfileForm::tr(
"Couldn't rename the profile to \"%1\"") }
69 { ProfileForm::tr(
"Profile already exists"),
70 ProfileForm::tr(
"A profile named \"%1\" already exists.") }
73 { ProfileForm::tr(
"Empty name"),
74 ProfileForm::tr(
"Empty name is unavaliable") }
78 static const QMap<IProfileInfo::SaveResult, QPair<QString, QString>> SAVE_ERROR = {
80 { ProfileForm::tr(
"Location not writable",
"Title of permissions popup"),
81 ProfileForm::tr(
"You do not have permission to write to that location. Choose "
82 "another, or cancel the save dialog.",
"text of permissions popup") },
85 { ProfileForm::tr(
"Failed to save file"),
86 ProfileForm::tr(
"The file you chose could not be saved.") }
89 { ProfileForm::tr(
"Empty path"),
90 ProfileForm::tr(
"Empty path is unavaliable.") }
94 static const QPair<QString, QString> CAN_NOT_CHANGE_PASSWORD = {
95 ProfileForm::tr(
"Couldn't change password"),
96 ProfileForm::tr(
"Couldn't change database password, "
97 "it may be corrupted or use the old password.")
103 , profileInfo{profileInfo}
105 bodyUI =
new Ui::IdentitySettings;
106 bodyUI->setupUi(
this);
108 const uint32_t maxNameLength = tox_max_name_length();
109 const QString toolTip = tr(
"Tox user names cannot exceed %1 characters.").arg(maxNameLength);
110 bodyUI->userNameLabel->setToolTip(toolTip);
111 bodyUI->userName->setMaxLength(
static_cast<int>(maxNameLength));
116 toxId->setToolTip(bodyUI->toxId->toolTip());
118 QVBoxLayout* toxIdGroup = qobject_cast<QVBoxLayout*>(bodyUI->toxGroup->layout());
119 delete toxIdGroup->replaceWidget(bodyUI->toxId, toxId);
120 bodyUI->toxId->hide();
122 bodyUI->qrLabel->setWordWrap(
true);
125 profilePicture->setPixmap(QPixmap(
":/img/contact_dark.svg"));
126 profilePicture->setContextMenuPolicy(Qt::CustomContextMenu);
127 profilePicture->setClickable(
true);
128 profilePicture->setObjectName(
"selfAvatar");
129 profilePicture->installEventFilter(
this);
130 profilePicture->setAccessibleName(
"Profile avatar");
131 profilePicture->setAccessibleDescription(
"Set a profile avatar shown to all contacts");
134 connect(profilePicture, &MaskablePixmapWidget::customContextMenuRequested,
137 QHBoxLayout* publicGrouplayout = qobject_cast<QHBoxLayout*>(bodyUI->publicGroup->layout());
138 publicGrouplayout->insertWidget(0, profilePicture);
139 publicGrouplayout->insertSpacing(1, 7);
141 timer.setInterval(750);
142 timer.setSingleShot(
true);
143 connect(&timer, &QTimer::timeout,
this, [=]() {
144 bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text().replace(
" ✔",
""));
150 profileInfo->connectTo_idChanged(
this, [=](
const ToxId&
id) { setToxId(
id); });
152 connect(bodyUI->statusMessage, &QLineEdit::editingFinished,
158 connect(bodyUI->deletePassButton, &QPushButton::clicked,
160 connect(bodyUI->changePassButton, &QPushButton::clicked,
162 connect(bodyUI->deletePassButton, &QPushButton::clicked,
164 connect(bodyUI->changePassButton, &QPushButton::clicked,
169 profileInfo->connectTo_usernameChanged(
171 [=](
const QString& val) { bodyUI->userName->setText(val); });
172 profileInfo->connectTo_statusMessageChanged(
174 [=](
const QString& val) { bodyUI->statusMessage->setText(val); });
176 for (QComboBox* cb : findChildren<QComboBox*>()) {
177 cb->installEventFilter(
this);
178 cb->setFocusPolicy(Qt::StrongFocus);
188 bodyUI->prFileLabel->setText(tr(
"Current profile: ") + name +
".tox");
201 window()->windowHandle()->alert(0);
210 contentLayout->
mainContent->layout()->addWidget(
this);
214 QString defaultPath = QDir(
Settings::getInstance().getPaths().getSettingsDirPath()).path().trimmed();
215 QString appPath = QApplication::applicationDirPath();
216 QString dirPath = portable ? appPath : defaultPath;
219 tr(
"Current profile location: %1").arg(QString(
"<a href=\"file://%1\">%1</a>").arg(dirPath));
221 bodyUI->dirPrLink->setText(dirPrLink);
222 bodyUI->dirPrLink->setOpenExternalLinks(
true);
223 bodyUI->dirPrLink->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByMouse);
224 bodyUI->dirPrLink->setMaximumSize(
bodyUI->dirPrLink->sizeHint());
225 bodyUI->userName->setFocus();
226 bodyUI->userName->selectAll();
231 if (
object ==
static_cast<QObject*
>(
profilePicture) && event->type() == QEvent::MouseButtonPress) {
232 QMouseEvent* mouseEvent =
static_cast<QMouseEvent*
>(event);
233 if (mouseEvent->button() == Qt::RightButton)
244 const QIcon icon = style()->standardIcon(QStyle::SP_DialogCancelButton);
245 const QAction* removeAction = contextMenu.addAction(icon, tr(
"Remove"));
246 const QAction* selectedItem = contextMenu.exec(pos);
248 if (selectedItem == removeAction) {
257 bodyUI->toxIdLabel->setText(
bodyUI->toxIdLabel->text() +
" ✔");
281 QString idString =
id.toString();
282 static const QString ToxIdColor = QStringLiteral(
"%1"
283 "<span style='color:blue'>%2</span>"
284 "<span style='color:gray'>%3</span>");
285 toxId->setText(ToxIdColor
286 .arg(idString.mid(0, 64))
287 .arg(idString.mid(64, 8))
288 .arg(idString.mid(72, 4)));
293 bodyUI->qrCode->setPixmap(QPixmap::fromImage(
qr->
getImage()->scaledToWidth(150)));
299 for (
auto type : QImageReader::supportedImageFormats()) {
300 res += QString(
"*.%1 ").arg(QString(type));
303 return tr(
"Images (%1)",
"filetype filter").arg(res.left(res.size() - 1));
309 const QString path = QFileDialog::getOpenFileName(Q_NULLPTR, tr(
"Choose a profile picture"),
310 QDir::homePath(), filter,
nullptr);
312 if (path.isEmpty()) {
326 const QString title = tr(
"Rename \"%1\"",
"renaming a profile").arg(cur);
327 const QString name = QInputDialog::getText(
this, title, title +
":");
328 if (name.isEmpty()) {
337 const QPair<QString, QString> error = RENAME_ERROR[result];
346 const QString path = QFileDialog::getSaveFileName(Q_NULLPTR, tr(
"Export profile"), current,
348 tr(
"Tox save file (*.tox)"));
349 if (path.isEmpty()) {
358 const QPair<QString, QString> error = SAVE_ERROR[result];
364 const QString title = tr(
"Delete profile",
"deletion confirmation title");
365 const QString question = tr(
"Are you sure you want to delete this profile?",
366 "deletion confirmation text");
372 if (manualDeleteFiles.empty()) {
377 QString
message = tr(
"The following files could not be deleted:") +
"\n\n";
378 for (
const QString&
file : manualDeleteFiles) {
383 message +=
"\n" + tr(
"Please manually remove them.");
396 bodyUI->changePassButton->setText(tr(
"Change password",
"button text"));
397 bodyUI->deletePassButton->setVisible(
true);
399 bodyUI->changePassButton->setText(tr(
"Set profile password",
"button text"));
400 bodyUI->deletePassButton->setVisible(
false);
412 const QString path = QFileDialog::getSaveFileName(
413 Q_NULLPTR, tr(
"Save",
"save qr image"), current,
414 tr(
"Save QrCode (*.png)",
"save dialog filter"));
415 if (path.isEmpty()) {
424 const QPair<QString, QString> error = SAVE_ERROR[result];
431 GUI::showInfo(tr(
"Nothing to remove"), tr(
"Your profile does not have a password!"));
435 const QString title = tr(
"Remove password",
"deletion confirmation title");
437 const QString body = tr(
"Are you sure you want to remove your password?");
443 GUI::showInfo(CAN_NOT_CHANGE_PASSWORD.first, CAN_NOT_CHANGE_PASSWORD.second);
449 const QString title = tr(
"Please enter a new password.");
451 if (dialog->exec() == QDialog::Rejected) {
457 GUI::showInfo(CAN_NOT_CHANGE_PASSWORD.first, CAN_NOT_CHANGE_PASSWORD.second);
463 bodyUI->retranslateUi(
this);
467 toxId->setToolTip(tr(
"This ID allows other Tox users to add and contact you.\n"
468 "Share it with your friends to begin chatting.\n\n"
469 "This ID includes the NoSpam code (in blue), and the checksum (in gray)."));