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)."));