dbhub: Make network code less centralised

This adds the possibility to handle network replies individually instead
of routing all of them through a central handler routine. The
centralised approach made the code more complicated than necessary and
would inevitably lead to confusion when sending similar requests
simultaneously.
This commit is contained in:
Martin Kleusberg
2020-07-24 15:29:06 +02:00
parent ddf5117331
commit 56a4b4b1e3
9 changed files with 144 additions and 268 deletions
+13 -3
View File
@@ -96,10 +96,21 @@ void MainWindow::init()
// Automatic update check
#ifdef CHECKNEWVERSION
connect(&RemoteNetwork::get(), &RemoteNetwork::networkReady, []() {
connect(&RemoteNetwork::get(), &RemoteNetwork::networkReady, [this]() {
// Check for a new version if automatic update check aren't disabled in the settings dialog
if(Settings::getValue("checkversion", "enabled").toBool())
RemoteNetwork::get().fetch(QUrl("https://download.sqlitebrowser.org/currentrelease"), RemoteNetwork::RequestTypeNewVersionCheck);
{
RemoteNetwork::get().fetch(QUrl("https://download.sqlitebrowser.org/currentrelease"), RemoteNetwork::RequestTypeCustom,
QString(), QVariant(), [this](const QByteArray& reply) {
QList<QByteArray> info = reply.split('\n');
if(info.size() >= 2)
{
QString version = info.at(0).trimmed();
QString url = info.at(1).trimmed();
checkNewVersion(version, url);
}
});
}
});
#endif
@@ -386,7 +397,6 @@ void MainWindow::init()
connect(ui->dbTreeWidget->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::changeTreeSelection);
connect(ui->dockEdit, &QDockWidget::visibilityChanged, this, &MainWindow::toggleEditDock);
connect(remoteDock, SIGNAL(openFile(QString)), this, SLOT(fileOpen(QString)));
connect(&RemoteNetwork::get(), &RemoteNetwork::gotCurrentVersion, this, &MainWindow::checkNewVersion);
connect(ui->actionDropQualifiedCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropQualifiedNames);
connect(ui->actionEnquoteNamesCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropEnquotedNames);
connect(&db, &DBBrowserDB::databaseInUseChanged, this, &MainWindow::updateDatabaseBusyStatus);
+22 -18
View File
@@ -6,6 +6,8 @@
#include <QUrl>
#include <QUrlQuery>
#include <json.hpp>
#include "RemoteDock.h"
#include "ui_RemoteDock.h"
#include "Settings.h"
@@ -17,6 +19,8 @@
#include "RemotePushDialog.h"
#include "PreferencesDialog.h"
using json = nlohmann::json;
RemoteDock::RemoteDock(MainWindow* parent)
: QDialog(parent),
ui(new Ui::RemoteDock),
@@ -46,9 +50,6 @@ RemoteDock::RemoteDock(MainWindow* parent)
// Whenever a new directory listing has been parsed, check if it was a new root dir and, if so, open the user's directory
connect(remoteModel, &RemoteModel::directoryListingParsed, this, &RemoteDock::newDirectoryNode);
// Show metadata for a database when we get it
connect(&RemoteNetwork::get(), &RemoteNetwork::gotMetadata, this, &RemoteDock::showMetadata);
// When the Preferences link is clicked in the no-certificates-label, open the preferences dialog. For other links than the ones we know,
// just open them in a web browser
connect(ui->labelNoCert, &QLabel::linkActivated, [this](const QString& link) {
@@ -448,30 +449,33 @@ void RemoteDock::fileOpened(const QString& filename)
void RemoteDock::refreshMetadata(const QString& username, const QString& dbname)
{
// Make request for meta data
QUrl url(RemoteNetwork::get().getInfoFromClientCert(remoteModel->currentClientCertificate(), RemoteNetwork::CertInfoServer) + "/metadata/get");
QUrlQuery query;
query.addQueryItem("username", username);
query.addQueryItem("folder", "/");
query.addQueryItem("dbname", dbname);
url.setQuery(query);
RemoteNetwork::get().fetch(url.toString(), RemoteNetwork::RequestTypeMetadata, remoteModel->currentClientCertificate());
}
RemoteNetwork::get().fetch(url.toString(), RemoteNetwork::RequestTypeCustom, remoteModel->currentClientCertificate(), [this](const QByteArray& reply) {
// Read and check results
json obj = json::parse(reply, nullptr, false);
if(obj.is_discarded() || !obj.is_object())
return;
void RemoteDock::showMetadata(const std::vector<RemoteMetadataBranchInfo>& branches, const std::string& commits,
const std::vector<RemoteMetadataReleaseInfo>& /*releases*/, const std::vector<RemoteMetadataReleaseInfo>& /*tags*/,
const std::string& /*default_branch*/, const std::string& web_page)
{
// Store all the commit information as-is
current_commit_json = commits;
// Store all the commit information as-is
json obj_commits = obj["commits"];
current_commit_json = obj_commits.dump();
// Store the link to the web page in the action for opening that link in a browser
ui->actionDatabaseOpenBrowser->setData(QString::fromStdString(web_page));
// Store the link to the web page in the action for opening that link in a browser
ui->actionDatabaseOpenBrowser->setData(QString::fromStdString(obj["web_page"]));
// Fill branches combo box
ui->comboDatabaseBranch->clear();
for(const auto& branch : branches)
ui->comboDatabaseBranch->addItem(QString::fromStdString(branch.name), QString::fromStdString(branch.commit_id));
ui->comboDatabaseBranch->setCurrentIndex(ui->comboDatabaseBranch->findText(ui->editDatabaseBranch->text()));
// Fill branches combo box
json obj_branches = obj["branches"];
ui->comboDatabaseBranch->clear();
for(auto it=obj_branches.cbegin();it!=obj_branches.cend();++it)
ui->comboDatabaseBranch->addItem(QString::fromStdString(it.key()), QString::fromStdString(it.value()["commit"]));
ui->comboDatabaseBranch->setCurrentIndex(ui->comboDatabaseBranch->findText(ui->editDatabaseBranch->text()));
});
}
void RemoteDock::deleteLocalDatabase(const QModelIndex& index)
-3
View File
@@ -44,9 +44,6 @@ private slots:
void newDirectoryNode(const QModelIndex& parent);
void switchToMainView();
void openLocalFile(const QModelIndex& idx);
void showMetadata(const std::vector<RemoteMetadataBranchInfo>& branches, const std::string& commits,
const std::vector<RemoteMetadataReleaseInfo>& releases, const std::vector<RemoteMetadataReleaseInfo>& tags,
const std::string& default_branch, const std::string& web_page);
void deleteLocalDatabase(const QModelIndex& index);
void openCurrentDatabaseInBrowser() const;
void refresh();
+7 -6
View File
@@ -103,8 +103,6 @@ RemoteModel::RemoteModel(QObject* parent) :
headerList({tr("Name"), tr("Last modified"), tr("Size"), tr("Commit")}),
rootItem(new RemoteModelItem())
{
// Set up signals
connect(&RemoteNetwork::get(), &RemoteNetwork::gotDirList, this, &RemoteModel::parseDirectoryListing);
}
RemoteModel::~RemoteModel()
@@ -128,10 +126,12 @@ void RemoteModel::setNewRootDir(const QString& url, const QString& cert)
void RemoteModel::refresh()
{
// Fetch root directory and put the reply data under the root item
RemoteNetwork::get().fetch(currentRootDirectory, RemoteNetwork::RequestTypeDirectory, currentClientCert, QModelIndex());
RemoteNetwork::get().fetch(currentRootDirectory, RemoteNetwork::RequestTypeCustom, currentClientCert, [this](const QByteArray& reply) {
parseDirectoryListing(reply, QModelIndex());
});
}
void RemoteModel::parseDirectoryListing(const QString& text, const QVariant& userdata)
void RemoteModel::parseDirectoryListing(const QString& text, QModelIndex parent)
{
// Load new JSON root document assuming it's an array
json array = json::parse(text.toStdString(), nullptr, false);
@@ -139,7 +139,6 @@ void RemoteModel::parseDirectoryListing(const QString& text, const QVariant& use
return;
// Get model index to store the new data under
QModelIndex parent = userdata.toModelIndex();
RemoteModelItem* parentItem = const_cast<RemoteModelItem*>(modelIndexToItem(parent));
// An invalid model index indicates that this is a new root item. This means the old one needs to be entirely deleted first.
@@ -306,7 +305,9 @@ void RemoteModel::fetchMore(const QModelIndex& parent)
// Fetch item URL
item->setFetchedDirectoryList(true);
RemoteNetwork::get().fetch(item->value(RemoteModelColumnUrl).toUrl(), RemoteNetwork::RequestTypeDirectory, currentClientCert, parent);
RemoteNetwork::get().fetch(item->value(RemoteModelColumnUrl).toUrl(), RemoteNetwork::RequestTypeCustom, currentClientCert, [this, parent](const QByteArray& reply) {
parseDirectoryListing(reply, parent);
});
}
const QString& RemoteModel::currentClientCertificate() const
+2 -3
View File
@@ -92,9 +92,8 @@ signals:
void directoryListingParsed(QModelIndex parent);
private slots:
// This is called whenever a network reply containing a directory listing arrives. json contains the reply data, userdata
// contains some custom data passed to the request. In this case we expect this to be the model index of the parent tree item.
void parseDirectoryListing(const QString& text, const QVariant& userdata);
// This is called whenever a network reply containing a directory listing arrives
void parseDirectoryListing(const QString& text, QModelIndex parent);
private:
// The header list is a list of column titles
+38 -117
View File
@@ -53,7 +53,6 @@ RemoteNetwork::RemoteNetwork() :
reloadSettings();
// Set up signals
connect(m_manager, &QNetworkAccessManager::finished, this, &RemoteNetwork::gotReply);
connect(m_manager, &QNetworkAccessManager::encrypted, this, &RemoteNetwork::gotEncrypted);
connect(m_manager, &QNetworkAccessManager::sslErrors, this, &RemoteNetwork::gotError);
}
@@ -161,35 +160,6 @@ void RemoteNetwork::gotEncrypted(QNetworkReply* reply)
void RemoteNetwork::gotReply(QNetworkReply* reply)
{
// Check if request was successful
if(reply->error() != QNetworkReply::NoError)
{
// Do not show error message when operation was cancelled on purpose
if(reply->error() != QNetworkReply::OperationCanceledError)
{
QMessageBox::warning(nullptr, qApp->applicationName(),
reply->errorString() + "\n" + reply->readAll());
}
reply->deleteLater();
return;
}
// Check for redirect
QString redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
if(!redirectUrl.isEmpty())
{
// Avoid redirect loop
if(reply->url() == redirectUrl)
{
reply->deleteLater();
return;
}
fetch(redirectUrl, static_cast<RequestType>(reply->property("type").toInt()), reply->property("certfile").toString(), reply->property("userdata"));
reply->deleteLater();
return;
}
// What type of data is this?
RequestType type = static_cast<RequestType>(reply->property("type").toInt());
@@ -222,56 +192,6 @@ void RemoteNetwork::gotReply(QNetworkReply* reply)
reply);
}
break;
case RequestTypeDirectory:
emit gotDirList(reply->readAll(), reply->property("userdata"));
break;
case RequestTypeNewVersionCheck:
{
QString version = reply->readLine().trimmed();
QString url = reply->readLine().trimmed();
emit gotCurrentVersion(version, url);
break;
}
case RequestTypeLicenceList:
{
// Read and check results
json obj = json::parse(reply->readAll(), nullptr, false);
if(obj.is_discarded() || !obj.is_object())
break;
// Parse data and build ordered licence map: order -> (short name, long name)
std::map<int, std::pair<std::string, std::string>> licences;
for(auto it=obj.cbegin();it!=obj.cend();++it)
licences.insert({it.value()["order"], {it.key(), it.value()["full_name"]}});
// Convert the map into an ordered vector and send it to anyone who's interested
std::vector<std::pair<std::string, std::string>> licence_list;
std::transform(licences.begin(), licences.end(), std::back_inserter(licence_list), [](const std::pair<int, std::pair<std::string, std::string>>& it) {
return it.second;
});
emit gotLicenceList(licence_list);
break;
}
case RequestTypeBranchList:
{
// Read and check results
json obj = json::parse(reply->readAll(), nullptr, false);
if(obj.is_discarded() || !obj.is_object())
break;
json obj_branches = obj["branches"];
// Parse data and assemble branch list
std::vector<std::string> branches;
for(auto it=obj_branches.cbegin();it!=obj_branches.cend();++it)
branches.push_back(it.key());
// Get default branch
std::string default_branch = (obj.contains("default_branch") && !obj["default_branch"].empty()) ? obj["default_branch"] : "master";
// Send branch list to anyone who is interested
emit gotBranchList(branches, default_branch);
break;
}
case RequestTypePush:
{
// Read and check results
@@ -288,41 +208,6 @@ void RemoteNetwork::gotReply(QNetworkReply* reply)
reply->property("source_file").toString());
break;
}
case RequestTypeMetadata:
{
// Read and check results
json obj = json::parse(reply->readAll(), nullptr, false);
if(obj.is_discarded() || !obj.is_object())
break;
// Extract and convert data
json obj_branches = obj["branches"];
json obj_commits = obj["commits"];
json obj_releases = obj["releases"];
json obj_tags = obj["tags"];
std::string default_branch = (obj.contains("default_branch") && !obj["default_branch"].empty()) ? obj["default_branch"] : "master";
std::vector<RemoteMetadataBranchInfo> branches;
for(auto it=obj_branches.cbegin();it!=obj_branches.cend();++it)
branches.emplace_back(it.key(), it.value()["commit"], it.value()["description"], it.value()["commit_count"]);
std::vector<RemoteMetadataReleaseInfo> releases;
for(auto it=obj_releases.cbegin();it!=obj_releases.cend();++it)
{
releases.emplace_back(it.key(), it.value()["commit"], it.value()["date"],
it.value()["description"], it.value()["email"],
it.value()["name"], it.value()["size"]);
}
std::vector<RemoteMetadataReleaseInfo> tags;
for(auto it=obj_tags.cbegin();it!=obj_tags.cend();++it)
{
tags.emplace_back(it.key(), it.value()["commit"], it.value()["date"],
it.value()["description"], it.value()["email"],
it.value()["name"], 0);
}
// Send data list to anyone who is interested
emit gotMetadata(branches, obj_commits.dump(), releases, tags, default_branch, obj["web_page"]);
break;
}
case RequestTypeDownload:
{
// It's a download
@@ -496,7 +381,8 @@ void RemoteNetwork::prepareProgressDialog(QNetworkReply* reply, bool upload, con
connect(reply, &QNetworkReply::downloadProgress, this, &RemoteNetwork::updateProgress);
}
void RemoteNetwork::fetch(const QUrl& url, RequestType type, const QString& clientCert, QVariant userdata)
void RemoteNetwork::fetch(const QUrl& url, RequestType type, const QString& clientCert,
std::function<void(QByteArray)> when_finished)
{
// Check if network is accessible. If not, abort right here
if(m_manager->networkAccessible() == QNetworkAccessManager::NotAccessible)
@@ -509,6 +395,9 @@ void RemoteNetwork::fetch(const QUrl& url, RequestType type, const QString& clie
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("User-Agent", QString("%1 %2").arg(qApp->organizationName(), APP_VERSION).toUtf8());
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
#endif
// Set SSL configuration when trying to access a file via the HTTPS protocol.
// Skip this step when no client certificate was specified. In this case the default HTTPS configuration is used.
@@ -527,7 +416,20 @@ void RemoteNetwork::fetch(const QUrl& url, RequestType type, const QString& clie
QNetworkReply* reply = m_manager->get(request);
reply->setProperty("type", type);
reply->setProperty("certfile", clientCert);
reply->setProperty("userdata", userdata);
// Hook up custom handler when there is one and global handler otherwise
if(when_finished)
{
connect(reply, &QNetworkReply::finished, reply, [this, when_finished, reply]() {
if(handleReply(reply))
when_finished(reply->readAll());
});
} else {
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if(handleReply(reply))
gotReply(reply);
});
}
// Initialise the progress dialog for this request, but only if this is a database file or a download.
// Directory listing and similar are small enough to be loaded without progress dialog.
@@ -633,3 +535,22 @@ void RemoteNetwork::clearAccessCache(const QString& clientCert)
m_manager->clearAccessCache();
}
}
bool RemoteNetwork::handleReply(QNetworkReply* reply)
{
// Check if request was successful
if(reply->error() != QNetworkReply::NoError)
{
// Do not show error message when operation was cancelled on purpose
if(reply->error() != QNetworkReply::OperationCanceledError)
{
QMessageBox::warning(nullptr, qApp->applicationName(),
reply->errorString() + "\n" + reply->readAll());
}
reply->deleteLater();
return false;
}
return true;
}
+7 -62
View File
@@ -4,6 +4,7 @@
#include <QObject>
#include <QtNetwork/QSslConfiguration>
#include <functional>
#include <map>
class QNetworkAccessManager;
@@ -14,52 +15,6 @@ class QNetworkRequest;
class QHttpMultiPart;
class QFile;
class RemoteMetadataBranchInfo
{
public:
RemoteMetadataBranchInfo(const std::string& _name, const std::string& _commit_id, const std::string& _description, unsigned int _commit_count) :
name(_name),
commit_id(_commit_id),
description(_description),
commit_count(_commit_count)
{}
RemoteMetadataBranchInfo() :
commit_count(0)
{}
std::string name;
std::string commit_id;
std::string description;
unsigned int commit_count;
};
class RemoteMetadataReleaseInfo
{
public:
RemoteMetadataReleaseInfo(const std::string& _name, const std::string& _commit_id, const std::string& _date,
const std::string& _description, const std::string& _email,
const std::string& _user_name, unsigned int _size) :
name(_name),
commit_id(_commit_id),
date(_date),
description(_description),
email(_email),
user_name(_user_name),
size(_size)
{}
RemoteMetadataReleaseInfo() :
size(0)
{}
std::string name;
std::string commit_id;
std::string date;
std::string description;
std::string email;
std::string user_name;
unsigned long size;
};
class RemoteNetwork : public QObject
{
Q_OBJECT
@@ -85,17 +40,13 @@ public:
enum RequestType
{
RequestTypeCustom,
RequestTypeDatabase,
RequestTypeDirectory,
RequestTypeNewVersionCheck,
RequestTypePush,
RequestTypeLicenceList,
RequestTypeBranchList,
RequestTypeMetadata,
RequestTypeDownload,
};
void fetch(const QUrl& url, RequestType type, const QString& clientCert = QString(), QVariant userdata = QVariant());
void fetch(const QUrl& url, RequestType type, const QString& clientCert = QString(), std::function<void(QByteArray)> when_finished = {});
void push(const QString& filename, const QUrl& url, const QString& clientCert, const QString& remotename,
const QString& commitMessage = QString(), const QString& licence = QString(), bool isPublic = false,
const QString& branch = QString("master"), bool forcePush = false, const QString& last_commit = QString());
@@ -105,16 +56,6 @@ signals:
// which might otherwise fail.
void networkReady();
// These signals are emitted when the fetch() calls are finished that are not requesting a remote database but other data, like
// a directory listing or the licence list.
void gotDirList(QString json, QVariant userdata);
void gotCurrentVersion(QString version, QString url);
void gotLicenceList(std::vector<std::pair<std::string, std::string>> licences);
void gotBranchList(std::vector<std::string> branches, std::string default_branch);
void gotMetadata(std::vector<RemoteMetadataBranchInfo> branches, std::string commits,
std::vector<RemoteMetadataReleaseInfo> releases, std::vector<RemoteMetadataReleaseInfo> tags,
std::string default_branch, std::string web_page);
// The fetchFinished() signal is emitted when a fetch() call for a database is finished
void fetchFinished(QString filename, QString identity, const QUrl& url, std::string new_commit_id, std::string branch,
QDateTime last_modified, QIODevice* device);
@@ -141,6 +82,10 @@ private:
// object. Otherwise Qt might reuse the old certificate if the requested URL has been used before.
void clearAccessCache(const QString& clientCert);
// This function is called for all network replies we get whether they are handled globally or individually.
// It mainly does some error checking and returns true if the actual handler should be called.
bool handleReply(QNetworkReply* reply);
QNetworkAccessManager* m_manager;
QNetworkConfigurationManager* m_configurationManager;
QProgressDialog* m_progress;
+55 -48
View File
@@ -2,17 +2,20 @@
#include <QUrlQuery>
#include <QRegExpValidator>
#include <json.hpp>
#include "RemotePushDialog.h"
#include "ui_RemotePushDialog.h"
#include "RemoteNetwork.h"
using json = nlohmann::json;
RemotePushDialog::RemotePushDialog(QWidget* parent, const QString& host, const QString& clientCert,
const QString& name, const QString& branch) :
QDialog(parent),
ui(new Ui::RemotePushDialog),
m_host(host),
m_clientCert(clientCert),
m_suggestedBranch(branch),
m_nameValidator(new QRegExpValidator(QRegExp("^[a-z,A-Z,0-9,\\.,\\-,\\_,\\(,\\),\\+,\\ ]+$"), this)),
m_branchValidator(new QRegExpValidator(QRegExp("^[a-z,A-Z,0-9,\\^,\\.,\\-,\\_,\\/,\\(,\\),\\:,\\&,\\ )]+$"), this))
{
@@ -28,12 +31,58 @@ RemotePushDialog::RemotePushDialog(QWidget* parent, const QString& host, const Q
checkInput();
// Fetch list of available licences
connect(&RemoteNetwork::get(), &RemoteNetwork::gotLicenceList, this, &RemotePushDialog::fillInLicences);
RemoteNetwork::get().fetch(host + "licence/list", RemoteNetwork::RequestTypeLicenceList, clientCert);
RemoteNetwork::get().fetch(host + "licence/list", RemoteNetwork::RequestTypeCustom, clientCert, [this](const QByteArray& reply) {
// Clear licence list
ui->comboLicence->clear();
// Prepare fetching list of available branches
connect(&RemoteNetwork::get(), &RemoteNetwork::gotBranchList, this, &RemotePushDialog::fillInBranches);
reloadBranchList();
// Read and check results
json obj = json::parse(reply, nullptr, false);
if(obj.is_discarded() || !obj.is_object())
return;
// Parse data and build ordered licence map: order -> (short name, long name)
std::map<int, std::pair<std::string, std::string>> licences;
for(auto it=obj.cbegin();it!=obj.cend();++it)
licences.insert({it.value()["order"], {it.key(), it.value()["full_name"]}});
// Parse licence list and fill combo box. Show the full name to the user and use the short name as user data.
for(auto it=licences.begin();it!=licences.end();++it)
ui->comboLicence->addItem(QString::fromStdString(it->second.second), QString::fromStdString(it->second.first));
});
// Fetch list of exsisting branches
QUrl url(m_host + "branch/list");
QUrlQuery query;
query.addQueryItem("username", RemoteNetwork::get().getInfoFromClientCert(m_clientCert, RemoteNetwork::CertInfoUser));
query.addQueryItem("folder", "/");
query.addQueryItem("dbname", ui->editName->text());
url.setQuery(query);
RemoteNetwork::get().fetch(url.toString(), RemoteNetwork::RequestTypeCustom, m_clientCert, [this, branch](const QByteArray& reply) {
// Read and check results
json obj = json::parse(reply, nullptr, false);
if(obj.is_discarded() || !obj.is_object())
return;
json obj_branches = obj["branches"];
// Get default branch
std::string default_branch = (obj.contains("default_branch") && !obj["default_branch"].empty()) ? obj["default_branch"] : "master";
// Clear branch list and add the default branch
ui->comboBranch->clear();
ui->comboBranch->addItem(QString::fromStdString(default_branch));
// Parse data and assemble branch list
std::vector<std::string> branches;
for(auto it=obj_branches.cbegin();it!=obj_branches.cend();++it)
{
if(it.key() != default_branch)
ui->comboBranch->addItem(QString::fromStdString(it.key()));
}
// If a branch was suggested, select it now
if(!branch.isEmpty())
ui->comboBranch->setCurrentIndex(ui->comboBranch->findText(branch));
});
}
RemotePushDialog::~RemotePushDialog()
@@ -104,45 +153,3 @@ bool RemotePushDialog::forcePush() const
{
return ui->checkForce->isChecked();
}
void RemotePushDialog::fillInLicences(const std::vector<std::pair<std::string, std::string>>& licences)
{
// Clear licence list
ui->comboLicence->clear();
// Parse licence list and fill combo box. Show the full name to the user and use the short name as user data.
for(const auto& it : licences)
ui->comboLicence->addItem(QString::fromStdString(it.second), QString::fromStdString(it.first));
}
void RemotePushDialog::fillInBranches(const std::vector<std::string>& branches, const std::string& default_branch)
{
// Clear branch list and add the default branch
ui->comboBranch->clear();
ui->comboBranch->addItem(QString::fromStdString(default_branch));
// Add rest of the branch list to the combo box
for(const std::string& branch : branches)
{
if(branch != default_branch)
ui->comboBranch->addItem(QString::fromStdString(branch));
}
// If a branch was suggested, select it now
if(!m_suggestedBranch.isEmpty())
ui->comboBranch->setCurrentIndex(ui->comboBranch->findText(m_suggestedBranch));
}
void RemotePushDialog::reloadBranchList()
{
// Assemble query URL
QUrl url(m_host + "branch/list");
QUrlQuery query;
query.addQueryItem("username", RemoteNetwork::get().getInfoFromClientCert(m_clientCert, RemoteNetwork::CertInfoUser));
query.addQueryItem("folder", "/");
query.addQueryItem("dbname", ui->editName->text());
url.setQuery(query);
// Send request
RemoteNetwork::get().fetch(url.toString(), RemoteNetwork::RequestTypeBranchList, m_clientCert);
}
-8
View File
@@ -32,9 +32,6 @@ private:
QString m_host;
QString m_clientCert;
// Suggested branch to preselect
QString m_suggestedBranch;
// Validators
QRegExpValidator* m_nameValidator;
QRegExpValidator* m_branchValidator;
@@ -42,11 +39,6 @@ private:
protected slots:
void checkInput();
void accept() override;
void reloadBranchList();
void fillInLicences(const std::vector<std::pair<std::string, std::string>>& licences);
void fillInBranches(const std::vector<std::string>& branches, const std::string& default_branch);
};
#endif