mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-07-28 09:14:18 -04:00
Merge branch 'meta/release-preparation' into release/2.1.1
This commit is contained in:
commit
26ff528a85
31 changed files with 1068 additions and 436 deletions
|
@ -218,6 +218,7 @@ target_link_libraries(${PROGNAME}
|
|||
Qt5::Widgets
|
||||
Qt5::Network
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GPGERROR_LIBRARIES}
|
||||
${ZLIB_LIBRARIES})
|
||||
|
||||
set_target_properties(${PROGNAME} PROPERTIES ENABLE_EXPORTS ON)
|
||||
|
@ -257,9 +258,25 @@ if(APPLE)
|
|||
endif()
|
||||
|
||||
if(MINGW)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
string(REPLACE "AMD" "Win" OUTPUT_FILE_POSTFIX "${CMAKE_HOST_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_GENERATOR "ZIP;NSIS")
|
||||
set(CPACK_STRIP_FILES ON)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSXC_VERSION_NUM}")
|
||||
set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSXC_VERSION}-${OUTPUT_FILE_POSTFIX}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${PROGNAME})
|
||||
set(CPACK_PACKAGE_VERSION ${KEEPASSXC_VERSION})
|
||||
set(CPACK_PACKAGE_VENDOR "${PROGNAME} Team")
|
||||
string(REGEX REPLACE "/" "\\\\\\\\" CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/share/windows/installer-header.bmp")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.GPL-2")
|
||||
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/share/windows/keepassxc.ico")
|
||||
set(CPACK_NSIS_MUI_UNIICON "${CPACK_NSIS_MUI_ICON}")
|
||||
set(CPACK_NSIS_INSTALLED_ICON_NAME "\\\\${PROGNAME}.exe")
|
||||
string(REGEX REPLACE "/" "\\\\\\\\" CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP "${CMAKE_SOURCE_DIR}/share/windows/installer-wizard.bmp")
|
||||
set(CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP "${CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP}")
|
||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${PROGNAME}.lnk' '$INSTDIR\\\\${PROGNAME}.exe'")
|
||||
set(CPACK_NSIS_DELETE_ICONS_EXTRA "Delete '$SMPROGRAMS\\\\$START_MENU\\\\${PROGNAME}.lnk'")
|
||||
set(CPACK_NSIS_URL_INFO_ABOUT "https://keepassxc.org")
|
||||
set(CPACK_NSIS_PACKAGE_NAME "${PROGNAME} v${KEEPASSXC_VERSION}")
|
||||
set(CPACK_NSIS_MUI_FINISHPAGE_RUN "../${PROGNAME}.exe")
|
||||
include(CPack)
|
||||
|
||||
install(CODE "
|
||||
|
@ -267,5 +284,9 @@ if(MINGW)
|
|||
" COMPONENT Runtime)
|
||||
|
||||
include(DeployQt4)
|
||||
install_qt4_executable(${PROGNAME}.exe "qjpeg;qgif;qico;qtaccessiblewidgets")
|
||||
install_qt4_executable(${PROGNAME}.exe)
|
||||
add_custom_command(TARGET ${PROGNAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${Qt5Core_DIR}/../../../share/qt5/plugins/platforms/qwindows$<$<CONFIG:Debug>:d>.dll
|
||||
$<TARGET_FILE_DIR:${PROGNAME}>)
|
||||
install(FILES $<TARGET_FILE_DIR:${PROGNAME}>/qwindows$<$<CONFIG:Debug>:d>.dll DESTINATION "platforms")
|
||||
endif()
|
||||
|
|
|
@ -353,6 +353,12 @@ void Entry::setTitle(const QString& title)
|
|||
|
||||
void Entry::setUrl(const QString& url)
|
||||
{
|
||||
bool remove = url != m_attributes->value(EntryAttributes::URLKey) &&
|
||||
(m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "1" ||
|
||||
m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "0");
|
||||
if (remove) {
|
||||
m_attributes->remove(EntryAttributes::RememberCmdExecAttr);
|
||||
}
|
||||
m_attributes->set(EntryAttributes::URLKey, url, m_attributes->isProtected(EntryAttributes::URLKey));
|
||||
}
|
||||
|
||||
|
@ -508,7 +514,8 @@ Entry* Entry::clone(CloneFlags flags) const
|
|||
entry->m_data.timeInfo.setLocationChanged(now);
|
||||
}
|
||||
|
||||
|
||||
if (flags & CloneRenameTitle)
|
||||
entry->setTitle(entry->title() + tr(" - Clone"));
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
|
|
@ -115,7 +115,8 @@ public:
|
|||
CloneNoFlags = 0,
|
||||
CloneNewUuid = 1, // generate a random uuid for the clone
|
||||
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
|
||||
CloneIncludeHistory = 4 // clone the history items
|
||||
CloneIncludeHistory = 4, // clone the history items
|
||||
CloneRenameTitle = 8 // add "-Clone" after the original title
|
||||
};
|
||||
Q_DECLARE_FLAGS(CloneFlags, CloneFlag)
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ const QString EntryAttributes::URLKey = "URL";
|
|||
const QString EntryAttributes::NotesKey = "Notes";
|
||||
const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey
|
||||
<< PasswordKey << URLKey << NotesKey);
|
||||
const QString EntryAttributes::RememberCmdExecAttr = "_EXEC_CMD";
|
||||
|
||||
EntryAttributes::EntryAttributes(QObject* parent)
|
||||
: QObject(parent)
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
static const QString URLKey;
|
||||
static const QString NotesKey;
|
||||
static const QStringList DefaultAttributes;
|
||||
static const QString RememberCmdExecAttr;
|
||||
static bool isDefaultAttribute(const QString& key);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
|
|
@ -42,7 +42,11 @@ QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Grou
|
|||
const QList<Group*> children = group->children();
|
||||
for (Group* childGroup : children) {
|
||||
if (childGroup->searchingEnabled() != Group::Disable) {
|
||||
searchResult.append(searchEntries(searchTerm, childGroup, caseSensitivity));
|
||||
if (matchGroup(searchTerm, childGroup, caseSensitivity)) {
|
||||
searchResult.append(childGroup->entriesRecursive());
|
||||
} else {
|
||||
searchResult.append(searchEntries(searchTerm, childGroup, caseSensitivity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,3 +73,21 @@ bool EntrySearcher::wordMatch(const QString& word, Entry* entry, Qt::CaseSensiti
|
|||
entry->url().contains(word, caseSensitivity) ||
|
||||
entry->notes().contains(word, caseSensitivity);
|
||||
}
|
||||
|
||||
bool EntrySearcher::matchGroup(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
|
||||
{
|
||||
const QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
|
||||
for (const QString& word : wordList) {
|
||||
if (!wordMatch(word, group, caseSensitivity)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EntrySearcher::wordMatch(const QString& word, const Group* group, Qt::CaseSensitivity caseSensitivity)
|
||||
{
|
||||
return group->name().contains(word, caseSensitivity) ||
|
||||
group->notes().contains(word, caseSensitivity);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ private:
|
|||
QList<Entry*> searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
|
||||
QList<Entry*> matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity);
|
||||
bool wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity);
|
||||
bool matchGroup(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
|
||||
bool wordMatch(const QString& word, const Group* group, Qt::CaseSensitivity caseSensitivity);
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_ENTRYSEARCHER_H
|
||||
|
|
|
@ -17,12 +17,20 @@
|
|||
*/
|
||||
|
||||
#include "Application.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QFileOpenEvent>
|
||||
#include <QSocketNotifier>
|
||||
|
||||
#include "autotype/AutoType.h"
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
|
||||
class XcbEventFilter : public QAbstractNativeEventFilter
|
||||
{
|
||||
|
@ -65,12 +73,18 @@ public:
|
|||
Application::Application(int& argc, char** argv)
|
||||
: QApplication(argc, argv)
|
||||
, m_mainWindow(nullptr)
|
||||
#ifdef Q_OS_UNIX
|
||||
, m_unixSignalNotifier(nullptr)
|
||||
#endif
|
||||
{
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
|
||||
installNativeEventFilter(new XcbEventFilter());
|
||||
#elif defined(Q_OS_WIN)
|
||||
installNativeEventFilter(new WinEventFilter());
|
||||
#endif
|
||||
#if defined(Q_OS_UNIX)
|
||||
registerUnixSignals();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::setMainWindow(QWidget* mainWindow)
|
||||
|
@ -98,3 +112,57 @@ bool Application::event(QEvent* event)
|
|||
|
||||
return QApplication::event(event);
|
||||
}
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
int Application::unixSignalSocket[2];
|
||||
|
||||
void Application::registerUnixSignals()
|
||||
{
|
||||
int result = ::socketpair(AF_UNIX, SOCK_STREAM, 0, unixSignalSocket);
|
||||
Q_ASSERT(0 == result);
|
||||
if (0 != result) {
|
||||
// do not register handles when socket creation failed, otherwise
|
||||
// application will be unresponsive to signals such as SIGINT or SIGTERM
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<int> const handledSignals = { SIGQUIT, SIGINT, SIGTERM, SIGHUP };
|
||||
for (auto s: handledSignals) {
|
||||
struct sigaction sigAction;
|
||||
|
||||
sigAction.sa_handler = handleUnixSignal;
|
||||
sigemptyset(&sigAction.sa_mask);
|
||||
sigAction.sa_flags = 0 | SA_RESTART;
|
||||
sigaction(s, &sigAction, nullptr);
|
||||
}
|
||||
|
||||
m_unixSignalNotifier = new QSocketNotifier(unixSignalSocket[1], QSocketNotifier::Read, this);
|
||||
connect(m_unixSignalNotifier, SIGNAL(activated(int)), this, SLOT(quitBySignal()));
|
||||
}
|
||||
|
||||
void Application::handleUnixSignal(int sig)
|
||||
{
|
||||
switch (sig) {
|
||||
case SIGQUIT:
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
{
|
||||
char buf = 0;
|
||||
::write(unixSignalSocket[0], &buf, sizeof(buf));
|
||||
return;
|
||||
}
|
||||
case SIGHUP:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::quitBySignal()
|
||||
{
|
||||
m_unixSignalNotifier->setEnabled(false);
|
||||
char buf;
|
||||
::read(unixSignalSocket[1], &buf, sizeof(buf));
|
||||
|
||||
if (nullptr != m_mainWindow)
|
||||
static_cast<MainWindow*>(m_mainWindow)->appExit();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <QApplication>
|
||||
|
||||
class QSocketNotifier;
|
||||
|
||||
class Application : public QApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -34,8 +36,23 @@ public:
|
|||
Q_SIGNALS:
|
||||
void openFile(const QString& filename);
|
||||
|
||||
private Q_SLOTS:
|
||||
#if defined(Q_OS_UNIX)
|
||||
void quitBySignal();
|
||||
#endif
|
||||
|
||||
private:
|
||||
QWidget* m_mainWindow;
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
/**
|
||||
* Register Unix signals such as SIGINT and SIGTERM for clean shutdown.
|
||||
*/
|
||||
void registerUnixSignals();
|
||||
QSocketNotifier* m_unixSignalNotifier;
|
||||
static void handleUnixSignal(int sig);
|
||||
static int unixSignalSocket[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_APPLICATION_H
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <QAction>
|
||||
#include <QDesktopServices>
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QFile>
|
||||
|
@ -312,8 +313,10 @@ void DatabaseWidget::cloneEntry()
|
|||
return;
|
||||
}
|
||||
|
||||
Entry* entry = currentEntry->clone(Entry::CloneNewUuid | Entry::CloneResetTimeInfo);
|
||||
Entry* entry = currentEntry->clone(Entry::CloneNewUuid | Entry::CloneResetTimeInfo | Entry::CloneRenameTitle);
|
||||
entry->setGroup(currentEntry->group());
|
||||
if (isInSearchMode())
|
||||
search(m_lastSearchText);
|
||||
m_entryView->setFocus();
|
||||
m_entryView->setCurrentEntry(entry);
|
||||
}
|
||||
|
@ -494,8 +497,46 @@ void DatabaseWidget::openUrlForEntry(Entry* entry)
|
|||
}
|
||||
|
||||
if (urlString.startsWith("cmd://")) {
|
||||
// check if decision to execute command was stored
|
||||
if (entry->attributes()->hasKey(EntryAttributes::RememberCmdExecAttr)) {
|
||||
if (entry->attributes()->value(EntryAttributes::RememberCmdExecAttr) == "1") {
|
||||
QProcess::startDetached(urlString.mid(6));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise ask user
|
||||
if (urlString.length() > 6) {
|
||||
QProcess::startDetached(urlString.mid(6));
|
||||
QString cmdTruncated = urlString.mid(6);
|
||||
if (cmdTruncated.length() > 400)
|
||||
cmdTruncated = cmdTruncated.left(400) + " […]";
|
||||
QMessageBox msgbox(QMessageBox::Icon::Question,
|
||||
tr("Execute command?"),
|
||||
tr("Do you really want to execute the following command?<br><br>%1<br>")
|
||||
.arg(cmdTruncated.toHtmlEscaped()),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
this
|
||||
);
|
||||
msgbox.setDefaultButton(QMessageBox::No);
|
||||
|
||||
QCheckBox* checkbox = new QCheckBox(tr("Remember my choice"), &msgbox);
|
||||
msgbox.setCheckBox(checkbox);
|
||||
bool remember = false;
|
||||
QObject::connect(checkbox, &QCheckBox::stateChanged, [&](int state) {
|
||||
if (static_cast<Qt::CheckState>(state) == Qt::CheckState::Checked) {
|
||||
remember = true;
|
||||
}
|
||||
});
|
||||
|
||||
int result = msgbox.exec();
|
||||
if (result == QMessageBox::Yes) {
|
||||
QProcess::startDetached(urlString.mid(6));
|
||||
}
|
||||
|
||||
if (remember) {
|
||||
entry->attributes()->set(EntryAttributes::RememberCmdExecAttr,
|
||||
result == QMessageBox::Yes ? "1" : "0");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -722,15 +763,10 @@ void DatabaseWidget::unlockDatabase(bool accepted)
|
|||
|
||||
replaceDatabase(db);
|
||||
|
||||
const QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
|
||||
for (Group* group : groups) {
|
||||
if (group->uuid() == m_groupBeforeLock) {
|
||||
m_groupView->setCurrentGroup(group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
restoreGroupEntryFocus(m_groupBeforeLock, m_entryBeforeLock);
|
||||
m_groupBeforeLock = Uuid();
|
||||
m_entryBeforeLock = Uuid();
|
||||
|
||||
setCurrentWidget(m_mainWidget);
|
||||
m_unlockDatabaseWidget->clearForms();
|
||||
Q_EMIT unlockedDatabase();
|
||||
|
@ -755,7 +791,7 @@ void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::Mod
|
|||
void DatabaseWidget::switchToEntryEdit()
|
||||
{
|
||||
Entry* entry = m_entryView->currentEntry();
|
||||
Q_ASSERT(entry);
|
||||
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
@ -766,7 +802,7 @@ void DatabaseWidget::switchToEntryEdit()
|
|||
void DatabaseWidget::switchToGroupEdit()
|
||||
{
|
||||
Group* group = m_groupView->currentGroup();
|
||||
Q_ASSERT(group);
|
||||
|
||||
if (!group) {
|
||||
return;
|
||||
}
|
||||
|
@ -943,6 +979,10 @@ void DatabaseWidget::lock()
|
|||
m_groupBeforeLock = m_db->rootGroup()->uuid();
|
||||
}
|
||||
|
||||
if (m_entryView->currentEntry()) {
|
||||
m_entryBeforeLock = m_entryView->currentEntry()->uuid();
|
||||
}
|
||||
|
||||
clearAllWidgets();
|
||||
m_unlockDatabaseWidget->load(m_filename);
|
||||
setCurrentWidget(m_unlockDatabaseWidget);
|
||||
|
@ -1028,7 +1068,22 @@ void DatabaseWidget::reloadDatabaseFile()
|
|||
}
|
||||
}
|
||||
|
||||
Uuid groupBeforeReload;
|
||||
if (m_groupView && m_groupView->currentGroup()) {
|
||||
groupBeforeReload = m_groupView->currentGroup()->uuid();
|
||||
}
|
||||
else {
|
||||
groupBeforeReload = m_db->rootGroup()->uuid();
|
||||
}
|
||||
|
||||
Uuid entryBeforeReload;
|
||||
if (m_entryView && m_entryView->currentEntry()) {
|
||||
entryBeforeReload = m_entryView->currentEntry()->uuid();
|
||||
}
|
||||
|
||||
replaceDatabase(db);
|
||||
restoreGroupEntryFocus(groupBeforeReload, entryBeforeReload);
|
||||
|
||||
}
|
||||
else {
|
||||
MessageBox::critical(this, tr("Autoreload Failed"),
|
||||
|
@ -1061,6 +1116,35 @@ QStringList DatabaseWidget::customEntryAttributes() const
|
|||
return entry->attributes()->customKeys();
|
||||
}
|
||||
|
||||
/*
|
||||
* Restores the focus on the group and entry that was focused
|
||||
* before the database was locked or reloaded.
|
||||
*/
|
||||
void DatabaseWidget::restoreGroupEntryFocus(Uuid groupUuid, Uuid entryUuid)
|
||||
{
|
||||
Group* restoredGroup = nullptr;
|
||||
const QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
|
||||
for (Group* group : groups) {
|
||||
if (group->uuid() == groupUuid) {
|
||||
restoredGroup = group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (restoredGroup != nullptr) {
|
||||
m_groupView->setCurrentGroup(restoredGroup);
|
||||
|
||||
const QList<Entry*> entries = restoredGroup->entries();
|
||||
for (Entry* entry : entries) {
|
||||
if (entry->uuid() == entryUuid) {
|
||||
m_entryView->setCurrentEntry(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool DatabaseWidget::isGroupSelected() const
|
||||
{
|
||||
return m_groupView->currentGroup() != nullptr;
|
||||
|
|
|
@ -163,6 +163,7 @@ private Q_SLOTS:
|
|||
// Database autoreload slots
|
||||
void onWatchedFileChanged();
|
||||
void reloadDatabaseFile();
|
||||
void restoreGroupEntryFocus(Uuid groupUuid, Uuid EntryUuid);
|
||||
|
||||
private:
|
||||
void setClipboardTextAndMinimize(const QString& text);
|
||||
|
@ -190,6 +191,7 @@ private:
|
|||
Group* m_newParent;
|
||||
QString m_filename;
|
||||
Uuid m_groupBeforeLock;
|
||||
Uuid m_entryBeforeLock;
|
||||
|
||||
// Search state
|
||||
QString m_lastSearchText;
|
||||
|
|
|
@ -364,7 +364,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
|
|||
bool groupSelected = dbWidget->isGroupSelected();
|
||||
|
||||
m_ui->actionEntryNew->setEnabled(!inSearch);
|
||||
m_ui->actionEntryClone->setEnabled(singleEntrySelected && !inSearch);
|
||||
m_ui->actionEntryClone->setEnabled(singleEntrySelected);
|
||||
m_ui->actionEntryEdit->setEnabled(singleEntrySelected);
|
||||
m_ui->actionEntryDelete->setEnabled(entriesSelected);
|
||||
m_ui->actionEntryCopyTitle->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTitle());
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
public Q_SLOTS:
|
||||
void openDatabase(const QString& fileName, const QString& pw = QString(),
|
||||
const QString& keyFile = QString());
|
||||
void appExit();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
@ -68,7 +69,6 @@ private Q_SLOTS:
|
|||
void applySettingsChanges();
|
||||
void trayIconTriggered(QSystemTrayIcon::ActivationReason reason);
|
||||
void toggleWindow();
|
||||
void appExit();
|
||||
void lockDatabasesAfterInactivity();
|
||||
void repairDatabase();
|
||||
|
||||
|
|
|
@ -155,15 +155,15 @@
|
|||
<addaction name="actionEntryCopyNotes"/>
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
<addaction name="actionEntryNew"/>
|
||||
<addaction name="actionEntryClone"/>
|
||||
<addaction name="actionEntryEdit"/>
|
||||
<addaction name="actionEntryDelete"/>
|
||||
<addaction name="actionEntryCopyUsername"/>
|
||||
<addaction name="actionEntryCopyPassword"/>
|
||||
<addaction name="menuEntryCopyAttribute"/>
|
||||
<addaction name="actionEntryAutoType"/>
|
||||
<addaction name="actionEntryOpenUrl"/>
|
||||
<addaction name="actionEntryEdit"/>
|
||||
<addaction name="actionEntryClone"/>
|
||||
<addaction name="actionEntryDelete"/>
|
||||
<addaction name="actionEntryNew"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuGroups">
|
||||
<property name="title">
|
||||
|
|
|
@ -41,6 +41,7 @@ SearchWidget::SearchWidget(QWidget *parent)
|
|||
connect(this, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear()));
|
||||
|
||||
new QShortcut(Qt::CTRL + Qt::Key_F, this, SLOT(searchFocus()), nullptr, Qt::ApplicationShortcut);
|
||||
new QShortcut(Qt::Key_Escape, m_ui->searchEdit, SLOT(clear()), nullptr, Qt::ApplicationShortcut);
|
||||
|
||||
m_ui->searchEdit->installEventFilter(this);
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ void EditEntryWidget::setupMain()
|
|||
add(tr("Entry"), m_mainWidget);
|
||||
|
||||
m_mainUi->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show"));
|
||||
m_mainUi->togglePasswordGeneratorButton->setIcon(filePath()->icon("actions", "password-generator", false));
|
||||
connect(m_mainUi->togglePasswordButton, SIGNAL(toggled(bool)), m_mainUi->passwordEdit, SLOT(setShowPassword(bool)));
|
||||
connect(m_mainUi->togglePasswordGeneratorButton, SIGNAL(toggled(bool)), SLOT(togglePasswordGeneratorButton(bool)));
|
||||
connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool)));
|
||||
|
@ -434,6 +435,9 @@ void EditEntryWidget::saveEntry()
|
|||
|
||||
void EditEntryWidget::updateEntryData(Entry* entry) const
|
||||
{
|
||||
entry->attributes()->copyCustomKeysFrom(m_entryAttributes);
|
||||
entry->attachments()->copyDataFrom(m_entryAttachments);
|
||||
|
||||
entry->setTitle(m_mainUi->titleEdit->text());
|
||||
entry->setUsername(m_mainUi->usernameEdit->text());
|
||||
entry->setUrl(m_mainUi->urlEdit->text());
|
||||
|
@ -443,9 +447,6 @@ void EditEntryWidget::updateEntryData(Entry* entry) const
|
|||
|
||||
entry->setNotes(m_mainUi->notesEdit->toPlainText());
|
||||
|
||||
entry->attributes()->copyCustomKeysFrom(m_entryAttributes);
|
||||
entry->attachments()->copyDataFrom(m_entryAttachments);
|
||||
|
||||
IconStruct iconStruct = m_iconsWidget->state();
|
||||
|
||||
if (iconStruct.number < 0) {
|
||||
|
|
|
@ -77,9 +77,6 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="togglePasswordGeneratorButton">
|
||||
<property name="text">
|
||||
<string>Generate</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -28,6 +28,16 @@
|
|||
#include "gui/MainWindow.h"
|
||||
#include "gui/MessageBox.h"
|
||||
|
||||
#ifdef QT_STATIC
|
||||
#include <QtPlugin>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
|
||||
#elif Q_OS_LINUX
|
||||
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#ifdef QT_NO_DEBUG
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue