Merge branch 'develop' into feature/yubikey

This commit is contained in:
Janek Bevendorff 2017-02-20 20:24:38 +01:00
commit a27147a75e
No known key found for this signature in database
GPG key ID: CFEC2F6850BFFA53
79 changed files with 8006 additions and 758 deletions

View file

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>455</width>
<height>238</height>
<height>266</height>
</rect>
</property>
<property name="windowTitle">
@ -53,7 +53,7 @@
</sizepolicy>
</property>
<property name="text">
<string notr="true">&lt;a href=&quot;https://www.keepassxc.org/&quot;&gt;https://www.keepassxc.org/&lt;/a&gt;</string>
<string notr="true">&lt;a href=&quot;https://keepassxc.org/&quot;&gt;https://keepassxc.org/&lt;/a&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
@ -69,7 +69,7 @@
</sizepolicy>
</property>
<property name="text">
<string>KeePassXC is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</string>
<string>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -82,7 +82,7 @@
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
@ -91,6 +91,9 @@
<property name="text">
<string>Using:</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
@ -99,6 +102,9 @@
<string>Extensions:
</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>

View file

@ -170,3 +170,8 @@ void ChangeMasterKeyWidget::ykDetected(int slot, bool blocking)
m_ui->challengeResponseCombo->addItem(yk.getName(), QVariant(slot));
m_ui->challengeResponseGroup->setEnabled(true);
}
void ChangeMasterKeyWidget::setCancelEnabled(bool enabled)
{
m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(enabled);
}

View file

@ -38,6 +38,7 @@ public:
void clearForms();
CompositeKey newMasterKey();
QLabel* headlineLabel();
void setCancelEnabled(bool enabled);
Q_SIGNALS:
void editFinished(bool accepted);

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>438</width>
<height>342</height>
<width>818</width>
<height>397</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@ -44,8 +44,8 @@
<property name="checked">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="enterPasswordLabel">
<property name="text">
<string>Enter password:</string>
@ -70,7 +70,7 @@
</item>
</layout>
</item>
<item row="1" column="0">
<item row="1" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="repeatPasswordLabel">
<property name="text">
<string>Repeat password:</string>

View file

@ -70,6 +70,13 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
connect(YubiKey::instance(), SIGNAL(detected(int,bool)),
SLOT(ykDetected(int,bool)),
Qt::QueuedConnection);
#ifdef Q_OS_MACOS
// add random padding to layouts to align widgets properly
m_ui->dialogButtonsLayout->setContentsMargins(10, 0, 15, 0);
m_ui->gridLayout->setContentsMargins(10, 0, 0, 0);
m_ui->labelLayout->setContentsMargins(10, 0, 10, 0);
#endif
}
DatabaseOpenWidget::~DatabaseOpenWidget()

View file

@ -10,7 +10,7 @@
<height>250</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0,0,1,0,0,3">
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0,1,0,0,3">
<property name="spacing">
<number>8</number>
</property>
@ -31,14 +31,24 @@
</spacer>
</item>
<item>
<widget class="QLabel" name="labelHeadline">
<property name="text">
<string>Enter master key</string>
<layout class="QVBoxLayout" name="labelLayout">
<property name="leftMargin">
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelFilename"/>
<property name="rightMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="labelHeadline">
<property name="text">
<string>Enter master key</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelFilename"/>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
@ -55,17 +65,20 @@
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="verticalSpacing">
<number>8</number>
</property>
<item row="1" column="0">
<item row="1" column="0" alignment="Qt::AlignVCenter">
<widget class="QCheckBox" name="checkKeyFile">
<property name="text">
<string>Key File:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<item row="0" column="0" alignment="Qt::AlignVCenter">
<widget class="QCheckBox" name="checkPassword">
<property name="text">
<string>Password:</string>
@ -73,9 +86,18 @@
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<layout class="QHBoxLayout" name="keyFileLayout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<item>
<widget class="QComboBox" name="comboKeyFile">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -97,7 +119,13 @@
</layout>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="passwordLayout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<item>
<widget class="PasswordEdit" name="editPassword">
<property name="echoMode">
@ -134,14 +162,21 @@
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<layout class="QHBoxLayout" name="dialogButtonsLayout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<property name="rightMargin">
<number>5</number>
</property>
</widget>
<item alignment="Qt::AlignRight">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
@ -178,7 +213,6 @@
<tabstop>checkKeyFile</tabstop>
<tabstop>comboKeyFile</tabstop>
<tabstop>buttonBrowseFile</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections/>

View file

@ -6,181 +6,225 @@
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>399</height>
<width>600</width>
<height>340</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,2,5,1">
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>3</height>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<widget class="QLabel" name="dbNameLabel">
<property name="text">
<string>Database name:</string>
<layout class="QHBoxLayout" name="horizontalLayout_5" stretch="0,1,0">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="dbNameEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="dbDescriptionLabel">
<property name="text">
<string>Database description:</string>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</spacer>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="dbDescriptionEdit"/>
</item>
<item row="9" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="historyMaxSizeSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> MiB</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>2000000000</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="8" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSpinBox" name="historyMaxItemsSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>2000000000</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSpinBox" name="transformRoundsSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000000</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="transformBenchmarkButton">
<property name="text">
<string>Benchmark</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="historyMaxItemsCheckBox">
<property name="text">
<string>Max. history items:</string>
<item>
<widget class="QWidget" name="widget" native="true">
<property name="maximumSize">
<size>
<width>800</width>
<height>16777215</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSpinBox" name="transformRoundsSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000000</number>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="transformBenchmarkButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>25</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Benchmark</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="dbNameLabel">
<property name="text">
<string>Database name:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="historyMaxSizeCheckBox">
<property name="text">
<string>Max. history size:</string>
</property>
</widget>
</item>
<item row="3" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="transformRoundsLabel">
<property name="text">
<string>Transform rounds:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="historyMaxItemsCheckBox">
<property name="text">
<string>Max. history items:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="dbNameEdit"/>
</item>
<item row="6" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSpinBox" name="historyMaxItemsSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>2000000000</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="defaultUsernameLabel">
<property name="text">
<string>Default username:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="dbDescriptionEdit"/>
</item>
<item row="7" column="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="historyMaxSizeSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> MiB</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>2000000000</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="recycleBinEnabledCheckBox">
<property name="text">
<string>Use recycle bin</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLineEdit" name="defaultUsernameEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="dbDescriptionLabel">
<property name="text">
<string>Database description:</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="AlgorithmComboBox">
<item>
<property name="text">
<string>AES: 256 Bit (default)</string>
</property>
</item>
<item>
<property name="text">
<string>Twofish: 256 Bit</string>
</property>
</item>
</widget>
</item>
<item row="2" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="AlgorithmLabel">
<property name="text">
<string>Algorithm:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="9" column="0">
<widget class="QCheckBox" name="historyMaxSizeCheckBox">
<property name="text">
<string>Max. history size:</string>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="transformRoundsLabel">
<property name="text">
<string>Transform rounds:</string>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="recycleBinEnabledCheckBox"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="defaultUsernameLabel">
<property name="text">
<string>Default username:</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Use recycle bin:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="defaultUsernameEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="AlgorithmLabel">
<property name="text">
<string>Algorithm:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="AlgorithmComboBox">
<item>
<property name="text">
<string>AES: 256 Bit (default)</string>
</property>
</item>
<item>
<property name="text">
<string>Twofish: 256 Bit</string>
</property>
</item>
</widget>
</spacer>
</item>
</layout>
</item>

View file

@ -77,14 +77,9 @@ DatabaseTabWidget::~DatabaseTabWidget()
void DatabaseTabWidget::toggleTabbar()
{
if (count() > 1) {
if (!tabBar()->isVisible()) {
tabBar()->show();
}
}
else {
if (tabBar()->isVisible()) {
tabBar()->hide();
}
tabBar()->show();
} else {
tabBar()->hide();
}
}
@ -94,10 +89,18 @@ void DatabaseTabWidget::newDatabase()
Database* db = new Database();
db->rootGroup()->setName(tr("Root"));
dbStruct.dbWidget = new DatabaseWidget(db, this);
CompositeKey emptyKey;
db->setKey(emptyKey);
insertDatabase(db, dbStruct);
if (!saveDatabaseAs(db)) {
closeDatabase(db);
return;
}
dbStruct.dbWidget->switchToMasterKeyChange();
dbStruct.dbWidget->switchToMasterKeyChange(true);
}
void DatabaseTabWidget::openDatabase()
@ -360,80 +363,78 @@ bool DatabaseTabWidget::saveDatabase(Database* db)
bool DatabaseTabWidget::saveDatabaseAs(Database* db)
{
DatabaseManagerStruct& dbStruct = m_dbList[db];
QString oldFileName;
if (dbStruct.saveToFilename) {
oldFileName = dbStruct.filePath;
}
else {
oldFileName = tr("New database").append(".kdbx");
}
QString fileName = fileDialog()->getSaveFileName(this, tr("Save database as"),
oldFileName, tr("KeePass 2 Database").append(" (*.kdbx)"),
nullptr, 0, "kdbx");
if (!fileName.isEmpty()) {
QFileInfo fileInfo(fileName);
QString lockFilePath;
if (fileInfo.exists()) {
// returns empty string when file doesn't exist
lockFilePath = fileInfo.canonicalPath();
while (true) {
DatabaseManagerStruct& dbStruct = m_dbList[db];
QString oldFileName;
if (dbStruct.saveToFilename) {
oldFileName = dbStruct.filePath;
} else {
oldFileName = tr("Passwords").append(".kdbx");
}
else {
lockFilePath = fileInfo.absolutePath();
}
QString lockFileName = QString("%1/.%2.lock").arg(lockFilePath, fileInfo.fileName());
QScopedPointer<QLockFile> lockFile(new QLockFile(lockFileName));
lockFile->setStaleLockTime(0);
if (!lockFile->tryLock()) {
// for now silently ignore if we can't create a lock file
// due to lack of permissions
if (lockFile->error() != QLockFile::PermissionError) {
QMessageBox::StandardButton result = MessageBox::question(this, tr("Save database as"),
tr("The database you are trying to save as is locked by another instance of KeePassXC.\n"
"Do you want to save it anyway?"),
QMessageBox::Yes | QMessageBox::No);
QString fileName = fileDialog()->getSaveFileName(this, tr("Save database as"),
oldFileName, tr("KeePass 2 Database").append(" (*.kdbx)"),
nullptr, 0, "kdbx");
if (!fileName.isEmpty()) {
QFileInfo fileInfo(fileName);
QString lockFilePath;
if (fileInfo.exists()) {
// returns empty string when file doesn't exist
lockFilePath = fileInfo.canonicalPath();
} else {
lockFilePath = fileInfo.absolutePath();
}
QString lockFileName = QString("%1/.%2.lock").arg(lockFilePath, fileInfo.fileName());
QScopedPointer<QLockFile> lockFile(new QLockFile(lockFileName));
lockFile->setStaleLockTime(0);
if (!lockFile->tryLock()) {
// for now silently ignore if we can't create a lock file
// due to lack of permissions
if (lockFile->error() != QLockFile::PermissionError) {
QMessageBox::StandardButton result = MessageBox::question(this, tr("Save database as"),
tr("The database you are trying to save as is locked by another instance of KeePassXC.\n"
"Do you want to save it anyway?"),
QMessageBox::Yes | QMessageBox::No);
if (result == QMessageBox::No) {
return false;
}
else {
// take over the lock file if possible
if (lockFile->removeStaleLockFile()) {
lockFile->tryLock();
if (result == QMessageBox::No) {
return false;
} else {
// take over the lock file if possible
if (lockFile->removeStaleLockFile()) {
lockFile->tryLock();
}
}
}
}
}
// setup variables so saveDatabase succeeds
dbStruct.saveToFilename = true;
dbStruct.canonicalFilePath = fileName;
// setup variables so saveDatabase succeeds
dbStruct.saveToFilename = true;
dbStruct.canonicalFilePath = fileName;
if (!saveDatabase(db)) {
// failed to save, revert back
dbStruct.saveToFilename = false;
dbStruct.canonicalFilePath = oldFileName;
if (!saveDatabase(db)) {
// failed to save, revert back
dbStruct.saveToFilename = false;
dbStruct.canonicalFilePath = oldFileName;
continue;
}
// refresh fileinfo since the file didn't exist before
fileInfo.refresh();
dbStruct.modified = false;
dbStruct.saveToFilename = true;
dbStruct.readOnly = false;
dbStruct.filePath = fileInfo.absoluteFilePath();
dbStruct.canonicalFilePath = fileInfo.canonicalFilePath();
dbStruct.fileName = fileInfo.fileName();
dbStruct.dbWidget->updateFilename(dbStruct.filePath);
delete dbStruct.lockFile;
dbStruct.lockFile = lockFile.take();
updateTabName(db);
updateLastDatabases(dbStruct.filePath);
return true;
} else {
return false;
}
// refresh fileinfo since the file didn't exist before
fileInfo.refresh();
dbStruct.modified = false;
dbStruct.saveToFilename = true;
dbStruct.readOnly = false;
dbStruct.filePath = fileInfo.absoluteFilePath();
dbStruct.canonicalFilePath = fileInfo.canonicalFilePath();
dbStruct.fileName = fileInfo.fileName();
dbStruct.dbWidget->updateFilename(dbStruct.filePath);
delete dbStruct.lockFile;
dbStruct.lockFile = lockFile.take();
updateTabName(db);
updateLastDatabases(dbStruct.filePath);
return true;
}
else {
return false;
}
}

View file

@ -817,9 +817,10 @@ void DatabaseWidget::switchToGroupEdit()
switchToGroupEdit(group, false);
}
void DatabaseWidget::switchToMasterKeyChange()
void DatabaseWidget::switchToMasterKeyChange(bool disableCancel)
{
m_changeMasterKeyWidget->clearForms();
m_changeMasterKeyWidget->setCancelEnabled(!disableCancel);
setCurrentWidget(m_changeMasterKeyWidget);
}

View file

@ -138,7 +138,7 @@ public Q_SLOTS:
void switchToView(bool accepted);
void switchToEntryEdit();
void switchToGroupEdit();
void switchToMasterKeyChange();
void switchToMasterKeyChange(bool disableCancel = false);
void switchToDatabaseSettings();
void switchToOpenDatabase(const QString& fileName);
void switchToOpenDatabase(const QString& fileName, const QString& password, const QString& keyFile);

View file

@ -52,11 +52,18 @@
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="topMargin">
<number>5</number>
</property>
</widget>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
@ -75,7 +82,6 @@
</customwidgets>
<tabstops>
<tabstop>categoryList</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections/>

View file

@ -28,6 +28,11 @@
#include "gui/IconModels.h"
#include "gui/MessageBox.h"
#include "http/qhttp/qhttpclient.hpp"
#include "http/qhttp/qhttpclientresponse.hpp"
using namespace qhttp::client;
IconStruct::IconStruct()
: uuid(Uuid())
, number(0)
@ -40,8 +45,7 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent)
, m_database(nullptr)
, m_defaultIconModel(new DefaultIconModel(this))
, m_customIconModel(new CustomIconModel(this))
, m_networkAccessMngr(new QNetworkAccessManager(this))
, m_networkOperation(nullptr)
, m_httpClient(nullptr)
{
m_ui->setupUi(this);
@ -59,8 +63,6 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent)
connect(m_ui->addButton, SIGNAL(clicked()), SLOT(addCustomIcon()));
connect(m_ui->deleteButton, SIGNAL(clicked()), SLOT(removeCustomIcon()));
connect(m_ui->faviconButton, SIGNAL(clicked()), SLOT(downloadFavicon()));
connect(m_networkAccessMngr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onRequestFinished(QNetworkReply*)) );
m_ui->faviconButton->setVisible(false);
}
@ -93,7 +95,7 @@ IconStruct EditWidgetIcons::state()
iconStruct.number = -1;
}
}
return iconStruct;
}
@ -103,7 +105,7 @@ void EditWidgetIcons::reset()
m_currentUuid = Uuid();
}
void EditWidgetIcons::load(Uuid currentUuid, Database* database, IconStruct iconStruct, const QString &url)
void EditWidgetIcons::load(const Uuid& currentUuid, Database* database, const IconStruct& iconStruct, const QString& url)
{
Q_ASSERT(database);
Q_ASSERT(!currentUuid.isNull());
@ -134,11 +136,11 @@ void EditWidgetIcons::load(Uuid currentUuid, Database* database, IconStruct icon
}
}
void EditWidgetIcons::setUrl(const QString &url)
void EditWidgetIcons::setUrl(const QString& url)
{
m_url = url;
m_ui->faviconButton->setVisible(!url.isEmpty());
abortFaviconDownload();
resetFaviconDownload();
}
void EditWidgetIcons::downloadFavicon()
@ -148,86 +150,98 @@ void EditWidgetIcons::downloadFavicon()
fetchFavicon(url);
}
void EditWidgetIcons::fetchFavicon(QUrl url)
void EditWidgetIcons::fetchFavicon(const QUrl& url)
{
if (m_networkOperation == nullptr) {
m_networkOperation = m_networkAccessMngr->get(QNetworkRequest(url));
m_ui->faviconButton->setDisabled(true);
if (nullptr == m_httpClient) {
m_httpClient = new QHttpClient(this);
}
bool requestMade = m_httpClient->request(qhttp::EHTTP_GET, url, [this, url](QHttpResponse* response) {
if (m_database == nullptr) {
return;
}
response->collectData();
response->onEnd([this, response, &url]() {
int status = response->status();
if (200 == status) {
QImage image;
image.loadFromData(response->collectedData());
if (!image.isNull()) {
//Set the image
Uuid uuid = Uuid::random();
m_database->metadata()->addCustomIcon(uuid, image.scaled(16, 16));
m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(),
m_database->metadata()->customIconsOrder());
QModelIndex index = m_customIconModel->indexFromUuid(uuid);
m_ui->customIconsView->setCurrentIndex(index);
m_ui->customIconsRadio->setChecked(true);
resetFaviconDownload();
} else {
fetchFaviconFromGoogle(url.host());
}
} else if (301 == status || 302 == status) {
// Check if server has sent a redirect
QUrl possibleRedirectUrl(response->headers().value("location", ""));
if (!possibleRedirectUrl.isEmpty() && possibleRedirectUrl != m_redirectUrl && m_redirectCount < 3) {
resetFaviconDownload(false);
m_redirectUrl = possibleRedirectUrl;
++m_redirectCount;
fetchFavicon(m_redirectUrl);
} else {
// website is trying to redirect to itself or
// maximum number of redirects has been reached, fall back to Google
fetchFaviconFromGoogle(url.host());
}
} else {
fetchFaviconFromGoogle(url.host());
}
});
});
if (!requestMade) {
resetFaviconDownload();
return;
}
m_httpClient->setConnectingTimeOut(5000, [this]() {
resetFaviconDownload();
MessageBox::warning(this, tr("Error"), tr("Unable to fetch favicon."));
});
m_ui->faviconButton->setDisabled(true);
}
void EditWidgetIcons::fetchFaviconFromGoogle(QString domain)
void EditWidgetIcons::fetchFaviconFromGoogle(const QString& domain)
{
if (m_fallbackToGoogle) {
abortFaviconDownload();
resetFaviconDownload();
m_fallbackToGoogle = false;
fetchFavicon(QUrl("http://www.google.com/s2/favicons?domain=" + domain));
} else {
abortFaviconDownload();
resetFaviconDownload();
MessageBox::warning(this, tr("Error"), tr("Unable to fetch favicon."));
}
}
void EditWidgetIcons::abortFaviconDownload(bool clearRedirect)
void EditWidgetIcons::resetFaviconDownload(bool clearRedirect)
{
if (m_networkOperation != nullptr) {
m_networkOperation->abort();
m_networkOperation->deleteLater();
m_networkOperation = nullptr;
}
if (clearRedirect) {
if (!m_redirectUrl.isEmpty()) {
m_redirectUrl.clear();
}
m_redirectUrl.clear();
m_redirectCount = 0;
}
if (nullptr != m_httpClient) {
m_httpClient->deleteLater();
m_httpClient = nullptr;
}
m_fallbackToGoogle = true;
m_ui->faviconButton->setDisabled(false);
}
void EditWidgetIcons::onRequestFinished(QNetworkReply *reply)
{
if (m_database == nullptr) {
return;
}
if (!reply->error()) {
QImage image;
image.loadFromData(reply->readAll());
if (!image.isNull()) {
//Set the image
Uuid uuid = Uuid::random();
m_database->metadata()->addCustomIcon(uuid, image.scaled(16, 16));
m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(),
m_database->metadata()->customIconsOrder());
QModelIndex index = m_customIconModel->indexFromUuid(uuid);
m_ui->customIconsView->setCurrentIndex(index);
m_ui->customIconsRadio->setChecked(true);
abortFaviconDownload();
}
else {
// Check if server has sent a redirect
QUrl possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (!possibleRedirectUrl.isEmpty() && possibleRedirectUrl != m_redirectUrl && m_redirectCount < 3) {
abortFaviconDownload(false);
m_redirectUrl = possibleRedirectUrl;
++m_redirectCount;
fetchFavicon(m_redirectUrl);
}
else { // Webpage is trying to redirect back to itself or the maximum number of redirects has been reached, fallback to Google
fetchFaviconFromGoogle(reply->url().host());
}
}
}
else { // Request Error e.g. 404, fallback to Google
fetchFaviconFromGoogle(reply->url().host());
}
}
void EditWidgetIcons::addCustomIcon()
{
if (m_database) {

View file

@ -20,9 +20,7 @@
#include <QWidget>
#include <QSet>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QUrl>
#include "core/Global.h"
#include "core/Uuid.h"
@ -32,6 +30,11 @@ class Database;
class DefaultIconModel;
class CustomIconModel;
namespace qhttp {
namespace client {
class QHttpClient;
}
}
namespace Ui {
class EditWidgetIcons;
}
@ -54,10 +57,10 @@ public:
IconStruct state();
void reset();
void load(Uuid currentUuid, Database* database, IconStruct iconStruct, const QString &url = QString());
void load(const Uuid& currentUuid, Database* database, const IconStruct& iconStruct, const QString& url = "");
public Q_SLOTS:
void setUrl(const QString &url);
void setUrl(const QString& url);
Q_SIGNALS:
void messageEditEntry(QString, MessageWidget::MessageType);
@ -65,10 +68,9 @@ Q_SIGNALS:
private Q_SLOTS:
void downloadFavicon();
void fetchFavicon(QUrl url);
void fetchFaviconFromGoogle(QString domain);
void abortFaviconDownload(bool clearRedirect = true);
void onRequestFinished(QNetworkReply *reply);
void fetchFavicon(const QUrl& url);
void fetchFaviconFromGoogle(const QString& domain);
void resetFaviconDownload(bool clearRedirect = true);
void addCustomIcon();
void removeCustomIcon();
void updateWidgetsDefaultIcons(bool checked);
@ -86,8 +88,7 @@ private:
unsigned short m_redirectCount = 0;
DefaultIconModel* const m_defaultIconModel;
CustomIconModel* const m_customIconModel;
QNetworkAccessManager* const m_networkAccessMngr;
QNetworkReply* m_networkOperation;
qhttp::client::QHttpClient* m_httpClient;
Q_DISABLE_COPY(EditWidgetIcons)
};

View file

@ -6,15 +6,27 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<width>437</width>
<height>300</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="defaultIconsRadio">
<property name="text">
<string>Use default icon</string>
<string>&amp;Use default icon</string>
</property>
</widget>
</item>
@ -46,7 +58,7 @@
<item>
<widget class="QRadioButton" name="customIconsRadio">
<property name="text">
<string>Use custom icon</string>
<string>Use custo&amp;m icon</string>
</property>
</widget>
</item>

View file

@ -14,6 +14,15 @@
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="1" column="1">
<widget class="QLineEdit" name="createdEdit">
<property name="sizePolicy">

View file

@ -22,6 +22,11 @@
#include <QShortcut>
#include <QTimer>
#if defined(Q_OS_LINUX) && ! defined(QT_NO_DBUS)
#include <QList>
#include <QtDBus/QtDBus>
#endif
#include "config-keepassx.h"
#include "autotype/AutoType.h"
@ -138,14 +143,14 @@ MainWindow::MainWindow()
this, SLOT(lockDatabasesAfterInactivity()));
applySettingsChanges();
setShortcut(m_ui->actionDatabaseNew, QKeySequence::New, Qt::CTRL + Qt::Key_N);
setShortcut(m_ui->actionDatabaseNew, QKeySequence::New, Qt::CTRL + Qt::SHIFT + Qt::Key_N);
setShortcut(m_ui->actionDatabaseOpen, QKeySequence::Open, Qt::CTRL + Qt::Key_O);
setShortcut(m_ui->actionDatabaseSave, QKeySequence::Save, Qt::CTRL + Qt::Key_S);
setShortcut(m_ui->actionDatabaseSaveAs, QKeySequence::SaveAs);
setShortcut(m_ui->actionDatabaseClose, QKeySequence::Close, Qt::CTRL + Qt::Key_W);
m_ui->actionLockDatabases->setShortcut(Qt::CTRL + Qt::Key_L);
setShortcut(m_ui->actionQuit, QKeySequence::Quit, Qt::CTRL + Qt::Key_Q);
m_ui->actionEntryNew->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_N);
m_ui->actionEntryNew->setShortcut(Qt::CTRL + Qt::Key_N);
m_ui->actionEntryEdit->setShortcut(Qt::CTRL + Qt::Key_E);
m_ui->actionEntryDelete->setShortcut(Qt::CTRL + Qt::Key_D);
m_ui->actionEntryClone->setShortcut(Qt::CTRL + Qt::Key_K);
@ -590,7 +595,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
if (minimizeOnClose && !appExitCalled)
{
event->ignore();
hide();
toggleWindow();
if (config()->get("security/lockdatabaseminimize").toBool()) {
m_ui->tabWidget->lockDatabases();
@ -758,18 +763,37 @@ void MainWindow::trayIconTriggered(QSystemTrayIcon::ActivationReason reason)
void MainWindow::toggleWindow()
{
if ((QApplication::activeWindow() == this) && isVisible() && !isMinimized()) {
hide();
setWindowState(windowState() | Qt::WindowMinimized);
QTimer::singleShot(0, this, SLOT(hide()));
if (config()->get("security/lockdatabaseminimize").toBool()) {
m_ui->tabWidget->lockDatabases();
}
}
else {
} else {
ensurePolished();
setWindowState(windowState() & ~Qt::WindowMinimized);
show();
raise();
activateWindow();
#if defined(Q_OS_LINUX) && ! defined(QT_NO_DBUS)
// re-register global D-Bus menu (needed on Ubuntu with Unity)
// see https://github.com/keepassxreboot/keepassxc/issues/271
// and https://bugreports.qt.io/browse/QTBUG-58723
// check for !isVisible(), because isNativeMenuBar() does not work with appmenu-qt5
if (!m_ui->menubar->isVisible()) {
QDBusMessage msg = QDBusMessage::createMethodCall(
"com.canonical.AppMenu.Registrar",
"/com/canonical/AppMenu/Registrar",
"com.canonical.AppMenu.Registrar",
"RegisterWindow");
QList<QVariant> args;
args << QVariant::fromValue(static_cast<uint32_t>(winId()))
<< QVariant::fromValue(QDBusObjectPath("/MenuBar/1"));
msg.setArguments(args);
QDBusConnection::sessionBus().send(msg);
}
#endif
}
}

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>278</height>
<width>575</width>
<height>284</height>
</rect>
</property>
<property name="sizePolicy">
@ -16,10 +16,25 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>284</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<layout class="QGridLayout" name="passwordFieldLayout">
<property name="bottomMargin">
@ -232,13 +247,19 @@ QProgressBar::chunk {
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="alphabetLayout">
<layout class="QHBoxLayout" name="alphabetLayout" stretch="0,0,0,0,1">
<item>
<widget class="QToolButton" name="checkBoxUpper">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
<height>25</height>
</size>
</property>
<property name="focusPolicy">
@ -260,10 +281,16 @@ QProgressBar::chunk {
</item>
<item>
<widget class="QToolButton" name="checkBoxLower">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
<height>25</height>
</size>
</property>
<property name="focusPolicy">
@ -285,10 +312,16 @@ QProgressBar::chunk {
</item>
<item>
<widget class="QToolButton" name="checkBoxNumbers">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
<height>25</height>
</size>
</property>
<property name="focusPolicy">
@ -310,10 +343,16 @@ QProgressBar::chunk {
</item>
<item>
<widget class="QToolButton" name="checkBoxSpecialChars">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
<height>25</height>
</size>
</property>
<property name="focusPolicy">

View file

@ -65,6 +65,7 @@ SettingsWidget::SettingsWidget(QWidget* parent)
#ifdef Q_OS_MAC
// systray not useful on OS X
m_generalUi->systrayShowCheckBox->setVisible(false);
m_generalUi->systrayMinimizeOnCloseCheckBox->setVisible(false);
m_generalUi->systrayMinimizeToTrayCheckBox->setVisible(false);
#endif

View file

@ -77,9 +77,10 @@ EditEntryWidget::EditEntryWidget(QWidget* parent)
connect(this, SIGNAL(accepted()), SLOT(saveEntry()));
connect(this, SIGNAL(rejected()), SLOT(cancel()));
connect(m_iconsWidget, SIGNAL(messageEditEntry(QString, MessageWidget::MessageType)), SLOT(showMessage(QString, MessageWidget::MessageType)));
connect(m_iconsWidget, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage()));
m_mainUi->passwordGenerator->layout()->setContentsMargins(0, 0, 0, 0);
}
EditEntryWidget::~EditEntryWidget()

View file

@ -7,10 +7,22 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>315</height>
<height>366</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="attributesBox">
<property name="title">

View file

@ -7,10 +7,22 @@
<x>0</x>
<y>0</y>
<width>567</width>
<height>347</height>
<height>348</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="enableButton">
<property name="text">
@ -37,14 +49,14 @@
<item>
<widget class="QRadioButton" name="inheritSequenceButton">
<property name="text">
<string>Inherit default Auto-Type sequence from the group</string>
<string>Inherit default Auto-Type sequence from the &amp;group</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="customSequenceButton">
<property name="text">
<string>Use custom Auto-Type sequence:</string>
<string>&amp;Use custom Auto-Type sequence:</string>
</property>
</widget>
</item>
@ -90,39 +102,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="assocAddButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>+</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="assocRemoveButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="2,1,1">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
@ -136,6 +116,50 @@
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="assocAddButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="text">
<string>+</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="assocRemoveButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@ -171,14 +195,14 @@
<item>
<widget class="QRadioButton" name="defaultWindowSequenceButton">
<property name="text">
<string>Use default sequence</string>
<string>Use default se&amp;quence</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="customWindowSequenceButton">
<property name="text">
<string>Set custom sequence:</string>
<string>Set custo&amp;m sequence:</string>
</property>
</widget>
</item>

View file

@ -11,6 +11,18 @@
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="historyView">
<property name="sortingEnabled">

View file

@ -6,35 +6,50 @@
<rect>
<x>0</x>
<y>0</y>
<width>372</width>
<height>364</height>
<width>692</width>
<height>323</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="topMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="titleLabel">
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="5" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="urlLabel">
<property name="text">
<string>Title:</string>
<string>URL:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="titleEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="usernameLabel">
<property name="text">
<string>Username:</string>
<item row="4" column="1">
<widget class="PasswordGeneratorWidget" name="passwordGenerator" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="usernameEdit"/>
</item>
<item row="3" column="0">
<item row="2" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>Password:</string>
@ -42,31 +57,6 @@
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="PasswordEdit" name="passwordEdit">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="togglePasswordButton">
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="QLabel" name="passwordRepeatLabel">
<property name="text">
<string>Repeat:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="PasswordEdit" name="passwordRepeatEdit">
@ -84,24 +74,46 @@
</item>
</layout>
</item>
<item row="7" column="0">
<widget class="QLabel" name="urlLabel">
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="PasswordEdit" name="passwordEdit">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="togglePasswordButton">
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="passwordRepeatLabel">
<property name="text">
<string>URL:</string>
<string>Repeat:</string>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="titleLabel">
<property name="text">
<string>Title:</string>
</property>
</widget>
</item>
<item row="9" column="0" alignment="Qt::AlignRight|Qt::AlignTop">
<widget class="QLabel" name="notesLabel">
<property name="text">
<string>Notes:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="urlEdit"/>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="expireCheck">
<property name="text">
<string>Expires</string>
</property>
</widget>
</item>
<item row="8" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QDateTimeEdit" name="expireDatePicker">
@ -115,6 +127,12 @@
</item>
<item>
<widget class="QPushButton" name="expirePresets">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Presets</string>
</property>
@ -122,13 +140,6 @@
</item>
</layout>
</item>
<item row="9" column="0">
<widget class="QLabel" name="notesLabel">
<property name="text">
<string>Notes:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QPlainTextEdit" name="notesEdit">
<property name="sizePolicy">
@ -139,8 +150,28 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="PasswordGeneratorWidget" name="passwordGenerator" native="true"/>
<item row="1" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="usernameLabel">
<property name="text">
<string>Username:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="titleEdit"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="usernameEdit"/>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="urlEdit"/>
</item>
<item row="7" column="0" alignment="Qt::AlignRight">
<widget class="QCheckBox" name="expireCheck">
<property name="text">
<string>Expires</string>
</property>
</widget>
</item>
</layout>
</widget>
@ -165,7 +196,6 @@
<tabstop>togglePasswordButton</tabstop>
<tabstop>togglePasswordGeneratorButton</tabstop>
<tabstop>urlEdit</tabstop>
<tabstop>expireCheck</tabstop>
<tabstop>expireDatePicker</tabstop>
<tabstop>expirePresets</tabstop>
<tabstop>notesEdit</tabstop>

View file

@ -140,15 +140,21 @@ Entry* EntryView::entryFromIndex(const QModelIndex& index)
void EntryView::switchToEntryListMode()
{
m_sortModel->hideColumn(0, false);
sortByColumn(1, Qt::AscendingOrder); // TODO: should probably be improved
m_sortModel->sort(1, Qt::AscendingOrder);
m_sortModel->sort(0, Qt::AscendingOrder);
sortByColumn(0, Qt::AscendingOrder);
m_inEntryListMode = true;
}
void EntryView::switchToGroupMode()
{
m_sortModel->hideColumn(0, true);
sortByColumn(-1, Qt::AscendingOrder);
m_sortModel->sort(-1, Qt::AscendingOrder);
m_sortModel->sort(0, Qt::AscendingOrder);
sortByColumn(0, Qt::AscendingOrder);
m_inEntryListMode = false;
}