Support read only opening of database files

When opening a read only database file show a 'Read only' note in the
status bar of the main window and disable all editing buttons in the UI.

See issue #402.
This commit is contained in:
Martin Kleusberg
2015-08-25 19:28:40 +02:00
parent a8c52eba12
commit 90bb4891b9
4 changed files with 52 additions and 33 deletions

View File

@@ -143,19 +143,26 @@ void MainWindow::init()
ui->viewMenu->actions().at(2)->setIcon(QIcon(":/icons/log_dock"));
// Set statusbar fields
statusEncryptionLabel = new QLabel(ui->statusbar);
statusEncryptionLabel->setEnabled(false);
statusEncryptionLabel->setVisible(false);
statusEncryptionLabel->setText(tr("Encrypted"));
statusEncryptionLabel->setToolTip(tr("Database is encrypted using SQLCipher"));
ui->statusbar->addPermanentWidget(statusEncryptionLabel);
statusReadOnlyLabel = new QLabel(ui->statusbar);
statusReadOnlyLabel->setEnabled(false);
statusReadOnlyLabel->setVisible(false);
statusReadOnlyLabel->setText(tr("Read only"));
statusReadOnlyLabel->setToolTip(tr("Database file is read only. Editing the database is disabled."));
ui->statusbar->addPermanentWidget(statusReadOnlyLabel);
statusEncodingLabel = new QLabel(ui->statusbar);
statusEncodingLabel->setEnabled(false);
statusEncodingLabel->setText("UTF-8");
statusEncodingLabel->setToolTip(tr("Database encoding"));
ui->statusbar->addPermanentWidget(statusEncodingLabel);
statusEncryptionLabel = new QLabel(ui->statusbar);
statusEncryptionLabel->setEnabled(false);
statusEncryptionLabel->setVisible(false);
statusEncryptionLabel->setText("Encrypted");
statusEncryptionLabel->setToolTip(tr("Database is encrypted using SQLCipher"));
ui->statusbar->addPermanentWidget(statusEncryptionLabel);
// Connect some more signals and slots
connect(ui->dataTable->filterHeader(), SIGNAL(sectionClicked(int)), this, SLOT(browseTableHeaderClicked(int)));
connect(ui->dataTable->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setRecordsetLabel()));
@@ -233,6 +240,7 @@ bool MainWindow::fileOpen(const QString& fileName, bool dontAddToRecentFiles)
{
statusEncodingLabel->setText(db.getPragma("encoding"));
statusEncryptionLabel->setVisible(db.encrypted());
statusReadOnlyLabel->setVisible(db.readOnly());
setCurrentFile(wFile);
if(!dontAddToRecentFiles)
addToRecentFilesMenu(wFile);
@@ -266,6 +274,8 @@ void MainWindow::fileNew()
setCurrentFile(fileName);
addToRecentFilesMenu(fileName);
statusEncodingLabel->setText(db.getPragma("encoding"));
statusEncryptionLabel->setVisible(false);
statusReadOnlyLabel->setVisible(false);
loadExtensionsFromSettings();
populateStructure();
resetBrowser();
@@ -393,10 +403,10 @@ void MainWindow::populateTable(const QString& tablename)
}
// Activate the add and delete record buttons and editing only if a table has been selected
bool is_table = db.getObjectByName(tablename).gettype() == "table";
ui->buttonNewRecord->setEnabled(is_table);
ui->buttonDeleteRecord->setEnabled(is_table);
ui->dataTable->setEditTriggers(is_table ? QAbstractItemView::SelectedClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed : QAbstractItemView::NoEditTriggers);
bool editable = db.getObjectByName(tablename).gettype() == "table" && !db.readOnly();
ui->buttonNewRecord->setEnabled(editable);
ui->buttonDeleteRecord->setEnabled(editable);
ui->dataTable->setEditTriggers(editable ? QAbstractItemView::SelectedClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed : QAbstractItemView::NoEditTriggers);
// Set the recordset label
setRecordsetLabel();
@@ -451,6 +461,7 @@ void MainWindow::fileClose()
populateStructure();
loadPragmas();
statusEncryptionLabel->setVisible(false);
statusReadOnlyLabel->setVisible(false);
// Delete the model for the Browse tab and create a new one
delete m_browseTableModel;
@@ -1015,10 +1026,6 @@ void MainWindow::openPreferences()
reloadSettings();
}
//******************************************************************
//** Tree Events
//******************************************************************
//** Db Tree Context Menu
void MainWindow::createTreeContextMenu(const QPoint &qPoint)
{
@@ -1056,14 +1063,14 @@ void MainWindow::changeTreeSelection()
// Activate actions
if(type == "table")
{
ui->editDeleteObjectAction->setEnabled(true);
ui->editModifyTableAction->setEnabled(true);
ui->editDeleteObjectAction->setEnabled(!db.readOnly());
ui->editModifyTableAction->setEnabled(!db.readOnly());
} else if(type == "view" || type == "trigger" || type == "index") {
ui->editDeleteObjectAction->setEnabled(true);
ui->editDeleteObjectAction->setEnabled(!db.readOnly());
}
if(type == "table" || type == "view")
{
ui->actionEditBrowseTable->setEnabled(true);
ui->actionEditBrowseTable->setEnabled(!db.readOnly());
ui->actionExportCsvPopup->setEnabled(true);
}
}
@@ -1153,24 +1160,26 @@ void MainWindow::dropEvent(QDropEvent *event)
void MainWindow::activateFields(bool enable)
{
bool write = !db.readOnly();
ui->fileCloseAction->setEnabled(enable);
ui->fileCompactAction->setEnabled(enable);
ui->fileCompactAction->setEnabled(enable && write);
ui->fileExportCSVAction->setEnabled(enable);
ui->fileExportSQLAction->setEnabled(enable);
ui->fileImportCSVAction->setEnabled(enable);
ui->editCreateTableAction->setEnabled(enable);
ui->editCreateIndexAction->setEnabled(enable);
ui->fileImportCSVAction->setEnabled(enable && write);
ui->editCreateTableAction->setEnabled(enable && write);
ui->editCreateIndexAction->setEnabled(enable && write);
ui->buttonNext->setEnabled(enable);
ui->buttonPrevious->setEnabled(enable);
ui->buttonBegin->setEnabled(enable);
ui->buttonEnd->setEnabled(enable);
ui->scrollAreaWidgetContents->setEnabled(enable);
ui->buttonBoxPragmas->setEnabled(enable);
ui->buttonBoxPragmas->setEnabled(enable && write);
ui->buttonGoto->setEnabled(enable);
ui->editGoto->setEnabled(enable);
ui->buttonRefresh->setEnabled(enable);
ui->buttonDeleteRecord->setEnabled(enable);
ui->buttonNewRecord->setEnabled(enable);
ui->buttonDeleteRecord->setEnabled(enable && write);
ui->buttonNewRecord->setEnabled(enable && write);
ui->actionExecuteSql->setEnabled(enable);
ui->actionLoadExtension->setEnabled(enable);
ui->actionSqlExecuteLine->setEnabled(enable);
@@ -1180,7 +1189,7 @@ void MainWindow::activateFields(bool enable)
ui->actionSqlSaveFileAs->setEnabled(enable);
ui->actionSqlSaveFile->setEnabled(enable);
ui->actionSaveProject->setEnabled(enable);
ui->actionEncryption->setEnabled(enable);
ui->actionEncryption->setEnabled(enable && write);
ui->buttonClearFilters->setEnabled(enable);
}

View File

@@ -105,6 +105,7 @@ private:
QLabel* statusEncodingLabel;
QLabel* statusEncryptionLabel;
QLabel* statusReadOnlyLabel;
DbStructureModel* dbStructureModel;

View File

@@ -10,6 +10,8 @@
#include <QSettings>
#include <QDebug>
#include <QInputDialog>
#include <QFileInfo>
#include <QDir>
// collation callbacks
int collCompare(void* /*pArg*/, int /*eTextRepA*/, const void* sA, int /*eTextRepB*/, const void* sB)
@@ -136,6 +138,11 @@ bool DBBrowserDB::open(const QString& db)
if(settings.value("/extensions/disableregex", false) == false)
sqlite3_create_function(_db, "REGEXP", 2, SQLITE_UTF8, NULL, regexp, NULL, NULL);
// Check if file is read only
QFileInfo fi(db);
QFileInfo fid(fi.absoluteDir().absolutePath());
isReadOnly = !fi.isWritable() || !fid.isWritable();
curDBFilename = db;
return true;
} else {
@@ -313,8 +320,6 @@ bool DBBrowserDB::revertAll()
bool DBBrowserDB::create ( const QString & db)
{
bool ok=false;
if (isOpen()) close();
// read encoding from settings and open with sqlite3_open for utf8
@@ -354,11 +359,13 @@ bool DBBrowserDB::create ( const QString & db)
executeSQL("DROP TABLE notempty;", false, false);
executeSQL("COMMIT;", false, false);
ok = true;
curDBFilename = db;
isEncrypted = false;
isReadOnly = false;
return true;
} else {
return false;
}
return ok;
}

View File

@@ -43,7 +43,7 @@ class DBBrowserDB : public QObject
Q_OBJECT
public:
explicit DBBrowserDB () : _db(0), isEncrypted(false) {}
explicit DBBrowserDB () : _db(0), isEncrypted(false), isReadOnly(false) {}
virtual ~DBBrowserDB (){}
bool open ( const QString & db);
bool attach(const QString& filename, QString attach_as = "");
@@ -106,6 +106,7 @@ public:
DBBrowserObject getObjectByName(const QString& name) const;
bool isOpen() const;
bool encrypted() const { return isEncrypted; }
bool readOnly() const { return isReadOnly; }
bool getDirty() const;
void logSQL(QString statement, int msgtype);
@@ -131,6 +132,7 @@ private:
QStringList savepointList;
bool isEncrypted;
bool isReadOnly;
bool tryEncryptionSettings(const QString& filename, bool* encrypted, CipherDialog*& cipherSettings);
};