add checkoutTo and open functionality

This commit is contained in:
Martin Marmsoler 2022-04-19 13:55:27 +02:00
parent 58a3b59421
commit 745d5cfc7d
5 changed files with 132 additions and 1 deletions

View File

@ -357,4 +357,37 @@ void Commit::setEmojiFile(const QString &file)
sEmojiFile = file;
}
Blob Commit::blob(const QString& file) const{
git::Blob blob;
if (!isValid())
return blob;
// searching for the correct blob
auto list = file.split("/");
bool found = false;
auto t = tree();
if (!t.isValid())
return blob;
for (int path_depth = 0; path_depth < list.count(); path_depth++) {
auto element = list[path_depth];
found = false;
for (int i = 0; i < t.count(); ++i) {
auto n = t.name(i);
if (n == element) {
if (path_depth >= list.count() -1)
blob = t.object(i);
else
t = t.object(i);
found = true;
break;
}
}
if (!found)
break;
}
return blob;
}
} // namespace git

View File

@ -14,6 +14,7 @@
#include "git2/commit.h"
#include "git2/revwalk.h"
#include "git2/reset.h"
#include "Blob.h"
class QDateTime;
@ -87,6 +88,8 @@ public:
// any commits are created and is not expected to change.
static void setEmojiFile(const QString &file);
Blob blob(const QString& file) const;
private:
Commit(git_commit *commit);
operator git_commit *() const;

View File

@ -21,6 +21,8 @@
#include <QDir>
#include <QMessageBox>
#include <QPushButton>
#include <QFileDialog>
#include <QDesktopServices>
namespace {
@ -234,8 +236,66 @@ FileContextMenu::FileContextMenu(
view->setViewMode(RepoView::DoubleTree);
});
checkout->setEnabled(!view->repo().isBare());
// Checkout to ...
QAction *checkoutTo = addAction(tr("Save Selected Version as ..."), [this, view, files] {
QFileDialog d(this);
d.setFileMode(QFileDialog::FileMode::Directory);
d.setOption(QFileDialog::ShowDirsOnly);
d.setWindowTitle(tr("Select new file directory"));
if (d.exec()) {
const auto folder = d.selectedFiles().first();
const auto save = view->addLogEntry(tr("Saving files"), tr("Saving files of selected version to disk"));
for (const auto& file: files) {
const auto saveFile = view->addLogEntry(tr("Save file ") + file, "Save file", save);
// assumption. file is a file not a folder!
if (!exportFile(view, folder, file))
view->error(saveFile, "save file", file, tr("Invalid Blob"));
}
view->setViewMode(RepoView::DoubleTree);
}
return true;
});
QAction *open = addAction(tr("Open this version"), [this, view, files] {
QString folder = QDir::tempPath();
const auto& file = files.first();
auto filename = file.split("/").last();
auto logentry = view->addLogEntry(tr("Opening file"), tr("Open ") + filename);
if (exportFile(view, folder, file))
QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(folder + "/" + filename).absoluteFilePath()));
else
view->error(logentry, tr("open file"), filename, tr("Blob is invalid."));
});
// should show a dialog to select an application
// Don't forgett to uncomment "openWith->setEnabled(!isBare);" below
// QAction *openWith = addAction(tr("Open this Version with ..."), [this, view, files] {
// QString folder = QDir::tempPath();
// const auto& file = files.first();
// auto filename = file.split("/").last();
// auto logentry = view->addLogEntry(tr("Opening file with ..."), tr("Open ") + filename);
// if (exportFile(view, folder, file))
// QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(folder + "/" + filename).absoluteFilePath()));
// else
// view->error(logentry, tr("open file"), filename, tr("Blob is invalid."));
// });
auto isBare = view->repo().isBare();
const auto blob = view->commits().first().blob(files.first());
checkout->setEnabled(!isBare);
checkout->setToolTip(!isBare ? "" : tr("Unable to checkout bare repositories"));
checkoutTo->setEnabled(!isBare && blob.isValid());
checkoutTo->setToolTip(!isBare ? "" : tr("Unable to checkout bare repositories"));
open->setEnabled(!isBare && blob.isValid());
open->setToolTip(!isBare ? "" : tr("Unable to open files from bare repository"));
//openWith->setEnabled(!isBare && blob.isValid());
/* disable checkout if the file is already
* in the current working directory */
git::Commit commit = commits.first();
foreach (const QString &file, files) {
if (commit.tree().id(file) == repo.workdirId(file)) {
@ -348,6 +408,21 @@ void FileContextMenu::ignoreFile()
}
}
bool FileContextMenu::exportFile(const RepoView* view, const QString& folder, const QString& file) {
const auto blob = view->commits().first().blob(file);
if (!blob.isValid())
return false;
auto filename = file.split("/").last();
QFile f(folder + "/" + filename);
if (!f.open(QFile::ReadWrite))
return false;
f.write(blob.content());
f.close();
return true;
}
void FileContextMenu::addExternalToolsAction(
const QList<ExternalTool *> &tools)
{

View File

@ -31,6 +31,7 @@ private slots:
void ignoreFile();
private:
void addExternalToolsAction(const QList<ExternalTool *> &tools);
bool exportFile(const RepoView *view, const QString& folder, const QString& file);
RepoView *mView;
const QStringList &mFiles;

View File

@ -141,10 +141,29 @@ public:
bool isLogVisible() const;
void setLogVisible(bool visible);
/*!
* \brief addLogEntry
* \param text The text which is shown after the title
* \param title The text which is shown in bold
* \param parent
* \return
*/
LogEntry *addLogEntry(
const QString &text,
const QString &title,
LogEntry *parent = nullptr);
/*!
* \brief error
* \param parent
* \param action The Action text
* \param name
* \param defaultError
*
* Example:
* Unable to Action 'Name' - the path
* \return
*/
LogEntry *error(
LogEntry *parent,
const QString &action,