Example #1
0
void DatabaseTabWidget::closeDatabaseFromSender()
{
    Q_ASSERT(sender());
    DatabaseWidget* dbWidget = static_cast<DatabaseWidget*>(sender());
    Database* db = databaseFromDatabaseWidget(dbWidget);
    int index = databaseIndex(db);
    setCurrentIndex(index);
    closeDatabase(db);
}
Example #2
0
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);
    }
}
Example #3
0
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()));
}
Example #4
0
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;
}
Example #5
0
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);
    }
}
Example #6
0
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();
}
Example #7
0
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);
    }
}
Example #8
0
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());
        }
    }