mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ private:
|
||||
|
||||
QLabel* statusEncodingLabel;
|
||||
QLabel* statusEncryptionLabel;
|
||||
QLabel* statusReadOnlyLabel;
|
||||
|
||||
DbStructureModel* dbStructureModel;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user