From dd323faf2a61d64428d7030c5e03b5e8483b4df5 Mon Sep 17 00:00:00 2001 From: Martin Kleusberg Date: Wed, 15 Jul 2020 15:22:52 +0200 Subject: [PATCH] dbhub: Add context menu action to delete local databases Add a context menu action to the list of locally cloned databases which allows you to delete the cloned databases. --- src/RemoteDatabase.cpp | 33 ++++++++++++++++++---------- src/RemoteDatabase.h | 25 +++++++++++++-------- src/RemoteDock.cpp | 41 +++++++++++++++++++++++++++++++++++ src/RemoteDock.h | 1 + src/RemoteDock.ui | 21 +++++++++++++++++- src/RemoteLocalFilesModel.cpp | 17 +++++++++++++++ src/RemoteLocalFilesModel.h | 4 +++- 7 files changed, 120 insertions(+), 22 deletions(-) diff --git a/src/RemoteDatabase.cpp b/src/RemoteDatabase.cpp index f4b48665..f154c917 100644 --- a/src/RemoteDatabase.cpp +++ b/src/RemoteDatabase.cpp @@ -940,17 +940,7 @@ QString RemoteDatabase::localCheckFile(const QString& local_file) } else { // Remove the apparently invalid entry from the local clones database to avoid future lookups and confusions. The file column should // be unique for the entire table because the files are all in the same directory and their names need to be unique because of this. - QString sql = QString("DELETE FROM local WHERE file=?"); - sqlite3_stmt* stmt; - if(sqlite3_prepare_v2(m_dbLocal, sql.toUtf8(), -1, &stmt, nullptr) != SQLITE_OK) - return QString(); - if(sqlite3_bind_text(stmt, 1, local_file.toUtf8(), local_file.toUtf8().length(), SQLITE_TRANSIENT)) - { - sqlite3_finalize(stmt); - return QString(); - } - sqlite3_step(stmt); - sqlite3_finalize(stmt); + localDeleteFile(local_file); // Return empty string to indicate a redownload request return QString(); @@ -1085,6 +1075,27 @@ RemoteDatabase::LocalFileInfo RemoteDatabase::localGetLocalFileInfo(QString file return result; } +void RemoteDatabase::localDeleteFile(QString filename) +{ + localAssureOpened(); + + // Remove the file's entry in our database + QString sql = QString("DELETE FROM local WHERE file=?"); + sqlite3_stmt* stmt; + if(sqlite3_prepare_v2(m_dbLocal, sql.toUtf8(), -1, &stmt, nullptr) != SQLITE_OK) + return; + if(sqlite3_bind_text(stmt, 1, filename.toUtf8(), filename.toUtf8().length(), SQLITE_TRANSIENT)) + { + sqlite3_finalize(stmt); + return; + } + sqlite3_step(stmt); + sqlite3_finalize(stmt); + + // Delete the actual file on disk + QFile::remove(Settings::getValue("remote", "clonedirectory").toString() + "/" + filename); +} + QString RemoteDatabase::LocalFileInfo::user_name() const { // Figure out the user name from the URL diff --git a/src/RemoteDatabase.h b/src/RemoteDatabase.h index a96ab140..8d289144 100644 --- a/src/RemoteDatabase.h +++ b/src/RemoteDatabase.h @@ -97,7 +97,7 @@ public: const QString& commitMessage = QString(), const QString& licence = QString(), bool isPublic = false, const QString& branch = QString("master"), bool forcePush = false); - // These function can be used to get information on locally checked out databases + // This class compiles all the information on a lcao database file class LocalFileInfo { public: @@ -121,15 +121,22 @@ public: void clear() { name = url = commit_id = file = branch = identity = {}; } QString user_name() const; - std::string name; - std::string url; - std::string commit_id; - std::string file; - std::string branch; - std::string identity; + std::string name; // Database name + std::string url; // URL for cloning + std::string commit_id; // Commit ID at the time of the cloning + std::string file; // Name of the local file on disk + std::string branch; // Cloned branch + std::string identity; // Identity used for cloning }; - std::vector localGetLocalFiles(QString identity); // Return a list of all checked out databases for a given identity - LocalFileInfo localGetLocalFileInfo(QString filename); // Return information on a single file + + // Return a list of all checked out databases for a given identity + std::vector localGetLocalFiles(QString identity); + + // Return information on a single file + LocalFileInfo localGetLocalFileInfo(QString filename); + + // Delete a local database clone + void localDeleteFile(QString filename); signals: // As soon as you can safely open a network connection, this signal is emitted. This can be used to delay early network requests diff --git a/src/RemoteDock.cpp b/src/RemoteDock.cpp index 4f20c226..dab2b39e 100644 --- a/src/RemoteDock.cpp +++ b/src/RemoteDock.cpp @@ -68,6 +68,18 @@ RemoteDock::RemoteDock(MainWindow* parent) ui->treeDatabaseCommits->expandAll(); }); + // Prepare context menu for list of local clones + connect(ui->treeLocal->selectionModel(), &QItemSelectionModel::currentChanged, [this](const QModelIndex& index, const QModelIndex&) { + // Only enable database actions when a database was selected + bool enable = index.isValid() && + !index.sibling(index.row(), RemoteLocalFilesModel::ColumnFile).data().isNull(); + ui->actionDeleteDatabase->setEnabled(enable); + }); + connect(ui->actionDeleteDatabase, &QAction::triggered, [this]() { + deleteLocalDatabase(ui->treeLocal->currentIndex()); + }); + ui->treeLocal->addAction(ui->actionDeleteDatabase); + // Initial setup reloadSettings(); } @@ -313,3 +325,32 @@ void RemoteDock::showMetadata(const std::vector& branc ui->comboDatabaseBranch->addItem(QString::fromStdString(tag.name) + " (" + tr("tag") + ")", QString::fromStdString(tag.commit_id)); ui->comboDatabaseBranch->setCurrentIndex(ui->comboDatabaseBranch->findText(ui->labelDatabaseBranch->text())); } + +void RemoteDock::deleteLocalDatabase(const QModelIndex& index) +{ + if(!index.isValid()) + return; + + QString filename = index.sibling(index.row(), RemoteLocalFilesModel::ColumnFile).data().toString(); + QString path = Settings::getValue("remote", "clonedirectory").toString() + "/" + filename; + + // Warn when trying to delete a currently opened database file + if(mainWindow->getDb().currentFile() == path) + { + QMessageBox::warning(this, QApplication::applicationName(), tr("The database you are trying to delete is currently opened. " + "Please close it before deleting.")); + return; + } + + // Let user confirm deleting the database + if(QMessageBox::warning(this, QApplication::applicationName(), tr("This deletes the local version of this database with all the " + "changes you have not committed yet. Are you sure you want to " + "delete this database?"), + QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Cancel) + { + return; + } + + // Delete the file + remoteLocalFilesModel->removeRow(index.row(), index.parent()); +} diff --git a/src/RemoteDock.h b/src/RemoteDock.h index b5731061..764b8d08 100644 --- a/src/RemoteDock.h +++ b/src/RemoteDock.h @@ -44,6 +44,7 @@ private slots: void showMetadata(const std::vector& branches, const std::string& commits, const std::vector& releases, const std::vector& tags, const std::string& default_branch); + void deleteLocalDatabase(const QModelIndex& index); signals: void openFile(QString file); diff --git a/src/RemoteDock.ui b/src/RemoteDock.ui index 9298877c..63b4f14c 100644 --- a/src/RemoteDock.ui +++ b/src/RemoteDock.ui @@ -121,7 +121,11 @@ - + + + Qt::ActionsContextMenu + + @@ -318,6 +322,21 @@ + + + false + + + + :/icons/close:/icons/close + + + Delete Database + + + Delete the local clone of this database + + diff --git a/src/RemoteLocalFilesModel.cpp b/src/RemoteLocalFilesModel.cpp index cb199622..683323bd 100644 --- a/src/RemoteLocalFilesModel.cpp +++ b/src/RemoteLocalFilesModel.cpp @@ -162,3 +162,20 @@ int RemoteLocalFilesModel::columnCount(const QModelIndex& /*parent*/) const { return rootItem->columnCount(); } + +bool RemoteLocalFilesModel::removeRows(int row, int count, const QModelIndex& parent) +{ + for(int i=0;i=0;i--) + { + auto item = static_cast(index(row + i, 0, parent).internalPointer()); + item->parent()->removeChild(item); + } + endRemoveRows(); + + return true; +} diff --git a/src/RemoteLocalFilesModel.h b/src/RemoteLocalFilesModel.h index 29216354..ee6e4786 100644 --- a/src/RemoteLocalFilesModel.h +++ b/src/RemoteLocalFilesModel.h @@ -20,7 +20,7 @@ public: void setIdentity(const QString& cert_filename); void refresh(); - QModelIndex index(int row, int column,const QModelIndex& parent = QModelIndex()) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex& index) const override; QVariant data(const QModelIndex& index, int role) const override; @@ -29,6 +29,8 @@ public: int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; + bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; + enum Columns { ColumnName,