/* * Copyright (C) 2012 Felix Geyer * Copyright (C) 2017 KeePassXC Team * * This program 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 2 or (at your option) * version 3 of the License. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "DetailsWidget.h" #include "ui_DetailsWidget.h" #include #include "core/Config.h" #include "core/FilePath.h" #include "core/TimeInfo.h" #include "gui/Clipboard.h" #include "gui/DatabaseWidget.h" DetailsWidget::DetailsWidget(QWidget* parent) : QWidget(parent) , m_ui(new Ui::DetailsWidget()) , m_locked(false) , m_currentEntry(nullptr) , m_currentGroup(nullptr) { m_ui->setupUi(this); connect(parent, SIGNAL(pressedEntry(Entry*)), SLOT(getSelectedEntry(Entry*))); connect(parent, SIGNAL(pressedGroup(Group*)), SLOT(getSelectedGroup(Group*))); connect(parent, SIGNAL(currentModeChanged(DatabaseWidget::Mode)), SLOT(setDatabaseMode(DatabaseWidget::Mode))); m_ui->totpButton->setIcon(filePath()->icon("actions", "chronometer")); m_ui->closeButton->setIcon(filePath()->icon("actions", "dialog-close")); connect(m_ui->totpButton, SIGNAL(toggled(bool)), SLOT(showTotp(bool))); connect(m_ui->closeButton, SIGNAL(toggled(bool)), SLOT(hideDetails())); this->hide(); } DetailsWidget::~DetailsWidget() { } void DetailsWidget::getSelectedEntry(Entry* selectedEntry) { m_currentEntry = selectedEntry; if (!config()->get("GUI/HideDetailsView").toBool()) { this->show(); } m_ui->stackedWidget->setCurrentIndex(EntryPreview); m_ui->tabWidget->setTabEnabled(AttributesTab, false); m_ui->tabWidget->setTabEnabled(NotesTab, false); m_ui->totpButton->hide(); m_ui->totpWidget->hide(); m_ui->totpButton->setChecked(false); auto icon = m_currentEntry->iconPixmap(); if (icon.width() > 16 || icon.height() > 16) { icon = icon.scaled(16, 16); } m_ui->entryIcon->setPixmap(icon); QString title = QString(" / "); Group* entry_group = m_currentEntry->group(); if (entry_group) { QStringList hierarchy = entry_group->hierarchy(); hierarchy.removeFirst(); title += hierarchy.join(" / "); if (hierarchy.size() > 0) { title += " / "; } } title.append(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->title())); m_ui->titleLabel->setText(title); m_ui->usernameLabel->setText(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->username())); if (!config()->get("security/hidepassworddetails").toBool()) { m_ui->passwordLabel->setText(shortPassword(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->password()))); m_ui->passwordLabel->setToolTip(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->password())); } else { m_ui->passwordLabel->setText("****"); } QString url = m_currentEntry->webUrl(); if (url != "") { url = QString("%2").arg(url).arg(shortUrl(url)); m_ui->urlLabel->setOpenExternalLinks(true); } else { url = shortUrl(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->url())); m_ui->urlLabel->setOpenExternalLinks(false); } m_ui->urlLabel->setText(url); TimeInfo entryTime = m_currentEntry->timeInfo(); if (entryTime.expires()) { m_ui->expirationLabel->setText(entryTime.expiryTime().toString(Qt::DefaultLocaleShortDate)); } else { m_ui->expirationLabel->setText(tr("Never")); } if (m_currentEntry->hasTotp()) { m_ui->totpButton->show(); updateTotp(); m_step = m_currentEntry->totpStep(); m_timer = new QTimer(this); connect(m_timer, SIGNAL(timeout()), this, SLOT(updateTotp())); m_timer->start(m_step * 10); } QString notes = m_currentEntry->notes(); if (!notes.isEmpty()) { m_ui->tabWidget->setTabEnabled(NotesTab, true); m_ui->notesEdit->setText(m_currentEntry->resolveMultiplePlaceholders(notes)); } QStringList customAttributes = m_currentEntry->attributes()->customKeys(); if (customAttributes.size() > 0) { m_ui->tabWidget->setTabEnabled(AttributesTab, true); m_ui->attributesEdit->clear(); QString attributesText = QString(); for (const QString& key : customAttributes) { QString value = m_currentEntry->attributes()->value(key); if (m_currentEntry->attributes()->isProtected(key)) { value = "[PROTECTED]"; } attributesText.append(QString("%1: %2
").arg(key, value)); } m_ui->attributesEdit->setText(attributesText); } } void DetailsWidget::getSelectedGroup(Group* selectedGroup) { m_currentGroup = selectedGroup; if (!config()->get("GUI/HideDetailsView").toBool()) { this->show(); } m_ui->stackedWidget->setCurrentIndex(GroupPreview); m_ui->tabWidget->setTabEnabled(AttributesTab, false); m_ui->tabWidget->setTabEnabled(NotesTab, false); m_ui->totpButton->hide(); m_ui->totpWidget->hide(); auto icon = m_currentGroup->iconPixmap(); if (icon.width() > 32 || icon.height() > 32) { icon = icon.scaled(32, 32); } m_ui->entryIcon->setPixmap(icon); QString title = " / "; QStringList hierarchy = m_currentGroup->hierarchy(); hierarchy.removeFirst(); title += hierarchy.join(" / "); if (hierarchy.size() > 0) { title += " / "; } m_ui->titleLabel->setText(title); m_ui->notesEdit->setText(m_currentGroup->notes()); QString searching = tr("Disabled"); if (m_currentGroup->resolveSearchingEnabled()) { searching = tr("Enabled"); } m_ui->searchingLabel->setText(searching); QString autotype = tr("Disabled"); if (m_currentGroup->resolveAutoTypeEnabled()) { autotype = tr("Enabled"); } m_ui->autotypeLabel->setText(autotype); TimeInfo groupTime = m_currentGroup->timeInfo(); if (groupTime.expires()) { m_ui->groupExpirationLabel->setText(groupTime.expiryTime().toString(Qt::DefaultLocaleShortDate)); } else { m_ui->groupExpirationLabel->setText(tr("Never")); } m_ui->groupCreationLabel->setText(groupTime.creationTime().toString(Qt::DefaultLocaleShortDate)); m_ui->groupModifyLabel->setText(groupTime.lastModificationTime().toString(Qt::DefaultLocaleShortDate)); m_ui->groupAccessLabel->setText(groupTime.lastAccessTime().toString(Qt::DefaultLocaleShortDate)); } void DetailsWidget::updateTotp() { if (m_locked) { m_timer->stop(); return; } QString totpCode = m_currentEntry->totp(); QString firstHalf = totpCode.left(totpCode.size()/2); QString secondHalf = totpCode.right(totpCode.size()/2); m_ui->totpLabel->setText(firstHalf + " " + secondHalf); } void DetailsWidget::showTotp(bool visible) { if (visible){ m_ui->totpWidget->show(); } else { m_ui->totpWidget->hide(); } } QString DetailsWidget::shortUrl(QString url) { QString newurl = ""; if (url.length() > 60) { newurl.append(url.left(20)); newurl.append("..."); newurl.append(url.right(20)); return newurl; } return url; } QString DetailsWidget::shortPassword(QString password) { QString newpassword = ""; if (password.length() > 60) { newpassword.append(password.left(50)); newpassword.append("..."); return newpassword; } return password; } void DetailsWidget::hideDetails() { this->hide(); } void DetailsWidget::setDatabaseMode(DatabaseWidget::Mode mode) { m_locked = false; if (mode == DatabaseWidget::LockedMode) { m_locked = true; return; } if (mode == DatabaseWidget::ViewMode) { if (m_ui->stackedWidget->currentIndex() == GroupPreview) { getSelectedGroup(m_currentGroup); } else { getSelectedEntry(m_currentEntry); } } } void DetailsWidget::copyToClipboard(const QString& text) { clipboard()->setText(text); }