From 1a87e30b95f0cda7b31e641a79ffc5bb46fb7521 Mon Sep 17 00:00:00 2001 From: thez3ro Date: Thu, 17 Aug 2017 21:02:21 +0200 Subject: [PATCH 01/10] add preview panel for entries and groups --- COPYING | 1 + .../application/22x22/actions/chronometer.png | Bin 0 -> 1675 bytes src/CMakeLists.txt | 1 + src/core/Group.cpp | 12 + src/core/Group.h | 1 + src/gui/DatabaseWidget.cpp | 46 +- src/gui/DatabaseWidget.h | 9 + src/gui/DetailsWidget.cpp | 213 +++++++ src/gui/DetailsWidget.h | 60 ++ src/gui/DetailsWidget.ui | 552 ++++++++++++++++++ src/gui/SettingsWidget.cpp | 4 + src/gui/SettingsWidgetGeneral.ui | 7 + src/gui/SettingsWidgetSecurity.ui | 7 + src/gui/entry/EntryView.cpp | 7 + src/gui/entry/EntryView.h | 2 + src/gui/group/GroupView.cpp | 7 + src/gui/group/GroupView.h | 2 + 17 files changed, 930 insertions(+), 1 deletion(-) create mode 100644 share/icons/application/22x22/actions/chronometer.png create mode 100644 src/gui/DetailsWidget.cpp create mode 100644 src/gui/DetailsWidget.h create mode 100644 src/gui/DetailsWidget.ui diff --git a/COPYING b/COPYING index 403e4564..e12f4534 100644 --- a/COPYING +++ b/COPYING @@ -156,6 +156,7 @@ License: LGPL-2.1 Comment: based on Nuvola icon theme Files: share/icons/application/*/actions/application-exit.png + share/icons/application/*/actions/chronometer.png share/icons/application/*/actions/configure.png share/icons/application/*/actions/dialog-close.png share/icons/application/*/actions/dialog-ok.png diff --git a/share/icons/application/22x22/actions/chronometer.png b/share/icons/application/22x22/actions/chronometer.png new file mode 100644 index 0000000000000000000000000000000000000000..71d6eabe5f7447958918c8c5d73ab060ada1d78c GIT binary patch literal 1675 zcmV;626Xv}P)izt!0M$-mqryuIZXgCJUomu zXU+fsMn*=qWipvpqmk$@HBI}jBuTJs8=U))BpI?Sqf{!bRjQRs%Z23+BC+U?+IH@| zOuqlmpc?%7KPEo@P9~Fa=){Q=IDh^;0N~uYbKTE(KR>j6`}Q~LjXLJ%=doHW@}}d! z_gpZ>5DrJs)wQ2mTU%im#)BvNleulN=#fw;99~??U!IwpU2z=e>i?oRd-iPip}s?x z6N$vZnb{dU-q=7(D#c}4rbHqE-}h0iR{7%6B0YJc^JqLy2M>M^j4>>HHE*O^w0qfX zwz#~qd~;-EMlc=+lVxIzk)kM2Rh3-VMIfM(CJ0+OucRCwK1Lv5voc9LzLL zwQXnHdzNKEmPB-ScT+GJguocobQ=2H9KrKIw3!+sf@RyVZ5zG4z0{iCfl_G$?d|Qa zA2@KJ2LN3hy$EKSW`9ddOEQ7K_FDi3qOi!frOH-e{0x7_be4+-4Ik zFTYHWu3sl55TN^0Q}8^GlF1}gRV7A5oOAe|M?`?E$bH9ta%^)lNs=;+Mg#F!44S6# zfU0si97Zr2<-|E+ZEgHNw{G#@zw-`{gu~diYZqsXfrvO01fEPLvAd&#bI(UC7W>wP zKmK93tE+2*d9J5gjRqKFV1huRD3YYA5EO-ES%x48^l)*JjPY^O(rM79o~=Yg2&gI% zW2l+6z*0WnpUdUqVx?MHw`?1p=YRkZ08tPCL4YJlxP9{`Ub}Ds=0_hPBFg|{ApU<< z0n4%wjzqCiTv?l(oP3FhG;w`>eNxx;pP8nCjZz6gRpo(T5a1lH=iyLa9{`|!>J;2& z69H8P-@Gw6=iD?+lq(fPqA^q|m8l~~j>rHCtXwYtYiVf-qA1e(`Z|wq+XmNhU|SX^ z0GxAfSr+$2k$bWX5OLr4Vb*F~k|fBojCefGv)L?aX6^d)^t1&4Y)5*>SGmR9gyXpQ z^!9D4R4QZ`26V$9P6T3%h%s_>og`6&@B8F)j&iw7^?IGMxg0#tr))O+=+XM4e-{b` z2LOa>rAmsdEHK87sllLJE|>YPjt->LX)r<9{1}`=4hBJj09oE_xJWpRnVA_lu1C7A zV_{)ocgp=Wl?wTuhgz+MjZz8OY?g|}BCLi*Yinzmnwq+D@BY1CUA=O34FEJv z!~Fa_XzR0SZ*P}0O*^b<+HX2KI(ql+-3v|A5DJALZsrTivQVv5kG878+CzHuHT3cIRNF)+1vLvJFG|f_}G`+gI`boW3|9ifW zU$t$!{3z{x5B` V=tXj1`11e&002ovPDHLkV1fyI8=(LI literal 0 HcmV?d00001 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3f0ba782..97ff5edf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -98,6 +98,7 @@ set(keepassx_SOURCES gui/DatabaseTabWidget.cpp gui/DatabaseWidget.cpp gui/DatabaseWidgetStateSync.cpp + gui/DetailsWidget.cpp gui/DialogyWidget.cpp gui/DragTabBar.cpp gui/EditWidget.cpp diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 644d2ff6..fa48d8ce 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -435,6 +435,18 @@ void Group::setParent(Database* db) QObject::setParent(db); } +QStringList Group::hierarchy() +{ + QStringList hierarchy; + Group* group = this; + while (group->parentGroup()) { + hierarchy << group->name(); + + group = group->parentGroup(); + } + return hierarchy; +} + Database* Group::database() { return m_db; diff --git a/src/core/Group.h b/src/core/Group.h index 27400703..2a9d2b18 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -106,6 +106,7 @@ public: Group* parentGroup(); const Group* parentGroup() const; void setParent(Group* parent, int index = -1); + QStringList hierarchy(); Database* database(); const Database* database() const; diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 6a425b5d..0b83002e 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -47,6 +47,7 @@ #include "gui/TotpDialog.h" #include "gui/DatabaseOpenWidget.h" #include "gui/DatabaseSettingsWidget.h" +#include "gui/DetailsWidget.h" #include "gui/KeePass1OpenWidget.h" #include "gui/MessageBox.h" #include "gui/UnlockDatabaseWidget.h" @@ -74,6 +75,9 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) mainLayout->addLayout(layout); m_splitter = new QSplitter(m_mainWidget); m_splitter->setChildrenCollapsible(false); + m_detailSplitter = new QSplitter(m_mainWidget); + m_detailSplitter->setOrientation(Qt::Vertical); + m_detailSplitter->setChildrenCollapsible(true); QWidget* rightHandSideWidget = new QWidget(m_splitter); @@ -99,10 +103,18 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) "border: 2px solid rgb(190, 190, 190);" "border-radius: 5px;"); + m_detailsView = new DetailsWidget(this); + QVBoxLayout* vLayout = new QVBoxLayout(rightHandSideWidget); vLayout->setMargin(0); vLayout->addWidget(m_searchingLabel); - vLayout->addWidget(m_entryView); + vLayout->addWidget(m_detailSplitter); + + m_detailSplitter->addWidget(m_entryView); + m_detailSplitter->addWidget(m_detailsView); + + m_detailSplitter->setStretchFactor(0, 80); + m_detailSplitter->setStretchFactor(1, 20); m_searchingLabel->setVisible(false); @@ -180,6 +192,12 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) connect(&m_fileWatchUnblockTimer, SIGNAL(timeout()), this, SLOT(unblockAutoReload())); connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged())); + connect(m_groupView, SIGNAL(groupPressed(Group*)), SLOT(emitPressedGroup(Group*))); + //connect(m_groupView, SIGNAL(groupChanged(Group*)), SLOT(emitPressedGroup(Group*))); + connect(m_entryView, SIGNAL(entryPressed(Entry*)), SLOT(emitPressedEntry(Entry*))); + //connect(m_entryView, SIGNAL(entrySelectionChanged()), SLOT(emitPressedEntry())); + connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(emitPressedEntry())); + m_databaseModified = false; m_fileWatchTimer.setSingleShot(true); @@ -1041,6 +1059,32 @@ void DatabaseWidget::emitEntryContextMenuRequested(const QPoint& pos) emit entryContextMenuRequested(m_entryView->viewport()->mapToGlobal(pos)); } +void DatabaseWidget::emitPressedEntry() +{ + Entry* currentEntry = m_entryView->currentEntry(); + emitPressedEntry(currentEntry); +} + +void DatabaseWidget::emitPressedEntry(Entry* currentEntry) +{ + if (!currentEntry) { + // if no entry is pressed, leave in details the last entry + return; + } + + emit pressedEntry(currentEntry); +} + +void DatabaseWidget::emitPressedGroup(Group* currentGroup) +{ + if (!currentGroup) { + // if no group is pressed, leave in details the last group + return; + } + + emit pressedGroup(currentGroup); +} + bool DatabaseWidget::dbHasKey() const { return m_db->hasKey(); diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 93482000..141248bd 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -27,6 +27,7 @@ #include "core/Uuid.h" #include "gui/entry/EntryModel.h" +#include "gui/DetailsWidget.h" #include "gui/MessageWidget.h" #include "gui/csvImport/CsvImportWizard.h" @@ -47,6 +48,7 @@ class QSplitter; class QLabel; class UnlockDatabaseWidget; class MessageWidget; +class DetailsWidget; class UnlockDatabaseDialog; class QFileSystemWatcher; @@ -115,6 +117,8 @@ signals: void databaseMerged(Database* mergedDb); void groupContextMenuRequested(const QPoint& globalPos); void entryContextMenuRequested(const QPoint& globalPos); + void pressedEntry(Entry* selectedEntry); + void pressedGroup(Group* selectedGroup); void unlockedDatabase(); void listModeAboutToActivate(); void listModeActivated(); @@ -179,6 +183,9 @@ private slots: void switchToGroupEdit(Group* entry, bool create); void emitGroupContextMenuRequested(const QPoint& pos); void emitEntryContextMenuRequested(const QPoint& pos); + void emitPressedEntry(); + void emitPressedEntry(Entry* currentEntry); + void emitPressedGroup(Group* currentGroup); void updateMasterKey(bool accepted); void openDatabase(bool accepted); void mergeDatabase(bool accepted); @@ -209,6 +216,7 @@ private: UnlockDatabaseWidget* m_unlockDatabaseWidget; UnlockDatabaseDialog* m_unlockDatabaseDialog; QSplitter* m_splitter; + QSplitter* m_detailSplitter; GroupView* m_groupView; EntryView* m_entryView; QLabel* m_searchingLabel; @@ -219,6 +227,7 @@ private: Uuid m_groupBeforeLock; Uuid m_entryBeforeLock; MessageWidget* m_messageWidget; + DetailsWidget* m_detailsView; // Search state QString m_lastSearchText; diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp new file mode 100644 index 00000000..d506d551 --- /dev/null +++ b/src/gui/DetailsWidget.cpp @@ -0,0 +1,213 @@ +/* + * 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" + +DetailsWidget::DetailsWidget(QWidget* parent) + : QWidget(parent) + , m_ui(new Ui::DetailsWidget()) + , 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*))); + + m_ui->totpButton->setIcon(filePath()->icon("actions", "chronometer")); + m_ui->closeButton->setIcon(filePath()->icon("actions", "dialog-close")); + m_ui->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show")); + + connect(m_ui->totpButton, SIGNAL(toggled(bool)), SLOT(showTotp(bool))); + connect(m_ui->closeButton, SIGNAL(toggled(bool)), SLOT(hideDetails())); + connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), SLOT(togglePasswordShown(bool))); + + 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->totpButton->hide(); + m_ui->totpWidget->hide(); + m_ui->totpButton->setChecked(false); + + m_ui->entryIcon->setPixmap(m_currentEntry->iconPixmap()); + + QStringList hierarchy = m_currentEntry->group()->hierarchy(); + QString title = " / "; + for (QString parent : hierarchy) { + title.append(parent); + title.append(" / "); + } + title.append(m_currentEntry->title()); + m_ui->titleLabel->setText(title); + + m_ui->usernameLabel->setText(m_currentEntry->username()); + m_ui->groupLabel->setText(m_currentEntry->group()->name()); + m_ui->notesEdit->setText(m_currentEntry->notes()); + + if (!config()->get("security/hidepassworddetails").toBool()) { + m_ui->passwordEdit->setText(m_currentEntry->password()); + m_ui->togglePasswordButton->show(); + } else { + m_ui->passwordEdit->setText("****"); + m_ui->togglePasswordButton->hide(); + } + + 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")); + } + + m_ui->creationLabel->setText(entryTime.creationTime().toString(Qt::DefaultLocaleShortDate)); + m_ui->modifyLabel->setText(entryTime.lastModificationTime().toString(Qt::DefaultLocaleShortDate)); + m_ui->accessLabel->setText(entryTime.lastAccessTime().toString(Qt::DefaultLocaleShortDate)); + + 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); + } +} + +void DetailsWidget::getSelectedGroup(Group* selectedGroup) +{ + m_currentGroup = selectedGroup; + + if (!config()->get("GUI/HideDetailsView").toBool()) { + this->show(); + } + + m_ui->stackedWidget->setCurrentIndex(GroupPreview); + + m_ui->totpButton->hide(); + m_ui->totpWidget->hide(); + + m_ui->entryIcon->setPixmap(m_currentGroup->iconPixmap()); + + QStringList hierarchy = m_currentGroup->hierarchy(); + QString title = " / "; + for (QString parent : hierarchy) { + title.append(parent); + title.append(" / "); + } + 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() +{ + 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; +} + +void DetailsWidget::hideDetails() +{ + this->hide(); +} + +void DetailsWidget::togglePasswordShown(bool showing) +{ + m_ui->passwordEdit->setShowPassword(showing); + bool blockSignals = m_ui->togglePasswordButton->blockSignals(true); + m_ui->togglePasswordButton->setChecked(showing); + m_ui->togglePasswordButton->blockSignals(blockSignals); +} \ No newline at end of file diff --git a/src/gui/DetailsWidget.h b/src/gui/DetailsWidget.h new file mode 100644 index 00000000..89e6cf62 --- /dev/null +++ b/src/gui/DetailsWidget.h @@ -0,0 +1,60 @@ +/* + * 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 . + */ + +#ifndef KEEPASSX_DETAILSWIDGET_H +#define KEEPASSX_DETAILSWIDGET_H + +#include + +#include "gui/DatabaseWidget.h" + +namespace Ui { + class DetailsWidget; +} + +class DetailsWidget : public QWidget +{ + Q_OBJECT + +public: + explicit DetailsWidget(QWidget* parent = nullptr); + ~DetailsWidget(); + + enum StackedWidgetIndex + { + EntryPreview = 0, + GroupPreview = 1, + }; + +private slots: + void getSelectedEntry(Entry* selectedEntry); + void getSelectedGroup(Group* selectedGroup); + void showTotp(bool visible); + void updateTotp(); + void hideDetails(); + void togglePasswordShown(bool showing); + +private: + const QScopedPointer m_ui; + Entry* m_currentEntry; + Group* m_currentGroup; + quint8 m_step; + QTimer* m_timer; + QString shortUrl(QString url); +}; + +#endif // KEEPASSX_DETAILSWIDGET_H diff --git a/src/gui/DetailsWidget.ui b/src/gui/DetailsWidget.ui new file mode 100644 index 00000000..fb6b7fb2 --- /dev/null +++ b/src/gui/DetailsWidget.ui @@ -0,0 +1,552 @@ + + + DetailsWidget + + + + 0 + 0 + 630 + 207 + + + + + 0 + 0 + + + + + 16777215 + 235 + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 20 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + + 12 + + + + Qt::AutoText + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + 10 + 75 + true + + + + + + + + + + + + + + Generate TOTP Token + + + + + + true + + + + + + + Generate TOTP Token + + + + + + true + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + 0 + 0 + + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + 75 + true + + + + Group + + + + + + + + 9 + 75 + true + + + + URL + + + + + + + + 75 + true + + + + Password + + + + + + + + 75 + true + + + + Username + + + + + + + + + + + + + + + + 0 + 0 + + + + 999 + + + true + + + + + + + true + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + + + 75 + true + + + + Modification + + + + + + + + 75 + true + + + + Access + + + + + + + + + + + + + + 75 + true + + + + Creation + + + + + + + + 75 + true + + + + Expiration + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + 75 + true + + + + Autotype + + + + + + + + + + + 75 + true + + + + Searching + + + + + + + + + + + 75 + true + + + + Expiration + + + + + + + + + + + + + + 75 + true + + + + Modification + + + + + + + + 75 + true + + + + Access + + + + + + + + + + + + + + 75 + true + + + + Creation + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + 0 + 50 + + + + + 16777215 + 50 + + + + Qt::ClickFocus + + + true + + + + + + + Notes + + + + + + + + + Qt::Horizontal + + + + + + + Search + + + + + Clear + + + + + + PasswordEdit + QLineEdit +
gui/PasswordEdit.h
+ 1 +
+
+ + +
diff --git a/src/gui/SettingsWidget.cpp b/src/gui/SettingsWidget.cpp index 8385bf26..aa0e5664 100644 --- a/src/gui/SettingsWidget.cpp +++ b/src/gui/SettingsWidget.cpp @@ -134,6 +134,7 @@ void SettingsWidget::loadSettings() m_generalUi->languageComboBox->setCurrentIndex(defaultIndex); } + m_generalUi->detailsHideCheckBox->setChecked(config()->get("GUI/HideDetailsView").toBool()); m_generalUi->systrayShowCheckBox->setChecked(config()->get("GUI/ShowTrayIcon").toBool()); m_generalUi->systrayMinimizeToTrayCheckBox->setChecked(config()->get("GUI/MinimizeToTray").toBool()); m_generalUi->systrayMinimizeOnCloseCheckBox->setChecked(config()->get("GUI/MinimizeOnClose").toBool()); @@ -160,6 +161,7 @@ void SettingsWidget::loadSettings() m_secUi->fallbackToGoogle->setChecked(config()->get("security/IconDownloadFallbackToGoogle").toBool()); m_secUi->passwordCleartextCheckBox->setChecked(config()->get("security/passwordscleartext").toBool()); + m_secUi->passwordDetailsCleartextCheckBox->setChecked(config()->get("security/hidepassworddetails").toBool()); m_secUi->passwordRepeatCheckBox->setChecked(config()->get("security/passwordsrepeat").toBool()); @@ -203,6 +205,7 @@ void SettingsWidget::saveSettings() config()->set("GUI/Language", m_generalUi->languageComboBox->itemData(currentLangIndex).toString()); + config()->set("GUI/HideDetailsView", m_generalUi->detailsHideCheckBox->isChecked()); config()->set("GUI/ShowTrayIcon", m_generalUi->systrayShowCheckBox->isChecked()); config()->set("GUI/MinimizeToTray", m_generalUi->systrayMinimizeToTrayCheckBox->isChecked()); config()->set("GUI/MinimizeOnClose", m_generalUi->systrayMinimizeOnCloseCheckBox->isChecked()); @@ -226,6 +229,7 @@ void SettingsWidget::saveSettings() config()->set("security/IconDownloadFallbackToGoogle", m_secUi->fallbackToGoogle->isChecked()); config()->set("security/passwordscleartext", m_secUi->passwordCleartextCheckBox->isChecked()); + config()->set("security/hidepassworddetails", m_secUi->passwordDetailsCleartextCheckBox->isChecked()); config()->set("security/passwordsrepeat", m_secUi->passwordRepeatCheckBox->isChecked()); // Security: clear storage if related settings are disabled diff --git a/src/gui/SettingsWidgetGeneral.ui b/src/gui/SettingsWidgetGeneral.ui index 1e62104c..7dc4487c 100644 --- a/src/gui/SettingsWidgetGeneral.ui +++ b/src/gui/SettingsWidgetGeneral.ui @@ -153,6 +153,13 @@ + + + + Hide the Details view + + + diff --git a/src/gui/SettingsWidgetSecurity.ui b/src/gui/SettingsWidgetSecurity.ui index 4233fdbd..53c69db6 100644 --- a/src/gui/SettingsWidgetSecurity.ui +++ b/src/gui/SettingsWidgetSecurity.ui @@ -136,6 +136,13 @@ + + + + Hide passwords in the preview panel + + + diff --git a/src/gui/entry/EntryView.cpp b/src/gui/entry/EntryView.cpp index 1bdd4fbc..ac8e6678 100644 --- a/src/gui/entry/EntryView.cpp +++ b/src/gui/entry/EntryView.cpp @@ -49,6 +49,8 @@ EntryView::EntryView(QWidget* parent) connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SIGNAL(entrySelectionChanged())); connect(m_model, SIGNAL(switchedToEntryListMode()), SLOT(switchToEntryListMode())); connect(m_model, SIGNAL(switchedToGroupMode()), SLOT(switchToGroupMode())); + + connect(this, SIGNAL(clicked(QModelIndex)), SLOT(emitEntryPressed(QModelIndex))); } void EntryView::keyPressEvent(QKeyEvent* event) @@ -99,6 +101,11 @@ void EntryView::emitEntryActivated(const QModelIndex& index) emit entryActivated(entry, static_cast(m_sortModel->mapToSource(index).column())); } +void EntryView::emitEntryPressed(const QModelIndex& index) +{ + emit entryPressed(entryFromIndex(index)); +} + void EntryView::setModel(QAbstractItemModel* model) { Q_UNUSED(model); diff --git a/src/gui/entry/EntryView.h b/src/gui/entry/EntryView.h index 6a545f62..14c6b7cc 100644 --- a/src/gui/entry/EntryView.h +++ b/src/gui/entry/EntryView.h @@ -47,6 +47,7 @@ public slots: signals: void entryActivated(Entry* entry, EntryModel::ModelColumn column); + void entryPressed(Entry* entry); void entrySelectionChanged(); protected: @@ -54,6 +55,7 @@ protected: private slots: void emitEntryActivated(const QModelIndex& index); + void emitEntryPressed(const QModelIndex& index); void switchToEntryListMode(); void switchToGroupMode(); diff --git a/src/gui/group/GroupView.cpp b/src/gui/group/GroupView.cpp index e9649e44..82d01e31 100644 --- a/src/gui/group/GroupView.cpp +++ b/src/gui/group/GroupView.cpp @@ -41,6 +41,8 @@ GroupView::GroupView(Database* db, QWidget* parent) connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(emitGroupChanged())); + connect(this, SIGNAL(clicked(QModelIndex)), SLOT(emitGroupPressed(QModelIndex))); + modelReset(); setDragEnabled(true); @@ -126,6 +128,11 @@ void GroupView::emitGroupChanged() emit groupChanged(currentGroup()); } +void GroupView::emitGroupPressed(const QModelIndex& index) +{ + emit groupPressed(m_model->groupFromIndex(index)); +} + void GroupView::syncExpandedState(const QModelIndex& parent, int start, int end) { for (int row = start; row <= end; row++) { diff --git a/src/gui/group/GroupView.h b/src/gui/group/GroupView.h index eaa29072..0a084425 100644 --- a/src/gui/group/GroupView.h +++ b/src/gui/group/GroupView.h @@ -38,11 +38,13 @@ public: signals: void groupChanged(Group* group); + void groupPressed(Group* group); private slots: void expandedChanged(const QModelIndex& index); void emitGroupChanged(const QModelIndex& index); void emitGroupChanged(); + void emitGroupPressed(const QModelIndex& index); void syncExpandedState(const QModelIndex& parent, int start, int end); void modelReset(); From 0e6fedc056f2f03400a3048c71c2faefd278f2df Mon Sep 17 00:00:00 2001 From: thez3ro Date: Thu, 31 Aug 2017 00:52:05 +0200 Subject: [PATCH 02/10] fix group parent, add details update by keyboard --- src/core/Group.cpp | 10 +++++--- src/gui/DatabaseWidget.cpp | 4 +-- src/gui/DetailsWidget.cpp | 52 ++++++++++++++++++++++---------------- src/gui/DetailsWidget.h | 2 +- src/gui/DetailsWidget.ui | 38 +++------------------------- 5 files changed, 43 insertions(+), 63 deletions(-) diff --git a/src/core/Group.cpp b/src/core/Group.cpp index fa48d8ce..1fee54a4 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -439,10 +439,14 @@ QStringList Group::hierarchy() { QStringList hierarchy; Group* group = this; - while (group->parentGroup()) { - hierarchy << group->name(); - + Group* parent = m_parent; + hierarchy << group->name(); + + while (parent) { group = group->parentGroup(); + parent = group->parentGroup(); + + hierarchy << group->name(); } return hierarchy; } diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 0b83002e..6571668c 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -193,9 +193,9 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged())); connect(m_groupView, SIGNAL(groupPressed(Group*)), SLOT(emitPressedGroup(Group*))); - //connect(m_groupView, SIGNAL(groupChanged(Group*)), SLOT(emitPressedGroup(Group*))); + connect(m_groupView, SIGNAL(groupChanged(Group*)), SLOT(emitPressedGroup(Group*))); connect(m_entryView, SIGNAL(entryPressed(Entry*)), SLOT(emitPressedEntry(Entry*))); - //connect(m_entryView, SIGNAL(entrySelectionChanged()), SLOT(emitPressedEntry())); + connect(m_entryView, SIGNAL(entrySelectionChanged()), SLOT(emitPressedEntry())); connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(emitPressedEntry())); m_databaseModified = false; diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index d506d551..ee051e9c 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -24,6 +24,7 @@ #include "core/Config.h" #include "core/FilePath.h" #include "core/TimeInfo.h" +#include "gui/Clipboard.h" DetailsWidget::DetailsWidget(QWidget* parent) : QWidget(parent) @@ -38,11 +39,9 @@ DetailsWidget::DetailsWidget(QWidget* parent) m_ui->totpButton->setIcon(filePath()->icon("actions", "chronometer")); m_ui->closeButton->setIcon(filePath()->icon("actions", "dialog-close")); - m_ui->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show")); connect(m_ui->totpButton, SIGNAL(toggled(bool)), SLOT(showTotp(bool))); connect(m_ui->closeButton, SIGNAL(toggled(bool)), SLOT(hideDetails())); - connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), SLOT(togglePasswordShown(bool))); this->hide(); } @@ -67,25 +66,31 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) m_ui->entryIcon->setPixmap(m_currentEntry->iconPixmap()); - QStringList hierarchy = m_currentEntry->group()->hierarchy(); QString title = " / "; - for (QString parent : hierarchy) { - title.append(parent); - title.append(" / "); + + Group* entry_group = m_currentEntry->group(); + if (entry_group) { + QStringList hierarchy = entry_group->hierarchy(); + + for (QString parent : hierarchy) { + title.append(parent); + title.append(" / "); + } } - title.append(m_currentEntry->title()); + title.append(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->title())); m_ui->titleLabel->setText(title); - m_ui->usernameLabel->setText(m_currentEntry->username()); - m_ui->groupLabel->setText(m_currentEntry->group()->name()); - m_ui->notesEdit->setText(m_currentEntry->notes()); + m_ui->usernameLabel->setText(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->username())); + if (entry_group) { + m_ui->groupLabel->setText(entry_group->name()); + } + m_ui->notesEdit->setText(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->notes())); if (!config()->get("security/hidepassworddetails").toBool()) { - m_ui->passwordEdit->setText(m_currentEntry->password()); - m_ui->togglePasswordButton->show(); + m_ui->passwordLabel->setText(shortPassword(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->password()))); + m_ui->passwordLabel->setToolTip(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->password())); } else { - m_ui->passwordEdit->setText("****"); - m_ui->togglePasswordButton->hide(); + m_ui->passwordLabel->setText("****"); } QString url = m_currentEntry->webUrl(); @@ -199,15 +204,18 @@ QString DetailsWidget::shortUrl(QString url) 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::togglePasswordShown(bool showing) -{ - m_ui->passwordEdit->setShowPassword(showing); - bool blockSignals = m_ui->togglePasswordButton->blockSignals(true); - m_ui->togglePasswordButton->setChecked(showing); - m_ui->togglePasswordButton->blockSignals(blockSignals); -} \ No newline at end of file diff --git a/src/gui/DetailsWidget.h b/src/gui/DetailsWidget.h index 89e6cf62..d4accf08 100644 --- a/src/gui/DetailsWidget.h +++ b/src/gui/DetailsWidget.h @@ -46,7 +46,6 @@ private slots: void showTotp(bool visible); void updateTotp(); void hideDetails(); - void togglePasswordShown(bool showing); private: const QScopedPointer m_ui; @@ -55,6 +54,7 @@ private: quint8 m_step; QTimer* m_timer; QString shortUrl(QString url); + QString shortPassword(QString password); }; #endif // KEEPASSX_DETAILSWIDGET_H diff --git a/src/gui/DetailsWidget.ui b/src/gui/DetailsWidget.ui index fb6b7fb2..b4c3150f 100644 --- a/src/gui/DetailsWidget.ui +++ b/src/gui/DetailsWidget.ui @@ -235,33 +235,6 @@ - - - - - - - 0 - 0 - - - - 999 - - - true - - - - - - - true - - - - - @@ -275,6 +248,9 @@ + + + @@ -539,14 +515,6 @@ - - - PasswordEdit - QLineEdit -
gui/PasswordEdit.h
- 1 -
-
From 4a5fc2104f82b1e43a9d9d12b909ad65c97a8014 Mon Sep 17 00:00:00 2001 From: thez3ro Date: Thu, 31 Aug 2017 00:57:50 +0200 Subject: [PATCH 03/10] fix notes label --- src/gui/DetailsWidget.ui | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/gui/DetailsWidget.ui b/src/gui/DetailsWidget.ui index b4c3150f..0f202c0f 100644 --- a/src/gui/DetailsWidget.ui +++ b/src/gui/DetailsWidget.ui @@ -459,6 +459,36 @@ + + + + + + + 75 + true + + + + Notes + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + @@ -487,13 +517,6 @@ - - - - Notes - - - From eb6582266533a979a753327b7f222867b7d146c3 Mon Sep 17 00:00:00 2001 From: thez3ro Date: Wed, 27 Sep 2017 19:18:13 +0200 Subject: [PATCH 04/10] layout update --- src/core/Group.cpp | 5 +- src/gui/DatabaseWidget.h | 1 - src/gui/DetailsWidget.cpp | 67 +++- src/gui/DetailsWidget.h | 10 + src/gui/DetailsWidget.ui | 727 ++++++++++++++++++++------------------ 5 files changed, 449 insertions(+), 361 deletions(-) diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 1fee54a4..6f70db34 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -440,14 +440,15 @@ QStringList Group::hierarchy() QStringList hierarchy; Group* group = this; Group* parent = m_parent; - hierarchy << group->name(); + hierarchy.prepend(group->name()); while (parent) { group = group->parentGroup(); parent = group->parentGroup(); - hierarchy << group->name(); + hierarchy.prepend(group->name()); } + return hierarchy; } diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 141248bd..404adb52 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -27,7 +27,6 @@ #include "core/Uuid.h" #include "gui/entry/EntryModel.h" -#include "gui/DetailsWidget.h" #include "gui/MessageWidget.h" #include "gui/csvImport/CsvImportWizard.h" diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index ee051e9c..45284c84 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -25,10 +25,12 @@ #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) { @@ -36,6 +38,7 @@ DetailsWidget::DetailsWidget(QWidget* parent) 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")); @@ -60,6 +63,9 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) 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); @@ -81,10 +87,6 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) m_ui->titleLabel->setText(title); m_ui->usernameLabel->setText(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->username())); - if (entry_group) { - m_ui->groupLabel->setText(entry_group->name()); - } - m_ui->notesEdit->setText(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->notes())); if (!config()->get("security/hidepassworddetails").toBool()) { m_ui->passwordLabel->setText(shortPassword(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->password()))); @@ -110,10 +112,6 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) m_ui->expirationLabel->setText(tr("Never")); } - m_ui->creationLabel->setText(entryTime.creationTime().toString(Qt::DefaultLocaleShortDate)); - m_ui->modifyLabel->setText(entryTime.lastModificationTime().toString(Qt::DefaultLocaleShortDate)); - m_ui->accessLabel->setText(entryTime.lastAccessTime().toString(Qt::DefaultLocaleShortDate)); - if (m_currentEntry->hasTotp()) { m_ui->totpButton->show(); updateTotp(); @@ -124,6 +122,28 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) 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) @@ -136,13 +156,18 @@ void DetailsWidget::getSelectedGroup(Group* selectedGroup) 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(); m_ui->entryIcon->setPixmap(m_currentGroup->iconPixmap()); - QStringList hierarchy = m_currentGroup->hierarchy(); QString title = " / "; + + QStringList hierarchy = m_currentGroup->hierarchy(); + for (QString parent : hierarchy) { title.append(parent); title.append(" / "); @@ -177,6 +202,10 @@ void DetailsWidget::getSelectedGroup(Group* selectedGroup) 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); @@ -219,3 +248,23 @@ 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); +} \ No newline at end of file diff --git a/src/gui/DetailsWidget.h b/src/gui/DetailsWidget.h index d4accf08..44989fd1 100644 --- a/src/gui/DetailsWidget.h +++ b/src/gui/DetailsWidget.h @@ -40,15 +40,25 @@ public: GroupPreview = 1, }; + enum TabWidgetIndex + { + GeneralTab = 0, + AttributesTab = 1, + NotesTab = 2, + }; + private slots: void getSelectedEntry(Entry* selectedEntry); void getSelectedGroup(Group* selectedGroup); void showTotp(bool visible); void updateTotp(); void hideDetails(); + void setDatabaseMode(DatabaseWidget::Mode mode); + void copyToClipboard(const QString& text); private: const QScopedPointer m_ui; + bool m_locked; Entry* m_currentEntry; Group* m_currentGroup; quint8 m_step; diff --git a/src/gui/DetailsWidget.ui b/src/gui/DetailsWidget.ui index 0f202c0f..2bc6653c 100644 --- a/src/gui/DetailsWidget.ui +++ b/src/gui/DetailsWidget.ui @@ -7,7 +7,7 @@ 0 0 630 - 207 + 180 @@ -19,7 +19,7 @@ 16777215 - 235 + 200 @@ -146,332 +146,326 @@
- - - - 0 - 0 - - + 0 - - - - 0 - - - 0 - - - 0 - - - 0 - + + false + + + false + + + false + + + false + + + + General + + - - - + + + + 0 + 0 + + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + - - - - - - 75 - true - - - - Group - - - - - - - - 9 - 75 - true - - - - URL - - - - - - - - 75 - true - - - - Password - - - - - - - - 75 - true - - - - Username - - - - - - - - - - - - - - 0 - 0 - - - - - - - - - + + + + + + + + + + 0 + 0 + + + + + 9 + 75 + true + + + + URL + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Password + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Qt::LeftToRight + + + Username + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Expiration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + - - - - - - - - 75 - true - - - - Modification - - - - - - - - 75 - true - - - - Access - - - - - - - - - - - - - - 75 - true - - - - Creation - - - - - - - - 75 - true - - - - Expiration - - - - - - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - + + + + + 0 + + + 0 + + + 0 + + + 0 + - - - + + + + + + + + + + + + + 75 + true + + + + Autotype + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + Expiration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + Searching + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + - - - - - 75 - true - - - - Autotype - - - - - - - - - - - 75 - true - - - - Searching - - - - - - - - - - - 75 - true - - - - Expiration - - + + + + + + + 75 + true + + + + Access + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + 75 + true + + + + Creation + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + Modification + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - - - - - - - - 75 - true - - - - Modification - - - - - - - - 75 - true - - - - Access - - - - - - - - - - - - - - 75 - true - - - - Creation - - - - - - - - - - - - - - - - - - - - - - - 75 - true - - - - Notes - + @@ -488,42 +482,77 @@ - - - - - - 0 - 1 - - - - - 0 - 50 - - - - - 16777215 - 50 - - - - Qt::ClickFocus - - - true - - - - - - - - - Qt::Horizontal - + + + + Attributes + + + + + + + 0 + 1 + + + + + 0 + 80 + + + + + 16777215 + 80 + + + + Qt::ClickFocus + + + true + + + + + + + + Notes + + + + + + + 0 + 1 + + + + + 0 + 80 + + + + + 16777215 + 80 + + + + Qt::ClickFocus + + + true + + + + + From d0f8d437396425b2907a2255f6730c3883b960f7 Mon Sep 17 00:00:00 2001 From: thez3ro Date: Thu, 28 Sep 2017 20:48:49 +0200 Subject: [PATCH 05/10] remove root group from path, resize icons to 16x16 --- src/gui/DetailsWidget.cpp | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index 45284c84..d0e9c4a4 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -70,17 +70,20 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) m_ui->totpWidget->hide(); m_ui->totpButton->setChecked(false); - m_ui->entryIcon->setPixmap(m_currentEntry->iconPixmap()); - - QString title = " / "; + 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(); - - for (QString parent : hierarchy) { - title.append(parent); - title.append(" / "); + hierarchy.removeFirst(); + title += hierarchy.join(" / "); + if (hierarchy.size() > 0) { + title += " / "; } } title.append(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->title())); @@ -162,15 +165,18 @@ void DetailsWidget::getSelectedGroup(Group* selectedGroup) m_ui->totpButton->hide(); m_ui->totpWidget->hide(); - m_ui->entryIcon->setPixmap(m_currentGroup->iconPixmap()); + 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(); - - for (QString parent : hierarchy) { - title.append(parent); - title.append(" / "); + hierarchy.removeFirst(); + title += hierarchy.join(" / "); + if (hierarchy.size() > 0) { + title += " / "; } m_ui->titleLabel->setText(title); From 9279bf76287238e2eb99ba757a48073e3beb21b6 Mon Sep 17 00:00:00 2001 From: thez3ro Date: Fri, 29 Sep 2017 20:37:37 +0200 Subject: [PATCH 06/10] fix group layout, add autotype associations --- src/gui/DetailsWidget.cpp | 44 ++- src/gui/DetailsWidget.h | 4 + src/gui/DetailsWidget.ui | 582 +++++++++++++++++++------------------- 3 files changed, 326 insertions(+), 304 deletions(-) diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index d0e9c4a4..dd80ea23 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -33,6 +33,8 @@ DetailsWidget::DetailsWidget(QWidget* parent) , m_locked(false) , m_currentEntry(nullptr) , m_currentGroup(nullptr) + , m_attributesWidget(nullptr) + , m_autotypeWidget(nullptr) { m_ui->setupUi(this); @@ -63,8 +65,14 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) m_ui->stackedWidget->setCurrentIndex(EntryPreview); + if (m_ui->tabWidget->count() < 4) { + m_ui->tabWidget->insertTab(static_cast(AttributesTab), m_attributesWidget, "Attributes"); + m_ui->tabWidget->insertTab(static_cast(AutotypeTab), m_autotypeWidget, "Autotype"); + } + m_ui->tabWidget->setTabEnabled(AttributesTab, false); m_ui->tabWidget->setTabEnabled(NotesTab, false); + m_ui->tabWidget->setTabEnabled(AutotypeTab, false); m_ui->totpButton->hide(); m_ui->totpWidget->hide(); @@ -147,6 +155,21 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) } m_ui->attributesEdit->setText(attributesText); } + + m_ui->autotypeTree->clear(); + AutoTypeAssociations* autotypeAssociations = m_currentEntry->autoTypeAssociations(); + QList items; + for (auto assoc : autotypeAssociations->getAll()) { + QStringList association = QStringList() << assoc.window << assoc.sequence; + if (association.at(1).isEmpty()) { + association.replace(1, m_currentEntry->effectiveAutoTypeSequence()); + } + items.append(new QTreeWidgetItem(m_ui->autotypeTree, association)); + } + if (items.count() > 0) { + m_ui->autotypeTree->addTopLevelItems(items); + m_ui->tabWidget->setTabEnabled(AutotypeTab, true); + } } void DetailsWidget::getSelectedGroup(Group* selectedGroup) @@ -159,8 +182,15 @@ void DetailsWidget::getSelectedGroup(Group* selectedGroup) m_ui->stackedWidget->setCurrentIndex(GroupPreview); - m_ui->tabWidget->setTabEnabled(AttributesTab, false); - m_ui->tabWidget->setTabEnabled(NotesTab, false); + if (m_ui->tabWidget->count() > 2) { + m_autotypeWidget = m_ui->tabWidget->widget(AutotypeTab); + m_attributesWidget = m_ui->tabWidget->widget(AttributesTab); + m_ui->tabWidget->removeTab(AutotypeTab); + m_ui->tabWidget->removeTab(AttributesTab); + } + + m_ui->tabWidget->setTabEnabled(GroupNotesTab, false); + m_ui->totpButton->hide(); m_ui->totpWidget->hide(); @@ -180,7 +210,11 @@ void DetailsWidget::getSelectedGroup(Group* selectedGroup) } m_ui->titleLabel->setText(title); - m_ui->notesEdit->setText(m_currentGroup->notes()); + QString notes = m_currentGroup->notes(); + if (!notes.isEmpty()) { + m_ui->tabWidget->setTabEnabled(GroupNotesTab, true); + m_ui->notesEdit->setText(notes); + } QString searching = tr("Disabled"); if (m_currentGroup->resolveSearchingEnabled()) { @@ -200,10 +234,6 @@ void DetailsWidget::getSelectedGroup(Group* selectedGroup) } 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() diff --git a/src/gui/DetailsWidget.h b/src/gui/DetailsWidget.h index 44989fd1..155c58f1 100644 --- a/src/gui/DetailsWidget.h +++ b/src/gui/DetailsWidget.h @@ -44,7 +44,9 @@ public: { GeneralTab = 0, AttributesTab = 1, + GroupNotesTab = 1, NotesTab = 2, + AutotypeTab = 3, }; private slots: @@ -63,6 +65,8 @@ private: Group* m_currentGroup; quint8 m_step; QTimer* m_timer; + QWidget* m_attributesWidget; + QWidget* m_autotypeWidget; QString shortUrl(QString url); QString shortPassword(QString password); }; diff --git a/src/gui/DetailsWidget.ui b/src/gui/DetailsWidget.ui index 2bc6653c..99164807 100644 --- a/src/gui/DetailsWidget.ui +++ b/src/gui/DetailsWidget.ui @@ -7,7 +7,7 @@ 0 0 630 - 180 + 200 @@ -159,9 +159,6 @@ false - - false - General @@ -179,308 +176,251 @@ 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - 0 - 0 - - - - - 9 - 75 - true - - - - URL - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 75 - true - - - - Password - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 75 - true - - - - Qt::LeftToRight - - - Username - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - 0 - 0 - - - - - 75 - true - - - - Expiration - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Expiration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 9 + 75 + true + + + + URL + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Password + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Qt::LeftToRight + + + Username + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - - - - 75 - true - - - - Autotype - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - Expiration - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - Searching - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - - - - - - 75 - true - - - - Access - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - 75 - true - - - - Creation - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - Modification - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Autotype + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Searching + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Expiration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -553,6 +493,54 @@ + + + Autotype + + + + + + QFrame::Sunken + + + true + + + true + + + false + + + 2 + + + false + + + 250 + + + 50 + + + true + + + + Window + + + + + Sequence + + + + + + From 71ae2a3458d23a164aa9137798e2c00029a6d220 Mon Sep 17 00:00:00 2001 From: thez3ro Date: Fri, 29 Sep 2017 22:02:07 +0200 Subject: [PATCH 07/10] remember last selected tab, hide passwords by default --- src/core/Config.cpp | 1 + src/gui/DetailsWidget.cpp | 19 +++++++++++++++++-- src/gui/DetailsWidget.h | 4 +++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/core/Config.cpp b/src/core/Config.cpp index a432b3c9..6899015a 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -131,6 +131,7 @@ void Config::init(const QString& fileName) m_defaults.insert("security/lockdatabasescreenlock", true); m_defaults.insert("security/passwordsrepeat", false); m_defaults.insert("security/passwordscleartext", false); + m_defaults.insert("security/hidepassworddetails", true); m_defaults.insert("security/autotypeask", true); m_defaults.insert("security/IconDownloadFallbackToGoogle", false); m_defaults.insert("GUI/Language", "system"); diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index dd80ea23..1ec891a6 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -35,6 +35,8 @@ DetailsWidget::DetailsWidget(QWidget* parent) , m_currentGroup(nullptr) , m_attributesWidget(nullptr) , m_autotypeWidget(nullptr) + , m_selectedTabEntry(0) + , m_selectedTabGroup(0) { m_ui->setupUi(this); @@ -47,6 +49,7 @@ DetailsWidget::DetailsWidget(QWidget* parent) connect(m_ui->totpButton, SIGNAL(toggled(bool)), SLOT(showTotp(bool))); connect(m_ui->closeButton, SIGNAL(toggled(bool)), SLOT(hideDetails())); + connect(m_ui->tabWidget, SIGNAL(tabBarClicked(int)), SLOT(updateTabIndex(int))); this->hide(); } @@ -170,6 +173,10 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) m_ui->autotypeTree->addTopLevelItems(items); m_ui->tabWidget->setTabEnabled(AutotypeTab, true); } + + if (m_ui->tabWidget->isTabEnabled(m_selectedTabEntry)) { + m_ui->tabWidget->setCurrentIndex(m_selectedTabEntry); + } } void DetailsWidget::getSelectedGroup(Group* selectedGroup) @@ -234,6 +241,10 @@ void DetailsWidget::getSelectedGroup(Group* selectedGroup) } else { m_ui->groupExpirationLabel->setText(tr("Never")); } + + if (m_ui->tabWidget->isTabEnabled(m_selectedTabGroup)) { + m_ui->tabWidget->setCurrentIndex(m_selectedTabGroup); + } } void DetailsWidget::updateTotp() @@ -301,6 +312,10 @@ void DetailsWidget::setDatabaseMode(DatabaseWidget::Mode mode) } } -void DetailsWidget::copyToClipboard(const QString& text) { - clipboard()->setText(text); +void DetailsWidget::updateTabIndex(int index) { + if (m_ui->stackedWidget->currentIndex() == GroupPreview) { + m_selectedTabGroup = index; + } else { + m_selectedTabEntry = index; + } } \ No newline at end of file diff --git a/src/gui/DetailsWidget.h b/src/gui/DetailsWidget.h index 155c58f1..5bc02600 100644 --- a/src/gui/DetailsWidget.h +++ b/src/gui/DetailsWidget.h @@ -56,7 +56,7 @@ private slots: void updateTotp(); void hideDetails(); void setDatabaseMode(DatabaseWidget::Mode mode); - void copyToClipboard(const QString& text); + void updateTabIndex(int index); private: const QScopedPointer m_ui; @@ -67,6 +67,8 @@ private: QTimer* m_timer; QWidget* m_attributesWidget; QWidget* m_autotypeWidget; + quint8 m_selectedTabEntry; + quint8 m_selectedTabGroup; QString shortUrl(QString url); QString shortPassword(QString password); }; From 8416d69f1e0b390b82c0c2dea7bd158e10eb7bed Mon Sep 17 00:00:00 2001 From: thez3ro Date: Tue, 24 Oct 2017 14:08:22 +0200 Subject: [PATCH 08/10] fix protected transalation --- src/gui/DetailsWidget.cpp | 8 ++++---- src/gui/entry/EditEntryWidget.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index 1ec891a6..51448a97 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -152,7 +152,7 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) for (const QString& key : customAttributes) { QString value = m_currentEntry->attributes()->value(key); if (m_currentEntry->attributes()->isProtected(key)) { - value = "[PROTECTED]"; + value = "" + tr("[PROTECTED]") + ""; } attributesText.append(QString("%1: %2
").arg(key, value)); } @@ -161,7 +161,7 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) m_ui->autotypeTree->clear(); AutoTypeAssociations* autotypeAssociations = m_currentEntry->autoTypeAssociations(); - QList items; + QList items; for (auto assoc : autotypeAssociations->getAll()) { QStringList association = QStringList() << assoc.window << assoc.sequence; if (association.at(1).isEmpty()) { @@ -273,7 +273,7 @@ QString DetailsWidget::shortUrl(QString url) QString newurl = ""; if (url.length() > 60) { newurl.append(url.left(20)); - newurl.append("..."); + newurl.append("…"); newurl.append(url.right(20)); return newurl; } @@ -285,7 +285,7 @@ QString DetailsWidget::shortPassword(QString password) QString newpassword = ""; if (password.length() > 60) { newpassword.append(password.left(50)); - newpassword.append("..."); + newpassword.append("…"); return newpassword; } return password; diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 463096b3..2d17c345 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -632,7 +632,7 @@ void EditEntryWidget::displayAttribute(QModelIndex index, bool showProtected) if (index.isValid()) { QString key = m_attributesModel->keyByIndex(index); if (showProtected) { - m_advancedUi->attributesEdit->setPlainText(tr("[PROTECTED] Press reveal to view or edit")); + m_advancedUi->attributesEdit->setPlainText(tr("[PROTECTED]") + " " + tr("Press reveal to view or edit")); m_advancedUi->attributesEdit->setEnabled(false); m_advancedUi->revealAttributeButton->setEnabled(true); m_advancedUi->protectAttributeButton->setChecked(true); From b9fd609bb20d6246db8f63dd43bc237ce05de641 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 25 Oct 2017 00:01:29 -0400 Subject: [PATCH 09/10] Resolve placeholders in entry details url --- src/core/Entry.cpp | 3 ++- src/gui/DetailsWidget.cpp | 11 +++++++++-- src/gui/DetailsWidget.ui | 9 ++++++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index d5afec04..edf5b6f2 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -243,7 +243,8 @@ QString Entry::url() const QString Entry::webUrl() const { - return resolveUrl(m_attributes->value(EntryAttributes::URLKey)); + QString url = resolveMultiplePlaceholders(m_attributes->value(EntryAttributes::URLKey)); + return resolveUrl(url); } QString Entry::username() const diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index 51448a97..deb7008a 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -110,10 +110,17 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) } QString url = m_currentEntry->webUrl(); - if (url != "") { - url = QString("%2").arg(url).arg(shortUrl(url)); + if (!url.isEmpty()) { + // URL is well formed and can be opened in a browser + // create a new display url that masks password placeholders + // the actual link will use the password + QString displayUrl = m_currentEntry->url(); + displayUrl = m_currentEntry->maskPasswordPlaceholders(displayUrl); + displayUrl = m_currentEntry->resolveMultiplePlaceholders(displayUrl); + url = QString("%2").arg(url).arg(shortUrl(displayUrl)); m_ui->urlLabel->setOpenExternalLinks(true); } else { + // Fallback to the raw url string url = shortUrl(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->url())); m_ui->urlLabel->setOpenExternalLinks(false); } diff --git a/src/gui/DetailsWidget.ui b/src/gui/DetailsWidget.ui index 99164807..fb31409f 100644 --- a/src/gui/DetailsWidget.ui +++ b/src/gui/DetailsWidget.ui @@ -188,6 +188,9 @@ 0 + + PointingHandCursor + @@ -289,7 +292,11 @@ - + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + From f3d85ae21917feff31806ef1c22bb76833cb914f Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 25 Oct 2017 23:29:01 -0400 Subject: [PATCH 10/10] Cleaned up url display code --- src/core/Entry.cpp | 7 +++++++ src/core/Entry.h | 1 + src/gui/DetailsWidget.cpp | 7 ++----- src/gui/entry/EntryModel.cpp | 3 +-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index edf5b6f2..91d757a9 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -247,6 +247,13 @@ QString Entry::webUrl() const return resolveUrl(url); } +QString Entry::displayUrl() const +{ + QString url = maskPasswordPlaceholders(m_attributes->value(EntryAttributes::URLKey)); + url = resolveMultiplePlaceholders(url); + return resolveUrl(url); +} + QString Entry::username() const { return m_attributes->value(EntryAttributes::UserNameKey); diff --git a/src/core/Entry.h b/src/core/Entry.h index 212c8668..d4d2b903 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -79,6 +79,7 @@ public: QString title() const; QString url() const; QString webUrl() const; + QString displayUrl() const; QString username() const; QString password() const; QString notes() const; diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index deb7008a..b805f9b1 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -114,10 +114,7 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry) // URL is well formed and can be opened in a browser // create a new display url that masks password placeholders // the actual link will use the password - QString displayUrl = m_currentEntry->url(); - displayUrl = m_currentEntry->maskPasswordPlaceholders(displayUrl); - displayUrl = m_currentEntry->resolveMultiplePlaceholders(displayUrl); - url = QString("%2").arg(url).arg(shortUrl(displayUrl)); + url = QString("%2").arg(url).arg(shortUrl(m_currentEntry->displayUrl())); m_ui->urlLabel->setOpenExternalLinks(true); } else { // Fallback to the raw url string @@ -325,4 +322,4 @@ void DetailsWidget::updateTabIndex(int index) { } else { m_selectedTabEntry = index; } -} \ No newline at end of file +} diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index 2f79f02d..4d357806 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -151,8 +151,7 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const } return result; case Url: - result = entry->maskPasswordPlaceholders(entry->url()); - result = entry->resolveMultiplePlaceholders(result); + result = entry->displayUrl(); if (attr->isReference(EntryAttributes::URLKey)) { result.prepend(tr("Ref: ","Reference abbreviation")); }