Merge pull request #1702 from dwilches/hotfix/1313-grey-out-apply-button

Grey out Apply button when there are no changes
This commit is contained in:
Janek Bevendorff 2018-03-31 13:54:43 +02:00 committed by GitHub
commit bd654ea1db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 116 additions and 2 deletions

View File

@ -117,6 +117,14 @@ bool EditWidget::readOnly() const
return m_readOnly; return m_readOnly;
} }
void EditWidget::enableApplyButton(bool enabled)
{
QPushButton* applyButton = m_ui->buttonBox->button(QDialogButtonBox::Apply);
if (applyButton) {
applyButton->setEnabled(enabled);
}
}
void EditWidget::showMessage(const QString& text, MessageWidget::MessageType type) void EditWidget::showMessage(const QString& text, MessageWidget::MessageType type)
{ {
m_ui->messageWidget->setCloseButtonVisible(false); m_ui->messageWidget->setCloseButtonVisible(false);

View File

@ -47,6 +47,7 @@ public:
QLabel* headlineLabel(); QLabel* headlineLabel();
void setReadOnly(bool readOnly); void setReadOnly(bool readOnly);
bool readOnly() const; bool readOnly() const;
void enableApplyButton(bool enabled);
signals: signals:
void apply(); void apply();

View File

@ -66,6 +66,13 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent)
connect(m_ui->deleteButton, SIGNAL(clicked()), SLOT(removeCustomIcon())); connect(m_ui->deleteButton, SIGNAL(clicked()), SLOT(removeCustomIcon()));
connect(m_ui->faviconButton, SIGNAL(clicked()), SLOT(downloadFavicon())); connect(m_ui->faviconButton, SIGNAL(clicked()), SLOT(downloadFavicon()));
connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated()));
connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated()));
connect(m_ui->defaultIconsView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
this, SIGNAL(widgetUpdated()));
connect(m_ui->customIconsView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
this, SIGNAL(widgetUpdated()));
m_ui->faviconButton->setVisible(false); m_ui->faviconButton->setVisible(false);
} }
@ -268,6 +275,8 @@ void EditWidgetIcons::addCustomIcon(const QImage& icon)
updateRadioButtonCustomIcons(); updateRadioButtonCustomIcons();
QModelIndex index = m_customIconModel->indexFromUuid(uuid); QModelIndex index = m_customIconModel->indexFromUuid(uuid);
m_ui->customIconsView->setCurrentIndex(index); m_ui->customIconsView->setCurrentIndex(index);
emit widgetUpdated();
} }
} }
@ -347,6 +356,8 @@ void EditWidgetIcons::removeCustomIcon()
} else { } else {
m_ui->defaultIconsView->setCurrentIndex(m_defaultIconModel->index(Group::DefaultIconNumber)); m_ui->defaultIconsView->setCurrentIndex(m_defaultIconModel->index(Group::DefaultIconNumber));
} }
emit widgetUpdated();
} }
} }
} }

View File

@ -62,6 +62,7 @@ public slots:
signals: signals:
void messageEditEntry(QString, MessageWidget::MessageType); void messageEditEntry(QString, MessageWidget::MessageType);
void messageEditEntryDismiss(); void messageEditEntryDismiss();
void widgetUpdated();
private slots: private slots:
void downloadFavicon(); void downloadFavicon();

View File

@ -95,6 +95,7 @@ EditEntryWidget::EditEntryWidget(QWidget* parent)
#endif #endif
setupProperties(); setupProperties();
setupHistory(); setupHistory();
setupEntryUpdate();
connect(this, SIGNAL(accepted()), SLOT(acceptEntry())); connect(this, SIGNAL(accepted()), SLOT(acceptEntry()));
connect(this, SIGNAL(rejected()), SLOT(cancel())); connect(this, SIGNAL(rejected()), SLOT(cancel()));
@ -227,6 +228,59 @@ void EditEntryWidget::setupHistory()
connect(m_historyUi->deleteAllButton, SIGNAL(clicked()), SLOT(deleteAllHistoryEntries())); connect(m_historyUi->deleteAllButton, SIGNAL(clicked()), SLOT(deleteAllHistoryEntries()));
} }
void EditEntryWidget::setupEntryUpdate()
{
// Entry tab
connect(m_mainUi->titleEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges()));
connect(m_mainUi->usernameEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges()));
connect(m_mainUi->passwordEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges()));
connect(m_mainUi->passwordRepeatEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges()));
connect(m_mainUi->urlEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges()));
connect(m_mainUi->expireCheck, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_mainUi->notesEnabled, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_mainUi->expireDatePicker, SIGNAL(dateTimeChanged(const QDateTime&)), this, SLOT(setUnsavedChanges()));
connect(m_mainUi->notesEdit, SIGNAL(textChanged()), this, SLOT(setUnsavedChanges()));
// Advanced tab
connect(m_advancedUi->attributesEdit, SIGNAL(textChanged()), this, SLOT(setUnsavedChanges()));
connect(m_advancedUi->protectAttributeButton, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_advancedUi->fgColorCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_advancedUi->bgColorCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_advancedUi->attachmentsWidget, SIGNAL(widgetUpdated()), this, SLOT(setUnsavedChanges()));
// Icon tab
connect(m_iconsWidget, SIGNAL(widgetUpdated()), this, SLOT(setUnsavedChanges()));
// Auto-Type tab
connect(m_autoTypeUi->enableButton, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_autoTypeUi->customWindowSequenceButton, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_autoTypeUi->inheritSequenceButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges()));
connect(m_autoTypeUi->customSequenceButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges()));
connect(m_autoTypeUi->windowSequenceEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges()));
connect(m_autoTypeUi->sequenceEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges()));
connect(m_autoTypeUi->windowTitleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_autoTypeUi->windowTitleCombo, SIGNAL(editTextChanged(const QString&)), this, SLOT(setUnsavedChanges()));
// Properties and History tabs don't need extra connections
#ifdef WITH_XC_SSHAGENT
// SSH Agent tab
if (config()->get("SSHAgent", false).toBool()) {
connect(m_sshAgentUi->attachmentRadioButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->externalFileRadioButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->attachmentComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->attachmentComboBox, SIGNAL(editTextChanged(const QString&)), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->externalFileEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->publicKeyEdit, SIGNAL(textChanged()), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->addKeyToAgentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->removeKeyFromAgentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->requireUserConfirmationCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->lifetimeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges()));
connect(m_sshAgentUi->lifetimeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setUnsavedChanges()));
}
#endif
}
void EditEntryWidget::emitHistoryEntryActivated(const QModelIndex& index) void EditEntryWidget::emitHistoryEntryActivated(const QModelIndex& index)
{ {
Q_ASSERT(!m_history); Q_ASSERT(!m_history);
@ -581,7 +635,6 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const Q
m_database = database; m_database = database;
m_create = create; m_create = create;
m_history = history; m_history = history;
m_saved = false;
if (history) { if (history) {
setHeadline(QString("%1 > %2").arg(parentName, tr("Entry history"))); setHeadline(QString("%1 > %2").arg(parentName, tr("Entry history")));
@ -601,6 +654,9 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const Q
setCurrentPage(0); setCurrentPage(0);
setPageHidden(m_historyWidget, m_history || m_entry->historyItems().count() < 1); setPageHidden(m_historyWidget, m_history || m_entry->historyItems().count() < 1);
// Force the user to Save/Apply/Discard new entries
setUnsavedChanges(m_create);
} }
void EditEntryWidget::setForms(const Entry* entry, bool restore) void EditEntryWidget::setForms(const Entry* entry, bool restore)
@ -780,7 +836,7 @@ bool EditEntryWidget::commitEntry()
} }
updateEntryData(m_entry); updateEntryData(m_entry);
m_saved = true; setUnsavedChanges(false);
if (!m_create) { if (!m_create) {
m_entry->endUpdate(); m_entry->endUpdate();
@ -871,6 +927,19 @@ void EditEntryWidget::cancel()
m_entry->setIcon(Entry::DefaultIconNumber); m_entry->setIcon(Entry::DefaultIconNumber);
} }
if (!m_saved) {
auto result = MessageBox::question(this, QString(), tr("Entry has unsaved changes"),
QMessageBox::Cancel | QMessageBox::Save | QMessageBox::Discard,
QMessageBox::Cancel);
if (result == QMessageBox::Cancel) {
return;
}
if (result == QMessageBox::Save) {
commitEntry();
m_saved = true;
}
}
clear(); clear();
emit editFinished(m_saved); emit editFinished(m_saved);
@ -940,6 +1009,8 @@ void EditEntryWidget::insertAttribute()
m_advancedUi->attributesView->setCurrentIndex(index); m_advancedUi->attributesView->setCurrentIndex(index);
m_advancedUi->attributesView->edit(index); m_advancedUi->attributesView->edit(index);
setUnsavedChanges(true);
} }
void EditEntryWidget::editCurrentAttribute() void EditEntryWidget::editCurrentAttribute()
@ -950,6 +1021,7 @@ void EditEntryWidget::editCurrentAttribute()
if (index.isValid()) { if (index.isValid()) {
m_advancedUi->attributesView->edit(index); m_advancedUi->attributesView->edit(index);
setUnsavedChanges(true);
} }
} }
@ -963,6 +1035,7 @@ void EditEntryWidget::removeCurrentAttribute()
if (MessageBox::question(this, tr("Confirm Remove"), tr("Are you sure you want to remove this attribute?"), if (MessageBox::question(this, tr("Confirm Remove"), tr("Are you sure you want to remove this attribute?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
m_entryAttributes->remove(m_attributesModel->keyByIndex(index)); m_entryAttributes->remove(m_attributesModel->keyByIndex(index));
setUnsavedChanges(true);
} }
} }
} }
@ -1047,9 +1120,11 @@ void EditEntryWidget::revealCurrentAttribute()
if (! m_advancedUi->attributesEdit->isEnabled()) { if (! m_advancedUi->attributesEdit->isEnabled()) {
QModelIndex index = m_advancedUi->attributesView->currentIndex(); QModelIndex index = m_advancedUi->attributesView->currentIndex();
if (index.isValid()) { if (index.isValid()) {
bool oldBlockSignals = m_advancedUi->attributesEdit->blockSignals(true);
QString key = m_attributesModel->keyByIndex(index); QString key = m_attributesModel->keyByIndex(index);
m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key)); m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key));
m_advancedUi->attributesEdit->setEnabled(true); m_advancedUi->attributesEdit->setEnabled(true);
m_advancedUi->attributesEdit->blockSignals(oldBlockSignals);
} }
} }
} }
@ -1083,6 +1158,7 @@ void EditEntryWidget::insertAutoTypeAssoc()
m_autoTypeUi->assocView->setCurrentIndex(newIndex); m_autoTypeUi->assocView->setCurrentIndex(newIndex);
loadCurrentAssoc(newIndex); loadCurrentAssoc(newIndex);
m_autoTypeUi->windowTitleCombo->setFocus(); m_autoTypeUi->windowTitleCombo->setFocus();
setUnsavedChanges(true);
} }
void EditEntryWidget::removeAutoTypeAssoc() void EditEntryWidget::removeAutoTypeAssoc()
@ -1091,6 +1167,7 @@ void EditEntryWidget::removeAutoTypeAssoc()
if (currentIndex.isValid()) { if (currentIndex.isValid()) {
m_autoTypeAssoc->remove(currentIndex.row()); m_autoTypeAssoc->remove(currentIndex.row());
setUnsavedChanges(true);
} }
} }
@ -1153,6 +1230,7 @@ void EditEntryWidget::restoreHistoryEntry()
QModelIndex index = m_sortModel->mapToSource(m_historyUi->historyView->currentIndex()); QModelIndex index = m_sortModel->mapToSource(m_historyUi->historyView->currentIndex());
if (index.isValid()) { if (index.isValid()) {
setForms(m_historyModel->entryFromIndex(index), true); setForms(m_historyModel->entryFromIndex(index), true);
setUnsavedChanges(true);
} }
} }
@ -1166,6 +1244,7 @@ void EditEntryWidget::deleteHistoryEntry()
} else { } else {
m_historyUi->deleteAllButton->setEnabled(false); m_historyUi->deleteAllButton->setEnabled(false);
} }
setUnsavedChanges(true);
} }
} }
@ -1178,6 +1257,7 @@ void EditEntryWidget::deleteAllHistoryEntries()
else { else {
m_historyUi->deleteAllButton->setEnabled(false); m_historyUi->deleteAllButton->setEnabled(false);
} }
setUnsavedChanges(true);
} }
QMenu* EditEntryWidget::createPresetsMenu() QMenu* EditEntryWidget::createPresetsMenu()
@ -1229,5 +1309,12 @@ void EditEntryWidget::pickColor()
QColor newColor = colorDialog.getColor(oldColor); QColor newColor = colorDialog.getColor(oldColor);
if (newColor.isValid()) { if (newColor.isValid()) {
setupColorButton(isForeground, newColor); setupColorButton(isForeground, newColor);
setUnsavedChanges(true);
} }
} }
void EditEntryWidget::setUnsavedChanges(bool hasUnsaved)
{
m_saved = !hasUnsaved;
enableApplyButton(hasUnsaved);
}

View File

@ -100,6 +100,7 @@ private slots:
void useExpiryPreset(QAction* action); void useExpiryPreset(QAction* action);
void toggleHideNotes(bool visible); void toggleHideNotes(bool visible);
void pickColor(); void pickColor();
void setUnsavedChanges(bool hasUnsaved = true);
#ifdef WITH_XC_SSHAGENT #ifdef WITH_XC_SSHAGENT
void updateSSHAgent(); void updateSSHAgent();
void updateSSHAgentAttachment(); void updateSSHAgentAttachment();
@ -122,6 +123,7 @@ private:
#endif #endif
void setupProperties(); void setupProperties();
void setupHistory(); void setupHistory();
void setupEntryUpdate();
void setupColorButton(bool foreground, const QColor& color); void setupColorButton(bool foreground, const QColor& color);
bool passwordsEqual(); bool passwordsEqual();

View File

@ -147,6 +147,7 @@ void EntryAttachmentsWidget::insertAttachments()
if (!insertAttachments(filenames, errorMessage)) { if (!insertAttachments(filenames, errorMessage)) {
errorOccurred(errorMessage); errorOccurred(errorMessage);
} }
emit widgetUpdated();
} }
void EntryAttachmentsWidget::removeSelectedAttachments() void EntryAttachmentsWidget::removeSelectedAttachments()
@ -170,6 +171,7 @@ void EntryAttachmentsWidget::removeSelectedAttachments()
keys.append(m_attachmentsModel->keyByIndex(index)); keys.append(m_attachmentsModel->keyByIndex(index));
} }
m_entryAttachments->remove(keys); m_entryAttachments->remove(keys);
emit widgetUpdated();
} }
} }

View File

@ -39,6 +39,7 @@ signals:
void errorOccurred(const QString& error); void errorOccurred(const QString& error);
void readOnlyChanged(bool readOnly); void readOnlyChanged(bool readOnly);
void buttonsVisibleChanged(bool isButtonsVisible); void buttonsVisibleChanged(bool isButtonsVisible);
void widgetUpdated();
private slots: private slots:
void insertAttachments(); void insertAttachments();

View File

@ -492,6 +492,7 @@ void TestGui::testAddEntry()
// Add entry "something 5" but click cancel button (does NOT add entry) // Add entry "something 5" but click cancel button (does NOT add entry)
QTest::mouseClick(entryNewWidget, Qt::LeftButton); QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QTest::keyClicks(titleEdit, "something 5"); QTest::keyClicks(titleEdit, "something 5");
MessageBox::setNextAnswer(QMessageBox::Discard);
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Cancel), Qt::LeftButton); QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Cancel), Qt::LeftButton);
QApplication::processEvents(); QApplication::processEvents();