void DatabaseTabWidget::closeDatabaseFromSender() { Q_ASSERT(sender()); DatabaseWidget* dbWidget = static_cast<DatabaseWidget*>(sender()); Database* db = databaseFromDatabaseWidget(dbWidget); int index = databaseIndex(db); setCurrentIndex(index); closeDatabase(db); }
void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, const QString& keyFile) { QFileInfo fileInfo(fileName); QString canonicalFilePath = fileInfo.canonicalFilePath(); if (canonicalFilePath.isEmpty()) { MessageBox::warning(this, tr("Warning"), tr("File not found!")); return; } QHashIterator<Database*, DatabaseManagerStruct> i(m_dbList); while (i.hasNext()) { i.next(); if (i.value().canonicalFilePath == canonicalFilePath) { setCurrentIndex(databaseIndex(i.key())); return; } } DatabaseManagerStruct dbStruct; // test if we can read/write or read the file QFile file(fileName); // TODO: error handling if (!file.open(QIODevice::ReadWrite)) { if (!file.open(QIODevice::ReadOnly)) { // can't open // TODO: error message return; } else { // can only open read-only dbStruct.readOnly = true; } } file.close(); Database* db = new Database(); dbStruct.dbWidget = new DatabaseWidget(db, this); dbStruct.saveToFilename = !dbStruct.readOnly; dbStruct.filePath = fileInfo.absoluteFilePath(); dbStruct.canonicalFilePath = canonicalFilePath; dbStruct.fileName = fileInfo.fileName(); insertDatabase(db, dbStruct); updateLastDatabases(dbStruct.filePath); if (!pw.isNull() || !keyFile.isEmpty()) { dbStruct.dbWidget->switchToOpenDatabase(dbStruct.filePath, pw, keyFile); } else { dbStruct.dbWidget->switchToOpenDatabase(dbStruct.filePath); } }
void DatabaseTabWidget::insertDatabase(Database* db, const DatabaseManagerStruct& dbStruct) { m_dbList.insert(db, dbStruct); addTab(dbStruct.dbWidget, ""); toggleTabbar(); updateTabName(db); int index = databaseIndex(db); setCurrentIndex(index); connectDatabase(db); connect(dbStruct.dbWidget, SIGNAL(closeRequest()), SLOT(closeDatabaseFromSender())); connect(dbStruct.dbWidget, SIGNAL(databaseChanged(Database*)), SLOT(changeDatabase(Database*))); connect(dbStruct.dbWidget, SIGNAL(unlockedDatabase()), SLOT(updateTabNameFromDbWidgetSender())); }
bool DatabaseTabWidget::closeDatabase(Database* db) { Q_ASSERT(db); const DatabaseManagerStruct& dbStruct = m_dbList.value(db); int index = databaseIndex(db); Q_ASSERT(index != -1); QString dbName = tabText(index); if (dbName.right(1) == "*") { dbName.chop(1); } if (dbStruct.dbWidget->isInEditMode() && db->hasKey() && dbStruct.dbWidget->isEditWidgetModified()) { QMessageBox::StandardButton result = MessageBox::question( this, tr("Close?"), tr("\"%1\" is in edit mode.\nDiscard changes and close anyway?").arg(dbName), QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel); if (result == QMessageBox::Cancel) { return false; } } if (dbStruct.modified) { if (config()->get("AutoSaveOnExit").toBool()) { if (!saveDatabase(db)) { return false; } } else { QMessageBox::StandardButton result = MessageBox::question( this, tr("Save changes?"), tr("\"%1\" was modified.\nSave changes?").arg(dbName), QMessageBox::Yes | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Yes); if (result == QMessageBox::Yes) { if (!saveDatabase(db)) { return false; } } else if (result == QMessageBox::Cancel) { return false; } } } deleteDatabase(db); return true; }
void DatabaseTabWidget::deleteDatabase(Database* db) { const DatabaseManagerStruct dbStruct = m_dbList.value(db); bool emitDatabaseWithFileClosed = dbStruct.saveToFilename; QString filePath = dbStruct.filePath; int index = databaseIndex(db); removeTab(index); toggleTabbar(); m_dbList.remove(db); delete dbStruct.dbWidget; delete db; if (emitDatabaseWithFileClosed) { Q_EMIT databaseWithFileClosed(filePath); } }
void DatabaseTabWidget::updateTabName(Database* db) { int index = databaseIndex(db); Q_ASSERT(index != -1); const DatabaseManagerStruct& dbStruct = m_dbList.value(db); QString tabName; if (dbStruct.saveToFilename || dbStruct.readOnly) { if (db->metadata()->name().isEmpty()) { tabName = dbStruct.fileName; } else { tabName = db->metadata()->name(); } setTabToolTip(index, dbStruct.filePath); } else { if (db->metadata()->name().isEmpty()) { tabName = tr("New database"); } else { tabName = QString("%1 [%2]").arg(db->metadata()->name(), tr("New database")); } } if (dbStruct.dbWidget->currentMode() == DatabaseWidget::LockedMode) { tabName.append(QString(" [%1]").arg(tr("locked"))); } if (dbStruct.modified) { tabName.append("*"); } setTabText(index, tabName); Q_EMIT tabNameChanged(); }
void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, const QString& keyFile) { QFileInfo fileInfo(fileName); QString canonicalFilePath = fileInfo.canonicalFilePath(); if (canonicalFilePath.isEmpty()) { MessageBox::warning(this, tr("Warning"), tr("File not found!")); return; } QHashIterator<Database*, DatabaseManagerStruct> i(m_dbList); while (i.hasNext()) { i.next(); if (i.value().canonicalFilePath == canonicalFilePath) { setCurrentIndex(databaseIndex(i.key())); return; } } DatabaseManagerStruct dbStruct; // test if we can read/write or read the file QFile file(fileName); if (!file.open(QIODevice::ReadWrite)) { if (!file.open(QIODevice::ReadOnly)) { MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") .append(file.errorString())); return; } else { // can only open read-only dbStruct.readOnly = true; } } file.close(); QLockFile* lockFile = new QLockFile(QString("%1/.%2.lock").arg(fileInfo.canonicalPath(), fileInfo.fileName())); lockFile->setStaleLockTime(0); if (!dbStruct.readOnly && !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("Open database"), tr("The database you are trying to open is locked by another instance of KeePassX.\n" "Do you want to open it anyway? Alternatively the database is opened read-only."), QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::No) { dbStruct.readOnly = true; delete lockFile; lockFile = nullptr; } else { // take over the lock file if possible if (lockFile->removeStaleLockFile()) { lockFile->tryLock(); } } } } Database* db = new Database(); dbStruct.dbWidget = new DatabaseWidget(db, this); dbStruct.lockFile = lockFile; dbStruct.saveToFilename = !dbStruct.readOnly; dbStruct.filePath = fileInfo.absoluteFilePath(); dbStruct.canonicalFilePath = canonicalFilePath; dbStruct.fileName = fileInfo.fileName(); insertDatabase(db, dbStruct); updateLastDatabases(dbStruct.filePath); if (!pw.isNull() || !keyFile.isEmpty()) { dbStruct.dbWidget->switchToOpenDatabase(dbStruct.filePath, pw, keyFile); } else { dbStruct.dbWidget->switchToOpenDatabase(dbStruct.filePath); } }
void DatabaseTabWidget::checkReloadDatabases() { QSet<QString> changedFiles; changedFiles = m_changedFiles.subtract(m_expectedFileChanges); m_changedFiles.clear(); if (changedFiles.isEmpty()) return; Q_FOREACH (DatabaseManagerStruct dbStruct, m_dbList) { QString filePath = dbStruct.filePath; Database * db = dbStruct.dbWidget->database(); if (!changedFiles.contains(filePath)) continue; QFileInfo fi(filePath); QDateTime lastModified = fi.lastModified(); if (dbStruct.lastModified == lastModified) continue; DatabaseWidget::Mode mode = dbStruct.dbWidget->currentMode(); if (mode == DatabaseWidget::None || mode == DatabaseWidget::LockedMode || !db->hasKey()) continue; ReloadBehavior reloadBehavior = ReloadBehavior(config()->get("ReloadBehavior").toInt()); if ( (reloadBehavior == AlwaysAsk) || (reloadBehavior == ReloadUnmodified && mode == DatabaseWidget::EditMode) || (reloadBehavior == ReloadUnmodified && dbStruct.modified)) { int res = QMessageBox::warning(this, fi.exists() ? tr("Database file changed") : tr("Database file removed"), tr("Do you want to discard your changes and reload?"), QMessageBox::Yes|QMessageBox::No); if (res == QMessageBox::No) continue; } if (fi.exists()) { //Ignore/cancel all edits dbStruct.dbWidget->switchToView(false); dbStruct.modified = false; //Save current group/entry Uuid currentGroup; if (Group* group = dbStruct.dbWidget->currentGroup()) currentGroup = group->uuid(); Uuid currentEntry; if (Entry* entry = dbStruct.dbWidget->entryView()->currentEntry()) currentEntry = entry->uuid(); QString searchText = dbStruct.dbWidget->searchText(); bool caseSensitive = dbStruct.dbWidget->caseSensitiveSearch(); bool allGroups = dbStruct.dbWidget->isAllGroupsSearch(); //Reload updated db CompositeKey key = db->key(); int tabPos = databaseIndex(db); closeDatabase(db); openDatabase(filePath, QString(), QString(), key, tabPos); //Restore current group/entry dbStruct = indexDatabaseManagerStruct(count() - 1); if (dbStruct.dbWidget && dbStruct.dbWidget->currentMode() == DatabaseWidget::ViewMode) { Database * db = dbStruct.dbWidget->database(); if (!currentGroup.isNull()) if (Group* group = db->resolveGroup(currentGroup)) dbStruct.dbWidget->groupView()->setCurrentGroup(group); if (!searchText.isEmpty()) dbStruct.dbWidget->search(searchText, caseSensitive, allGroups); if (!currentEntry.isNull()) if (Entry* entry = db->resolveEntry(currentEntry)) dbStruct.dbWidget->entryView()->setCurrentEntry(entry); } } else { //Ignore/cancel all edits dbStruct.dbWidget->switchToView(false); dbStruct.modified = false; //Close database closeDatabase(dbStruct.dbWidget->database()); } }