dbhub: Add remote dock with directory browsing support · stjordanis/sqlitebrowser@3e4f3fc · GitHub
Skip to content

Commit 3e4f3fc

Browse files
committed
dbhub: Add remote dock with directory browsing support
This adds a new dock to the main window that contains all the remote functionality (or is supposed to contain it all in the future). It also adds a directory browsing feature which allows you to browse through the folders and files on the dbhub server. By double clicking a database you can download and open it. The Open Remote menu action isn't needed anymore and has been removed. This also fixes an issue with pushing databases where, after sending the file is completed, the save dialog was opened. Note that this is still WIP and is far from polished.
1 parent dc3550e commit 3e4f3fc

16 files changed

Lines changed: 758 additions & 49 deletions

‎CMakeLists.txt‎

Lines changed: 5 additions & 0 deletions

‎src/MainWindow.cpp‎

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "FileDialog.h"
2222
#include "ColumnDisplayFormatDialog.h"
2323
#include "FilterTableHeader.h"
24+
#include "RemoteDock.h"
2425

2526
#include <QFile>
2627
#include <QApplication>
@@ -55,8 +56,10 @@ MainWindow::MainWindow(QWidget* parent)
5556
ui(new Ui::MainWindow),
5657
m_browseTableModel(new SqliteTableModel(db, this, Settings::getSettingsValue("db", "prefetchsize").toInt())),
5758
m_currentTabTableModel(m_browseTableModel),
59+
m_remoteDb(new RemoteDatabase),
5860
editDock(new EditDialog(this)),
5961
plotDock(new PlotDock(this)),
62+
remoteDock(new RemoteDock(this)),
6063
gotoValidator(new QIntValidator(0, 0, this))
6164
{
6265
ui->setupUi(this);
@@ -68,6 +71,7 @@ MainWindow::MainWindow(QWidget* parent)
6871

6972
MainWindow::~MainWindow()
7073
{
74+
delete m_remoteDb;
7175
delete gotoValidator;
7276
delete ui;
7377
}
@@ -77,6 +81,7 @@ void MainWindow::init()
7781
// Load window settings
7882
tabifyDockWidget(ui->dockLog, ui->dockPlot);
7983
tabifyDockWidget(ui->dockLog, ui->dockSchema);
84+
tabifyDockWidget(ui->dockLog, ui->dockRemote);
8085

8186
// Connect SQL logging and database state setting to main window
8287
connect(&db, SIGNAL(dbChanged(bool)), this, SLOT(dbState(bool)));
@@ -107,6 +112,7 @@ void MainWindow::init()
107112
// Create docks
108113
ui->dockEdit->setWidget(editDock);
109114
ui->dockPlot->setWidget(plotDock);
115+
ui->dockRemote->setWidget(remoteDock);
110116

111117
// Restore window geometry
112118
restoreGeometry(Settings::getSettingsValue("MainWindow", "geometry").toByteArray());
@@ -183,10 +189,12 @@ void MainWindow::init()
183189

184190
// Add menu item for edit dock
185191
ui->viewMenu->insertAction(ui->viewDBToolbarAction, ui->dockEdit->toggleViewAction());
192+
ui->viewMenu->actions().at(3)->setShortcut(QKeySequence(tr("Ctrl+E")));
186193
ui->viewMenu->actions().at(3)->setIcon(QIcon(":/icons/log_dock"));
187194

188-
// Add keyboard shortcut for "Edit Cell" dock
189-
ui->viewMenu->actions().at(3)->setShortcut(QKeySequence(tr("Ctrl+E")));
195+
// Add menu item for plot dock
196+
ui->viewMenu->insertAction(ui->viewDBToolbarAction, ui->dockRemote->toggleViewAction());
197+
ui->viewMenu->actions().at(4)->setIcon(QIcon(":/icons/log_dock"));
190198

191199
// If we're not compiling in SQLCipher, hide its FAQ link in the help menu
192200
#ifndef ENABLE_SQLCIPHER
@@ -223,7 +231,7 @@ void MainWindow::init()
223231
connect(ui->dataTable->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDataColumnPopupMenu(QPoint)));
224232
connect(ui->dataTable->verticalHeader(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showRecordPopupMenu(QPoint)));
225233
connect(ui->dockEdit, SIGNAL(visibilityChanged(bool)), this, SLOT(toggleEditDock(bool)));
226-
connect(&m_remoteDb, SIGNAL(openFile(QString)), this, SLOT(fileOpen(QString)));
234+
connect(m_remoteDb, SIGNAL(openFile(QString)), this, SLOT(fileOpen(QString)));
227235

228236
// Lambda function for keyboard shortcuts for selecting next/previous table in Browse Data tab
229237
connect(ui->dataTable, &ExtendedTableWidget::switchTable, [this](bool next) {
@@ -274,6 +282,7 @@ void MainWindow::init()
274282
ui->dockLog->setWindowTitle(ui->dockLog->windowTitle().remove('&'));
275283
ui->dockPlot->setWindowTitle(ui->dockPlot->windowTitle().remove('&'));
276284
ui->dockSchema->setWindowTitle(ui->dockSchema->windowTitle().remove('&'));
285+
ui->dockRemote->setWindowTitle(ui->dockRemote->windowTitle().remove('&'));
277286
}
278287

279288
bool MainWindow::fileOpen(const QString& fileName, bool dontAddToRecentFiles, bool readOnly)
@@ -1717,11 +1726,17 @@ void MainWindow::reloadSettings()
17171726
populateTable();
17181727

17191728
// Hide or show the File → Remote menu as needed
1720-
QAction *remoteMenuAction = ui->menuRemote->menuAction();
1721-
remoteMenuAction->setVisible(Settings::getSettingsValue("remote", "active").toBool());
1729+
bool showRemoteActions = Settings::getSettingsValue("remote", "active").toBool();
1730+
ui->menuRemote->menuAction()->setVisible(showRemoteActions);
1731+
ui->viewMenu->actions().at(4)->setVisible(showRemoteActions);
1732+
if(!showRemoteActions)
1733+
ui->dockRemote->setHidden(true);
17221734

17231735
// Update the remote database connection settings
1724-
m_remoteDb.reloadSettings();
1736+
m_remoteDb->reloadSettings();
1737+
1738+
// Reload remote dock settings
1739+
remoteDock->reloadSettings();
17251740
}
17261741

17271742
void MainWindow::httpresponse(QNetworkReply *reply)
@@ -1801,23 +1816,13 @@ void MainWindow::httpresponse(QNetworkReply *reply)
18011816
reply->deleteLater();
18021817
}
18031818

1804-
void MainWindow::on_actionOpen_Remote_triggered()
1805-
{
1806-
QString url = QInputDialog::getText(this, qApp->applicationName(), tr("Please enter the URL of the database file to open."));
1807-
if(!url.isEmpty())
1808-
{
1809-
QStringList certs = Settings::getSettingsValue("remote", "client_certificates").toStringList();
1810-
m_remoteDb.fetchDatabase(url, (certs.size() ? certs.at(0) : ""));
1811-
}
1812-
}
1813-
18141819
void MainWindow::on_actionSave_Remote_triggered()
18151820
{
18161821
QString url = QInputDialog::getText(this, qApp->applicationName(), tr("Please enter the URL of the database file to save."));
18171822
if(!url.isEmpty())
18181823
{
18191824
QStringList certs = Settings::getSettingsValue("remote", "client_certificates").toStringList();
1820-
m_remoteDb.pushDatabase(db.currentFile(), url, (certs.size() ? certs.at(0) : ""));
1825+
m_remoteDb->push(db.currentFile(), url, (certs.size() ? certs.at(0) : ""));
18211826
}
18221827
}
18231828

‎src/MainWindow.h‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class SqliteTableModel;
1818
class DbStructureModel;
1919
class QNetworkReply;
2020
class QNetworkAccessManager;
21+
class RemoteDock;
2122

2223
namespace Ui {
2324
class MainWindow;
@@ -83,7 +84,7 @@ class MainWindow : public QMainWindow
8384
~MainWindow();
8485

8586
DBBrowserDB& getDb() { return db; }
86-
const RemoteDatabase& getRemote() const { return m_remoteDb; }
87+
RemoteDatabase& getRemote() { return *m_remoteDb; }
8788

8889
enum Tabs
8990
{
@@ -137,13 +138,16 @@ class MainWindow : public QMainWindow
137138

138139
QMap<QString, BrowseDataTableSettings> browseTableSettings;
139140

141+
RemoteDatabase* m_remoteDb;
142+
140143
EditDialog* editDock;
141144
PlotDock* plotDock;
145+
RemoteDock* remoteDock;
146+
142147
QIntValidator* gotoValidator;
143148

144149
DBBrowserDB db;
145150
QString defaultBrowseTableEncoding;
146-
RemoteDatabase m_remoteDb;
147151

148152
QNetworkAccessManager* m_NetworkManager;
149153

@@ -205,7 +209,6 @@ private slots:
205209
void exportTableToJson();
206210
void fileSave();
207211
void fileRevert();
208-
void on_actionOpen_Remote_triggered();
209212
void on_actionSave_Remote_triggered();
210213
void exportDatabaseToSQL();
211214
void importDatabaseFromSQL();

‎src/MainWindow.ui‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,6 @@
883883
<property name="title">
884884
<string>Remote</string>
885885
</property>
886-
<addaction name="actionOpen_Remote"/>
887886
<addaction name="actionSave_Remote"/>
888887
</widget>
889888
<addaction name="fileNewAction"/>
@@ -1120,6 +1119,15 @@
11201119
</layout>
11211120
</widget>
11221121
</widget>
1122+
<widget class="QDockWidget" name="dockRemote">
1123+
<property name="windowTitle">
1124+
<string>&amp;Remote</string>
1125+
</property>
1126+
<attribute name="dockWidgetArea">
1127+
<number>2</number>
1128+
</attribute>
1129+
<widget class="QWidget" name="dockWidgetContents_5"/>
1130+
</widget>
11231131
<action name="fileNewAction">
11241132
<property name="icon">
11251133
<iconset resource="icons/icons.qrc">
@@ -1737,11 +1745,6 @@
17371745
<enum>QAction::NoRole</enum>
17381746
</property>
17391747
</action>
1740-
<action name="actionOpen_Remote">
1741-
<property name="text">
1742-
<string>Open from Remote</string>
1743-
</property>
1744-
</action>
17451748
<action name="actionSave_Remote">
17461749
<property name="text">
17471750
<string>Save to Remote</string>

‎src/RemoteDatabase.cpp‎

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,28 +86,38 @@ void RemoteDatabase::gotReply(QNetworkReply* reply)
8686
if(reply->error() != QNetworkReply::NoError)
8787
{
8888
QMessageBox::warning(0, qApp->applicationName(),
89-
tr("Error opening remote database file from %1.\n%2").arg(reply->url().toString()).arg(reply->errorString()));
89+
tr("Error when connecting to %1.\n%2").arg(reply->url().toString()).arg(reply->errorString()));
9090
reply->deleteLater();
9191
return;
9292
}
9393

94-
// Ask user where to store the database file
95-
QString saveFileAs = FileDialog::getSaveFileName(0, qApp->applicationName(), FileDialog::getSqlDatabaseFileFilter(), reply->url().fileName());
96-
if(!saveFileAs.isEmpty())
97-
{
98-
// Save the downloaded data under the selected file name
99-
QFile file(saveFileAs);
100-
file.open(QIODevice::WriteOnly);
101-
file.write(reply->readAll());
102-
file.close();
94+
// What type of data is this?
95+
QString type = reply->property("type").toString();
10396

104-
// Tell the application to open this file
105-
emit openFile(saveFileAs);
97+
// Handle the reply data
98+
if(type == "database")
99+
{
100+
// It's a database file. Ask user where to store the database file.
101+
QString saveFileAs = FileDialog::getSaveFileName(0, qApp->applicationName(), FileDialog::getSqlDatabaseFileFilter(), reply->url().fileName());
102+
if(!saveFileAs.isEmpty())
103+
{
104+
// Save the downloaded data under the selected file name
105+
QFile file(saveFileAs);
106+
file.open(QIODevice::WriteOnly);
107+
file.write(reply->readAll());
108+
file.close();
109+
110+
// Tell the application to open this file
111+
emit openFile(saveFileAs);
112+
}
113+
} else if(type == "dir") {
114+
emit gotDirList(reply->readAll(), reply->property("userdata"));
106115
}
107116

108117
// Delete reply later, i.e. after returning from this slot function
109118
m_currentReply = nullptr;
110-
m_progress->hide();
119+
if(type == "database" || type == "push")
120+
m_progress->hide();
111121
reply->deleteLater();
112122
}
113123

@@ -133,7 +143,7 @@ void RemoteDatabase::gotError(QNetworkReply* reply, const QList<QSslError>& erro
133143
}
134144

135145
// Build an error message and short it to the user
136-
QString message = tr("Error opening remote database file from %1.\n%2").arg(reply->url().toString()).arg(errors.at(0).errorString());
146+
QString message = tr("Error opening remote file at %1.\n%2").arg(reply->url().toString()).arg(errors.at(0).errorString());
137147
QMessageBox::warning(0, qApp->applicationName(), message);
138148

139149
// Delete reply later, i.e. after returning from this slot function
@@ -235,7 +245,7 @@ void RemoteDatabase::prepareProgressDialog(bool upload, const QString& url)
235245
connect(m_currentReply, &QNetworkReply::downloadProgress, this, &RemoteDatabase::updateProgress);
236246
}
237247

238-
void RemoteDatabase::fetchDatabase(const QString& url, const QString& clientCert)
248+
void RemoteDatabase::fetch(const QString& url, bool isDatabase, const QString& clientCert, QVariant userdata)
239249
{
240250
// Check if network is accessible. If not, abort right here
241251
if(m_manager->networkAccessible() == QNetworkAccessManager::NotAccessible)
@@ -260,12 +270,19 @@ void RemoteDatabase::fetchDatabase(const QString& url, const QString& clientCert
260270

261271
// Fetch database and save pending reply. Note that we're only supporting one active download here at the moment.
262272
m_currentReply = m_manager->get(request);
273+
if(isDatabase)
274+
m_currentReply->setProperty("type", "database");
275+
else
276+
m_currentReply->setProperty("type", "dir");
277+
m_currentReply->setProperty("userdata", userdata);
263278

264-
// Initialise the progress dialog for this request
265-
prepareProgressDialog(false, url);
279+
// Initialise the progress dialog for this request, but only if this is a database file. Directory listing are small enough to be loaded
280+
// without progress dialog.
281+
if(isDatabase)
282+
prepareProgressDialog(false, url);
266283
}
267284

268-
void RemoteDatabase::pushDatabase(const QString& filename, const QString& url, const QString& clientCert)
285+
void RemoteDatabase::push(const QString& filename, const QString& url, const QString& clientCert)
269286
{
270287
// Check if network is accessible. If not, abort right here
271288
if(m_manager->networkAccessible() == QNetworkAccessManager::NotAccessible)
@@ -304,6 +321,7 @@ void RemoteDatabase::pushDatabase(const QString& filename, const QString& url, c
304321

305322
// Fetch database and save pending reply. Note that we're only supporting one active download here at the moment.
306323
m_currentReply = m_manager->put(request, file_data);
324+
m_currentReply->setProperty("type", "push");
307325

308326
// Initialise the progress dialog for this request
309327
prepareProgressDialog(true, url);

‎src/RemoteDatabase.h‎

Lines changed: 3 additions & 2 deletions

0 commit comments

Comments
 (0)