Page MenuHomePhabricator (Chris)

No OneTemporary

Size
376 KB
Referenced Files
None
Subscribers
None
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/src/AvatarLoader.cpp b/src/AvatarLoader.cpp
index 5e6a6ac..9f5eb38 100644
--- a/src/AvatarLoader.cpp
+++ b/src/AvatarLoader.cpp
@@ -1,161 +1,161 @@
#include "AvatarLoader.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "MemoryReader.h"
#include "webclient.h"
#include <QCryptographicHash>
#include <QDebug>
#include <QWaitCondition>
namespace {
const int MAX_CACHE_COUNT = 1000;
const int ICON_SIZE = 128;
}
using WebClientPtr = std::shared_ptr<WebClient>;
struct AvatarLoader::Private {
QMutex mutex;
QWaitCondition condition;
std::deque<RequestItem> requested;
std::deque<RequestItem> completed;
- BasicMainWindow *mainwindow = nullptr;
+ MainWindow *mainwindow = nullptr;
WebClientPtr web;
};
AvatarLoader::AvatarLoader()
: m(new Private)
{
}
AvatarLoader::~AvatarLoader()
{
delete m;
}
-void AvatarLoader::start(BasicMainWindow *mainwindow)
+void AvatarLoader::start(MainWindow *mainwindow)
{
m->mainwindow = mainwindow;
QThread::start();
}
void AvatarLoader::run()
{
m->web = std::make_shared<WebClient>(m->mainwindow->webContext());
while (1) {
if (isInterruptionRequested()) return;
std::deque<RequestItem> requests;
{
QMutexLocker lock(&m->mutex);
if (m->requested.empty()) {
m->condition.wait(&m->mutex);
}
if (!m->requested.empty()) {
std::swap(requests, m->requested);
}
}
for (RequestItem &item : requests) {
if (isInterruptionRequested()) return;
if (strchr(item.email.c_str(), '@')) {
QString id;
{
QCryptographicHash hash(QCryptographicHash::Md5);
hash.addData(item.email.c_str(), item.email.size());
QByteArray ba = hash.result();
char tmp[100];
for (int i = 0; i < ba.size(); i++) {
sprintf(tmp + i * 2, "%02x", ba.data()[i] & 0xff);
}
id = tmp;
}
QString url = "https://www.gravatar.com/avatar/%1?s=%2";
url = url.arg(id).arg(ICON_SIZE);
if (m->web->get(WebClient::Request(url.toStdString())) == 200) {
if (!m->web->response().content.empty()) {
MemoryReader reader(m->web->response().content.data(), m->web->response().content.size());
reader.open(MemoryReader::ReadOnly);
QImage image;
image.load(&reader, nullptr);
int w = image.width();
int h = image.height();
if (w > 0 && h > 0) {
item.image = image;
{
QMutexLocker lock(&m->mutex);
size_t i = m->requested.size();
while (i > 0) {
i--;
if (m->requested[i].email == item.email) {
m->requested.erase(m->requested.begin() + i);
}
}
while (m->completed.size() >= MAX_CACHE_COUNT) {
m->completed.pop_back();
}
m->completed.push_front(item);
}
emit updated();
continue;
}
}
} else {
m->mainwindow->emitWriteLog(QString("Failed to fetch the avatar.\n").toUtf8());
QString msg = QString::fromStdString(m->web->error().message() + '\n');
m->mainwindow->emitWriteLog(msg.toUtf8());
}
}
}
}
}
QIcon AvatarLoader::fetch(std::string const &email, bool request) const
{
QMutexLocker lock(&m->mutex);
RequestItem item;
item.email = email;
for (size_t i = 0; i < m->completed.size(); i++) {
if (item.email == m->completed[i].email) {
item = m->completed[i];
m->completed.erase(m->completed.begin() + i);
m->completed.insert(m->completed.begin(), item);
return QIcon(QPixmap::fromImage(item.image));
}
}
if (request) {
bool waiting = false;
for (RequestItem const &r : m->requested) {
if (item.email == r.email) {
waiting = true;
break;
}
}
if (!waiting) {
m->requested.push_back(item);
m->condition.wakeOne();
}
}
return QIcon();
}
void AvatarLoader::stop()
{
{
QMutexLocker lock(&m->mutex);
requestInterruption();
m->requested.clear();
m->condition.wakeAll();
}
if (!wait(3000)) {
terminate();
}
if (m->web) {
m->web->close();
m->web.reset();
}
m->completed.clear();
}
diff --git a/src/AvatarLoader.h b/src/AvatarLoader.h
index b43c433..b48f3aa 100644
--- a/src/AvatarLoader.h
+++ b/src/AvatarLoader.h
@@ -1,37 +1,37 @@
#ifndef AVATARLOADER_H
#define AVATARLOADER_H
#include "GitHubAPI.h"
#include <QIcon>
#include <QThread>
#include <QMutex>
#include <deque>
#include <set>
#include <string>
-class BasicMainWindow;
+class MainWindow;
class WebContext;
class AvatarLoader : public QThread {
Q_OBJECT
private:
struct RequestItem {
std::string email;
QImage image;
};
struct Private;
Private *m;
protected:
void run() override;
public:
AvatarLoader();
~AvatarLoader() override;
QIcon fetch(std::string const &email, bool request) const;
void stop();
- void start(BasicMainWindow *mainwindow);
+ void start(MainWindow *mainwindow);
signals:
void updated();
};
#endif // AVATARLOADER_H
diff --git a/src/BasicMainWindow.cpp b/src/BasicMainWindow.cpp
index 8139e6e..56035fb 100644
--- a/src/BasicMainWindow.cpp
+++ b/src/BasicMainWindow.cpp
@@ -1,3094 +1,2938 @@
#include "ApplicationGlobal.h"
#include "BasicMainWindow.h"
#include "CheckoutDialog.h"
#include "CloneDialog.h"
#include "CommitDialog.h"
#include "CommitExploreWindow.h"
#include "CommitViewWindow.h"
#include "CreateRepositoryDialog.h"
#include "DeleteBranchDialog.h"
#include "DoYouWantToInitDialog.h"
#include "FileHistoryWindow.h"
#include "FilePropertyDialog.h"
#include "FileUtil.h"
#include "Git.h"
#include "GitDiff.h"
#include "MemoryReader.h"
#include "MySettings.h"
#include "PushDialog.h"
#include "RepositoryPropertyDialog.h"
#include "SelectCommandDialog.h"
#include "SetGlobalUserDialog.h"
#include "SetUserDialog.h"
#include "SettingsDialog.h"
#include "Terminal.h"
#include "TextEditDialog.h"
#include "UserEvent.h"
#include "WelcomeWizardDialog.h"
#include "common/joinpath.h"
#include "common/misc.h"
#include "SubmoduleAddDialog.h"
#include "gpg.h"
#include "gunzip.h"
#include "platform.h"
#include "webclient.h"
#include <QDesktopServices>
#include <QDir>
#include <QDirIterator>
#include <QEvent>
#include <QFileIconProvider>
#include <QListWidget>
#include <QMenu>
#include <QMessageBox>
#include <QStandardPaths>
#include <QTreeWidgetItem>
#include <functional>
#include <memory>
class AsyncExecGitThread_ : public QThread {
private:
GitPtr g;
std::function<void(GitPtr g)> callback;
public:
AsyncExecGitThread_(GitPtr const &g, std::function<void(GitPtr const &g)> const &callback)
: g(g)
, callback(callback)
{
}
protected:
void run() override
{
callback(g);
}
};
//
-struct BasicMainWindow::Private {
- ApplicationSettings appsettings;
-
- QIcon repository_icon;
- QIcon folder_icon;
- QIcon signature_good_icon;
- QIcon signature_dubious_icon;
- QIcon signature_bad_icon;
- QPixmap transparent_pixmap;
-
- QString starting_dir;
- Git::Context gcx;
- RepositoryItem current_repo;
-
- QList<RepositoryItem> repos;
- Git::CommitItemList logs;
- QList<Git::Diff> diff_result;
- QList<Git::Submodule> submodules;
-
- QStringList added;
- QStringList remotes;
- QString current_remote_name;
- Git::Branch current_branch;
- unsigned int temp_file_counter = 0;
-
- std::string ssh_passphrase_user;
- std::string ssh_passphrase_pass;
-
- std::string http_uid;
- std::string http_pwd;
-
- std::map<QString, GitHubAPI::User> committer_map; // key is email
-
- PtyProcess pty_process;
- bool pty_process_ok = false;
- PtyCondition pty_condition = PtyCondition::None;
-
- WebContext webcx;
-
- AvatarLoader avatar_loader;
- int update_files_list_counter = 0;
- int update_commit_table_counter = 0;
-
- bool interaction_canceled = false;
- InteractionMode interaction_mode = InteractionMode::None;
-
- QString repository_filter_text;
- bool uncommited_changes = false;
-
- std::map<QString, QList<Git::Branch>> branch_map;
- std::map<QString, QList<Git::Tag>> tag_map;
- std::map<int, QList<Label>> label_map;
- std::map<QString, Git::Diff> diff_cache;
- GitObjectCache objcache;
-
- bool remote_changed = false;
-
- ServerType server_type = ServerType::Standard;
- GitHubRepositoryInfo github;
-
- QString head_id;
- bool force_fetch = false;
-
- RepositoryItem temp_repo_for_clone_complete;
- QVariant pty_process_completion_data;
-};
BasicMainWindow::BasicMainWindow(QWidget *parent)
: QMainWindow(parent)
- , m(new Private)
+// , m1(new Private1)
{
- loadApplicationSettings();
- m->starting_dir = QDir::current().absolutePath();
-
- { // load graphic resources
- QFileIconProvider icons;
- m->folder_icon = icons.icon(QFileIconProvider::Folder);
- m->repository_icon = QIcon(":/image/repository.png");
- m->signature_good_icon = QIcon(":/image/signature-good.png");
- m->signature_bad_icon = QIcon(":/image/signature-bad.png");
- m->signature_dubious_icon = QIcon(":/image/signature-dubious.png");
- m->transparent_pixmap = QPixmap(":/image/transparent.png");
- }
}
BasicMainWindow::~BasicMainWindow()
{
- setRemoteMonitoringEnabled(false);
- deleteTempFiles();
- delete m;
+// delete m1;
}
-ApplicationSettings *BasicMainWindow::appsettings()
+ApplicationSettings *MainWindow::appsettings()
{
- return &m->appsettings;
+ return &m1->appsettings;
}
-const ApplicationSettings *BasicMainWindow::appsettings() const
+const ApplicationSettings *MainWindow::appsettings() const
{
- return &m->appsettings;
+ return &m1->appsettings;
}
-WebContext *BasicMainWindow::webContext()
+WebContext *MainWindow::webContext()
{
- return &m->webcx;
+ return &m1->webcx;
}
-QString BasicMainWindow::gitCommand() const
+QString MainWindow::gitCommand() const
{
- return m->gcx.git_command;
+ return m1->gcx.git_command;
}
namespace {
} // namespace
-bool BasicMainWindow::event(QEvent *event)
-{
- if (event->type() == (QEvent::Type)EventUserFunction) {
- if (auto *e = (UserFunctionEvent *)event) {
- e->func(e->var);
- return true;
- }
- }
- return QMainWindow::event(event);
-}
+//bool BasicMainWindow::event(QEvent *event)
+//{
+// if (event->type() == (QEvent::Type)EventUserFunction) {
+// if (auto *e = (UserFunctionEvent *)event) {
+// e->func(e->var);
+// return true;
+// }
+// }
+// return QMainWindow::event(event);
+//}
-void BasicMainWindow::postUserFunctionEvent(const std::function<void(QVariant const &)> &fn, QVariant const &v)
+void MainWindow::postUserFunctionEvent(const std::function<void(QVariant const &)> &fn, QVariant const &v)
{
qApp->postEvent(this, new UserFunctionEvent(fn, v));
}
-void BasicMainWindow::autoOpenRepository(QString dir)
+void MainWindow::autoOpenRepository(QString dir)
{
auto Open = [&](RepositoryItem const &item){
setCurrentRepository(item, true);
openRepository(false, true);
};
RepositoryItem const *repo = findRegisteredRepository(&dir);
if (repo) {
Open(*repo);
return;
}
RepositoryItem newitem;
GitPtr g = git(dir);
if (isValidWorkingCopy(g)) {
ushort const *left = dir.utf16();
ushort const *right = left + dir.size();
if (right[-1] == '/' || right[-1] == '\\') {
right--;
}
ushort const *p = right;
while (left + 1 < p && !(p[-1] == '/' || p[-1] == '\\')) p--;
if (p < right) {
newitem.local_dir = dir;
newitem.name = QString::fromUtf16(p, right - p);
saveRepositoryBookmark(newitem);
Open(newitem);
return;
}
} else {
DoYouWantToInitDialog dlg(this, dir);
if (dlg.exec() == QDialog::Accepted) {
createRepository(dir);
}
}
}
-GitPtr BasicMainWindow::git(QString const &dir, QString const &sshkey) const
+GitPtr MainWindow::git(QString const &dir, QString const &sshkey) const
{
- GitPtr g = std::make_shared<Git>(m->gcx, dir, sshkey);
+ GitPtr g = std::make_shared<Git>(m1->gcx, dir, sshkey);
if (g && QFileInfo(g->gitCommand()).isExecutable()) {
g->setLogCallback(git_callback, (void *)this);
return g;
} else {
QString text = tr("git command not specified") + '\n';
- const_cast<BasicMainWindow *>(this)->writeLog(text);
+ const_cast<MainWindow *>(this)->writeLog(text);
return GitPtr();
}
}
-GitPtr BasicMainWindow::git()
+GitPtr MainWindow::git()
{
RepositoryItem const &item = currentRepository();
return git(item.local_dir, item.ssh_key);
}
-GitPtr BasicMainWindow::git(Git::Submodule const &submod)
+GitPtr MainWindow::git(Git::Submodule const &submod)
{
if (!submod) return {};
RepositoryItem const &item = currentRepository();
return git(item.local_dir / submod.path, item.ssh_key);
}
-QPixmap BasicMainWindow::getTransparentPixmap()
+QPixmap MainWindow::getTransparentPixmap()
{
- return m->transparent_pixmap;
+ return m1->transparent_pixmap;
}
-QIcon BasicMainWindow::committerIcon(int row) const
+QIcon MainWindow::committerIcon(int row) const
{
QIcon icon;
if (isAvatarEnabled() && isOnlineMode()) {
auto const &logs = getLogs();
if (row >= 0 && row < (int)logs.size()) {
Git::CommitItem const &commit = logs[row];
if (commit.email.indexOf('@') > 0) {
std::string email = commit.email.toStdString();
icon = getAvatarLoader()->fetch(email, true); // from gavatar
}
}
}
return icon;
}
-Git::CommitItem const *BasicMainWindow::commitItem(int row) const
+Git::CommitItem const *MainWindow::commitItem(int row) const
{
auto const &logs = getLogs();
if (row >= 0 && row < (int)logs.size()) {
return &logs[row];
}
return nullptr;
}
-QIcon BasicMainWindow::verifiedIcon(char s) const
+QIcon MainWindow::verifiedIcon(char s) const
{
Git::SignatureGrade g = Git::evaluateSignature(s);
switch (g) {
case Git::SignatureGrade::Good:
- return m->signature_good_icon;
+ return m1->signature_good_icon;
case Git::SignatureGrade::Bad:
- return m->signature_bad_icon;
+ return m1->signature_bad_icon;
case Git::SignatureGrade::Unknown:
case Git::SignatureGrade::Dubious:
case Git::SignatureGrade::Missing:
- return m->signature_dubious_icon;
+ return m1->signature_dubious_icon;
}
return QIcon();
}
-QString BasicMainWindow::currentWorkingCopyDir() const
+QString MainWindow::currentWorkingCopyDir() const
{
- return m->current_repo.local_dir;
+ return m1->current_repo.local_dir;
}
-bool BasicMainWindow::isRepositoryOpened() const
+bool MainWindow::isRepositoryOpened() const
{
return Git::isValidWorkingCopy(currentWorkingCopyDir());
}
-QList<BasicMainWindow::Label> const *BasicMainWindow::label(int row) const
+QList<BasicMainWindow::Label> const *MainWindow::label(int row) const
{
auto it = getLabelMap()->find(row);
if (it != getLabelMap()->end()) {
return &it->second;
}
return nullptr;
}
-QList<BasicMainWindow::Label> BasicMainWindow::sortedLabels(int row) const
+QList<BasicMainWindow::Label> MainWindow::sortedLabels(int row) const
{
QList<BasicMainWindow::Label> list;
- auto const *p = const_cast<BasicMainWindow *>(this)->label(row);
+ auto const *p = const_cast<MainWindow *>(this)->label(row);
if (p && !p->empty()) {
list = *p;
std::sort(list.begin(), list.end(), [](BasicMainWindow::Label const &l, BasicMainWindow::Label const &r){
auto Compare = [](BasicMainWindow::Label const &l, BasicMainWindow::Label const &r){
if (l.kind < r.kind) return -1;
if (l.kind > r.kind) return 1;
if (l.text < r.text) return -1;
if (l.text > r.text) return 1;
return 0;
};
return Compare(l, r) < 0;
});
}
return list;
}
-bool BasicMainWindow::saveAs(QString const &id, QString const &dstpath)
+bool MainWindow::saveAs(QString const &id, QString const &dstpath)
{
if (id.startsWith(PATH_PREFIX)) {
return saveFileAs(id.mid(1), dstpath);
} else {
return saveBlobAs(id, dstpath);
}
}
-bool BasicMainWindow::testRemoteRepositoryValidity(QString const &url, QString const &sshkey)
+bool MainWindow::testRemoteRepositoryValidity(QString const &url, QString const &sshkey)
{
bool ok;
{
OverrideWaitCursor;
ok = isValidRemoteURL(url, sshkey);
}
QString pass = tr("The URL is a valid repository");
QString fail = tr("Failed to access the URL");
QString text = "%1\n\n%2";
text = text.arg(url).arg(ok ? pass : fail);
QString title = tr("Remote Repository");
if (ok) {
QMessageBox::information(this, title, text);
} else {
QMessageBox::critical(this, title, text);
}
return ok;
}
-void BasicMainWindow::addWorkingCopyDir(QString const &dir, bool open)
+void MainWindow::addWorkingCopyDir(QString const &dir, bool open)
{
addWorkingCopyDir(dir, QString(), open);
}
-bool BasicMainWindow::queryCommit(QString const &id, Git::CommitItem *out)
+bool MainWindow::queryCommit(QString const &id, Git::CommitItem *out)
{
*out = Git::CommitItem();
GitPtr g = git();
return g->queryCommit(id, out);
}
-QAction *BasicMainWindow::addMenuActionProperty(QMenu *menu)
+QAction *MainWindow::addMenuActionProperty(QMenu *menu)
{
return menu->addAction(tr("&Property"));
}
-void BasicMainWindow::checkout(QWidget *parent, Git::CommitItem const *commit, std::function<void()> accepted_callback)
-{
- if (!commit) return;
- GitPtr g = git();
- if (!isValidWorkingCopy(g)) return;
- QStringList tags;
- QStringList all_local_branches;
- QStringList local_branches;
- QStringList remote_branches;
- {
- NamedCommitList named_commits = namedCommitItems(Branches | Tags | Remotes);
- for (NamedCommitItem const &item : named_commits) {
- QString name = item.name;
- if (item.id == commit->commit_id) {
- if (item.type == NamedCommitItem::Type::Tag) {
- tags.push_back(name);
- } else if (item.type == NamedCommitItem::Type::BranchLocal || item.type == NamedCommitItem::Type::BranchRemote) {
- int i = name.lastIndexOf('/');
- if (i < 0 && name == "HEAD") continue;
- if (i > 0 && name.mid(i + 1) == "HEAD") continue;
- if (item.type == NamedCommitItem::Type::BranchLocal) {
- local_branches.push_back(name);
- } else if (item.type == NamedCommitItem::Type::BranchRemote) {
- remote_branches.push_back(name);
- }
- }
- }
- if (item.type == NamedCommitItem::Type::BranchLocal) {
- all_local_branches.push_back(name);
- }
- }
- }
-
- CheckoutDialog dlg(parent, tags, all_local_branches, local_branches, remote_branches);
- if (dlg.exec() == QDialog::Accepted) {
- if (accepted_callback) {
- accepted_callback();
- }
- CheckoutDialog::Operation op = dlg.operation();
- QString name = dlg.branchName();
- QString id = commit->commit_id;
- if (id.isEmpty() && !commit->parent_ids.isEmpty()) {
- id = commit->parent_ids.front();
- }
- bool ok = false;
- setLogEnabled(g, true);
- if (op == CheckoutDialog::Operation::HeadDetached) {
- if (!id.isEmpty()) {
- ok = g->git(QString("checkout \"%1\"").arg(id), true);
- }
- } else if (op == CheckoutDialog::Operation::CreateLocalBranch) {
- if (!name.isEmpty() && !id.isEmpty()) {
- ok = g->git(QString("checkout -b \"%1\" \"%2\"").arg(name).arg(id), true);
- }
- } else if (op == CheckoutDialog::Operation::ExistingLocalBranch) {
- if (!name.isEmpty()) {
- ok = g->git(QString("checkout \"%1\"").arg(name), true);
- }
- }
- if (ok) {
- openRepository(true);
- }
- }
-}
-
-void BasicMainWindow::jumpToCommit(QString id)
+void MainWindow::jumpToCommit(QString id)
{
GitPtr g = git();
id = g->rev_parse(id);
if (!id.isEmpty()) {
int row = rowFromCommitId(id);
setCurrentLogRow(row);
}
}
-void BasicMainWindow::execCommitViewWindow(Git::CommitItem const *commit)
+void MainWindow::execCommitViewWindow(Git::CommitItem const *commit)
{
CommitViewWindow win(this, commit);
win.exec();
}
-void BasicMainWindow::execCommitExploreWindow(QWidget *parent, Git::CommitItem const *commit)
+void MainWindow::execCommitExploreWindow(QWidget *parent, Git::CommitItem const *commit)
{
CommitExploreWindow win(parent, this, getObjCache(), commit);
win.exec();
}
-void BasicMainWindow::execFileHistory(QString const &path)
+void MainWindow::execFileHistory(QString const &path)
{
if (path.isEmpty()) return;
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
FileHistoryWindow dlg(this);
dlg.prepare(g, path);
dlg.exec();
}
-void BasicMainWindow::execFilePropertyDialog(QListWidgetItem *item)
+void MainWindow::execFilePropertyDialog(QListWidgetItem *item)
{
if (item) {
QString path = getFilePath(item);
QString id = getObjectID(item);
FilePropertyDialog dlg(this);
dlg.exec(this, path, id);
}
}
-QString BasicMainWindow::selectGitCommand(bool save)
+QString MainWindow::selectGitCommand(bool save)
{
char const *exe = GIT_COMMAND;
QString path = gitCommand();
auto fn = [&](QString const &path){
setGitCommand(path, save);
};
QStringList list = whichCommand_(exe);
#ifdef Q_OS_WIN
{
QStringList newlist;
QString suffix1 = "\\bin\\" GIT_COMMAND;
QString suffix2 = "\\cmd\\" GIT_COMMAND;
for (QString const &s : list) {
newlist.push_back(s);
auto DoIt = [&](QString const &suffix){
if (s.endsWith(suffix)) {
QString t = s.mid(0, s.size() - suffix.size());
QString t1 = t + "\\mingw64\\bin\\" GIT_COMMAND;
if (misc::isExecutable(t1)) newlist.push_back(t1);
QString t2 = t + "\\mingw\\bin\\" GIT_COMMAND;
if (misc::isExecutable(t2)) newlist.push_back(t2);
}
};
DoIt(suffix1);
DoIt(suffix2);
}
std::sort(newlist.begin(), newlist.end());
auto end = std::unique(newlist.begin(), newlist.end());
list.clear();
for (auto it = newlist.begin(); it != end; it++) {
list.push_back(*it);
}
}
#endif
return selectCommand_("Git", exe, list, path, fn);
}
-QString BasicMainWindow::selectFileCommand(bool save)
+QString MainWindow::selectFileCommand(bool save)
{
char const *exe = FILE_COMMAND;
QString path = global->file_command;
auto fn = [&](QString const &path){
setFileCommand(path, save);
};
QStringList list = whichCommand_(exe);
#ifdef Q_OS_WIN
QString dir = misc::getApplicationDir();
QString path1 = dir / FILE_COMMAND;
QString path2;
int i = dir.lastIndexOf('/');
int j = dir.lastIndexOf('\\');
if (i < j) i = j;
if (i > 0) {
path2 = dir.mid(0, i) / FILE_COMMAND;
}
path1 = misc::normalizePathSeparator(path1);
path2 = misc::normalizePathSeparator(path2);
if (misc::isExecutable(path1)) list.push_back(path1);
if (misc::isExecutable(path2)) list.push_back(path2);
#endif
return selectCommand_("File", exe, list, path, fn);
}
-QString BasicMainWindow::selectGpgCommand(bool save)
+QString MainWindow::selectGpgCommand(bool save)
{
QString path = global->gpg_command;
auto fn = [&](QString const &path){
setGpgCommand(path, save);
};
QStringList list = whichCommand_(GPG_COMMAND, GPG2_COMMAND);
QStringList cmdlist;
cmdlist.push_back(GPG_COMMAND);
cmdlist.push_back(GPG2_COMMAND);
return selectCommand_("GPG", cmdlist, list, path, fn);
}
-QString BasicMainWindow::selectSshCommand(bool save)
+QString MainWindow::selectSshCommand(bool save)
{
- QString path = m->gcx.ssh_command;
+ QString path = m1->gcx.ssh_command;
auto fn = [&](QString const &path){
setSshCommand(path, save);
};
QStringList list = whichCommand_(SSH_COMMAND);
QStringList cmdlist;
cmdlist.push_back(SSH_COMMAND);
return selectCommand_("ssh", cmdlist, list, path, fn);
}
-Git::Branch const &BasicMainWindow::currentBranch() const
+Git::Branch const &MainWindow::currentBranch() const
{
- return m->current_branch;
+ return m1->current_branch;
}
-void BasicMainWindow::setCurrentBranch(Git::Branch const &b)
+void MainWindow::setCurrentBranch(Git::Branch const &b)
{
- m->current_branch = b;
+ m1->current_branch = b;
}
-RepositoryItem const &BasicMainWindow::currentRepository() const
+RepositoryItem const &MainWindow::currentRepository() const
{
- return m->current_repo;
+ return m1->current_repo;
}
-QString BasicMainWindow::currentRepositoryName() const
+QString MainWindow::currentRepositoryName() const
{
return currentRepository().name;
}
-QString BasicMainWindow::currentRemoteName() const
+QString MainWindow::currentRemoteName() const
{
- return m->current_remote_name;
+ return m1->current_remote_name;
}
-QString BasicMainWindow::currentBranchName() const
+QString MainWindow::currentBranchName() const
{
return currentBranch().name;
}
-bool BasicMainWindow::isValidWorkingCopy(const GitPtr &g) const
+bool MainWindow::isValidWorkingCopy(const GitPtr &g) const
{
return g && g->isValidWorkingCopy();
}
-QString BasicMainWindow::determinFileType_(QString const &path, bool mime, std::function<void (QString const &, QByteArray *)> const &callback) const
+QString MainWindow::determinFileType_(QString const &path, bool mime, std::function<void (QString const &, QByteArray *)> const &callback) const
{
- const_cast<BasicMainWindow *>(this)->checkFileCommand();
+ const_cast<MainWindow *>(this)->checkFileCommand();
return misc::determinFileType(global->file_command, path, mime, callback);
}
-QString BasicMainWindow::determinFileType(QString const &path, bool mime)
+QString MainWindow::determinFileType(QString const &path, bool mime)
{
return determinFileType_(path, mime, [](QString const &cmd, QByteArray *ba){
misc2::runCommand(cmd, ba);
});
}
-QString BasicMainWindow::determinFileType(QByteArray in, bool mime)
+QString MainWindow::determinFileType(QByteArray in, bool mime)
{
if (in.isEmpty()) return QString();
if (in.size() > 10) {
if (memcmp(in.data(), "\x1f\x8b\x08", 3) == 0) { // gzip
QBuffer buf;
MemoryReader reader(in.data(), in.size());
reader.open(MemoryReader::ReadOnly);
buf.open(QBuffer::WriteOnly);
gunzip z;
z.set_maximul_size(100000);
z.decode(&reader, &buf);
in = buf.buffer();
}
}
// ファイル名を "-" にすると、リダイレクトで標準入力へ流し込める。
return determinFileType_("-", mime, [&](QString const &cmd, QByteArray *ba){
int r = misc2::runCommand(cmd, &in, ba);
if (r != 0) {
ba->clear();
}
});
}
-QList<Git::Tag> BasicMainWindow::queryTagList()
+QList<Git::Tag> MainWindow::queryTagList()
{
QList<Git::Tag> list;
Git::CommitItem const *commit = selectedCommitItem();
if (commit && Git::isValidID(commit->commit_id)) {
list = findTag(commit->commit_id);
}
return list;
}
-int BasicMainWindow::limitLogCount() const
+int MainWindow::limitLogCount() const
{
int n = appsettings()->maximum_number_of_commit_item_acquisitions;
return (n >= 1 && n <= 100000) ? n : 10000;
}
-TextEditorThemePtr BasicMainWindow::themeForTextEditor()
+TextEditorThemePtr MainWindow::themeForTextEditor()
{
return global->theme->text_editor_theme;
}
-Git::Object BasicMainWindow::cat_file_(GitPtr const &g, QString const &id)
+Git::Object MainWindow::cat_file_(GitPtr const &g, QString const &id)
{
if (isValidWorkingCopy(g)) {
QString path_prefix = PATH_PREFIX;
if (id.startsWith(path_prefix)) {
QString path = g->workingRepositoryDir();
path = path / id.mid(path_prefix.size());
QFile file(path);
if (file.open(QFile::ReadOnly)) {
Git::Object obj;
obj.content = file.readAll();
return obj;
}
} else if (Git::isValidID(id)) {
return getObjCache()->catFile(id);;
}
}
return Git::Object();
}
-Git::Object BasicMainWindow::cat_file(QString const &id)
+Git::Object MainWindow::cat_file(QString const &id)
{
return cat_file_(git(), id);
}
-QString BasicMainWindow::newTempFilePath()
+QString MainWindow::newTempFilePath()
{
QString tmpdir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
- QString path = tmpdir / tempfileHeader() + QString::number(m->temp_file_counter);
- m->temp_file_counter++;
+ QString path = tmpdir / tempfileHeader() + QString::number(m1->temp_file_counter);
+ m1->temp_file_counter++;
return path;
}
-QString BasicMainWindow::findFileID(QString const &commit_id, QString const &file)
+QString MainWindow::findFileID(QString const &commit_id, QString const &file)
{
return lookupFileID(getObjCache(), commit_id, file);
}
/**
* @brief ファイルリストのテキストを作成
* @param data
* @return
*/
-std::pair<QString, QString> BasicMainWindow::makeFileItemText(ObjectData const &data)
+std::pair<QString, QString> MainWindow::makeFileItemText(ObjectData const &data)
{
QString header = data.header;
if (header.isEmpty()) {
header = "(??\?) "; // damn trigraph
}
QString text = data.path;
if (data.submod) {
text += QString(" <%0> %1").arg(data.submod.id.mid(0, 7)).arg(data.submod_commit.message);
}
return {header, text};
}
/**
* @brief ファイルリストを更新
* @param id
* @param diff_list
* @param listwidget
*/
-void BasicMainWindow::updateFilesList(QString const &id, QList<Git::Diff> *diff_list, QListWidget *listwidget)
+void MainWindow::updateFilesList2(QString const &id, QList<Git::Diff> *diff_list, QListWidget *listwidget)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
listwidget->clear();
auto AddItem = [&](ObjectData const &data){
auto [header, text] = makeFileItemText(data);
QListWidgetItem *item = new QListWidgetItem(text);
item->setSizeHint(QSize(item->sizeHint().width(), 18));
item->setData(FilePathRole, data.path);
item->setData(DiffIndexRole, data.idiff);
item->setData(HunkIndexRole, -1);
item->setData(HeaderRole, header);
listwidget->addItem(item);
};
GitDiff dm(getObjCache());
if (!dm.diff(id, submodules(), diff_list)) return;
addDiffItems(diff_list, AddItem);
}
-void BasicMainWindow::setAppSettings(const ApplicationSettings &appsettings)
+void MainWindow::setAppSettings(const ApplicationSettings &appsettings)
{
- m->appsettings = appsettings;
+ m1->appsettings = appsettings;
}
-QPixmap BasicMainWindow::getTransparentPixmap() const
+QPixmap MainWindow::getTransparentPixmap() const
{
- return m->transparent_pixmap;
+ return m1->transparent_pixmap;
}
-QIcon BasicMainWindow::getSignatureBadIcon() const
+QIcon MainWindow::getSignatureBadIcon() const
{
- return m->signature_bad_icon;
+ return m1->signature_bad_icon;
}
-QIcon BasicMainWindow::getSignatureDubiousIcon() const
+QIcon MainWindow::getSignatureDubiousIcon() const
{
- return m->signature_dubious_icon;
+ return m1->signature_dubious_icon;
}
-QIcon BasicMainWindow::getSignatureGoodIcon() const
+QIcon MainWindow::getSignatureGoodIcon() const
{
- return m->signature_good_icon;
+ return m1->signature_good_icon;
}
-QIcon BasicMainWindow::getFolderIcon() const
+QIcon MainWindow::getFolderIcon() const
{
- return m->folder_icon;
+ return m1->folder_icon;
}
-QIcon BasicMainWindow::getRepositoryIcon() const
+QIcon MainWindow::getRepositoryIcon() const
{
- return m->repository_icon;
+ return m1->repository_icon;
}
-const Git::CommitItemList &BasicMainWindow::getLogs() const
+const Git::CommitItemList &MainWindow::getLogs() const
{
- return m->logs;
+ return m1->logs;
}
-Git::CommitItem const *BasicMainWindow::getLog(int index) const
+Git::CommitItem const *MainWindow::getLog(int index) const
{
- return (index >= 0 && index < (int)m->logs.size()) ? &m->logs[index] : nullptr;
+ return (index >= 0 && index < (int)m1->logs.size()) ? &m1->logs[index] : nullptr;
}
-Git::CommitItemList *BasicMainWindow::getLogsPtr()
+Git::CommitItemList *MainWindow::getLogsPtr()
{
- return &m->logs;
+ return &m1->logs;
}
-void BasicMainWindow::setLogs(const Git::CommitItemList &logs)
+void MainWindow::setLogs(const Git::CommitItemList &logs)
{
- m->logs = logs;
+ m1->logs = logs;
}
-void BasicMainWindow::clearLogs()
+void MainWindow::clearLogs()
{
- m->logs.clear();
+ m1->logs.clear();
}
-BasicMainWindow::PtyCondition BasicMainWindow::getPtyCondition()
+BasicMainWindow::PtyCondition MainWindow::getPtyCondition()
{
- return m->pty_condition;
+ return m1->pty_condition;
}
-void BasicMainWindow::setPtyUserData(QVariant const &userdata)
+void MainWindow::setPtyUserData(QVariant const &userdata)
{
- m->pty_process.setVariant(userdata);
+ m1->pty_process.setVariant(userdata);
}
-void BasicMainWindow::setPtyCondition(const PtyCondition &ptyCondition)
+void MainWindow::setPtyCondition(const PtyCondition &ptyCondition)
{
- m->pty_condition = ptyCondition;
+ m1->pty_condition = ptyCondition;
}
-PtyProcess *BasicMainWindow::getPtyProcess()
+PtyProcess *MainWindow::getPtyProcess()
{
- return &m->pty_process;
+ return &m1->pty_process;
}
-bool BasicMainWindow::getPtyProcessOk() const
+bool MainWindow::getPtyProcessOk() const
{
- return m->pty_process_ok;
+ return m1->pty_process_ok;
}
-void BasicMainWindow::setPtyProcessOk(bool pty_process_ok)
+void MainWindow::setPtyProcessOk(bool pty_process_ok)
{
- m->pty_process_ok = pty_process_ok;
+ m1->pty_process_ok = pty_process_ok;
}
-const QList<RepositoryItem> &BasicMainWindow::getRepos() const
+const QList<RepositoryItem> &MainWindow::getRepos() const
{
- return m->repos;
+ return m1->repos;
}
-QList<RepositoryItem> *BasicMainWindow::getReposPtr()
+QList<RepositoryItem> *MainWindow::getReposPtr()
{
- return &m->repos;
+ return &m1->repos;
}
-void BasicMainWindow::setCurrentRemoteName(QString const &name)
+void MainWindow::setCurrentRemoteName(QString const &name)
{
- m->current_remote_name = name;
+ m1->current_remote_name = name;
}
-AvatarLoader *BasicMainWindow::getAvatarLoader()
+AvatarLoader *MainWindow::getAvatarLoader()
{
- return &m->avatar_loader;
+ return &m1->avatar_loader;
}
-AvatarLoader const *BasicMainWindow::getAvatarLoader() const
+AvatarLoader const *MainWindow::getAvatarLoader() const
{
- return &m->avatar_loader;
+ return &m1->avatar_loader;
}
-int *BasicMainWindow::ptrUpdateFilesListCounter()
+int *MainWindow::ptrUpdateFilesListCounter()
{
- return &m->update_files_list_counter;
+ return &m1->update_files_list_counter;
}
-int *BasicMainWindow::ptrUpdateCommitTableCounter()
+int *MainWindow::ptrUpdateCommitTableCounter()
{
- return &m->update_commit_table_counter;
+ return &m1->update_commit_table_counter;
}
-bool BasicMainWindow::interactionCanceled() const
+bool MainWindow::interactionCanceled() const
{
- return m->interaction_canceled;
+ return m1->interaction_canceled;
}
-void BasicMainWindow::setInteractionCanceled(bool canceled)
+void MainWindow::setInteractionCanceled(bool canceled)
{
- m->interaction_canceled = canceled;
+ m1->interaction_canceled = canceled;
}
-BasicMainWindow::InteractionMode BasicMainWindow::interactionMode() const
+BasicMainWindow::InteractionMode MainWindow::interactionMode() const
{
- return m->interaction_mode;
+ return m1->interaction_mode;
}
-void BasicMainWindow::setInteractionMode(const InteractionMode &im)
+void MainWindow::setInteractionMode(const InteractionMode &im)
{
- m->interaction_mode = im;
+ m1->interaction_mode = im;
}
-QString BasicMainWindow::getRepositoryFilterText() const
+QString MainWindow::getRepositoryFilterText() const
{
- return m->repository_filter_text;
+ return m1->repository_filter_text;
}
-void BasicMainWindow::setRepositoryFilterText(QString const &text)
+void MainWindow::setRepositoryFilterText(QString const &text)
{
- m->repository_filter_text = text;
+ m1->repository_filter_text = text;
}
-void BasicMainWindow::setUncommitedChanges(bool uncommited_changes)
+void MainWindow::setUncommitedChanges(bool uncommited_changes)
{
- m->uncommited_changes = uncommited_changes;
+ m1->uncommited_changes = uncommited_changes;
}
-QList<Git::Diff> *BasicMainWindow::diffResult()
+QList<Git::Diff> *MainWindow::diffResult()
{
- return &m->diff_result;
+ return &m1->diff_result;
}
-void BasicMainWindow::setDiffResult(const QList<Git::Diff> &diffs)
+void MainWindow::setDiffResult(const QList<Git::Diff> &diffs)
{
- m->diff_result = diffs;
+ m1->diff_result = diffs;
}
-const QList<Git::Submodule> &BasicMainWindow::submodules() const
+const QList<Git::Submodule> &MainWindow::submodules() const
{
- return m->submodules;
+ return m1->submodules;
}
-void BasicMainWindow::setSubmodules(const QList<Git::Submodule> &submodules)
+void MainWindow::setSubmodules(const QList<Git::Submodule> &submodules)
{
- m->submodules = submodules;
+ m1->submodules = submodules;
}
-std::map<QString, Git::Diff> *BasicMainWindow::getDiffCacheMap()
+std::map<QString, Git::Diff> *MainWindow::getDiffCacheMap()
{
- return &m->diff_cache;
+ return &m1->diff_cache;
}
-bool BasicMainWindow::getRemoteChanged() const
+bool MainWindow::getRemoteChanged() const
{
- return m->remote_changed;
+ return m1->remote_changed;
}
-void BasicMainWindow::setRemoteChanged(bool remote_changed)
+void MainWindow::setRemoteChanged(bool remote_changed)
{
- m->remote_changed = remote_changed;
+ m1->remote_changed = remote_changed;
}
-void BasicMainWindow::setServerType(const ServerType &server_type)
+void MainWindow::setServerType(const ServerType &server_type)
{
- m->server_type = server_type;
+ m1->server_type = server_type;
}
-GitHubRepositoryInfo *BasicMainWindow::ptrGitHub()
+GitHubRepositoryInfo *MainWindow::ptrGitHub()
{
- return &m->github;
+ return &m1->github;
}
-std::map<int, QList<BasicMainWindow::Label>> *BasicMainWindow::getLabelMap()
+std::map<int, QList<BasicMainWindow::Label>> *MainWindow::getLabelMap()
{
- return &m->label_map;
+ return &m1->label_map;
}
-std::map<int, QList<BasicMainWindow::Label>> const *BasicMainWindow::getLabelMap() const
+std::map<int, QList<BasicMainWindow::Label>> const *MainWindow::getLabelMap() const
{
- return &m->label_map;
+ return &m1->label_map;
}
-void BasicMainWindow::clearLabelMap()
+void MainWindow::clearLabelMap()
{
- m->label_map.clear();
+ m1->label_map.clear();
}
-GitObjectCache *BasicMainWindow::getObjCache()
+GitObjectCache *MainWindow::getObjCache()
{
- return &m->objcache;
+ return &m1->objcache;
}
-bool BasicMainWindow::getForceFetch() const
+bool MainWindow::getForceFetch() const
{
- return m->force_fetch;
+ return m1->force_fetch;
}
-void BasicMainWindow::setForceFetch(bool force_fetch)
+void MainWindow::setForceFetch(bool force_fetch)
{
- m->force_fetch = force_fetch;
+ m1->force_fetch = force_fetch;
}
-std::map<QString, QList<Git::Tag>> *BasicMainWindow::ptrTagMap()
+std::map<QString, QList<Git::Tag>> *MainWindow::ptrTagMap()
{
- return &m->tag_map;
+ return &m1->tag_map;
}
-QString BasicMainWindow::getHeadId() const
+QString MainWindow::getHeadId() const
{
- return m->head_id;
+ return m1->head_id;
}
-void BasicMainWindow::setHeadId(QString const &head_id)
+void MainWindow::setHeadId(QString const &head_id)
{
- m->head_id = head_id;
+ m1->head_id = head_id;
}
-void BasicMainWindow::setPtyProcessCompletionData(QVariant const &value)
+void MainWindow::setPtyProcessCompletionData(QVariant const &value)
{
- m->pty_process_completion_data = value;
+ m1->pty_process_completion_data = value;
}
-QVariant const &BasicMainWindow::getTempRepoForCloneCompleteV() const
+QVariant const &MainWindow::getTempRepoForCloneCompleteV() const
{
- return m->pty_process_completion_data;
+ return m1->pty_process_completion_data;
}
-void BasicMainWindow::updateCommitGraph()
+void MainWindow::updateCommitGraph()
{
auto const &logs = getLogs();
auto *logsp = getLogsPtr();
const size_t LogCount = logs.size();
// 樹形図情報を構築する
if (LogCount > 0) {
auto LogItem = [&](size_t i)->Git::CommitItem &{ return logsp->at(i); };
enum { // 有向グラフを構築するあいだ CommitItem::marker_depth をフラグとして使用する
UNKNOWN = 0,
KNOWN = 1,
};
for (Git::CommitItem &item : *logsp) {
item.marker_depth = UNKNOWN;
}
// コミットハッシュを検索して、親コミットのインデックスを求める
for (size_t i = 0; i < LogCount; i++) {
Git::CommitItem *item = &LogItem(i);
item->parent_lines.clear();
if (item->parent_ids.empty()) {
item->resolved = true;
} else {
for (int j = 0; j < item->parent_ids.size(); j++) { // 親の数だけループ
QString const &parent_id = item->parent_ids[j]; // 親のハッシュ値
for (size_t k = i + 1; k < LogCount; k++) { // 親を探す
if (LogItem(k).commit_id == parent_id) { // ハッシュ値が一致したらそれが親
item->parent_lines.emplace_back(k); // インデックス値を記憶
LogItem(k).has_child = true;
LogItem(k).marker_depth = KNOWN;
item->resolved = true;
break;
}
}
}
}
}
std::vector<Element> elements; // 線分リスト
{ // 線分リストを作成する
std::deque<Task> tasks; // 未処理タスクリスト
{
for (size_t i = 0; i < LogCount; i++) {
Git::CommitItem *item = &LogItem(i);
if (item->marker_depth == UNKNOWN) {
int n = item->parent_lines.size(); // 最初のコミットアイテム
for (int j = 0; j < n; j++) {
tasks.emplace_back(i, j); // タスクを追加
}
}
item->marker_depth = UNKNOWN;
}
}
while (!tasks.empty()) { // タスクが残っているならループ
Element e;
Task task;
{ // 最初のタスクを取り出す
task = tasks.front();
tasks.pop_front();
}
e.indexes.push_back(task.index); // 先頭のインデックスを追加
int index = LogItem(task.index).parent_lines[task.parent].index; // 開始インデックス
while (index > 0 && (size_t)index < LogCount) { // 最後に到達するまでループ
e.indexes.push_back(index); // インデックスを追加
int n = LogItem(index).parent_lines.size(); // 親の数
if (n == 0) break; // 親がないなら終了
Git::CommitItem *item = &LogItem(index);
if (item->marker_depth == KNOWN) break; // 既知のアイテムに到達したら終了
item->marker_depth = KNOWN; // 既知のアイテムにする
for (int i = 1; i < n; i++) {
tasks.emplace_back(index, i); // タスク追加
}
index = LogItem(index).parent_lines[0].index; // 次の親(親リストの先頭の要素)
}
if (e.indexes.size() >= 2) {
elements.push_back(e);
}
}
}
// 線情報をクリア
for (Git::CommitItem &item : *logsp) {
item.marker_depth = -1;
item.parent_lines.clear();
}
// マークと線の深さを決める
if (!elements.empty()) {
{ // 優先順位を調整する
std::sort(elements.begin(), elements.end(), [](Element const &left, Element const &right){
int i = 0;
{ // 長いものを優先して左へ
int l = left.indexes.back() - left.indexes.front();
int r = right.indexes.back() - right.indexes.front();
i = r - l; // 降順
}
if (i == 0) {
// コミットが新しいものを優先して左へ
int l = left.indexes.front();
int r = right.indexes.front();
i = l - r; // 昇順
}
return i < 0;
});
// 子の無いブランチ(タグ等)が複数連続しているとき、古いコミットを右に寄せる
{
for (size_t i = 0; i + 1 < elements.size(); i++) {
Element *e = &elements[i];
int index1 = e->indexes.front();
if (index1 > 0 && !LogItem(index1).has_child) { // 子がない
// 新しいコミットを探す
for (size_t j = i + 1; j < elements.size(); j++) { // 現在位置より後ろを探す
Element *f = &elements[j];
int index2 = f->indexes.front();
if (index1 == index2 + 1) { // 一つだけ新しいコミット
Element t = std::move(*f);
elements.erase(elements.begin() + j); // 移動元を削除
elements.insert(elements.begin() + i, std::move(t)); // 現在位置に挿入
}
}
// 古いコミットを探す
size_t j = 0;
while (j < i) { // 現在位置より前を探す
Element *f = &elements[j];
int index2 = f->indexes.front();
if (index1 + 1 == index2) { // 一つだけ古いコミット
Element t = std::move(*f);
elements.erase(elements.begin() + j); // 移動元を削除
elements.insert(elements.begin() + i, std::move(t)); // 現在位置の次に挿入
index1 = index2;
f = e;
} else {
j++;
}
}
}
}
}
}
{ // 最初の線は深さを0にする
Element *e = &elements.front();
for (size_t i = 0; i < e->indexes.size(); i++) {
int index = e->indexes[i];
LogItem(index).marker_depth = 0; // マークの深さを設定
e->depth = 0; // 線の深さを設定
}
}
// 最初以外の線分の深さを決める
for (size_t i = 1; i < elements.size(); i++) { // 最初以外をループ
Element *e = &elements[i];
int depth = 1;
while (1) { // 失敗したら繰り返し
for (size_t j = 0; j < i; j++) { // 既に処理済みの線を調べる
Element const *f = &elements[j]; // 検査対象
if (e->indexes.size() == 2) { // 二つしかない場合
int from = e->indexes[0]; // 始点
int to = e->indexes[1]; // 終点
if (LogItem(from).has_child) {
for (size_t k = 0; k + 1 < f->indexes.size(); k++) { // 検査対象の全ての線分を調べる
int curr = f->indexes[k];
int next = f->indexes[k + 1];
if (from > curr && to == next) { // 決定済みの線に直結できるか判定
e->indexes.back() = from + 1; // 現在の一行下に直結する
e->depth = elements[j].depth; // 接続先の深さ
goto DONE; // 決定
}
}
}
}
if (depth == f->depth) { // 同じ深さ
if (e->indexes.back() > f->indexes.front() && e->indexes.front() < f->indexes.back()) { // 重なっている
goto FAIL; // この深さには線を置けないのでやりなおし
}
}
}
for (size_t j = 0; j < e->indexes.size(); j++) {
int index = e->indexes[j];
Git::CommitItem *item = &LogItem(index);
if (j == 0 && item->has_child) { // 最初のポイントで子がある場合
// nop
} else if ((j > 0 && j + 1 < e->indexes.size()) || item->marker_depth < 0) { // 最初と最後以外、または、未確定の場合
item->marker_depth = depth; // マークの深さを設定
}
}
e->depth = depth; // 深さを決定
goto DONE; // 決定
FAIL:;
depth++; // 一段深くして再挑戦
}
DONE:;
}
// 線情報を生成する
for (auto &e : elements) {
auto ColorNumber = [&](){ return e.depth; };
size_t count = e.indexes.size();
for (size_t i = 0; i + 1 < count; i++) {
int curr = e.indexes[i];
int next = e.indexes[i + 1];
TreeLine line(next, e.depth);
line.color_number = ColorNumber();
line.bend_early = (i + 2 < count || !LogItem(next).resolved);
if (i + 2 == count) {
int join = false;
if (count > 2) { // 直結ではない
join = true;
} else if (!LogItem(curr).has_child) { // 子がない
join = true;
int d = LogItem(curr).marker_depth; // 開始点の深さ
for (int j = curr + 1; j < next; j++) {
Git::CommitItem *item = &LogItem(j);
if (item->marker_depth == d) { // 衝突する
join = false; // 迂回する
break;
}
}
}
if (join) {
line.depth = LogItem(next).marker_depth; // 合流する先のアイテムの深さと同じにする
}
}
LogItem(curr).parent_lines.push_back(line); // 線を追加
}
}
} else {
if (LogCount == 1) { // コミットが一つだけ
LogItem(0).marker_depth = 0;
}
}
}
}
-bool BasicMainWindow::fetch(GitPtr const &g, bool prune)
+bool MainWindow::fetch(GitPtr const &g, bool prune)
{
setPtyCondition(PtyCondition::Fetch);
setPtyProcessOk(true);
g->fetch(getPtyProcess(), prune);
while (1) {
if (getPtyProcess()->wait(1)) break;
QApplication::processEvents();
}
return getPtyProcessOk();
}
-bool BasicMainWindow::fetch_tags_f(GitPtr const &g)
+bool MainWindow::fetch_tags_f(GitPtr const &g)
{
setPtyCondition(PtyCondition::Fetch);
setPtyProcessOk(true);
g->fetch_tags_f(getPtyProcess());
while (1) {
if (getPtyProcess()->wait(1)) break;
QApplication::processEvents();
}
return getPtyProcessOk();
}
-bool BasicMainWindow::git_callback(void *cookie, const char *ptr, int len)
+bool MainWindow::git_callback(void *cookie, const char *ptr, int len)
{
- auto *mw = (BasicMainWindow *)cookie;
+ auto *mw = (MainWindow *)cookie;
mw->emitWriteLog(QByteArray(ptr, len));
return true;
}
-QString BasicMainWindow::selectCommand_(QString const &cmdname, QStringList const &cmdfiles, QStringList const &list, QString path, std::function<void (QString const &)> const &callback)
+QString MainWindow::selectCommand_(QString const &cmdname, QStringList const &cmdfiles, QStringList const &list, QString path, std::function<void (QString const &)> const &callback)
{
QString window_title = tr("Select %1 command");
window_title = window_title.arg(cmdfiles.front());
SelectCommandDialog dlg(this, cmdname, cmdfiles, path, list);
dlg.setWindowTitle(window_title);
if (dlg.exec() == QDialog::Accepted) {
path = dlg.selectedFile();
path = misc::normalizePathSeparator(path);
QFileInfo info(path);
if (info.isExecutable()) {
callback(path);
return path;
}
}
return QString();
}
-QString BasicMainWindow::selectCommand_(QString const &cmdname, QString const &cmdfile, QStringList const &list, QString const &path, std::function<void (QString const &)> const &callback)
+QString MainWindow::selectCommand_(QString const &cmdname, QString const &cmdfile, QStringList const &list, QString const &path, std::function<void (QString const &)> const &callback)
{
QStringList cmdfiles;
cmdfiles.push_back(cmdfile);
return selectCommand_(cmdname, cmdfiles, list, path, callback);
}
-bool BasicMainWindow::checkGitCommand()
+bool MainWindow::checkGitCommand()
{
while (1) {
if (misc::isExecutable(gitCommand())) {
return true;
}
if (selectGitCommand(true).isEmpty()) {
close();
return false;
}
}
}
-bool BasicMainWindow::checkFileCommand()
+bool MainWindow::checkFileCommand()
{
while (1) {
if (misc::isExecutable(global->file_command)) {
return true;
}
if (selectFileCommand(true).isEmpty()) {
close();
return false;
}
}
}
-bool BasicMainWindow::checkExecutable(QString const &path)
+bool MainWindow::checkExecutable(QString const &path)
{
if (QFileInfo(path).isExecutable()) {
return true;
}
QString text = "The specified program '%1' is not executable.\n";
text = text.arg(path);
writeLog(text);
return false;
}
-void BasicMainWindow::internalSaveCommandPath(QString const &path, bool save, QString const &name)
+void MainWindow::internalSaveCommandPath(QString const &path, bool save, QString const &name)
{
if (checkExecutable(path)) {
if (save) {
MySettings s;
s.beginGroup("Global");
s.setValue(name, path);
s.endGroup();
}
}
}
-QStringList BasicMainWindow::whichCommand_(QString const &cmdfile1, QString const &cmdfile2)
+QStringList MainWindow::whichCommand_(QString const &cmdfile1, QString const &cmdfile2)
{
QStringList list;
if (!cmdfile1.isEmpty()){
std::vector<std::string> vec;
FileUtil::qwhich(cmdfile1.toStdString(), &vec);
for (std::string const &s : vec) {
list.push_back(QString::fromStdString(s));
}
}
if (!cmdfile2.isEmpty()){
std::vector<std::string> vec;
FileUtil::qwhich(cmdfile2.toStdString(), &vec);
for (std::string const &s : vec) {
list.push_back(QString::fromStdString(s));
}
}
return list;
}
-void BasicMainWindow::setWindowTitle_(Git::User const &user)
+void MainWindow::setWindowTitle_(Git::User const &user)
{
if (user.name.isEmpty() && user.email.isEmpty()) {
setWindowTitle(qApp->applicationName());
} else {
setWindowTitle(QString("%1 : %2 <%3>")
.arg(qApp->applicationName())
.arg(user.name)
.arg(user.email)
);
}
}
-bool BasicMainWindow::execSetGlobalUserDialog()
+bool MainWindow::execSetGlobalUserDialog()
{
SetGlobalUserDialog dlg(this);
if (dlg.exec() == QDialog::Accepted) {
GitPtr g = git();
Git::User user = dlg.user();
g->setUser(user, true);
updateWindowTitle(g);
return true;
}
return false;
}
-bool BasicMainWindow::saveByteArrayAs(const QByteArray &ba, QString const &dstpath)
+bool MainWindow::saveByteArrayAs(const QByteArray &ba, QString const &dstpath)
{
QFile file(dstpath);
if (file.open(QFile::WriteOnly)) {
file.write(ba);
file.close();
return true;
}
QString msg = "Failed to open the file '%1' for write";
msg = msg.arg(dstpath);
qDebug() << msg;
return false;
}
-bool BasicMainWindow::saveFileAs(QString const &srcpath, QString const &dstpath)
+bool MainWindow::saveFileAs(QString const &srcpath, QString const &dstpath)
{
QFile f(srcpath);
if (f.open(QFile::ReadOnly)) {
QByteArray ba = f.readAll();
if (saveByteArrayAs(ba, dstpath)) {
return true;
}
} else {
QString msg = "Failed to open the file '%1' for read";
msg = msg.arg(srcpath);
qDebug() << msg;
}
return false;
}
-bool BasicMainWindow::saveBlobAs(QString const &id, QString const &dstpath)
+bool MainWindow::saveBlobAs(QString const &id, QString const &dstpath)
{
Git::Object obj = cat_file(id);
if (!obj.content.isEmpty()) {
if (saveByteArrayAs(obj.content, dstpath)) {
return true;
}
} else {
QString msg = "Failed to get the content of the object '%1'";
msg = msg.arg(id);
qDebug() << msg;
}
return false;
}
-void BasicMainWindow::revertAllFiles()
+void MainWindow::revertAllFiles()
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
QString cmd = "git reset --hard HEAD";
if (askAreYouSureYouWantToRun(tr("Revert all files"), "> " + cmd)) {
g->resetAllFiles();
openRepository(true);
}
}
-void BasicMainWindow::deleteTags(Git::CommitItem const &commit)
+void MainWindow::deleteTags(Git::CommitItem const &commit)
{
auto it = ptrTagMap()->find(commit.commit_id);
if (it != ptrTagMap()->end()) {
QStringList names;
QList<Git::Tag> const &tags = it->second;
for (Git::Tag const &tag : tags) {
names.push_back(tag.name);
}
deleteTags(names);
}
}
-bool BasicMainWindow::isAvatarEnabled() const
+bool MainWindow::isAvatarEnabled() const
{
return appsettings()->get_committer_icon;
}
-bool BasicMainWindow::isGitHub() const
+bool MainWindow::isGitHub() const
{
- return m->server_type == ServerType::GitHub;
+ return m1->server_type == ServerType::GitHub;
}
-QStringList BasicMainWindow::remotes() const
+QStringList MainWindow::remotes() const
{
- return m->remotes;
+ return m1->remotes;
}
-QList<Git::Branch> BasicMainWindow::findBranch(QString const &id)
+QList<Git::Branch> MainWindow::findBranch(QString const &id)
{
auto it = branchMapRef().find(id);
if (it != branchMapRef().end()) {
return it->second;
}
return QList<Git::Branch>();
}
-QString BasicMainWindow::saveAsTemp(QString const &id)
+QString MainWindow::saveAsTemp(QString const &id)
{
QString path = newTempFilePath();
saveAs(id, path);
return path;
}
-QString BasicMainWindow::tempfileHeader() const
+QString MainWindow::tempfileHeader() const
{
QString name = "jp_soramimi_Guitar_%1_";
return name.arg(QApplication::applicationPid());
}
-void BasicMainWindow::deleteTempFiles()
+void MainWindow::deleteTempFiles()
{
QString dir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
QString name = tempfileHeader();
QDirIterator it(dir, { name + "*" });
while (it.hasNext()) {
QString path = it.next();
QFile::remove(path);
}
}
-QString BasicMainWindow::getCommitIdFromTag(QString const &tag)
+QString MainWindow::getCommitIdFromTag(QString const &tag)
{
return getObjCache()->getCommitIdFromTag(tag);
}
-bool BasicMainWindow::isValidRemoteURL(QString const &url, QString const &sshkey)
+bool MainWindow::isValidRemoteURL(QString const &url, QString const &sshkey)
{
if (url.indexOf('\"') >= 0) {
return false;
}
stopPtyProcess();
GitPtr g = git(QString(), sshkey);
QString cmd = "ls-remote \"%1\" HEAD";
cmd = cmd.arg(url);
bool f = g->git(cmd, false, false, getPtyProcess());
{
QTime time;
time.start();
while (!getPtyProcess()->wait(10)) {
if (time.elapsed() > 10000) {
f = false;
break;
}
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
stopPtyProcess();
}
if (f) {
f = (getPtyProcess()->getExitCode() == 0);
}
QString line;
{
std::vector<char> v;
getPtyProcess()->readResult(&v);
if (!v.empty()) {
line = QString::fromUtf8(&v[0], v.size()).trimmed();
}
}
if (f) {
qDebug() << "This is a valid repository.";
int i = -1;
for (int j = 0; j < line.size(); j++) {
ushort c = line.utf16()[j];
if (QChar(c).isSpace()) {
i = j;
break;
}
}
QString head;
if (i == GIT_ID_LENGTH) {
QString id = line.mid(0, i);
QString name = line.mid(i + 1).trimmed();
qDebug() << id << name;
if (name == "HEAD" && Git::isValidID(id)) {
head = id;
}
}
if (head.isEmpty()) {
qDebug() << "But HEAD not found";
}
return true;
}
qDebug() << "This is not a repository.";
return false;
}
-QString BasicMainWindow::getObjectID(QListWidgetItem *item)
+QString MainWindow::getObjectID(QListWidgetItem *item)
{
int i = indexOfDiff(item);
if (i >= 0 && i < diffResult()->size()) {
Git::Diff const &diff = diffResult()->at(i);
return diff.blob.a_id;
}
return QString();
}
-void BasicMainWindow::addWorkingCopyDir(QString dir, QString name, bool open)
+void MainWindow::addWorkingCopyDir(QString dir, QString name, bool open)
{
if (dir.endsWith(".git")) {
int i = dir.size();
if (i > 4) {
ushort c = dir.utf16()[i - 5];
if (c == '/' || c == '\\') {
dir = dir.mid(0, i - 5);
}
}
}
if (!Git::isValidWorkingCopy(dir)) {
if (QFileInfo(dir).isDir()) {
QString text;
text += tr("The folder is not a valid git repository.") + '\n';
text += '\n';
text += dir + '\n';
text += '\n';
text += tr("Do you want to initialize it as a git repository ?") + '\n';
int r = QMessageBox::information(this, tr("Initialize Repository") , text, QMessageBox::Yes, QMessageBox::No);
if (r == QMessageBox::Yes) {
createRepository(dir);
}
}
return;
}
if (name.isEmpty()) {
name = makeRepositoryName(dir);
}
RepositoryItem item;
item.local_dir = dir;
item.name = name;
saveRepositoryBookmark(item);
if (open) {
setCurrentRepository(item, true);
GitPtr g = git(item.local_dir);
openRepository_(g);
}
}
-QString BasicMainWindow::makeRepositoryName(QString const &loc)
+QString MainWindow::makeRepositoryName(QString const &loc)
{
int i = loc.lastIndexOf('/');
int j = loc.lastIndexOf('\\');
if (i < j) i = j;
if (i >= 0) {
i++;
j = loc.size();
if (loc.endsWith(".git")) {
j -= 4;
}
return loc.mid(i, j - i);
}
return QString();
}
-void BasicMainWindow::clearAuthentication()
+void MainWindow::clearAuthentication()
{
clearSshAuthentication();
- m->http_uid.clear();
- m->http_pwd.clear();
+ m1->http_uid.clear();
+ m1->http_pwd.clear();
}
-void BasicMainWindow::onAvatarUpdated()
+void MainWindow::onAvatarUpdated()
{
updateCommitTableLater();
}
-QStringList BasicMainWindow::findGitObject(const QString &id) const
+QStringList MainWindow::findGitObject(const QString &id) const
{
QStringList list;
std::set<QString> set;
if (Git::isValidID(id)) {
{
QString a = id.mid(0, 2);
QString b = id.mid(2);
- QString dir = m->current_repo.local_dir / ".git/objects" / a;
+ QString dir = m1->current_repo.local_dir / ".git/objects" / a;
QDirIterator it(dir);
while (it.hasNext()) {
it.next();
QFileInfo info = it.fileInfo();
if (info.isFile()) {
QString c = info.fileName();
if (c.startsWith(b)) {
set.insert(set.end(), a + c);
}
}
}
}
{
- QString dir = m->current_repo.local_dir / ".git/objects/pack";
+ QString dir = m1->current_repo.local_dir / ".git/objects/pack";
QDirIterator it(dir);
while (it.hasNext()) {
it.next();
QFileInfo info = it.fileInfo();
if (info.isFile() && info.fileName().startsWith("pack-") && info.fileName().endsWith(".idx")) {
GitPackIdxV2 idx;
idx.parse(info.absoluteFilePath());
idx.each([&](GitPackIdxItem const *item){
if (item->id.startsWith(id)) {
set.insert(item->id);
}
return true;
});
}
}
}
for (QString const &s : set) {
list.push_back(s);
}
}
return list;
}
-void BasicMainWindow::writeLog(const char *ptr, int len)
+void MainWindow::writeLog(const char *ptr, int len)
{
internalWriteLog(ptr, len);
}
-void BasicMainWindow::writeLog(const QString &str)
+void MainWindow::writeLog(const QString &str)
{
std::string s = str.toStdString();
writeLog(s.c_str(), s.size());
}
-void BasicMainWindow::emitWriteLog(QByteArray const &ba)
+void MainWindow::emitWriteLog(QByteArray const &ba)
{
emit signalWriteLog(ba);
}
-void BasicMainWindow::writeLog_(QByteArray ba)
+void MainWindow::writeLog_(QByteArray ba)
{
if (!ba.isEmpty()) {
writeLog(ba.data(), ba.size());
}
}
-void BasicMainWindow::queryRemotes(GitPtr const &g)
+void MainWindow::queryRemotes(GitPtr const &g)
{
if (!g) return;
- m->remotes = g->getRemotes();
- std::sort(m->remotes.begin(), m->remotes.end());
+ m1->remotes = g->getRemotes();
+ std::sort(m1->remotes.begin(), m1->remotes.end());
}
-void BasicMainWindow::msgNoRepositorySelected()
+void MainWindow::msgNoRepositorySelected()
{
QMessageBox::warning(this, qApp->applicationName(), tr("No repository selected"));
}
-bool BasicMainWindow::runOnRepositoryDir(std::function<void (QString)> const &callback, RepositoryItem const *repo)
+bool MainWindow::runOnRepositoryDir(std::function<void (QString)> const &callback, RepositoryItem const *repo)
{
if (!repo) {
- repo = &m->current_repo;
+ repo = &m1->current_repo;
}
QString dir = repo->local_dir;
dir.replace('\\', '/');
if (QFileInfo(dir).isDir()) {
callback(dir);
return true;
}
msgNoRepositorySelected();
return false;
}
-void BasicMainWindow::clearSshAuthentication()
+void MainWindow::clearSshAuthentication()
{
- m->ssh_passphrase_user.clear();
- m->ssh_passphrase_pass.clear();
+ m1->ssh_passphrase_user.clear();
+ m1->ssh_passphrase_pass.clear();
}
-QString BasicMainWindow::getFilePath(QListWidgetItem *item)
+QString MainWindow::getFilePath(QListWidgetItem *item)
{
if (!item) return QString();
return item->data(FilePathRole).toString();
}
-bool BasicMainWindow::isGroupItem(QTreeWidgetItem *item)
+bool MainWindow::isGroupItem(QTreeWidgetItem *item)
{
if (item) {
int index = item->data(0, IndexRole).toInt();
if (index == GroupItem) {
return true;
}
}
return false;
}
-int BasicMainWindow::indexOfLog(QListWidgetItem *item)
+int MainWindow::indexOfLog(QListWidgetItem *item)
{
if (!item) return -1;
return item->data(IndexRole).toInt();
}
-int BasicMainWindow::indexOfDiff(QListWidgetItem *item)
+int MainWindow::indexOfDiff(QListWidgetItem *item)
{
if (!item) return -1;
return item->data(DiffIndexRole).toInt();
}
-int BasicMainWindow::getHunkIndex(QListWidgetItem *item)
+int MainWindow::getHunkIndex(QListWidgetItem *item)
{
if (!item) return -1;
return item->data(HunkIndexRole).toInt();
}
-void BasicMainWindow::initNetworking()
+void MainWindow::initNetworking()
{
std::string http_proxy;
std::string https_proxy;
if (appsettings()->proxy_type == "auto") {
#ifdef Q_OS_WIN
http_proxy = misc::makeProxyServerURL(getWin32HttpProxy().toStdString());
#else
auto getienv = [](std::string const &name)->char const *{
char **p = environ;
while (*p) {
if (strncasecmp(*p, name.c_str(), name.size()) == 0) {
char const *e = *p + name.size();
if (*e == '=') {
return e + 1;
}
}
p++;
}
return nullptr;
};
char const *p;
p = getienv("http_proxy");
if (p) {
http_proxy = misc::makeProxyServerURL(std::string(p));
}
p = getienv("https_proxy");
if (p) {
https_proxy = misc::makeProxyServerURL(std::string(p));
}
#endif
} else if (appsettings()->proxy_type == "manual") {
http_proxy = appsettings()->proxy_server.toStdString();
}
webContext()->set_http_proxy(http_proxy);
webContext()->set_https_proxy(https_proxy);
}
-QString BasicMainWindow::abbrevCommitID(Git::CommitItem const &commit)
+QString MainWindow::abbrevCommitID(Git::CommitItem const &commit)
{
return commit.commit_id.mid(0, 7);
}
-bool BasicMainWindow::saveRepositoryBookmarks() const
+bool MainWindow::saveRepositoryBookmarks() const
{
QString path = getBookmarksFilePath();
return RepositoryBookmark::save(path, &getRepos());
}
-QString BasicMainWindow::getBookmarksFilePath() const
+QString MainWindow::getBookmarksFilePath() const
{
return global->app_config_dir / "bookmarks.xml";
}
-void BasicMainWindow::stopPtyProcess()
+void MainWindow::stopPtyProcess()
{
getPtyProcess()->stop();
- QDir::setCurrent(m->starting_dir);
+ QDir::setCurrent(m1->starting_dir);
}
-void BasicMainWindow::abortPtyProcess()
+void MainWindow::abortPtyProcess()
{
stopPtyProcess();
setPtyProcessOk(false);
setInteractionCanceled(true);
}
-void BasicMainWindow::saveApplicationSettings()
+void MainWindow::saveApplicationSettings()
{
- SettingsDialog::saveSettings(&m->appsettings);
+ SettingsDialog::saveSettings(&m1->appsettings);
}
-void BasicMainWindow::loadApplicationSettings()
+void MainWindow::loadApplicationSettings()
{
- SettingsDialog::loadSettings(&m->appsettings);
+ SettingsDialog::loadSettings(&m1->appsettings);
}
-bool BasicMainWindow::execWelcomeWizardDialog()
+bool MainWindow::execWelcomeWizardDialog()
{
WelcomeWizardDialog dlg(this);
dlg.set_git_command_path(appsettings()->git_command);
dlg.set_file_command_path(appsettings()->file_command);
dlg.set_default_working_folder(appsettings()->default_working_dir);
if (misc::isExecutable(appsettings()->git_command)) {
gitCommand() = appsettings()->git_command;
- Git g(m->gcx, {}, {});
+ Git g(m1->gcx, {}, {});
Git::User user = g.getUser(Git::Source::Global);
dlg.set_user_name(user.name);
dlg.set_user_email(user.email);
}
if (dlg.exec() == QDialog::Accepted) {
setGitCommand(dlg.git_command_path(), false);
setFileCommand(dlg.file_command_path(), false);
// appsettings()->git_command = dlg.git_command_path();
appsettings()->file_command = dlg.file_command_path();
// m->gcx.git_command = appsettings()->git_command;
global->file_command = appsettings()->file_command;
appsettings()->default_working_dir = dlg.default_working_folder();
saveApplicationSettings();
if (misc::isExecutable(appsettings()->git_command)) {
GitPtr g = git();
Git::User user;
user.name = dlg.user_name();
user.email = dlg.user_email();
g->setUser(user, true);
}
return true;
}
return false;
}
-void BasicMainWindow::execRepositoryPropertyDialog(RepositoryItem const &repo, bool open_repository_menu)
+void MainWindow::execRepositoryPropertyDialog(RepositoryItem const &repo, bool open_repository_menu)
{
QString workdir = repo.local_dir;
if (workdir.isEmpty()) {
workdir = currentWorkingCopyDir();
}
QString name = repo.name;
if (name.isEmpty()) {
name = makeRepositoryName(workdir);
}
GitPtr g = git(workdir, repo.ssh_key);
- RepositoryPropertyDialog dlg(this, &m->gcx, g, repo, open_repository_menu);
+ RepositoryPropertyDialog dlg(this, &m1->gcx, g, repo, open_repository_menu);
dlg.exec();
if (dlg.isRemoteChanged()) {
emit remoteInfoChanged();
}
}
-void BasicMainWindow::execSetUserDialog(Git::User const &global_user, Git::User const &repo_user, QString const &reponame)
+void MainWindow::execSetUserDialog(Git::User const &global_user, Git::User const &repo_user, QString const &reponame)
{
SetUserDialog dlg(this, global_user, repo_user, reponame);
if (dlg.exec() == QDialog::Accepted) {
GitPtr g = git();
Git::User user = dlg.user();
if (dlg.isGlobalChecked()) {
g->setUser(user, true);
}
if (dlg.isRepositoryChecked()) {
g->setUser(user, false);
}
updateWindowTitle(g);
}
}
-QString BasicMainWindow::executableOrEmpty(QString const &path)
+QString MainWindow::executableOrEmpty(QString const &path)
{
return checkExecutable(path) ? path : QString();
}
-void BasicMainWindow::setGitCommand(QString path, bool save)
+void MainWindow::setGitCommand(QString path, bool save)
{
- appsettings()->git_command = m->gcx.git_command = executableOrEmpty(path);
+ appsettings()->git_command = m1->gcx.git_command = executableOrEmpty(path);
internalSaveCommandPath(path, save, "GitCommand");
}
-void BasicMainWindow::setFileCommand(QString path, bool save)
+void MainWindow::setFileCommand(QString path, bool save)
{
appsettings()->file_command = global->file_command = executableOrEmpty(path);
internalSaveCommandPath(path, save, "FileCommand");
}
-void BasicMainWindow::setGpgCommand(QString path, bool save)
+void MainWindow::setGpgCommand(QString path, bool save)
{
appsettings()->gpg_command = global->gpg_command = executableOrEmpty(path);
internalSaveCommandPath(path, save, "GpgCommand");
if (!global->gpg_command.isEmpty()) {
GitPtr g = git();
g->configGpgProgram(global->gpg_command, true);
}
}
-void BasicMainWindow::setSshCommand(QString path, bool save)
+void MainWindow::setSshCommand(QString path, bool save)
{
appsettings()->ssh_command = executableOrEmpty(path);
internalSaveCommandPath(path, save, "SshCommand");
}
-void BasicMainWindow::logGitVersion()
+void MainWindow::logGitVersion()
{
GitPtr g = git();
QString s = g->version();
if (!s.isEmpty()) {
s += '\n';
writeLog(s);
}
}
-void BasicMainWindow::setUnknownRepositoryInfo()
+void MainWindow::setUnknownRepositoryInfo()
{
setRepositoryInfo("---", "");
- Git g(m->gcx, {}, {});
+ Git g(m1->gcx, {}, {});
Git::User user = g.getUser(Git::Source::Global);
setWindowTitle_(user);
}
-void BasicMainWindow::internalClearRepositoryInfo()
+void MainWindow::internalClearRepositoryInfo()
{
setHeadId(QString());
setCurrentBranch(Git::Branch());
setServerType(ServerType::Standard);
- m->github = GitHubRepositoryInfo();
+ m1->github = GitHubRepositoryInfo();
}
-void BasicMainWindow::checkUser()
+void MainWindow::checkUser()
{
- Git g(m->gcx, {}, {});
+ Git g(m1->gcx, {}, {});
while (1) {
Git::User user = g.getUser(Git::Source::Global);
if (!user.name.isEmpty() && !user.email.isEmpty()) {
return; // ok
}
if (!execSetGlobalUserDialog()) {
return;
}
}
}
-void BasicMainWindow::openRepository(bool validate, bool waitcursor, bool keep_selection)
+void MainWindow::openRepository(bool validate, bool waitcursor, bool keep_selection)
{
if (validate) {
QString dir = currentWorkingCopyDir();
if (!QFileInfo(dir).isDir()) {
int r = QMessageBox::warning(this, tr("Open Repository"), dir + "\n\n" + tr("No such folder") + "\n\n" + tr("Remove from bookmark ?"), QMessageBox::Ok, QMessageBox::Cancel);
if (r == QMessageBox::Ok) {
removeSelectedRepositoryFromBookmark(false);
}
return;
}
if (!Git::isValidWorkingCopy(dir)) {
QMessageBox::warning(this, tr("Open Repository"), tr("Not a valid git repository") + "\n\n" + dir);
return;
}
}
if (waitcursor) {
OverrideWaitCursor;
openRepository(false, false, keep_selection);
return;
}
GitPtr g = git(); // ポインタの有効性チェックはしない(nullptrでも続行)
openRepository_(g, keep_selection);
}
-void BasicMainWindow::updateRepository()
+void MainWindow::updateRepository()
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
OverrideWaitCursor;
openRepository_(g);
}
-void BasicMainWindow::reopenRepository(bool log, std::function<void(GitPtr const &)> const &callback)
+void MainWindow::reopenRepository(bool log, std::function<void(GitPtr const &)> const &callback)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
- setRemoteMonitoringEnabled(false);
-
OverrideWaitCursor;
if (log) {
setLogEnabled(g, true);
AsyncExecGitThread_ th(g, callback);
th.start();
while (1) {
if (th.wait(1)) break;
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
setLogEnabled(g, false);
} else {
callback(g);
}
openRepository_(g);
-
- setRemoteMonitoringEnabled(true);
}
-void BasicMainWindow::openSelectedRepository()
+void MainWindow::openSelectedRepository()
{
RepositoryItem const *repo = selectedRepositoryItem();
if (repo) {
setCurrentRepository(*repo, true);
openRepository(true);
}
}
-bool BasicMainWindow::isThereUncommitedChanges() const
+bool MainWindow::isThereUncommitedChanges() const
{
- return m->uncommited_changes;
+ return m1->uncommited_changes;
}
/**
* @brief コミットに対応する差分情報を作成
* @param id コミットID
* @param ok
* @return
*/
-QList<Git::Diff> BasicMainWindow::makeDiffs(QString id, bool *ok)
+QList<Git::Diff> MainWindow::makeDiffs(QString id, bool *ok)
{
QList<Git::Diff> out;
GitPtr g = git();
if (!isValidWorkingCopy(g)) {
if (ok) *ok = false;
return {};
}
Git::FileStatusList list = g->status_s();
setUncommitedChanges(!list.empty());
if (id.isEmpty() && !isThereUncommitedChanges()) {
id = getObjCache()->revParse("HEAD");
}
updateSubmodules(g, id);
bool uncommited = (id.isEmpty() && isThereUncommitedChanges());
GitDiff dm(getObjCache());
if (uncommited) {
dm.diff_uncommited(submodules(), &out);
} else {
dm.diff(id, submodules(), &out);
}
if (ok) *ok = true;
return out;
}
-void BasicMainWindow::addDiffItems(const QList<Git::Diff> *diff_list, const std::function<void (ObjectData const &data)> &add_item)
+void MainWindow::addDiffItems(const QList<Git::Diff> *diff_list, const std::function<void (ObjectData const &data)> &add_item)
{
for (int idiff = 0; idiff < diff_list->size(); idiff++) {
Git::Diff const &diff = diff_list->at(idiff);
QString header;
switch (diff.type) {
case Git::Diff::Type::Modify: header = "(chg) "; break;
case Git::Diff::Type::Copy: header = "(cpy) "; break;
case Git::Diff::Type::Rename: header = "(ren) "; break;
case Git::Diff::Type::Create: header = "(add) "; break;
case Git::Diff::Type::Delete: header = "(del) "; break;
case Git::Diff::Type::ChType: header = "(chg) "; break;
case Git::Diff::Type::Unmerged: header = "(unmerged) "; break;
}
ObjectData data;
data.id = diff.blob.b_id;
data.path = diff.path;
data.submod = diff.submodule;
data.submod_commit = diff.submodule_commit;
data.header = header;
data.idiff = idiff;
add_item(data);
}
}
/**
* @brief コミットログを取得する
* @param g
* @return
*/
-Git::CommitItemList BasicMainWindow::retrieveCommitLog(GitPtr const &g)
+Git::CommitItemList MainWindow::retrieveCommitLog(GitPtr const &g)
{
Git::CommitItemList list = g->log(limitLogCount());
// 親子関係を調べて、順番が狂っていたら、修正する。
std::set<QString> set;
const size_t count = list.size();
size_t limit = count;
size_t i = 0;
while (i < count) {
size_t newpos = -1;
for (QString const &parent : list[i].parent_ids) {
if (set.find(parent) != set.end()) {
for (size_t j = 0; j < i; j++) {
if (parent == list[j].commit_id) {
if (newpos == (size_t)-1 || j < newpos) {
newpos = j;
}
qDebug() << "fix commit order" << list[i].commit_id;
break;
}
}
}
}
set.insert(set.end(), list[i].commit_id);
if (newpos != (size_t)-1) {
if (limit == 0) break; // まず無いと思うが、もし、無限ループに陥ったら
Git::CommitItem t = list[i];
t.strange_date = true;
list.erase(list.begin() + i);
list.insert(list.begin() + newpos, t);
i = newpos;
limit--;
}
i++;
}
return list;
}
-void BasicMainWindow::queryBranches(GitPtr const &g)
+void MainWindow::queryBranches(GitPtr const &g)
{
Q_ASSERT(g);
- m->branch_map.clear();
+ m1->branch_map.clear();
QList<Git::Branch> branches = g->branches();
for (Git::Branch const &b : branches) {
if (b.isCurrent()) {
setCurrentBranch(b);
}
branchMapRef()[b.id].append(b);
}
}
-std::map<QString, QList<Git::Branch>> &BasicMainWindow::branchMapRef()
+std::map<QString, QList<Git::Branch>> &MainWindow::branchMapRef()
{
- return m->branch_map;
+ return m1->branch_map;
}
-void BasicMainWindow::updateCommitTableLater()
+void MainWindow::updateCommitTableLater()
{
*ptrUpdateCommitTableCounter() = 200;
}
-void BasicMainWindow::updateRemoteInfo()
+void MainWindow::updateRemoteInfo()
{
queryRemotes(git());
- m->current_remote_name = QString();
+ m1->current_remote_name = QString();
{
Git::Branch const &r = currentBranch();
- m->current_remote_name = r.remote;
+ m1->current_remote_name = r.remote;
}
- if (m->current_remote_name.isEmpty()) {
- if (m->remotes.size() == 1) {
- m->current_remote_name = m->remotes[0];
+ if (m1->current_remote_name.isEmpty()) {
+ if (m1->remotes.size() == 1) {
+ m1->current_remote_name = m1->remotes[0];
}
}
emit remoteInfoChanged();
}
-void BasicMainWindow::updateWindowTitle(GitPtr const &g)
+void MainWindow::updateWindowTitle(GitPtr const &g)
{
if (isValidWorkingCopy(g)) {
Git::User user = g->getUser(Git::Source::Default);
setWindowTitle_(user);
} else {
setUnknownRepositoryInfo();
}
}
-QString BasicMainWindow::makeCommitInfoText(int row, QList<BasicMainWindow::Label> *label_list)
+QString MainWindow::makeCommitInfoText(int row, QList<BasicMainWindow::Label> *label_list)
{
QString message_ex;
Git::CommitItem const *commit = &getLogs()[row];
{ // branch
if (label_list) {
if (commit->commit_id == getHeadId()) {
Label label(Label::Head);
label.text = "HEAD";
label_list->push_back(label);
}
}
QList<Git::Branch> list = findBranch(commit->commit_id);
for (Git::Branch const &b : list) {
if (b.flags & Git::Branch::HeadDetachedAt) continue;
if (b.flags & Git::Branch::HeadDetachedFrom) continue;
Label label(Label::LocalBranch);
label.text = b.name;
if (!b.remote.isEmpty()) {
label.kind = Label::RemoteBranch;
label.text = "remotes" / b.remote / label.text;
}
if (b.ahead > 0) {
label.info += tr(", %1 ahead").arg(b.ahead);
}
if (b.behind > 0) {
label.info += tr(", %1 behind").arg(b.behind);
}
message_ex += " {" + label.text + label.info + '}';
if (label_list) label_list->push_back(label);
}
}
{ // tag
QList<Git::Tag> list = findTag(commit->commit_id);
for (Git::Tag const &t : list) {
Label label(Label::Tag);
label.text = t.name;
message_ex += QString(" {#%1}").arg(label.text);
if (label_list) label_list->push_back(label);
}
}
return message_ex;
}
-void BasicMainWindow::removeRepositoryFromBookmark(int index, bool ask)
+void MainWindow::removeRepositoryFromBookmark(int index, bool ask)
{
if (ask) {
int r = QMessageBox::warning(this, tr("Confirm Remove"), tr("Are you sure you want to remove the repository from bookmarks ?") + '\n' + tr("(Files will NOT be deleted)"), QMessageBox::Ok, QMessageBox::Cancel);
if (r != QMessageBox::Ok) return;
}
auto *repos = getReposPtr();
if (index >= 0 && index < repos->size()) {
repos->erase(repos->begin() + index);
saveRepositoryBookmarks();
updateRepositoriesList();
}
}
-void BasicMainWindow::clone(QString url, QString dir)
+void MainWindow::clone(QString url, QString dir)
{
if (!isOnlineMode()) return;
if (dir.isEmpty()) {
dir = defaultWorkingDir();
}
while (1) {
QString ssh_key;
- CloneDialog dlg(this, url, dir, &m->gcx);
+ CloneDialog dlg(this, url, dir, &m1->gcx);
if (dlg.exec() != QDialog::Accepted) {
return;
}
const CloneDialog::Action action = dlg.action();
url = dlg.url();
dir = dlg.dir();
ssh_key = dlg.overridedSshKey();
RepositoryItem repos_item_data;
repos_item_data.local_dir = dir;
repos_item_data.local_dir.replace('\\', '/');
repos_item_data.name = makeRepositoryName(dir);
repos_item_data.ssh_key = ssh_key;
// クローン先ディレクトリを求める
Git::CloneData clone_data = Git::preclone(url, dir);
if (action == CloneDialog::Action::Clone) {
// 既存チェック
QFileInfo info(dir);
if (info.isFile()) {
QString msg = dir + "\n\n" + tr("A file with same name already exists");
QMessageBox::warning(this, tr("Clone"), msg);
continue;
}
if (info.isDir()) {
QString msg = dir + "\n\n" + tr("A folder with same name already exists");
QMessageBox::warning(this, tr("Clone"), msg);
continue;
}
// クローン先ディレクトリの存在チェック
QString basedir = misc::normalizePathSeparator(clone_data.basedir);
if (!QFileInfo(basedir).isDir()) {
int i = basedir.indexOf('/');
int j = basedir.indexOf('\\');
if (i < j) i = j;
if (i < 0) {
QString msg = basedir + "\n\n" + tr("Invalid folder");
QMessageBox::warning(this, tr("Clone"), msg);
continue;
}
QString msg = basedir + "\n\n" + tr("No such folder. Create it now ?");
if (QMessageBox::warning(this, tr("Clone"), msg, QMessageBox::Ok, QMessageBox::Cancel) != QMessageBox::Ok) {
continue;
}
// ディレクトリを作成
QString base = basedir.mid(0, i + 1);
QString sub = basedir.mid(i + 1);
QDir(base).mkpath(sub);
}
GitPtr g = git(QString(), repos_item_data.ssh_key);
setPtyUserData(QVariant::fromValue<RepositoryItem>(repos_item_data));
setPtyCondition(PtyCondition::Clone);
setPtyProcessOk(true);
g->clone(clone_data, getPtyProcess());
} else if (action == CloneDialog::Action::AddExisting) {
addWorkingCopyDir(dir, true);
}
return; // done
}
}
-void BasicMainWindow::submodule_add(QString url, QString local_dir)
+void MainWindow::submodule_add(QString url, QString local_dir)
{
if (!isOnlineMode()) return;
if (local_dir.isEmpty()) return;
QString dir = local_dir;
while (1) {
- SubmoduleAddDialog dlg(this, url, dir, &m->gcx);
+ SubmoduleAddDialog dlg(this, url, dir, &m1->gcx);
if (dlg.exec() != QDialog::Accepted) {
return;
}
url = dlg.url();
dir = dlg.dir();
const QString ssh_key = dlg.overridedSshKey();
RepositoryItem repos_item_data;
repos_item_data.local_dir = dir;
repos_item_data.local_dir.replace('\\', '/');
repos_item_data.name = makeRepositoryName(dir);
repos_item_data.ssh_key = ssh_key;
Git::CloneData data = Git::preclone(url, dir);
bool force = dlg.isForce();
GitPtr g = git(local_dir, repos_item_data.ssh_key);
auto callback = [&](GitPtr const &g){
g->submodule_add(data, force, getPtyProcess());
};
{
- setRemoteMonitoringEnabled(false);
-
OverrideWaitCursor;
{
setLogEnabled(g, true);
AsyncExecGitThread_ th(g, callback);
th.start();
while (1) {
if (th.wait(1)) break;
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
setLogEnabled(g, false);
}
openRepository_(g);
-
- setRemoteMonitoringEnabled(true);
}
return; // done
}
}
-void BasicMainWindow::checkout()
-{
- checkout(this, selectedCommitItem());
-}
-void BasicMainWindow::commit(bool amend)
+
+void MainWindow::commit(bool amend)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
QString message;
QString previousMessage;
if (amend) {
message = getLogs()[0].message;
} else {
QString id = g->getCherryPicking();
if (Git::isValidID(id)) {
message = g->getMessage(id);
} else {
for (Git::CommitItem const &item : getLogs()) {
if (!item.commit_id.isEmpty()) {
previousMessage = item.message;
break;
}
}
}
}
while (1) {
Git::User user = g->getUser(Git::Source::Default);
QString sign_id = g->signingKey(Git::Source::Default);
gpg::Data key;
{
QList<gpg::Data> keys;
gpg::listKeys(global->gpg_command, &keys);
for (gpg::Data const &k : keys) {
if (k.id == sign_id) {
key = k;
}
}
}
CommitDialog dlg(this, currentRepositoryName(), user, key, previousMessage);
dlg.setText(message);
if (dlg.exec() == QDialog::Accepted) {
QString text = dlg.text();
if (text.isEmpty()) {
QMessageBox::warning(this, tr("Commit"), tr("Commit message can not be omitted."));
continue;
}
bool sign = dlg.isSigningEnabled();
bool ok;
if (amend || dlg.isAmend()) {
ok = g->commit_amend_m(text, sign, getPtyProcess());
} else {
ok = g->commit(text, sign, getPtyProcess());
}
if (ok) {
setForceFetch(true);
updateStatusBarText();
openRepository(true);
} else {
QString err = g->errorMessage().trimmed();
err += "\n*** ";
err += tr("Failed to commit");
err += " ***\n";
writeLog(err);
}
}
break;
}
}
-void BasicMainWindow::commitAmend()
+void MainWindow::commitAmend()
{
commit(true);
}
-void BasicMainWindow::pushSetUpstream(QString const &remote, QString const &branch)
+void MainWindow::pushSetUpstream(QString const &remote, QString const &branch)
{
if (remote.isEmpty()) return;
if (branch.isEmpty()) return;
int exitcode = 0;
QString errormsg;
reopenRepository(true, [&](GitPtr g){
g->push_u(remote, branch, getPtyProcess());
while (1) {
if (getPtyProcess()->wait(1)) break;
QApplication::processEvents();
}
exitcode = getPtyProcess()->getExitCode();
errormsg = getPtyProcess()->getMessage();
});
if (exitcode == 128) {
if (errormsg.indexOf("Connection refused") >= 0) {
QMessageBox::critical(this, qApp->applicationName(), tr("Connection refused."));
return;
}
}
updateRemoteInfo();
}
-bool BasicMainWindow::pushSetUpstream(bool testonly)
+bool MainWindow::pushSetUpstream(bool testonly)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return false;
QStringList remotes = g->getRemotes();
QString current_branch = currentBranchName();
QStringList branches;
for (Git::Branch const &b : g->branches()) {
branches.push_back(b.name);
}
if (remotes.isEmpty() || branches.isEmpty()) {
return false;
}
if (testonly) {
return true;
}
PushDialog dlg(this, remotes, branches, PushDialog::RemoteBranch(QString(), current_branch));
if (dlg.exec() == QDialog::Accepted) {
PushDialog::Action a = dlg.action();
if (a == PushDialog::PushSimple) {
push();
} else if (a == PushDialog::PushSetUpstream) {
QString remote = dlg.remote();
QString branch = dlg.branch();
pushSetUpstream(remote, branch);
}
return true;
}
return false;
}
-void BasicMainWindow::push()
+void MainWindow::push()
{
if (!isOnlineMode()) return;
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
if (g->getRemotes().isEmpty()) {
QMessageBox::warning(this, qApp->applicationName(), tr("No remote repository is registered."));
RepositoryItem const &repo = currentRepository();
execRepositoryPropertyDialog(repo, true);
return;
}
int exitcode = 0;
QString errormsg;
reopenRepository(true, [&](GitPtr g){
g->push(false, getPtyProcess());
while (1) {
if (getPtyProcess()->wait(1)) break;
QApplication::processEvents();
}
exitcode = getPtyProcess()->getExitCode();
errormsg = getPtyProcess()->getMessage();
});
if (exitcode == 128) {
if (errormsg.indexOf("no upstream branch") >= 0) {
QString brname = currentBranchName();
QString msg = tr("The current branch %1 has no upstream branch.");
msg = msg.arg(brname);
msg += '\n';
msg += tr("You try push --set-upstream");
QMessageBox::warning(this, qApp->applicationName(), msg);
pushSetUpstream(false);
return;
}
if (errormsg.indexOf("Connection refused") >= 0) {
QMessageBox::critical(this, qApp->applicationName(), tr("Connection refused."));
return;
}
}
}
#ifdef Q_OS_MAC
namespace {
bool isValidDir(QString const &dir)
{
if (dir.indexOf('\"') >= 0 || dir.indexOf('\\') >= 0) return false;
return QFileInfo(dir).isDir();
}
}
#include <QProcess>
#endif
-void BasicMainWindow::openTerminal(RepositoryItem const *repo)
+void MainWindow::openTerminal(RepositoryItem const *repo)
{
runOnRepositoryDir([](QString dir){
#ifdef Q_OS_MAC
if (!isValidDir(dir)) return;
QString cmd = "open -n -a /Applications/Utilities/Terminal.app --args \"%1\"";
cmd = cmd.arg(dir);
QProcess::execute(cmd);
#else
Terminal::open(dir);
#endif
}, repo);
}
-void BasicMainWindow::openExplorer(RepositoryItem const *repo)
+void MainWindow::openExplorer(RepositoryItem const *repo)
{
runOnRepositoryDir([](QString dir){
#ifdef Q_OS_MAC
if (!isValidDir(dir)) return;
QString cmd = "open \"%1\"";
cmd = cmd.arg(dir);
QProcess::execute(cmd);
#else
QDesktopServices::openUrl(dir);
#endif
}, repo);
}
-Git::CommitItem const *BasicMainWindow::selectedCommitItem() const
+Git::CommitItem const *MainWindow::selectedCommitItem() const
{
int i = selectedLogIndex();
return commitItem(i);
}
-void BasicMainWindow::deleteBranch(Git::CommitItem const *commit)
+void MainWindow::deleteBranch(Git::CommitItem const *commit)
{
if (!commit) return;
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
QStringList all_branch_names;
QStringList current_local_branch_names;
{
NamedCommitList named_commits = namedCommitItems(Branches);
for (NamedCommitItem const &item : named_commits) {
if (item.name == "HEAD") continue;
if (item.id == commit->commit_id) {
current_local_branch_names.push_back(item.name);
}
all_branch_names.push_back(item.name);
}
}
DeleteBranchDialog dlg(this, false, all_branch_names, current_local_branch_names);
if (dlg.exec() == QDialog::Accepted) {
setLogEnabled(g, true);
QStringList names = dlg.selectedBranchNames();
int count = 0;
for (QString const &name : names) {
if (g->git(QString("branch -D \"%1\"").arg(name))) {
count++;
} else {
writeLog(tr("Failed to delete the branch '%1'").arg(name) + '\n');
}
}
if (count > 0) {
openRepository(true, true, true);
}
}
}
-void BasicMainWindow::deleteBranch()
+void MainWindow::deleteBranch()
{
deleteBranch(selectedCommitItem());
}
QStringList MainWindow::remoteBranches(QString const &id, QStringList *all)
{
if (all) all->clear();
QStringList list;
GitPtr g = git();
if (isValidWorkingCopy(g)) {
NamedCommitList named_commits = namedCommitItems(Branches | Remotes);
for (NamedCommitItem const &item : named_commits) {
if (item.id == id && !item.remote.isEmpty()) {
list.push_back(item.remote / item.name);
}
if (all && !item.remote.isEmpty() && item.name != "HEAD") {
all->push_back(item.remote / item.name);
}
}
}
return list;
}
void MainWindow::deleteRemoteBranch(Git::CommitItem const *commit)
{
if (!commit) return;
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
QStringList all_branches;
QStringList remote_branches = remoteBranches(commit->commit_id, &all_branches);
if (remote_branches.isEmpty()) return;
DeleteBranchDialog dlg(this, true, all_branches, remote_branches);
if (dlg.exec() == QDialog::Accepted) {
setLogEnabled(g, true);
QStringList names = dlg.selectedBranchNames();
for (QString const &name : names) {
int i = name.indexOf('/');
if (i > 0) {
QString remote = name.mid(0, i);
QString branch = ':' + name.mid(i + 1);
pushSetUpstream(remote, branch);
}
}
}
}
-bool BasicMainWindow::askAreYouSureYouWantToRun(QString const &title, QString const &command)
+bool MainWindow::askAreYouSureYouWantToRun(QString const &title, QString const &command)
{
QString message = tr("Are you sure you want to run the following command ?");
QString text = "%1\n\n%2";
text = text.arg(message).arg(command);
return QMessageBox::warning(this, title, text, QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Ok;
}
-bool BasicMainWindow::editFile(QString const &path, QString const &title)
+bool MainWindow::editFile(QString const &path, QString const &title)
{
return TextEditDialog::editFile(this, path, title);
}
-void BasicMainWindow::resetFile(QStringList const &paths)
+void MainWindow::resetFile(QStringList const &paths)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
if (paths.isEmpty()) {
// nop
} else {
QString cmd = "git checkout -- \"%1\"";
cmd = cmd.arg(paths[0]);
if (askAreYouSureYouWantToRun(tr("Reset a file"), "> " + cmd)) {
for (QString const &path : paths) {
g->resetFile(path);
}
openRepository(true);
}
}
}
-void BasicMainWindow::saveRepositoryBookmark(RepositoryItem item)
+void MainWindow::saveRepositoryBookmark(RepositoryItem item)
{
if (item.local_dir.isEmpty()) return;
if (item.name.isEmpty()) {
item.name = tr("Unnamed");
}
auto *repos = getReposPtr();
bool done = false;
for (auto &repo : *repos) {
RepositoryItem *p = &repo;
if (item.local_dir == p->local_dir) {
*p = item;
done = true;
break;
}
}
if (!done) {
repos->push_back(item);
}
saveRepositoryBookmarks();
updateRepositoriesList();
}
-void BasicMainWindow::setCurrentRepository(RepositoryItem const &repo, bool clear_authentication)
+void MainWindow::setCurrentRepository(RepositoryItem const &repo, bool clear_authentication)
{
if (clear_authentication) {
clearAuthentication();
}
- m->current_repo = repo;
+ m1->current_repo = repo;
}
-void BasicMainWindow::internalDeleteTags(QStringList const &tagnames)
+void MainWindow::internalDeleteTags(QStringList const &tagnames)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
if (!tagnames.isEmpty()) {
reopenRepository(false, [&](GitPtr g){
for (QString const &name : tagnames) {
g->delete_tag(name, true);
}
});
}
}
-bool BasicMainWindow::internalAddTag(QString const &name)
+bool MainWindow::internalAddTag(QString const &name)
{
if (name.isEmpty()) return false;
GitPtr g = git();
if (!isValidWorkingCopy(g)) return false;
QString commit_id;
Git::CommitItem const *commit = selectedCommitItem();
if (commit && !commit->commit_id.isEmpty()) {
commit_id = commit->commit_id;
}
if (!Git::isValidID(commit_id)) return false;
bool ok = false;
reopenRepository(false, [&](GitPtr g){
ok = g->tag(name, commit_id);
});
return ok;
}
-NamedCommitList BasicMainWindow::namedCommitItems(int flags)
+NamedCommitList MainWindow::namedCommitItems(int flags)
{
NamedCommitList items;
if (flags & Branches) {
for (auto const &pair: branchMapRef()) {
QList<Git::Branch> const &list = pair.second;
for (Git::Branch const &b : list) {
if (b.isHeadDetached()) continue;
if (flags & NamedCommitFlag::Remotes) {
// nop
} else {
if (!b.remote.isEmpty()) continue;
}
NamedCommitItem item;
if (b.remote.isEmpty()) {
if (b.name == "HEAD") {
item.type = NamedCommitItem::Type::None;
} else {
item.type = NamedCommitItem::Type::BranchLocal;
}
} else {
item.type = NamedCommitItem::Type::BranchRemote;
item.remote = b.remote;
}
item.name = b.name;
item.id = b.id;
items.push_back(item);
}
}
}
if (flags & Tags) {
for (auto const &pair: *ptrTagMap()) {
QList<Git::Tag> const &list = pair.second;
for (Git::Tag const &t : list) {
NamedCommitItem item;
item.type = NamedCommitItem::Type::Tag;
item.name = t.name;
item.id = t.id;
if (item.name.startsWith("refs/tags/")) {
item.name = item.name.mid(10);
}
items.push_back(item);
}
}
}
return items;
}
-int BasicMainWindow::rowFromCommitId(QString const &id)
+int MainWindow::rowFromCommitId(QString const &id)
{
auto const &logs = getLogs();
for (size_t i = 0; i < logs.size(); i++) {
Git::CommitItem const &item = logs[i];
if (item.commit_id == id) {
return (int)i;
}
}
return -1;
}
-void BasicMainWindow::createRepository(QString const &dir)
+void MainWindow::createRepository(QString const &dir)
{
CreateRepositoryDialog dlg(this, dir);
if (dlg.exec() == QDialog::Accepted) {
QString path = dlg.path();
if (QFileInfo(path).isDir()) {
if (Git::isValidWorkingCopy(path)) {
// A valid git repository already exists there.
} else {
GitPtr g = git(path);
if (g->init()) {
QString name = dlg.name();
if (!name.isEmpty()) {
addWorkingCopyDir(path, name, true);
}
QString remote_name = dlg.remoteName();
QString remote_url = dlg.remoteURL();
if (!remote_name.isEmpty() && !remote_url.isEmpty()) {
Git::Remote r;
r.name = remote_name;
r.url = remote_url;
g->addRemoteURL(r);
}
}
}
} else {
// not dir
}
}
}
-void BasicMainWindow::setLogEnabled(GitPtr const &g, bool f)
+void MainWindow::setLogEnabled(GitPtr const &g, bool f)
{
if (f) {
g->setLogCallback(git_callback, this);
} else {
g->setLogCallback(nullptr, nullptr);
}
}
-QList<Git::Tag> BasicMainWindow::findTag(QString const &id)
+QList<Git::Tag> MainWindow::findTag(QString const &id)
{
auto it = ptrTagMap()->find(id);
if (it != ptrTagMap()->end()) {
return it->second;
}
return QList<Git::Tag>();
}
-void BasicMainWindow::sshSetPassphrase(std::string const &user, std::string const &pass)
+void MainWindow::sshSetPassphrase(std::string const &user, std::string const &pass)
{
- m->ssh_passphrase_user = user;
- m->ssh_passphrase_pass = pass;
+ m1->ssh_passphrase_user = user;
+ m1->ssh_passphrase_pass = pass;
}
-std::string BasicMainWindow::sshPassphraseUser() const
+std::string MainWindow::sshPassphraseUser() const
{
- return m->ssh_passphrase_user;
+ return m1->ssh_passphrase_user;
}
-std::string BasicMainWindow::sshPassphrasePass() const
+std::string MainWindow::sshPassphrasePass() const
{
- return m->ssh_passphrase_pass;
+ return m1->ssh_passphrase_pass;
}
-void BasicMainWindow::httpSetAuthentication(std::string const &user, std::string const &pass)
+void MainWindow::httpSetAuthentication(std::string const &user, std::string const &pass)
{
- m->http_uid = user;
- m->http_pwd = pass;
+ m1->http_uid = user;
+ m1->http_pwd = pass;
}
-std::string BasicMainWindow::httpAuthenticationUser() const
+std::string MainWindow::httpAuthenticationUser() const
{
- return m->http_uid;
+ return m1->http_uid;
}
-std::string BasicMainWindow::httpAuthenticationPass() const
+std::string MainWindow::httpAuthenticationPass() const
{
- return m->http_pwd;
+ return m1->http_pwd;
}
-void BasicMainWindow::doGitCommand(std::function<void(GitPtr g)> const &callback)
+void MainWindow::doGitCommand(std::function<void(GitPtr g)> const &callback)
{
GitPtr g = git();
if (isValidWorkingCopy(g)) {
OverrideWaitCursor;
callback(g);
openRepository(false, false);
}
}
diff --git a/src/BasicMainWindow.h b/src/BasicMainWindow.h
index 4eb5093..982db00 100644
--- a/src/BasicMainWindow.h
+++ b/src/BasicMainWindow.h
@@ -1,414 +1,407 @@
-#ifndef BASICMAINWINDOW_H
-#define BASICMAINWINDOW_H
-
-#include "Git.h"
-#include "GitObjectManager.h"
-#include "MyProcess.h"
-#include "RepositoryData.h"
-#include "TextEditorTheme.h"
+#ifndef BASICH
+#define BASICH
+
+//#include "AvatarLoader.h"
+//#include "Git.h"
+//#include "GitHubAPI.h"
+//#include "GitObjectManager.h"
+//#include "RepositoryData.h"
+//#include "TextEditorTheme.h"
+//#include "main.h"
+//#include "webclient.h"
#include <QMainWindow>
-#include <functional>
+//#include <functional>
-class ApplicationSettings;
-class AvatarLoader;
-class QListWidget;
-class QListWidgetItem;
-class QTreeWidgetItem;
-class WebContext;
+//class ApplicationSettings;
+//class AvatarLoader;
+//class QListWidget;
+//class QListWidgetItem;
+//class QTreeWidgetItem;
+//class WebContext;
struct GitHubRepositoryInfo {
QString owner_account_name;
QString repository_name;
};
#define PATH_PREFIX "*"
class BasicMainWindow : public QMainWindow {
Q_OBJECT
- friend class RepositoryPropertyDialog;
+// friend class RepositoryPropertyDialog;
public:
struct Label {
enum {
Head,
LocalBranch,
RemoteBranch,
Tag,
};
int kind;
QString text;
QString info;
Label(int kind = LocalBranch)
: kind(kind)
{
}
};
enum {
IndexRole = Qt::UserRole,
FilePathRole,
DiffIndexRole,
HunkIndexRole,
HeaderRole,
};
enum CloneOperation {
Clone,
SubmoduleAdd,
};
protected:
enum class PtyCondition {
None,
Clone,
Fetch,
Pull,
Push,
};
enum InteractionMode {
None,
Busy,
};
enum NamedCommitFlag {
Branches = 0x0001,
Tags = 0x0002,
Remotes = 0x0100,
};
enum class FilesListType {
SingleList,
SideBySide,
};
struct Task {
int index = 0;
int parent = 0;
Task() = default;
Task(int index, int parent)
: index(index)
, parent(parent)
{
}
};
struct Element {
int depth = 0;
std::vector<int> indexes;
};
enum {
GroupItem = -1,
};
- struct Private;
- Private *m;
private:
- static bool git_callback(void *cookie, const char *ptr, int len);
-
- QString selectCommand_(QString const &cmdname, QStringList const &cmdfiles, QStringList const &list, QString path, std::function<void (QString const &)> const &callback);
- QString selectCommand_(QString const &cmdname, QString const &cmdfile, QStringList const &list, QString const &path, std::function<void (QString const &)> const &callback);
-
- bool checkGitCommand();
- bool checkFileCommand();
- bool checkExecutable(QString const &path);
- void internalSaveCommandPath(QString const &path, bool save, QString const &name);
- QStringList whichCommand_(QString const &cmdfile1, QString const &cmdfile2 = QString());
-
- void setWindowTitle_(Git::User const &user);
- bool execSetGlobalUserDialog();
-
- bool saveByteArrayAs(const QByteArray &ba, QString const &dstpath);
- bool saveFileAs(QString const &srcpath, QString const &dstpath);
- bool saveBlobAs(QString const &id, QString const &dstpath);
-
- void updateFilesList(Git::CommitItem const &commit, bool wait);
-
- void revertAllFiles();
-
- void setCurrentRemoteName(QString const &name);
-
- void deleteTags(Git::CommitItem const &commit);
-
- bool isAvatarEnabled() const;
- bool isGitHub() const;
- QStringList remotes() const;
- QList<Git::Branch> findBranch(QString const &id);
- QString saveAsTemp(QString const &id);
- QString tempfileHeader() const;
- void deleteTempFiles();
- QString getCommitIdFromTag(QString const &tag);
- bool isValidRemoteURL(QString const &url, const QString &sshkey);
- QString getObjectID(QListWidgetItem *item);
- void addWorkingCopyDir(QString dir, QString name, bool open);
- static QString makeRepositoryName(QString const &loc);
- void clearAuthentication();
- RepositoryItem const *findRegisteredRepository(QString *workdir) const;
- void queryRemotes(const GitPtr &g);
- bool runOnRepositoryDir(std::function<void (QString)> const &callback, RepositoryItem const *repo);
- void clearSshAuthentication();
- QString executableOrEmpty(const QString &path);
+// static bool git_callback(void *cookie, const char *ptr, int len);
+
+// QString selectCommand_(QString const &cmdname, QStringList const &cmdfiles, QStringList const &list, QString path, std::function<void (QString const &)> const &callback);
+// QString selectCommand_(QString const &cmdname, QString const &cmdfile, QStringList const &list, QString const &path, std::function<void (QString const &)> const &callback);
+
+// bool checkGitCommand();
+// bool checkFileCommand();
+// bool checkExecutable(QString const &path);
+// void internalSaveCommandPath(QString const &path, bool save, QString const &name);
+// QStringList whichCommand_(QString const &cmdfile1, QString const &cmdfile2 = QString());
+
+// void setWindowTitle_(Git::User const &user);
+// bool execSetGlobalUserDialog();
+
+// bool saveByteArrayAs(const QByteArray &ba, QString const &dstpath);
+// bool saveFileAs(QString const &srcpath, QString const &dstpath);
+// bool saveBlobAs(QString const &id, QString const &dstpath);
+
+// void updateFilesList(Git::CommitItem const &commit, bool wait);
+
+// void revertAllFiles();
+
+// void setCurrentRemoteName(QString const &name);
+
+// void deleteTags(Git::CommitItem const &commit);
+
+// bool isAvatarEnabled() const;
+// bool isGitHub() const;
+// QStringList remotes() const;
+// QList<Git::Branch> findBranch(QString const &id);
+// QString saveAsTemp(QString const &id);
+// QString tempfileHeader() const;
+// void deleteTempFiles();
+// QString getCommitIdFromTag(QString const &tag);
+// bool isValidRemoteURL(QString const &url, const QString &sshkey);
+// QString getObjectID(QListWidgetItem *item);
+// void addWorkingCopyDir(QString dir, QString name, bool open);
+// static QString makeRepositoryName(QString const &loc);
+// void clearAuthentication();
+// RepositoryItem const *findRegisteredRepository(QString *workdir) const;
+// void queryRemotes(const GitPtr &g);
+// bool runOnRepositoryDir(std::function<void (QString)> const &callback, RepositoryItem const *repo);
+// void clearSshAuthentication();
+ // QString executableOrEmpty(const QString &path);
+ // bool runOnRepositoryDir(const std::function<void (QString)> &callback, const RepositoryItem *repo);
protected:
- static QString getFilePath(QListWidgetItem *item);
- static bool isGroupItem(QTreeWidgetItem *item);
- static int indexOfLog(QListWidgetItem *item);
- static int indexOfDiff(QListWidgetItem *item);
- static int getHunkIndex(QListWidgetItem *item);
-
- void initNetworking();
- bool saveRepositoryBookmarks() const;
- QString getBookmarksFilePath() const;
-
- void stopPtyProcess();
- void abortPtyProcess();
-
- bool execWelcomeWizardDialog();
- void execRepositoryPropertyDialog(const RepositoryItem &repo, bool open_repository_menu = false);
- void execSetUserDialog(Git::User const &global_user, Git::User const &repo_user, QString const &reponame);
- void setGitCommand(QString path, bool save);
- void setFileCommand(QString path, bool save);
- void setGpgCommand(QString path, bool save);
- void setSshCommand(QString path, bool save);
- void logGitVersion();
- void setUnknownRepositoryInfo();
- void internalClearRepositoryInfo();
- void checkUser();
- void openRepository(bool validate, bool waitcursor = true, bool keep_selection = false);
- void updateRepository();
- void reopenRepository(bool log, const std::function<void(GitPtr const &)> &callback);
- void openSelectedRepository();
+// static QString getFilePath(QListWidgetItem *item);
+// static bool isGroupItem(QTreeWidgetItem *item);
+// static int indexOfLog(QListWidgetItem *item);
+// static int indexOfDiff(QListWidgetItem *item);
+// static int getHunkIndex(QListWidgetItem *item);
+
+// void initNetworking();
+// bool saveRepositoryBookmarks() const;
+// QString getBookmarksFilePath() const;
+
+// void stopPtyProcess();
+// void abortPtyProcess();
+
+// bool execWelcomeWizardDialog();
+// void execRepositoryPropertyDialog(const RepositoryItem &repo, bool open_repository_menu = false);
+// void execSetUserDialog(Git::User const &global_user, Git::User const &repo_user, QString const &reponame);
+// void setGitCommand(QString path, bool save);
+// void setFileCommand(QString path, bool save);
+// void setGpgCommand(QString path, bool save);
+// void setSshCommand(QString path, bool save);
+// void logGitVersion();
+// void setUnknownRepositoryInfo();
+// void internalClearRepositoryInfo();
+// void checkUser();
+// void openRepository(bool validate, bool waitcursor = true, bool keep_selection = false);
+// void updateRepository();
+// void reopenRepository(bool log, const std::function<void(GitPtr const &)> &callback);
+// void openSelectedRepository();
// void checkRemoteUpdate();
- bool isThereUncommitedChanges() const;
- QList<Git::Diff> makeDiffs(QString id, bool *ok);
- struct ObjectData {
- QString id;
- QString path;
- Git::Submodule submod;
- Git::CommitItem submod_commit;
- QString header;
- int idiff;
- };
- void addDiffItems(const QList<Git::Diff> *diff_list, const std::function<void (ObjectData const &data)> &add_item);
- Git::CommitItemList retrieveCommitLog(const GitPtr &g);
-
- void queryBranches(const GitPtr &g);
- std::map<QString, QList<Git::Branch>> &branchMapRef();
-
- void updateCommitTableLater();
- void updateRemoteInfo();
- void updateWindowTitle(const GitPtr &g);
- QString makeCommitInfoText(int row, QList<Label> *label_list);
- void removeRepositoryFromBookmark(int index, bool ask);
-
- void clone(QString url = {}, QString dir = {});
- void submodule_add(QString url = {}, QString local_dir = {});
- void checkout();
- void commit(bool amend = false);
- void commitAmend();
- void pushSetUpstream(QString const &remote, QString const &branch);
- bool pushSetUpstream(bool testonly);
- void push();
-
- void openTerminal(RepositoryItem const *repo);
- void openExplorer(RepositoryItem const *repo);
- Git::CommitItem const *selectedCommitItem() const;
- void deleteBranch(Git::CommitItem const *commit);
- void deleteBranch();
- bool askAreYouSureYouWantToRun(QString const &title, QString const &command);
- bool editFile(QString const &path, QString const &title);
- void resetFile(QStringList const &paths);
- void saveRepositoryBookmark(RepositoryItem item);
- void setCurrentRepository(RepositoryItem const &repo, bool clear_authentication);
- void internalDeleteTags(QStringList const &tagnames);
- bool internalAddTag(QString const &name);
- NamedCommitList namedCommitItems(int flags);
- int rowFromCommitId(QString const &id);
- void createRepository(QString const &dir);
- void setLogEnabled(const GitPtr &g, bool f);
- QList<Git::Tag> findTag(QString const &id);
- void sshSetPassphrase(std::string const &user, std::string const &pass);
- std::string sshPassphraseUser() const;
- std::string sshPassphrasePass() const;
- void httpSetAuthentication(std::string const &user, std::string const &pass);
- std::string httpAuthenticationUser() const;
- std::string httpAuthenticationPass() const;
+// bool isThereUncommitedChanges() const;
+// QList<Git::Diff> makeDiffs(QString id, bool *ok);
+// void addDiffItems(const QList<Git::Diff> *diff_list, const std::function<void (ObjectData const &data)> &add_item);
+// Git::CommitItemList retrieveCommitLog(const GitPtr &g);
+
+// void queryBranches(const GitPtr &g);
+// std::map<QString, QList<Git::Branch>> &branchMapRef();
+
+// void updateCommitTableLater();
+// void updateRemoteInfo();
+// void updateWindowTitle(const GitPtr &g);
+// QString makeCommitInfoText(int row, QList<Label> *label_list);
+// void removeRepositoryFromBookmark(int index, bool ask);
+
+// void clone(QString url = {}, QString dir = {});
+// void submodule_add(QString url = {}, QString local_dir = {});
+// void checkout();
+// void commit(bool amend = false);
+// void commitAmend();
+// void pushSetUpstream(QString const &remote, QString const &branch);
+// bool pushSetUpstream(bool testonly);
+// void push();
+
+// void openTerminal(RepositoryItem const *repo);
+// void openExplorer(RepositoryItem const *repo);
+// Git::CommitItem const *selectedCommitItem() const;
+// void deleteBranch(Git::CommitItem const *commit);
+// void deleteBranch();
+// bool askAreYouSureYouWantToRun(QString const &title, QString const &command);
+// bool editFile(QString const &path, QString const &title);
+// void resetFile(QStringList const &paths);
+// void saveRepositoryBookmark(RepositoryItem item);
+// void set(RepositoryItem const &repo, bool clear_authentication);
+// void internalDeleteTags(QStringList const &tagnames);
+// bool internalAddTag(QString const &name);
+// NamedCommitList namedCommitItems(int flags);
+// int rowFromCommitId(QString const &id);
+// void createRepository(QString const &dir);
+// void setLogEnabled(const GitPtr &g, bool f);
+// QList<Git::Tag> findTag(QString const &id);
+// void sshSetPassphrase(std::string const &user, std::string const &pass);
+// std::string sshPassphraseUser() const;
+// std::string sshPassphrasePass() const;
+// void httpSetAuthentication(std::string const &user, std::string const &pass);
+// std::string httpAuthenticationUser() const;
+// std::string httpAuthenticationPass() const;
public:
- Git::CommitItemList const &getLogs() const;
- Git::CommitItem const *getLog(int index) const;
+// Git::CommitItemList const &getLogs() const;
+// Git::CommitItem const *getLog(int index) const;
protected:
- bool event(QEvent *event) override;
- void postUserFunctionEvent(const std::function<void(QVariant const &)> &fn, QVariant const &v = QVariant());
+// bool event(QEvent *event) override;
+// void postUserFunctionEvent(const std::function<void(QVariant const &)> &fn, QVariant const &v = QVariant());
- void doGitCommand(std::function<void(GitPtr)> const &callback);
+// void doGitCommand(std::function<void(GitPtr)> const &callback);
- Git::CommitItemList *getLogsPtr();
- void setLogs(const Git::CommitItemList &logs);
- void clearLogs();
+// Git::CommitItemList *getLogsPtr();
+// void setLogs(const Git::CommitItemList &logs);
+// void clearLogs();
- PtyProcess *getPtyProcess();
- PtyCondition getPtyCondition();
- bool getPtyProcessOk() const;
- void setPtyProcessOk(bool pty_process_ok);
- void setPtyUserData(QVariant const &userdata);
- void setPtyCondition(const PtyCondition &ptyCondition);
+// PtyProcess *getPtyProcess();
+// PtyCondition getPtyCondition();
+// bool getPtyProcessOk() const;
+// void setPtyProcessOk(bool pty_process_ok);
+// void setPtyUserData(QVariant const &userdata);
+// void setPtyCondition(const PtyCondition &ptyCondition);
- QList<RepositoryItem> const &getRepos() const;
- QList<RepositoryItem> *getReposPtr();
+// QList<RepositoryItem> const &getRepos() const;
+// QList<RepositoryItem> *getReposPtr();
- QString getCurrentRemoteName() const;
+// QString getCurrentRemoteName() const;
- AvatarLoader *getAvatarLoader();
- const AvatarLoader *getAvatarLoader() const;
+// AvatarLoader *getAvatarLoader();
+// const AvatarLoader *getAvatarLoader() const;
- int *ptrUpdateFilesListCounter();
- int *ptrUpdateCommitTableCounter();
+// int *ptrUpdateFilesListCounter();
+// int *ptrUpdateCommitTableCounter();
- bool interactionCanceled() const;
- void setInteractionCanceled(bool canceled);
+// bool interactionCanceled() const;
+// void setInteractionCanceled(bool canceled);
- InteractionMode interactionMode() const;
- void setInteractionMode(const InteractionMode &im);
+// InteractionMode interactionMode() const;
+// void setInteractionMode(const InteractionMode &im);
- QString getRepositoryFilterText() const;
- void setRepositoryFilterText(QString const &text);
+// QString getRepositoryFilterText() const;
+// void setRepositoryFilterText(QString const &text);
- void setUncommitedChanges(bool uncommited_changes);
+// void setUncommitedChanges(bool uncommited_changes);
- QList<Git::Diff> *diffResult();
- std::map<QString, Git::Diff> *getDiffCacheMap();
+// QList<Git::Diff> *diffResult();
+// std::map<QString, Git::Diff> *getDiffCacheMap();
- bool getRemoteChanged() const;
- void setRemoteChanged(bool remote_changed);
+// bool getRemoteChanged() const;
+// void setRemoteChanged(bool remote_changed);
- void setServerType(const ServerType &server_type);
+// void setServerType(const ServerType &server_type);
- GitHubRepositoryInfo *ptrGitHub();
+// GitHubRepositoryInfo *ptrGitHub();
- std::map<int, QList<Label>> *getLabelMap();
- const std::map<int, QList<Label>> *getLabelMap() const;
- void clearLabelMap();
+// std::map<int, QList<Label>> *getLabelMap();
+// const std::map<int, QList<Label>> *getLabelMap() const;
+// void clearLabelMap();
- GitObjectCache *getObjCache();
+// GitObjectCache *getObjCache();
- bool getForceFetch() const;
- void setForceFetch(bool force_fetch);
+// bool getForceFetch() const;
+// void setForceFetch(bool force_fetch);
- std::map<QString, QList<Git::Tag>> *ptrTagMap();
+// std::map<QString, QList<Git::Tag>> *ptrTagMap();
- QString getHeadId() const;
- void setHeadId(QString const &head_id);
+// QString getHeadId() const;
+// void setHeadId(QString const &head_id);
- void setPtyProcessCompletionData(QVariant const &value);
- QVariant const &getTempRepoForCloneCompleteV() const;
+// void setPtyProcessCompletionData(QVariant const &value);
+// QVariant const &getTempRepoForCloneCompleteV() const;
- void updateCommitGraph();
- bool fetch(const GitPtr &g, bool prune);
- bool fetch_tags_f(const GitPtr &g);
+// void updateCommitGraph();
+// bool fetch(const GitPtr &g, bool prune);
+// bool fetch_tags_f(const GitPtr &g);
protected:
- virtual void setCurrentLogRow(int row) = 0;
- virtual void updateFilesList(QString id, bool wait) = 0;
- virtual void setRepositoryInfo(QString const &reponame, QString const &brname) = 0;
- virtual void deleteTags(QStringList const &tagnames) = 0;
- virtual void internalWriteLog(const char *ptr, int len) = 0;
- virtual void removeSelectedRepositoryFromBookmark(bool ask) = 0;
- virtual void openRepository_(GitPtr g, bool keep_selection = false) = 0;
- virtual void updateRepositoriesList() = 0;
- virtual void clearFileList() = 0;
- virtual RepositoryItem const *selectedRepositoryItem() const = 0;
- virtual void setRemoteMonitoringEnabled(bool enable) { (void)enable; }
- virtual void updateStatusBarText() {}
- void msgNoRepositorySelected();
- bool isRepositoryOpened() const;
- void updateSubmodules(GitPtr g, QString id);
- static std::pair<QString, QString> makeFileItemText(const ObjectData &data);
+// virtual void setCurrentLogRow(int row) = 0;
+// virtual void updateFilesList(QString id, bool wait) = 0;
+// virtual void setRepositoryInfo(QString const &reponame, QString const &brname) = 0;
+// virtual void deleteTags(QStringList const &tagnames) = 0;
+// virtual void internalWriteLog(const char *ptr, int len) = 0;
+// virtual void removeSelectedRepositoryFromBookmark(bool ask) = 0;
+// virtual void openRepository_(GitPtr g, bool keep_selection = false) = 0;
+// virtual void updateRepositoriesList() = 0;
+// virtual void clearFileList() = 0;
+// virtual RepositoryItem const *selectedRepositoryItem() const = 0;
+// virtual void updateStatusBarText() {}
+// void msgNoRepositorySelected();
+// bool isRepositoryOpened() const;
+// void updateSubmodules(GitPtr g, QString id);
+// static std::pair<QString, QString> makeFileItemText(const ObjectData &data);
public:
explicit BasicMainWindow(QWidget *parent = nullptr);
~BasicMainWindow() override;
- ApplicationSettings *appsettings();
- const ApplicationSettings *appsettings() const;
- WebContext *webContext();
- QString gitCommand() const;
- void autoOpenRepository(QString dir);
- GitPtr git(QString const &dir, const QString &sshkey = {}) const;
- GitPtr git();
- GitPtr git(const Git::Submodule &submod);
- QPixmap getTransparentPixmap();
- QIcon committerIcon(int row) const;
- Git::CommitItem const *commitItem(int row) const;
- QIcon verifiedIcon(char s) const;
- virtual QString currentWorkingCopyDir() const;
- const QList<Label> *label(int row) const;
- bool saveAs(QString const &id, QString const &dstpath);
- bool testRemoteRepositoryValidity(QString const &url, const QString &sshkey);
- QString defaultWorkingDir() const;
- void addWorkingCopyDir(const QString &dir, bool open);
- bool queryCommit(QString const &id, Git::CommitItem *out);
- QAction *addMenuActionProperty(QMenu *menu);
- void checkout(QWidget *parent, Git::CommitItem const *commit, std::function<void()> accepted_callback = nullptr);
- void jumpToCommit(QString id);
- void execCommitViewWindow(Git::CommitItem const *commit);
- void execCommitExploreWindow(QWidget *parent, Git::CommitItem const *commit);
- void execCommitPropertyDialog(QWidget *parent, Git::CommitItem const *commit);
- void execFileHistory(QString const &path);
- void execFileHistory(QListWidgetItem *item);
- void execFilePropertyDialog(QListWidgetItem *item);
- QString selectGitCommand(bool save);
- QString selectFileCommand(bool save);
- QString selectGpgCommand(bool save);
- QString selectSshCommand(bool save);
- Git::Branch const &currentBranch() const;
- void setCurrentBranch(Git::Branch const &b);
- const RepositoryItem &currentRepository() const;
- QString currentRepositoryName() const;
- QString currentRemoteName() const;
- QString currentBranchName() const;
- bool isValidWorkingCopy(const GitPtr &g) const;
- QString determinFileType_(QString const &path, bool mime, std::function<void (QString const &, QByteArray *)> const &callback) const;
- QString determinFileType(QString const &path, bool mime);
- QString determinFileType(QByteArray in, bool mime);
- QList<Git::Tag> queryTagList();
- int limitLogCount() const;
- TextEditorThemePtr themeForTextEditor();
- Git::Object cat_file_(const GitPtr &g, QString const &id);
- Git::Object cat_file(QString const &id);
- QString newTempFilePath();
- QString findFileID(QString const &commit_id, QString const &file);
- void updateFilesList(QString const &id, QList<Git::Diff> *diff_list, QListWidget *listwidget);
- void setAppSettings(const ApplicationSettings &appsettings);
-
- QIcon getRepositoryIcon() const;
- QIcon getFolderIcon() const;
- QIcon getSignatureGoodIcon() const;
- QIcon getSignatureDubiousIcon() const;
- QIcon getSignatureBadIcon() const;
- QPixmap getTransparentPixmap() const;
-
- static QString abbrevCommitID(Git::CommitItem const &commit);
- QStringList findGitObject(const QString &id) const;
-
- void writeLog(const char *ptr, int len);
- void writeLog(QString const &str);
- void emitWriteLog(const QByteArray &ba);
- QList<Label> sortedLabels(int row) const;
-
- virtual bool isOnlineMode() const = 0;
- virtual int selectedLogIndex() const = 0;
- void changeSshKey(const QString &localdir, const QString &sshkey);
- void saveApplicationSettings();
- void loadApplicationSettings();
- void setDiffResult(const QList<Git::Diff> &diffs);
- const QList<Git::Submodule> &submodules() const;
- void setSubmodules(const QList<Git::Submodule> &submodules);
+// ApplicationSettings *appsettings();
+// const ApplicationSettings *appsettings() const;
+// WebContext *webContext();
+// QString gitCommand() const;
+// void autoOpenRepository(QString dir);
+// GitPtr git(QString const &dir, const QString &sshkey = {}) const;
+// GitPtr git();
+// GitPtr git(const Git::Submodule &submod);
+// QPixmap getTransparentPixmap();
+// QIcon committerIcon(int row) const;
+// Git::CommitItem const *commitItem(int row) const;
+// QIcon verifiedIcon(char s) const;
+// virtual QString currentWorkingCopyDir() const;
+// const QList<Label> *label(int row) const;
+// bool saveAs(QString const &id, QString const &dstpath);
+// bool testRemoteRepositoryValidity(QString const &url, const QString &sshkey);
+// QString defaultWorkingDir() const;
+// void addWorkingCopyDir(const QString &dir, bool open);
+// bool queryCommit(QString const &id, Git::CommitItem *out);
+// QAction *addMenuActionProperty(QMenu *menu);
+// void checkout(QWidget *parent, Git::CommitItem const *commit, std::function<void()> accepted_callback = nullptr);
+// void jumpToCommit(QString id);
+// void execCommitViewWindow(Git::CommitItem const *commit);
+// void execCommitExploreWindow(QWidget *parent, Git::CommitItem const *commit);
+// void execCommitPropertyDialog(QWidget *parent, Git::CommitItem const *commit);
+// void (QString const &path);
+// void (QListWidgetItem *item);
+// void execFilePropertyDialog(QListWidgetItem *item);
+// QString selectGitCommand(bool save);
+// QString selectFileCommand(bool save);
+// QString selectGpgCommand(bool save);
+// QString selectSshCommand(bool save);
+// Git::Branch const &currentBranch() const;
+// void setCurrentBranch(Git::Branch const &b);
+// const RepositoryItem &() const;
+// QString Name() const;
+// QString currentRemoteName() const;
+// QString currentBranchName() const;
+// bool isValidWorkingCopy(const GitPtr &g) const;
+// QString determinFileType_(QString const &path, bool mime, std::function<void (QString const &, QByteArray *)> const &callback) const;
+// QString determinFileType(QString const &path, bool mime);
+// QString determinFileType(QByteArray in, bool mime);
+// QList<Git::Tag> queryTagList();
+// int limitLogCount() const;
+// TextEditorThemePtr themeForTextEditor();
+// Git::Object cat_file_(const GitPtr &g, QString const &id);
+// Git::Object cat_file(QString const &id);
+// QString newTempFilePath();
+// QString findFileID(QString const &commit_id, QString const &file);
+// void updateFilesList2(QString const &id, QList<Git::Diff> *diff_list, QListWidget *listwidget);
+// void setAppSettings(const ApplicationSettings &appsettings);
+
+// QIcon getRepositoryIcon() const;
+// QIcon getFolderIcon() const;
+// QIcon getSignatureGoodIcon() const;
+// QIcon getSignatureDubiousIcon() const;
+// QIcon getSignatureBadIcon() const;
+// QPixmap getTransparentPixmap() const;
+
+// static QString abbrevCommitID(Git::CommitItem const &commit);
+// QStringList findGitObject(const QString &id) const;
+
+// void writeLog(const char *ptr, int len);
+// void writeLog(QString const &str);
+// void emitWriteLog(const QByteArray &ba);
+// QList<Label> sortedLabels(int row) const;
+
+// void changeSshKey(const QString &localdir, const QString &sshkey);
+// void saveApplicationSettings();
+// void loadApplicationSettings();
+// void setDiffResult(const QList<Git::Diff> &diffs);
+// const QList<Git::Submodule> &submodules() const;
+// void setSubmodules(const QList<Git::Submodule> &submodules);
protected slots:
- void onAvatarUpdated();
+// void onAvatarUpdated();
public slots:
- void writeLog_(QByteArray ba);
-signals:
- void signalWriteLog(QByteArray ba);
- void remoteInfoChanged();
-// void signalCheckRemoteUpdate();
+ // void writeLog_(QByteArray ba);
+//signals:
+// void signalWriteLog(QByteArray ba);
+// void remoteInfoChanged();
+ // void signalCheckRemoteUpdate();
+private slots:
+// void onAvatarUpdated();
};
-#endif // BASICMAINWINDOW_H
+#endif // BASICH
diff --git a/src/BasicRepositoryDialog.cpp b/src/BasicRepositoryDialog.cpp
index 711c665..1abeaf9 100644
--- a/src/BasicRepositoryDialog.cpp
+++ b/src/BasicRepositoryDialog.cpp
@@ -1,100 +1,100 @@
#include "BasicRepositoryDialog.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include <QTableWidget>
#include <QHeaderView>
struct BasicRepositoryDialog::Private {
- BasicMainWindow *mainwindow = nullptr;
+ MainWindow *mainwindow = nullptr;
GitPtr git;
QList<Git::Remote> remotes;
};
-BasicRepositoryDialog::BasicRepositoryDialog(BasicMainWindow *mainwindow, GitPtr const &g)
+BasicRepositoryDialog::BasicRepositoryDialog(MainWindow *mainwindow, GitPtr const &g)
: QDialog(mainwindow)
, m(new Private)
{
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
m->mainwindow = mainwindow;
m->git = g;
}
BasicRepositoryDialog::~BasicRepositoryDialog()
{
delete m;
}
-BasicMainWindow *BasicRepositoryDialog::mainwindow()
+MainWindow *BasicRepositoryDialog::mainwindow()
{
return m->mainwindow;
}
GitPtr BasicRepositoryDialog::git()
{
return m->git;
}
QList<Git::Remote> const *BasicRepositoryDialog::remotes() const
{
return &m->remotes;
}
void BasicRepositoryDialog::getRemotes_()
{
GitPtr g = git();
if (g->isValidWorkingCopy()) {
g->getRemoteURLs(&m->remotes);
}
}
void BasicRepositoryDialog::setSshKey_(QString const &sshkey)
{
m->git->setSshKey(sshkey);
}
QString BasicRepositoryDialog::updateRemotesTable(QTableWidget *tablewidget)
{
tablewidget->clear();
m->remotes.clear();
getRemotes_();
QString url;
QString alturl;
int rows = m->remotes.size();
tablewidget->setColumnCount(3);
tablewidget->setRowCount(rows);
auto newQTableWidgetItem = [](QString const &text){
auto *item = new QTableWidgetItem;
item->setSizeHint(QSize(20, 20));
item->setText(text);
return item;
};
auto SetHeaderItem = [&](int col, QString const &text){
tablewidget->setHorizontalHeaderItem(col, newQTableWidgetItem(text));
};
SetHeaderItem(0, tr("Name"));
SetHeaderItem(1, tr("Purpose"));
SetHeaderItem(2, tr("URL"));
for (int row = 0; row < rows; row++) {
Git::Remote const &r = m->remotes[row];
if (r.purpose == "push") {
url = r.url;
} else {
alturl = r.url;
}
auto SetItem = [&](int col, QString const &text){
tablewidget->setItem(row, col, newQTableWidgetItem(text));
};
SetItem(0, r.name);
SetItem(1, r.purpose);
SetItem(2, r.url);
}
tablewidget->horizontalHeader()->setStretchLastSection(true);
if (url.isEmpty()) {
url = alturl;
}
return url;
}
diff --git a/src/BasicRepositoryDialog.h b/src/BasicRepositoryDialog.h
index 8e79d00..f4efc5b 100644
--- a/src/BasicRepositoryDialog.h
+++ b/src/BasicRepositoryDialog.h
@@ -1,28 +1,28 @@
#ifndef BASICREPOSITORYDIALOG_H
#define BASICREPOSITORYDIALOG_H
#include <QDialog>
#include "Git.h"
class QTableWidget;
-class BasicMainWindow;
+class MainWindow;
class BasicRepositoryDialog : public QDialog {
public:
- explicit BasicRepositoryDialog(BasicMainWindow *mainwindow, const GitPtr &g);
+ explicit BasicRepositoryDialog(MainWindow *mainwindow, const GitPtr &g);
~BasicRepositoryDialog() override;
private:
struct Private;
Private *m;
protected:
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
GitPtr git();
QString updateRemotesTable(QTableWidget *tablewidget);
const QList<Git::Remote> *remotes() const;
void getRemotes_();
void setSshKey_(const QString &sshkey);
};
#endif // BASICREPOSITORYDIALOG_H
diff --git a/src/BigDiffWindow.cpp b/src/BigDiffWindow.cpp
index 03fb935..67c795c 100644
--- a/src/BigDiffWindow.cpp
+++ b/src/BigDiffWindow.cpp
@@ -1,84 +1,84 @@
#include <memory>
#include "BigDiffWindow.h"
#include "ui_BigDiffWindow.h"
struct BigDiffWindow::Private {
TextEditorEnginePtr text_editor_engine;
FileDiffWidget::InitParam_ param;
};
BigDiffWindow::BigDiffWindow(QWidget *parent)
: QDialog(parent)
, ui(new Ui::BigDiffWindow)
, m(new Private)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
flags |= Qt::WindowMaximizeButtonHint;
setWindowFlags(flags);
ui->widget_diff->setMaximizeButtonEnabled(false);
connect(ui->widget_diff, &FileDiffWidget::textcodecChanged, [&](){ updateDiffView(); });
}
BigDiffWindow::~BigDiffWindow()
{
delete m;
delete ui;
}
void BigDiffWindow::setTextCodec(QTextCodec *codec)
{
m->text_editor_engine = std::make_shared<TextEditorEngine>();
ui->widget_diff->setTextCodec(codec);
}
void BigDiffWindow::updateDiffView()
{
ui->widget_diff->updateDiffView(m->param.diff, m->param.uncommited);
}
-void BigDiffWindow::init(BasicMainWindow *mw, FileDiffWidget::InitParam_ const &param)
+void BigDiffWindow::init(MainWindow *mw, FileDiffWidget::InitParam_ const &param)
{
ui->widget_diff->bind(mw);
m->param = param;
{
QString name = m->param.diff.path;
int i = name.lastIndexOf('/');
if (i >= 0) {
name = name.mid(i + 1);
}
ui->lineEdit_center->setText(name);
}
auto Text = [](QString id){
if (id.startsWith(PATH_PREFIX)) {
id = id.mid(1);
}
return id;
};
ui->lineEdit_left->setText(Text(m->param.diff.blob.a_id));
ui->lineEdit_right->setText(Text(m->param.diff.blob.b_id));
switch (m->param.view_style) {
case FileDiffWidget::ViewStyle::LeftOnly:
ui->widget_diff->setLeftOnly(m->param.bytes_a, m->param.diff);
break;
case FileDiffWidget::ViewStyle::RightOnly:
ui->widget_diff->setRightOnly(m->param.bytes_b, m->param.diff);
break;
case FileDiffWidget::ViewStyle::SideBySideText:
ui->widget_diff->setSideBySide(m->param.bytes_a, m->param.diff, m->param.uncommited, m->param.workingdir);
break;
case FileDiffWidget::ViewStyle::SideBySideImage:
ui->widget_diff->setSideBySide_(m->param.bytes_a, m->param.bytes_b, m->param.workingdir);
break;
}
}
diff --git a/src/BigDiffWindow.h b/src/BigDiffWindow.h
index 95e75ec..dec3d3b 100644
--- a/src/BigDiffWindow.h
+++ b/src/BigDiffWindow.h
@@ -1,29 +1,29 @@
#ifndef BIGDIFFWINDOW_H
#define BIGDIFFWINDOW_H
#include <QDialog>
#include "Git.h"
#include "FileDiffWidget.h"
namespace Ui {
class BigDiffWindow;
}
class BigDiffWindow : public QDialog {
Q_OBJECT
private:
struct Private;
Private *m;
public:
explicit BigDiffWindow(QWidget *parent = nullptr);
~BigDiffWindow() override;
- void init(BasicMainWindow *mw, const FileDiffWidget::InitParam_ &param);
+ void init(MainWindow *mw, const FileDiffWidget::InitParam_ &param);
void setTextCodec(QTextCodec *codec);
private:
Ui::BigDiffWindow *ui;
void updateDiffView();
QString fileName() const;
};
#endif // BIGDIFFWINDOW_H
diff --git a/src/CloneDialog.cpp b/src/CloneDialog.cpp
index 6141cdb..5c22c5d 100644
--- a/src/CloneDialog.cpp
+++ b/src/CloneDialog.cpp
@@ -1,156 +1,156 @@
#include "CloneDialog.h"
#include "ui_CloneDialog.h"
#include "ApplicationGlobal.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "SearchFromGitHubDialog.h"
#include "common/joinpath.h"
#include "common/misc.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QStandardPaths>
#include <QThread>
enum SearchRepository {
None,
GitHub,
};
struct CloneDialog::Private {
QString url;
QString repo_name;
QString default_working_dir;
bool ok = false;
QString errmsg;
CloneDialog::Action action = CloneDialog::Action::Clone;
};
-CloneDialog::CloneDialog(BasicMainWindow *parent, QString const &url, QString const &defworkdir, Git::Context const *gcx)
+CloneDialog::CloneDialog(MainWindow *parent, QString const &url, QString const &defworkdir, Git::Context const *gcx)
: QDialog(parent)
, ui(new Ui::CloneDialog)
, m(new Private)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
m->default_working_dir = defworkdir;
ui->lineEdit_working_dir->setText(m->default_working_dir);
ui->lineEdit_repo_location->setText(url);
ui->comboBox->addItem(tr("Search"));
ui->comboBox->addItem(tr("GitHub"));
ui->advanced_option->setSshKeyOverrigingEnabled(!gcx->ssh_command.isEmpty());
#ifdef Q_OS_MACX
ui->comboBox->setMinimumWidth(100);
#endif
ui->lineEdit_repo_location->setFocus();
}
CloneDialog::~CloneDialog()
{
delete m;
delete ui;
}
CloneDialog::Action CloneDialog::action() const
{
return m->action;
}
-BasicMainWindow *CloneDialog::mainwindow()
+MainWindow *CloneDialog::mainwindow()
{
- return qobject_cast<BasicMainWindow *>(parent());
+ return qobject_cast<MainWindow *>(parent());
}
QString CloneDialog::url()
{
return ui->lineEdit_repo_location->text();
}
QString CloneDialog::dir()
{
return ui->lineEdit_working_dir->text();
}
void CloneDialog::on_lineEdit_repo_location_textChanged(QString const &text)
{
QString path;
int i = text.lastIndexOf('/');
int j = text.lastIndexOf('\\');
if (i < j) i = j;
j = text.size();
if (text.endsWith(".git")) {
j -= 4;
}
if (i >= 0 && i < j) {
path = text.mid(i, j - i);
}
m->repo_name = path;
path = m->default_working_dir / m->repo_name;
path = misc::normalizePathSeparator(path);
ui->lineEdit_working_dir->setText(path);
}
void CloneDialog::on_comboBox_currentIndexChanged(int index)
{
if (index == GitHub) {
SearchFromGitHubDialog dlg(this, mainwindow());
if (dlg.exec() == QDialog::Accepted) {
ui->lineEdit_repo_location->setText(dlg.url());
}
}
ui->comboBox->setCurrentIndex(0);
}
void CloneDialog::on_pushButton_test_clicked()
{
mainwindow()->testRemoteRepositoryValidity(url(), overridedSshKey());
}
void CloneDialog::on_pushButton_browse_clicked()
{
QString path = ui->lineEdit_working_dir->text();
path = QFileDialog::getExistingDirectory(this, tr("Checkout into"), path);
if (!path.isEmpty()) {
m->default_working_dir = path;
path = m->default_working_dir / m->repo_name;
path = misc::normalizePathSeparator(path);
ui->lineEdit_working_dir->setText(path);
}
}
void CloneDialog::on_pushButton_open_existing_clicked()
{
QString dir = mainwindow()->defaultWorkingDir();
dir = QFileDialog::getExistingDirectory(this, tr("Open existing directory"), dir);
if (QFileInfo(dir).isDir()) {
QString url;
GitPtr g = mainwindow()->git(dir);
QList<Git::Remote> vec;
if (g->isValidWorkingCopy()) {
g->getRemoteURLs(&vec);
}
for (Git::Remote const &r : vec) {
if (r.purpose == "push" || url.isEmpty()) {
url = r.url;
}
}
ui->lineEdit_repo_location->setText(url);
ui->lineEdit_working_dir->setText(dir);
m->action = CloneDialog::Action::AddExisting;
done(Accepted);
}
}
QString CloneDialog::overridedSshKey() const
{
return ui->advanced_option->sshKey();
}
diff --git a/src/CloneDialog.h b/src/CloneDialog.h
index 7c7ca2e..e3e12cc 100644
--- a/src/CloneDialog.h
+++ b/src/CloneDialog.h
@@ -1,45 +1,45 @@
#ifndef CLONEDIALOG_H
#define CLONEDIALOG_H
#include <QDialog>
#include <QThread>
#include "Git.h"
namespace Ui {
class CloneDialog;
}
-class BasicMainWindow;
+class MainWindow;
class CloneDialog : public QDialog {
Q_OBJECT
private:
Ui::CloneDialog *ui;
struct Private;
Private *m;
using GitPtr = std::shared_ptr<Git>;
private:
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
public:
- explicit CloneDialog(BasicMainWindow *parent, QString const &url, QString const &defworkdir, const Git::Context *gcx);
+ explicit CloneDialog(MainWindow *parent, QString const &url, QString const &defworkdir, const Git::Context *gcx);
~CloneDialog() override;
enum class Action {
Clone,
AddExisting,
};
Action action() const;
QString url();
QString dir();
QString overridedSshKey() const;
private slots:
void on_lineEdit_repo_location_textChanged(QString const &text);
void on_pushButton_test_clicked();
void on_comboBox_currentIndexChanged(int index);
void on_pushButton_browse_clicked();
void on_pushButton_open_existing_clicked();
};
#endif // CLONEDIALOG_H
diff --git a/src/CloneDialog.ui b/src/CloneDialog.ui
index 99d9427..2d14dba 100644
--- a/src/CloneDialog.ui
+++ b/src/CloneDialog.ui
@@ -1,194 +1,194 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CloneDialog</class>
<widget class="QDialog" name="CloneDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>612</width>
- <height>211</height>
+ <width>632</width>
+ <height>290</height>
</rect>
</property>
<property name="windowTitle">
<string>Clone</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Remote</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="RepositoryLineEdit" name="lineEdit_repo_location">
<property name="minimumSize">
<size>
<width>320</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="pushButton_test">
<property name="text">
<string>&amp;Test</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Local</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="DirectoryLineEdit" name="lineEdit_working_dir"/>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="pushButton_browse">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="RemoteAdvancedOptionWidget" name="advanced_option" native="true">
<property name="minimumSize">
<size>
<width>0</width>
- <height>78</height>
+ <height>110</height>
</size>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="comboBox"/>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_open_existing">
<property name="text">
<string>Open existing local directory...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Clone</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>RepositoryLineEdit</class>
<extends>QLineEdit</extends>
<header>RepositoryLineEdit.h</header>
</customwidget>
<customwidget>
<class>DirectoryLineEdit</class>
<extends>QLineEdit</extends>
<header>DirectoryLineEdit.h</header>
</customwidget>
<customwidget>
<class>RemoteAdvancedOptionWidget</class>
<extends>QWidget</extends>
<header>RemoteAdvancedOptionWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>lineEdit_repo_location</tabstop>
<tabstop>pushButton_test</tabstop>
<tabstop>lineEdit_working_dir</tabstop>
<tabstop>pushButton_browse</tabstop>
<tabstop>comboBox</tabstop>
<tabstop>pushButton_open_existing</tabstop>
<tabstop>pushButton</tabstop>
<tabstop>pushButton_2</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>pushButton</sender>
<signal>clicked()</signal>
<receiver>CloneDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>152</x>
<y>269</y>
</hint>
<hint type="destinationlabel">
<x>104</x>
<y>320</y>
</hint>
</hints>
</connection>
<connection>
<sender>pushButton_2</sender>
<signal>clicked()</signal>
<receiver>CloneDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>244</x>
<y>270</y>
</hint>
<hint type="destinationlabel">
<x>238</x>
<y>317</y>
</hint>
</hints>
</connection>
</connections>
</ui>
diff --git a/src/CommitDialog.cpp b/src/CommitDialog.cpp
index d37e6c4..20efef2 100644
--- a/src/CommitDialog.cpp
+++ b/src/CommitDialog.cpp
@@ -1,111 +1,111 @@
#include "CommitDialog.h"
#include "ui_CommitDialog.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "ConfigSigningDialog.h"
#include <QDir>
-CommitDialog::CommitDialog(BasicMainWindow *parent, QString const &reponame, Git::User const &user, gpg::Data const &key, QString const &previousMessage)
+CommitDialog::CommitDialog(MainWindow *parent, QString const &reponame, Git::User const &user, gpg::Data const &key, QString const &previousMessage)
: QDialog(parent)
, ui(new Ui::CommitDialog)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
key_ = key;
previousMessage_ = previousMessage;
ui->label_reponame->setText(reponame);
ui->label_commit_author->setText(user.name);
ui->label_commit_mail->setText(user.email);
ui->checkbox_amend->setChecked(false);
if (previousMessage_.isEmpty()) {
ui->checkbox_amend->hide();
}
updateSigningInfo();
ui->plainTextEdit->setFocus();
}
CommitDialog::~CommitDialog()
{
delete ui;
}
-BasicMainWindow *CommitDialog::mainwindow()
+MainWindow *CommitDialog::mainwindow()
{
- return qobject_cast<BasicMainWindow *>(parent());
+ return qobject_cast<MainWindow *>(parent());
}
void CommitDialog::updateSigningInfo()
{
GitPtr g = mainwindow()->git();
Git::SignPolicy pol = g->signPolicy(Git::Source::Default);
if (!key_.id.isEmpty()) {
if (pol == Git::SignPolicy::True) {
ui->groupBox_gpg_sign->setCheckable(false);
} else {
ui->groupBox_gpg_sign->setCheckable(true);
ui->groupBox_gpg_sign->setChecked(false);
}
ui->label_sign_id->setText(key_.id);
ui->label_sign_name->setText(key_.name);
ui->label_sign_mail->setText(key_.mail);
} else {
ui->groupBox_gpg_sign->setChecked(false);
ui->groupBox_gpg_sign->setEnabled(false);
}
}
bool CommitDialog::isSigningEnabled() const
{
return ui->groupBox_gpg_sign->isChecked();
}
bool CommitDialog::isAmend() const
{
return ui->checkbox_amend->isChecked();
}
void CommitDialog::setText(QString const &text)
{
ui->plainTextEdit->setPlainText(text);
QTextCursor cur = ui->plainTextEdit->textCursor();
cur.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
ui->plainTextEdit->setTextCursor(cur);
}
QString CommitDialog::text() const
{
return ui->plainTextEdit->toPlainText();
}
void CommitDialog::keyPressEvent(QKeyEvent *event)
{
if (event->modifiers() & Qt::ControlModifier) {
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
event->accept();
accept();
return;
}
}
QDialog::keyPressEvent(event);
}
void CommitDialog::on_pushButton_config_signing_clicked()
{
ConfigSigningDialog dlg(this, mainwindow(), true);
if (dlg.exec() == QDialog::Accepted) {
updateSigningInfo();
}
}
void CommitDialog::on_checkbox_amend_stateChanged(int state)
{
setText(state == Qt::Checked ? previousMessage_ : QString(""));
}
diff --git a/src/CommitDialog.h b/src/CommitDialog.h
index 878f154..dee858c 100644
--- a/src/CommitDialog.h
+++ b/src/CommitDialog.h
@@ -1,40 +1,40 @@
#ifndef COMMITDIALOG_H
#define COMMITDIALOG_H
#include "Git.h"
#include "gpg.h"
#include <QDialog>
-class BasicMainWindow;
+class MainWindow;
namespace Ui {
class CommitDialog;
}
class CommitDialog : public QDialog {
Q_OBJECT
public:
- explicit CommitDialog(BasicMainWindow *parent, QString const &reponame, Git::User const &user, gpg::Data const &key, QString const &previousMessage);
+ explicit CommitDialog(MainWindow *parent, QString const &reponame, Git::User const &user, gpg::Data const &key, QString const &previousMessage);
~CommitDialog() override;
void setText(QString const &text);
QString text() const;
bool isSigningEnabled() const;
bool isAmend() const;
protected:
void keyPressEvent(QKeyEvent *event) override;
private:
Ui::CommitDialog *ui;
gpg::Data key_;
QString previousMessage_;
// QDialog interface
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
void updateSigningInfo();
private slots:
void on_pushButton_config_signing_clicked();
void on_checkbox_amend_stateChanged(int state);
};
#endif // COMMITDIALOG_H
diff --git a/src/CommitExploreWindow.cpp b/src/CommitExploreWindow.cpp
index 9b76a4e..0e6b7a5 100644
--- a/src/CommitExploreWindow.cpp
+++ b/src/CommitExploreWindow.cpp
@@ -1,279 +1,279 @@
#include "CommitExploreWindow.h"
#include "ui_CommitExploreWindow.h"
#include "GitObjectManager.h"
#include "ImageViewWidget.h"
#include "MainWindow.h"
#include "common/misc.h"
#include "main.h"
#include "platform.h"
#include <QFileIconProvider>
#include <QMenu>
#include <memory>
static QTreeWidgetItem *newQTreeWidgetItem()
{
auto *item = new QTreeWidgetItem;
item->setSizeHint(0, QSize(20, 20));
return item;
}
enum {
ItemTypeRole = Qt::UserRole,
ObjectIdRole,
FilePathRole,
};
struct CommitExploreWindow::Private {
- BasicMainWindow *mainwindow;
+ MainWindow *mainwindow;
GitObjectCache *objcache;
Git::CommitItem const *commit;
QString root_tree_id;
GitTreeItemList tree_item_list;
Git::Object content_object;
ObjectContent content;
TextEditorEnginePtr text_editor_engine;
};
-CommitExploreWindow::CommitExploreWindow(QWidget *parent, BasicMainWindow *mainwin, GitObjectCache *objcache, Git::CommitItem const *commit)
+CommitExploreWindow::CommitExploreWindow(QWidget *parent, MainWindow *mainwin, GitObjectCache *objcache, Git::CommitItem const *commit)
: QDialog(parent)
, ui(new Ui::CommitExploreWindow)
, m(new Private)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
flags |= Qt::WindowMaximizeButtonHint;
setWindowFlags(flags);
m->mainwindow = mainwin;
m->objcache = objcache;
m->commit = commit;
m->text_editor_engine = std::make_shared<TextEditorEngine>();
ui->widget_fileview->bind(mainwin, nullptr, ui->verticalScrollBar, ui->horizontalScrollBar, mainwin->themeForTextEditor());
ui->widget_fileview->setDiffMode(m->text_editor_engine, ui->verticalScrollBar, ui->horizontalScrollBar);
ui->splitter->setSizes({100, 100, 200});
// set text
ui->lineEdit_commit_id->setText(commit->commit_id);
ui->lineEdit_date->setText(misc::makeDateTimeString(commit->commit_date));
ui->lineEdit_author->setText(commit->author);
{
GitCommit c;
GitCommit::parseCommit(objcache, m->commit->commit_id, &c);
m->root_tree_id = c.tree_id;
}
{
GitCommitTree tree(objcache);
tree.parseTree(m->root_tree_id);
}
{
QTreeWidgetItem *rootitem = newQTreeWidgetItem();
rootitem->setText(0, tr("Commit"));
rootitem->setData(0, ItemTypeRole, (int)GitTreeItem::TREE);
rootitem->setData(0, ObjectIdRole, m->root_tree_id);
ui->treeWidget->addTopLevelItem(rootitem);
loadTree(m->root_tree_id);
rootitem->setExpanded(true);
}
}
CommitExploreWindow::~CommitExploreWindow()
{
delete m;
delete ui;
}
-BasicMainWindow *CommitExploreWindow::mainwindow()
+MainWindow *CommitExploreWindow::mainwindow()
{
return m->mainwindow;
}
void CommitExploreWindow::clearContent()
{
m->content = ObjectContent();
}
void CommitExploreWindow::expandTreeItem_(QTreeWidgetItem *item)
{
if (item->childCount() == 1) {
if (item->child(0)->text(0).isEmpty()) {
delete item->takeChild(0);
}
}
if (item->childCount() == 0) {
QFileIconProvider icons;
QString path = item->data(0, FilePathRole).toString();
QString tree_id = item->data(0, ObjectIdRole).toString();
loadTree(tree_id);
for (GitTreeItem const &ti : m->tree_item_list) {
if (ti.type == GitTreeItem::TREE) {
QTreeWidgetItem *child = newQTreeWidgetItem();
child->setIcon(0, icons.icon(QFileIconProvider::Folder));
child->setText(0, ti.name);
child->setData(0, ItemTypeRole, (int)ti.type);
child->setData(0, ObjectIdRole, ti.id);
child->setData(0, FilePathRole, misc::joinWithSlash(path, ti.name));
QTreeWidgetItem *placeholder = newQTreeWidgetItem();
child->addChild(placeholder);
item->addChild(child);
}
}
}
}
void CommitExploreWindow::on_treeWidget_itemExpanded(QTreeWidgetItem *item)
{
expandTreeItem_(item);
}
void CommitExploreWindow::loadTree(QString const &tree_id)
{
GitCommitTree tree(m->objcache);
tree.parseTree(tree_id);
m->tree_item_list = *tree.treelist();
std::sort(m->tree_item_list.begin(), m->tree_item_list.end(), [](GitTreeItem const &left, GitTreeItem const &right){
int l = (left.type == GitTreeItem::TREE) ? 0 : 1;
int r = (right.type == GitTreeItem::TREE) ? 0 : 1;
if (l != r) return l < r;
return left.name.compare(right.name, Qt::CaseInsensitive) < 0;
});
}
void CommitExploreWindow::doTreeItemChanged_(QTreeWidgetItem *current)
{
ui->listWidget->clear();
QString path = current->data(0, FilePathRole).toString();
QString tree_id = current->data(0, ObjectIdRole).toString();
loadTree(tree_id);
QFileIconProvider icons;
for (GitTreeItem const &ti : m->tree_item_list) {
QIcon icon;
if (ti.type == GitTreeItem::TREE) {
icon = icons.icon(QFileIconProvider::Folder);
} else {
#ifdef Q_OS_WIN
{
int i = ti.name.lastIndexOf('.');
if (i > 0) {
QString ext = ti.name.mid(i + 1);
icon = winIconFromExtensionLarge(ext);
}
}
#endif
if (icon.isNull()) {
icon = icons.icon(QFileIconProvider::File);
}
}
auto *p = new QListWidgetItem;
p->setIcon(icon);
p->setText(ti.name);
p->setData(ItemTypeRole, (int)ti.type);
p->setData(ObjectIdRole, ti.id);
p->setData(FilePathRole, misc::joinWithSlash(path, ti.name));
ui->listWidget->addItem(p);
}
}
void CommitExploreWindow::on_treeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem * /*previous*/)
{
clearContent();
doTreeItemChanged_(current);
}
void CommitExploreWindow::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
{
Q_ASSERT(item);
GitTreeItem::Type type = (GitTreeItem::Type)item->data(ItemTypeRole).toInt();
if (type == GitTreeItem::TREE) {
QString tree_id = item->data(ObjectIdRole).toString();
clearContent();
QTreeWidgetItem *parent = ui->treeWidget->currentItem();
expandTreeItem_(parent);
parent->setExpanded(true);
int n = parent->childCount();
for (int i = 0; i < n; i++) {
QTreeWidgetItem *child = parent->child(i);
if (child->data(0, ItemTypeRole).toInt() == GitTreeItem::TREE) {
QString tid = child->data(0, ObjectIdRole).toString();
if (tid == tree_id) {
child->setExpanded(true);
ui->treeWidget->setCurrentItem(child);
break;
}
}
}
}
}
void CommitExploreWindow::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem * /*previous*/)
{
if (!current) return;
GitTreeItem::Type type = (GitTreeItem::Type)current->data(ItemTypeRole).toInt();
if (type == GitTreeItem::BLOB) {
QString id = current->data(ObjectIdRole).toString();
m->content_object = m->objcache->catFile(id);
QString path = current->data(FilePathRole).toString();
clearContent();
QString mimetype = mainwindow()->determinFileType(m->content_object.content, true);
if (misc::isImage(mimetype)) {
ui->widget_fileview->setImage(mimetype, m->content_object.content, id, path);
} else {
ui->widget_fileview->setText(m->content_object.content, mainwindow(), id, path);
}
} else {
clearContent();
}
}
void CommitExploreWindow::on_verticalScrollBar_valueChanged(int)
{
ui->widget_fileview->refrectScrollBar();
}
void CommitExploreWindow::on_horizontalScrollBar_valueChanged(int)
{
ui->widget_fileview->refrectScrollBar();
}
void CommitExploreWindow::on_listWidget_customContextMenuRequested(const QPoint &pos)
{
(void)pos;
QListWidgetItem *current = ui->listWidget->currentItem();
if (!current) return;
GitTreeItem::Type type = (GitTreeItem::Type)current->data(ItemTypeRole).toInt();
if (type == GitTreeItem::BLOB) {
QMenu menu;
QAction *a_history = menu.addAction("History");
QAction *a = menu.exec(QCursor::pos() + QPoint(8, -8));
if (a) {
if (a == a_history) {
QString path = current->data(FilePathRole).toString();
mainwindow()->execFileHistory(path);
return;
}
}
}
}
diff --git a/src/CommitExploreWindow.h b/src/CommitExploreWindow.h
index 2a887e1..5b05f9d 100644
--- a/src/CommitExploreWindow.h
+++ b/src/CommitExploreWindow.h
@@ -1,42 +1,42 @@
#ifndef COMMITEXPLOREWINDOW_H
#define COMMITEXPLOREWINDOW_H
#include <QDialog>
#include "FileDiffWidget.h"
namespace Ui {
class CommitExploreWindow;
}
class QTreeWidgetItem;
class QListWidgetItem;
class GitObjectCache;
class CommitExploreWindow : public QDialog {
Q_OBJECT
private:
Ui::CommitExploreWindow *ui;
struct Private;
Private *m;
void loadTree(QString const &tree_id);
void doTreeItemChanged_(QTreeWidgetItem *current);
void expandTreeItem_(QTreeWidgetItem *item);
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
public:
- explicit CommitExploreWindow(QWidget *parent, BasicMainWindow *mainwin, GitObjectCache *objcache, Git::CommitItem const *commit);
+ explicit CommitExploreWindow(QWidget *parent, MainWindow *mainwin, GitObjectCache *objcache, Git::CommitItem const *commit);
~CommitExploreWindow() override;
void clearContent();
private slots:
void on_treeWidget_itemExpanded(QTreeWidgetItem *item);
void on_treeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
void on_listWidget_itemDoubleClicked(QListWidgetItem *item);
void on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
void on_verticalScrollBar_valueChanged(int);
void on_horizontalScrollBar_valueChanged(int);
void on_listWidget_customContextMenuRequested(const QPoint &pos);
};
#endif // COMMITEXPLOREWINDOW_H
diff --git a/src/CommitPropertyDialog.cpp b/src/CommitPropertyDialog.cpp
index 68299af..937c906 100644
--- a/src/CommitPropertyDialog.cpp
+++ b/src/CommitPropertyDialog.cpp
@@ -1,171 +1,171 @@
#include "CommitPropertyDialog.h"
#include "ui_CommitPropertyDialog.h"
#include "ApplicationGlobal.h"
#include "AvatarLoader.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "common/misc.h"
#include "gpg.h"
#include "main.h"
struct CommitPropertyDialog::Private {
- BasicMainWindow *mainwindow;
+ MainWindow *mainwindow;
Git::CommitItem commit;
AvatarLoader avatar_loader;
};
-void CommitPropertyDialog::init(BasicMainWindow *mw)
+void CommitPropertyDialog::init(MainWindow *mw)
{
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
ui->pushButton_jump->setVisible(false);
m->mainwindow = mw;
ui->lineEdit_message->setText(m->commit.message);
ui->lineEdit_commit_id->setText(m->commit.commit_id);
ui->lineEdit_date->setText(misc::makeDateTimeString(m->commit.commit_date));
ui->lineEdit_author->setText(m->commit.author);
ui->lineEdit_mail->setText(m->commit.email);
QString text;
for (QString const &id : m->commit.parent_ids) {
text += id + '\n';
}
ui->plainTextEdit_parent_ids->setPlainText(text);
gpg::Data key;
int n1 = m->commit.fingerprint.size();
if (n1 > 0) {
QList<gpg::Data> keys;
if (gpg::listKeys(global->gpg_command, &keys)) {
for (gpg::Data const &k : keys) {
int n2 = k.fingerprint.size();
if (n2 > 0) {
int n = std::min(n1, n2);
char const *p1 = m->commit.fingerprint.data() + n1 - n;
char const *p2 = k.fingerprint.data() + n2 - n;
if (memcmp(p1, p2, n) == 0) {
key = k;
break;
}
}
}
} else {
qDebug() << "Failed to get gpg keys";
}
if (key.id.isEmpty()) {
// gpgコマンドが登録されていないなど、keyidが取得できなかったとき
key.id = tr("<Unknown>");
}
}
if (key.id.isEmpty()) {
ui->frame_sign->setVisible(false);
} else {
{
int w = ui->label_signature_icon->width();
int h = ui->label_signature_icon->width();
QIcon icon = mainwindow()->verifiedIcon(m->commit.signature);
ui->label_signature_icon->setPixmap(icon.pixmap(w, h));
}
ui->lineEdit_sign_id->setText(key.id);
ui->lineEdit_sign_name->setText(key.name);
ui->lineEdit_sign_mail->setText(key.mail);
}
m->avatar_loader.start(mainwindow());
connect(&m->avatar_loader, &AvatarLoader::updated, [&](){
updateAvatar(false);
});
updateAvatar(true);
}
void CommitPropertyDialog::updateAvatar(bool request)
{
if (!mainwindow()->isOnlineMode()) return;
auto SetAvatar = [&](QString const &email, QLabel *label){
if (mainwindow()->appsettings()->get_committer_icon) {
label->setFixedSize(QSize(48, 48));
QIcon icon = m->avatar_loader.fetch(email.toStdString(), request);
setAvatar(icon, label);
} else {
label->setVisible(false);
}
};
SetAvatar(ui->lineEdit_mail->text(), ui->label_user_avatar);
SetAvatar(ui->lineEdit_sign_mail->text(), ui->label_sign_avatar);
}
-CommitPropertyDialog::CommitPropertyDialog(QWidget *parent, BasicMainWindow *mw, Git::CommitItem const *commit)
+CommitPropertyDialog::CommitPropertyDialog(QWidget *parent, MainWindow *mw, Git::CommitItem const *commit)
: QDialog(parent)
, ui(new Ui::CommitPropertyDialog)
, m(new Private)
{
ui->setupUi(this);
m->commit = *commit;
init(mw);
}
-CommitPropertyDialog::CommitPropertyDialog(QWidget *parent, BasicMainWindow *mw, QString const &commit_id)
+CommitPropertyDialog::CommitPropertyDialog(QWidget *parent, MainWindow *mw, QString const &commit_id)
: QDialog(parent)
, ui(new Ui::CommitPropertyDialog)
, m(new Private)
{
ui->setupUi(this);
mw->queryCommit(commit_id, &m->commit);
init(mw);
}
CommitPropertyDialog::~CommitPropertyDialog()
{
m->avatar_loader.stop();
delete m;
delete ui;
}
-BasicMainWindow *CommitPropertyDialog::mainwindow()
+MainWindow *CommitPropertyDialog::mainwindow()
{
return m->mainwindow;
}
void CommitPropertyDialog::setAvatar(QIcon const &icon, QLabel *label)
{
QPixmap pm = icon.pixmap(label->size());
label->setPixmap(pm);
}
void CommitPropertyDialog::showCheckoutButton(bool f)
{
ui->pushButton_checkout->setVisible(f);
}
void CommitPropertyDialog::showJumpButton(bool f)
{
ui->pushButton_jump->setVisible(f);
}
void CommitPropertyDialog::on_pushButton_checkout_clicked()
{
mainwindow()->checkout(this, &m->commit, [&](){ hide(); });
done(QDialog::Rejected);
}
void CommitPropertyDialog::on_pushButton_jump_clicked()
{
mainwindow()->jumpToCommit(m->commit.commit_id);
done(QDialog::Accepted);
}
void CommitPropertyDialog::on_pushButton_details_clicked()
{
mainwindow()->execCommitViewWindow(&m->commit);
}
void CommitPropertyDialog::on_pushButton_explorer_clicked()
{
mainwindow()->execCommitExploreWindow(this, &m->commit);
}
diff --git a/src/CommitPropertyDialog.h b/src/CommitPropertyDialog.h
index fe8af68..ae5860d 100644
--- a/src/CommitPropertyDialog.h
+++ b/src/CommitPropertyDialog.h
@@ -1,41 +1,42 @@
#ifndef COMMITPROPERTYDIALOG_H
#define COMMITPROPERTYDIALOG_H
#include <QDialog>
#include "Git.h"
+class MainWindow;
class QLabel;
namespace Ui {
class CommitPropertyDialog;
}
class BasicMainWindow;
class CommitPropertyDialog : public QDialog {
Q_OBJECT
private:
struct Private;
Private *m;
public:
- explicit CommitPropertyDialog(QWidget *parent, BasicMainWindow *mw, Git::CommitItem const *commit);
- explicit CommitPropertyDialog(QWidget *parent, BasicMainWindow *mw, QString const &commit_id);
+ explicit CommitPropertyDialog(QWidget *parent, MainWindow *mw, Git::CommitItem const *commit);
+ explicit CommitPropertyDialog(QWidget *parent, MainWindow *mw, QString const &commit_id);
~CommitPropertyDialog() override;
void showCheckoutButton(bool f);
void showJumpButton(bool f);
private slots:
void on_pushButton_checkout_clicked();
void on_pushButton_details_clicked();
void on_pushButton_explorer_clicked();
void on_pushButton_jump_clicked();
private:
Ui::CommitPropertyDialog *ui;
- void init(BasicMainWindow *mw);
- BasicMainWindow *mainwindow();
+ void init(MainWindow *mw);
+ MainWindow *mainwindow();
void setAvatar(const QIcon &icon, QLabel *label);
void updateAvatar(bool request);
};
#endif // COMMITPROPERTYDIALOG_H
diff --git a/src/CommitViewWindow.cpp b/src/CommitViewWindow.cpp
index f7cdea4..ffcca25 100644
--- a/src/CommitViewWindow.cpp
+++ b/src/CommitViewWindow.cpp
@@ -1,71 +1,71 @@
#include "CommitViewWindow.h"
#include "ui_CommitViewWindow.h"
#include <QMenu>
struct CommitViewWindow::Private {
Git::CommitItem const *commit = nullptr;
QList<Git::Diff> diff_list;
};
-CommitViewWindow::CommitViewWindow(BasicMainWindow *parent, Git::CommitItem const *commit)
+CommitViewWindow::CommitViewWindow(MainWindow *parent, Git::CommitItem const *commit)
: QDialog(parent)
, ui(new Ui::CommitViewWindow)
, m(new Private)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
m->commit = commit;
ui->widget_diff->bind(mainwindow());
ui->lineEdit_message->setText(m->commit->message);
ui->lineEdit_id->setText(m->commit->commit_id);
- mainwindow()->updateFilesList(m->commit->commit_id, &m->diff_list, ui->listWidget_files);
+ mainwindow()->updateFilesList2(m->commit->commit_id, &m->diff_list, ui->listWidget_files);
ui->listWidget_files->setCurrentRow(0);
}
CommitViewWindow::~CommitViewWindow()
{
delete m;
delete ui;
}
-BasicMainWindow *CommitViewWindow::mainwindow()
+MainWindow *CommitViewWindow::mainwindow()
{
- return qobject_cast<BasicMainWindow *>(parent());
+ return qobject_cast<MainWindow *>(parent());
}
void CommitViewWindow::on_listWidget_files_currentRowChanged(int currentRow)
{
if (currentRow >= 0 && currentRow < m->diff_list.size()) {
Git::Diff const &diff = m->diff_list[currentRow];
ui->widget_diff->updateDiffView(diff, false);
}
}
void CommitViewWindow::on_listWidget_files_customContextMenuRequested(const QPoint &pos)
{
GitPtr g = mainwindow()->git();
if (!mainwindow()->isValidWorkingCopy(g)) return;
QMenu menu;
QAction *a_history = menu.addAction(tr("History"));
QAction *a_properties = mainwindow()->addMenuActionProperty(&menu);
QPoint pt = ui->listWidget_files->mapToGlobal(pos) + QPoint(8, -8);
QAction *a = menu.exec(pt);
if (a) {
QListWidgetItem *item = ui->listWidget_files->currentItem();
if (a == a_history) {
mainwindow()->execFileHistory(item);
} else if (a == a_properties) {
mainwindow()->execFilePropertyDialog(item);
}
}
}
diff --git a/src/CommitViewWindow.h b/src/CommitViewWindow.h
index 6097663..8c5b3c1 100644
--- a/src/CommitViewWindow.h
+++ b/src/CommitViewWindow.h
@@ -1,33 +1,33 @@
#ifndef COMMITVIEWWINDOW_H
#define COMMITVIEWWINDOW_H
#include "Git.h"
#include <QDialog>
-class BasicMainWindow;
+class MainWindow;
namespace Ui {
class CommitViewWindow;
}
class CommitViewWindow : public QDialog {
Q_OBJECT
private:
struct Private;
Private *m;
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
public:
- explicit CommitViewWindow(BasicMainWindow *parent, Git::CommitItem const *commit);
+ explicit CommitViewWindow(MainWindow *parent, Git::CommitItem const *commit);
~CommitViewWindow() override;
private slots:
void on_listWidget_files_currentRowChanged(int currentRow);
void on_listWidget_files_customContextMenuRequested(const QPoint &pos);
private:
Ui::CommitViewWindow *ui;
};
#endif // COMMITVIEWWINDOW_H
diff --git a/src/ConfigSigningDialog.cpp b/src/ConfigSigningDialog.cpp
index 6f005ae..2c8d67c 100644
--- a/src/ConfigSigningDialog.cpp
+++ b/src/ConfigSigningDialog.cpp
@@ -1,76 +1,76 @@
#include "ConfigSigningDialog.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "ui_ConfigSigningDialog.h"
-ConfigSigningDialog::ConfigSigningDialog(QWidget *parent, BasicMainWindow *mw, bool local_enable)
+ConfigSigningDialog::ConfigSigningDialog(QWidget *parent, MainWindow *mw, bool local_enable)
: QDialog(parent)
, ui(new Ui::ConfigSigningDialog)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
mainwindow_ = mw;
if (!mainwindow()->git()->isValidWorkingCopy()) {
local_enable = false;
}
ui->label_local->setVisible(local_enable);
ui->comboBox_sign_local->setVisible(local_enable);
updateSigningInfo();
}
ConfigSigningDialog::~ConfigSigningDialog()
{
delete ui;
}
-BasicMainWindow *ConfigSigningDialog::mainwindow()
+MainWindow *ConfigSigningDialog::mainwindow()
{
return mainwindow_;
}
void ConfigSigningDialog::updateSigningInfo()
{
GitPtr g = mainwindow()->git();
auto InitComboBox = [](QComboBox *cb, Git::SignPolicy pol){
cb->addItem("unset");
cb->addItem("false");
cb->addItem("true");
QString t;
if (pol == Git::SignPolicy::Unset) {
t = "unset";
} else if (pol == Git::SignPolicy::False) {
t = "false";
} else if (pol == Git::SignPolicy::True) {
t = "true";
}
cb->setCurrentText(t);
};
gpol_ = g->signPolicy(Git::Source::Global);
lpol_ = g->signPolicy(Git::Source::Local);
InitComboBox(ui->comboBox_sign_global, gpol_);
InitComboBox(ui->comboBox_sign_local, lpol_);
}
void ConfigSigningDialog::accept()
{
GitPtr g = mainwindow()->git();
auto SetSignPolicy = [&](QComboBox *cb, Git::Source src, Git::SignPolicy oldpol){
Git::SignPolicy pol = Git::SignPolicy::Unset;
QString s = cb->currentText();
if (s == "false") {
pol = Git::SignPolicy::False;
} else if (s == "true") {
pol = Git::SignPolicy::True;
}
if (pol != oldpol) g->setSignPolicy(src, pol);
};
SetSignPolicy(ui->comboBox_sign_global, Git::Source::Global, gpol_);
SetSignPolicy(ui->comboBox_sign_local, Git::Source::Local, lpol_);
QDialog::accept();
}
diff --git a/src/ConfigSigningDialog.h b/src/ConfigSigningDialog.h
index 40bc4d5..5ce9722 100644
--- a/src/ConfigSigningDialog.h
+++ b/src/ConfigSigningDialog.h
@@ -1,35 +1,35 @@
#ifndef CONFIGSIGNINGDIALOG_H
#define CONFIGSIGNINGDIALOG_H
#include "Git.h"
#include "gpg.h"
#include <QDialog>
-class BasicMainWindow;
+class MainWindow;
namespace Ui {
class ConfigSigningDialog;
}
class ConfigSigningDialog : public QDialog {
Q_OBJECT
public:
- explicit ConfigSigningDialog(QWidget *parent, BasicMainWindow *mw, bool local_enable);
+ explicit ConfigSigningDialog(QWidget *parent, MainWindow *mw, bool local_enable);
~ConfigSigningDialog() override;
private:
Ui::ConfigSigningDialog *ui;
- BasicMainWindow *mainwindow_;
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow_;
+ MainWindow *mainwindow();
Git::SignPolicy gpol_;
Git::SignPolicy lpol_;
void updateSigningInfo();
public slots:
void accept() override;
};
#endif // CONFIGSIGNINGDIALOG_H
diff --git a/src/CreateRepositoryDialog.cpp b/src/CreateRepositoryDialog.cpp
index 1ea0260..9722413 100644
--- a/src/CreateRepositoryDialog.cpp
+++ b/src/CreateRepositoryDialog.cpp
@@ -1,132 +1,132 @@
#include "CreateRepositoryDialog.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "common/misc.h"
#include "ui_CreateRepositoryDialog.h"
#include <QFileDialog>
#include <QMessageBox>
#include "Git.h"
-CreateRepositoryDialog::CreateRepositoryDialog(BasicMainWindow *parent, QString const &dir) :
+CreateRepositoryDialog::CreateRepositoryDialog(MainWindow *parent, QString const &dir) :
QDialog(parent),
ui(new Ui::CreateRepositoryDialog)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
already_exists_ = tr("A valid git repository already exists there.");
ui->lineEdit_path->setText(dir);
ui->groupBox_remote->setChecked(false);
ui->lineEdit_remote_name->setText("origin");
validate(false);
}
CreateRepositoryDialog::~CreateRepositoryDialog()
{
delete ui;
}
-BasicMainWindow *CreateRepositoryDialog::mainwindow()
+MainWindow *CreateRepositoryDialog::mainwindow()
{
- return qobject_cast<BasicMainWindow *>(parent());
+ return qobject_cast<MainWindow *>(parent());
}
void CreateRepositoryDialog::accept()
{
QString path = ui->lineEdit_path->text();
if (!QFileInfo(path).isDir()) {
QMessageBox::warning(this, tr("Create Repository"), tr("The specified path is not a directory."));
return;
}
if (Git::isValidWorkingCopy(path)) {
QMessageBox::warning(this, tr("Create Repository"), already_exists_);
return;
}
if (!QFileInfo(path).isDir()) {
QMessageBox::warning(this, tr("Create Repository"), tr("The specified path is not a directory."));
return;
}
if (remoteName().indexOf('\"') >= 0 || remoteURL().indexOf('\"') >= 0) { // 手抜き
QMessageBox::warning(this, tr("Create Repository"), tr("Remote name is invalid."));
return;
}
done(QDialog::Accepted);
}
void CreateRepositoryDialog::on_pushButton_browse_path_clicked()
{
QString path = QFileDialog::getExistingDirectory(this, tr("Destination Path"), mainwindow()->defaultWorkingDir());
if (!path.isEmpty()) {
path = misc::normalizePathSeparator(path);
ui->lineEdit_path->setText(path);
}
}
QString CreateRepositoryDialog::path() const
{
return ui->lineEdit_path->text();
}
QString CreateRepositoryDialog::name() const
{
return ui->lineEdit_name->text();
}
QString CreateRepositoryDialog::remoteName() const
{
return ui->groupBox_remote->isChecked() ? ui->lineEdit_remote_name->text() : QString();
}
QString CreateRepositoryDialog::remoteURL() const
{
return ui->groupBox_remote->isChecked() ? ui->lineEdit_remote_url->text() : QString();
}
void CreateRepositoryDialog::validate(bool change_name)
{
QString path = this->path();
{
QString text;
if (Git::isValidWorkingCopy(path)) {
text = already_exists_;
}
ui->label_warning->setText(text);
}
if (change_name) {
int i = path.lastIndexOf('/');
int j = path.lastIndexOf('\\');
if (i < j) i = j;
if (i >= 0) {
QString name = path.mid(i + 1);
ui->lineEdit_name->setText(name);
}
}
}
void CreateRepositoryDialog::on_lineEdit_path_textChanged(QString const &)
{
validate(true);
}
void CreateRepositoryDialog::on_lineEdit_name_textChanged(QString const &)
{
validate(false);
}
void CreateRepositoryDialog::on_groupBox_remote_toggled(bool)
{
validate(false);
}
void CreateRepositoryDialog::on_pushButton_test_repo_clicked()
{
QString url = ui->lineEdit_remote_url->text();
mainwindow()->testRemoteRepositoryValidity(url, {});
validate(false);
}
diff --git a/src/CreateRepositoryDialog.h b/src/CreateRepositoryDialog.h
index 8156ff3..be8c7c4 100644
--- a/src/CreateRepositoryDialog.h
+++ b/src/CreateRepositoryDialog.h
@@ -1,42 +1,42 @@
#ifndef CREATEREPOSITORYDIALOG_H
#define CREATEREPOSITORYDIALOG_H
#include <QDialog>
namespace Ui {
class CreateRepositoryDialog;
}
-class BasicMainWindow;
+class MainWindow;
class CreateRepositoryDialog : public QDialog {
Q_OBJECT
private:
QString already_exists_;
public:
- explicit CreateRepositoryDialog(BasicMainWindow *parent, QString const &dir = QString());
+ explicit CreateRepositoryDialog(MainWindow *parent, QString const &dir = QString());
~CreateRepositoryDialog() override;
QString path() const;
QString name() const;
QString remoteName() const;
QString remoteURL() const;
private slots:
void on_lineEdit_path_textChanged(QString const &arg1);
void on_pushButton_browse_path_clicked();
void on_lineEdit_name_textChanged(QString const &arg1);
void on_groupBox_remote_toggled(bool arg1);
void on_pushButton_test_repo_clicked();
private:
Ui::CreateRepositoryDialog *ui;
void validate(bool change_name);
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
public slots:
void accept() override;
};
#endif // CREATEREPOSITORYDIALOG_H
diff --git a/src/EditRemoteDialog.cpp b/src/EditRemoteDialog.cpp
index aa4a713..e7653b4 100644
--- a/src/EditRemoteDialog.cpp
+++ b/src/EditRemoteDialog.cpp
@@ -1,84 +1,84 @@
#include "EditRemoteDialog.h"
#include "ui_EditRemoteDialog.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include <QFileDialog>
#include <QStandardPaths>
-EditRemoteDialog::EditRemoteDialog(BasicMainWindow *parent, Operation op, const Git::Context *gcx)
+EditRemoteDialog::EditRemoteDialog(MainWindow *parent, Operation op, const Git::Context *gcx)
: QDialog(parent)
, ui(new Ui::EditRemoteDialog)
{
ui->setupUi(this);
if (op == RemoteSet) {
ui->lineEdit_name->setReadOnly(true);
ui->lineEdit_name->setEnabled(false);
}
ui->advanced_option->setSshKeyOverrigingEnabled(!gcx->ssh_command.isEmpty());
}
EditRemoteDialog::~EditRemoteDialog()
{
delete ui;
}
-BasicMainWindow *EditRemoteDialog::mainwindow()
+MainWindow *EditRemoteDialog::mainwindow()
{
- return qobject_cast<BasicMainWindow *>(parent());
+ return qobject_cast<MainWindow *>(parent());
}
void EditRemoteDialog::setName(QString const &s) const
{
ui->lineEdit_name->setText(s);
}
void EditRemoteDialog::setUrl(QString const &s) const
{
ui->lineEdit_url->setText(s);
}
void EditRemoteDialog::setSshKey(QString const &s) const
{
ui->advanced_option->setSshKey(s);
}
QString EditRemoteDialog::name() const
{
return ui->lineEdit_name->text();
}
QString EditRemoteDialog::url() const
{
return ui->lineEdit_url->text();
}
QString EditRemoteDialog::sshKey() const
{
return ui->advanced_option->sshKey();
}
int EditRemoteDialog::exec()
{
if (ui->lineEdit_name->text().isEmpty()) {
ui->lineEdit_name->setFocus();
} else {
ui->lineEdit_url->setFocus();
}
return QDialog::exec();
}
void EditRemoteDialog::on_pushButton_test_clicked()
{
QString url = ui->lineEdit_url->text();
if (mainwindow()->testRemoteRepositoryValidity(url, sshKey())) {
ui->pushButton_ok->setFocus();
} else {
ui->lineEdit_url->setFocus();
}
}
diff --git a/src/EditRemoteDialog.h b/src/EditRemoteDialog.h
index 7b35e65..9bb1e00 100644
--- a/src/EditRemoteDialog.h
+++ b/src/EditRemoteDialog.h
@@ -1,39 +1,39 @@
#ifndef EDITREMOTEDIALOG_H
#define EDITREMOTEDIALOG_H
#include <QDialog>
#include "Git.h"
-class BasicMainWindow;
+class MainWindow;
namespace Ui {
class EditRemoteDialog;
}
class EditRemoteDialog : public QDialog {
Q_OBJECT
public:
enum Operation {
RemoteAdd,
RemoteSet,
};
private:
Ui::EditRemoteDialog *ui;
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
public:
- explicit EditRemoteDialog(BasicMainWindow *parent, Operation op, const Git::Context *gcx);
+ explicit EditRemoteDialog(MainWindow *parent, Operation op, const Git::Context *gcx);
~EditRemoteDialog() override;
void setName(QString const &s) const;
void setUrl(QString const &s) const;
void setSshKey(const QString &s) const;
QString name() const;
QString url() const;
QString sshKey() const;
int exec() override;
private slots:
void on_pushButton_test_clicked();
};
#endif // EDITREMOTEDIALOG_H
diff --git a/src/FileDiffWidget.cpp b/src/FileDiffWidget.cpp
index 604cd8e..e48fa2b 100644
--- a/src/FileDiffWidget.cpp
+++ b/src/FileDiffWidget.cpp
@@ -1,745 +1,745 @@
#include "ApplicationGlobal.h"
#include "BigDiffWindow.h"
#include "FileDiffWidget.h"
#include "GitDiff.h"
#include "MainWindow.h"
#include "Theme.h"
#include "common/joinpath.h"
#include "common/misc.h"
#include "ui_FileDiffWidget.h"
#include <QBuffer>
#include <QDebug>
#include <QKeyEvent>
#include <QMenu>
#include <QPainter>
#include <QStyle>
#include <QTextCodec>
#include <memory>
enum {
DiffIndexRole = Qt::UserRole,
};
struct FileDiffWidget::Private {
- BasicMainWindow *mainwindow = nullptr;
+ MainWindow *mainwindow = nullptr;
FileDiffWidget::InitParam_ init_param_;
Git::CommitItemList commit_item_list;
std::vector<std::string> original_lines;
TextEditorEnginePtr engine_left;
TextEditorEnginePtr engine_right;
TextDiffLineList left_lines;
TextDiffLineList right_lines;
int max_line_length = 0;
int term_cursor_row = 0;
int term_cursor_col = 0;
QTextCodec *text_codec = nullptr;
};
FileDiffWidget::FileDiffWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::FileDiffWidget)
, m(new Private)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
ui->widget_diff_slider->init([&](DiffPane pane, int width, int height){
return makeDiffPixmap(pane, width, height);
}, global->theme);
connect(ui->widget_diff_slider, &FileDiffSliderWidget::valueChanged, this, &FileDiffWidget::scrollTo);
connect(ui->widget_diff_left->texteditor(), &TextEditorWidget::moved, this, &FileDiffWidget::onMoved);
connect(ui->widget_diff_right->texteditor(), &TextEditorWidget::moved, this, &FileDiffWidget::onMoved);
setFocusAcceptable(Qt::ClickFocus);
QWidget::setTabOrder(ui->widget_diff_slider, ui->widget_diff_left);
QWidget::setTabOrder(ui->widget_diff_left, ui->widget_diff_right);
int n = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
ui->toolButton_fullscreen->setFixedSize(n, n);
setMaximizeButtonEnabled(true);
m->engine_left = std::make_shared<TextEditorEngine>();
m->engine_right = std::make_shared<TextEditorEngine>();
ui->widget_diff_left->setDiffMode(m->engine_left, ui->verticalScrollBar, ui->horizontalScrollBar);
ui->widget_diff_right->setDiffMode(m->engine_right, ui->verticalScrollBar, ui->horizontalScrollBar);
setViewType(FileViewType::None);
}
FileDiffWidget::~FileDiffWidget()
{
delete m;
delete ui;
}
void FileDiffWidget::setViewType(FileViewType type)
{
ui->widget_diff_left->setViewType(type);
ui->widget_diff_right->setViewType(type);
}
void FileDiffWidget::setMaximizeButtonEnabled(bool f)
{
ui->toolButton_fullscreen->setVisible(f);
ui->toolButton_fullscreen->setEnabled(f);
}
FileDiffWidget::ViewStyle FileDiffWidget::viewstyle() const
{
return m->init_param_.view_style;
}
-void FileDiffWidget::bind(BasicMainWindow *mw)
+void FileDiffWidget::bind(MainWindow *mw)
{
Q_ASSERT(mw);
m->mainwindow = mw;
ui->widget_diff_left->bind(mw, this, ui->verticalScrollBar, ui->horizontalScrollBar, mw->themeForTextEditor());
ui->widget_diff_right->bind(mw, this, ui->verticalScrollBar, ui->horizontalScrollBar, mw->themeForTextEditor());
connect(ui->verticalScrollBar, &QAbstractSlider::valueChanged, this, &FileDiffWidget::onVerticalScrollValueChanged);
connect(ui->horizontalScrollBar, &QAbstractSlider::valueChanged, this, &FileDiffWidget::onHorizontalScrollValueChanged);
}
-BasicMainWindow *FileDiffWidget::mainwindow()
+MainWindow *FileDiffWidget::mainwindow()
{
return m->mainwindow;
}
GitPtr FileDiffWidget::git()
{
if (!mainwindow()) {
qDebug() << "Maybe, you forgot to call FileDiffWidget::bind() ?";
return GitPtr();
}
return mainwindow()->git();
}
Git::Object FileDiffWidget::cat_file(GitPtr const &/*g*/, QString const &id)
{
return mainwindow()->cat_file(id);
}
int FileDiffWidget::totalTextLines() const
{
return m->engine_left->document.lines.size();
}
void FileDiffWidget::clearDiffView()
{
ui->widget_diff_slider->clear(false);
}
int FileDiffWidget::fileviewHeight() const
{
return ui->widget_diff_left->height();
}
void FileDiffWidget::resetScrollBarValue()
{
ui->verticalScrollBar->setValue(0);
ui->horizontalScrollBar->setValue(0);
}
void FileDiffWidget::scrollToBottom()
{
QScrollBar *sb = ui->verticalScrollBar;
sb->setValue(sb->maximum());
}
void FileDiffWidget::updateSliderCursor()
{
if (viewstyle() == SideBySideText) {
ui->widget_diff_slider->clear(true);
}
}
void FileDiffWidget::updateControls()
{
updateSliderCursor();
}
void FileDiffWidget::makeSideBySideDiffData(Git::Diff const &diff, std::vector<std::string> const &original_lines, TextDiffLineList *left_lines, TextDiffLineList *right_lines)
{
left_lines->clear();
right_lines->clear();
m->original_lines = original_lines;
size_t linenum = original_lines.size();
std::vector<HunkItem> hunks;
int number = 0;
for (auto it = diff.hunks.begin(); it != diff.hunks.end(); it++, number++) {
std::string at = it->at;
if (strncmp(at.c_str(), "@@ -", 4) == 0) {
size_t pos = 0;
size_t len = 0;
char const *p = at.c_str() + 4;
auto ParseNumber = [&](){
size_t v = 0;
while (isdigit(*p & 0xff)) {
v = v * 10 + (*p - '0');
p++;
}
return v;
};
pos = ParseNumber();
if (*p == ',') {
p++;
len = ParseNumber();
} else {
len = 1;
}
if (pos > 0) pos--;
HunkItem item;
item.hunk_number = number;
item.pos = pos;
item.len = len;
for (std::string const &line : it->lines) {
item.lines.push_back(line);
}
hunks.push_back(item);
}
}
std::sort(hunks.begin(), hunks.end(), [](HunkItem const &l, HunkItem const &r){
return l.pos + l.len < r.pos + r.len;
});
size_t h = hunks.size();
while (linenum > 0 || h > 0) {
while (h > 0) {
int hunk_number = h - 1;
HunkItem const &hi = hunks[hunk_number];
if (hi.pos + hi.len < linenum) {
break;
}
std::vector<TextDiffLine> tmp_left;
std::vector<TextDiffLine> tmp_right;
int minus = 0;
int plus = 0;
auto FlushBlank = [&](){
while (minus < plus) {
tmp_left.emplace_back();
minus++;
}
while (minus > plus) {
tmp_right.emplace_back();
plus++;
}
minus = plus = 0;
};
for (auto line : hi.lines) {
int c = line[0] & 0xff;
line = line.substr(1);
if (c == '-') {
minus++;
TextDiffLine l(line, TextDiffLine::Del);
l.hunk_number = hunk_number;
tmp_left.push_back(l);
} else if (c == '+') {
plus++;
TextDiffLine l(line, TextDiffLine::Add);
l.hunk_number = hunk_number;
tmp_right.push_back(l);
} else {
FlushBlank();
TextDiffLine l(line, TextDiffLine::Normal);
l.hunk_number = hunk_number;
tmp_left.push_back(l);
tmp_right.push_back(l);
}
}
FlushBlank();
auto ComplementNewLine = [](std::vector<TextDiffLine> *lines){
for (TextDiffLine &line : *lines) {
int n = line.text.size();
if (n > 0) {
int c = line.text[n - 1] & 0xff;
if (c != '\r' && c != '\n') {
line.text.push_back('\n');
}
}
}
};
ComplementNewLine(&tmp_left);
ComplementNewLine(&tmp_right);
for (auto it = tmp_left.rbegin(); it != tmp_left.rend(); it++) {
TextDiffLine l(*it);
if (m->text_codec) {
if (!l.text.isEmpty()) {
QString s = QString::fromUtf8(l.text.data(), l.text.size());
l.text = m->text_codec->fromUnicode(s);
}
}
left_lines->push_back(l);
}
for (auto it = tmp_right.rbegin(); it != tmp_right.rend(); it++) {
TextDiffLine l(*it);
if (m->text_codec) {
if (!l.text.isEmpty()) {
QString s = QString::fromUtf8(l.text.data(), l.text.size());
l.text = m->text_codec->fromUnicode(s);
}
}
right_lines->push_back(l);
}
linenum = hi.pos;
h--;
}
if (linenum > 0) {
linenum--;
if (linenum < (size_t)original_lines.size()) {
std::string line = original_lines[linenum];
left_lines->push_back(TextDiffLine(line, TextDiffLine::Normal));
right_lines->push_back(TextDiffLine(line, TextDiffLine::Normal));
}
}
}
std::reverse(left_lines->begin(), left_lines->end());
std::reverse(right_lines->begin(), right_lines->end());
}
void FileDiffWidget::setDiffText(Git::Diff const &diff, TextDiffLineList const &left, TextDiffLineList const &right)
{
m->max_line_length = 0;
enum Pane {
Left,
Right,
};
auto SetLineNumber = [&](TextDiffLineList const &lines, Pane pane, TextDiffLineList *out){
out->clear();
int linenum = 1;
for (TextDiffLine const &line : lines) {
TextDiffLine item = line;
switch (item.type) {
case TextDiffLine::Normal:
item.line_number = linenum++;
break;
case TextDiffLine::Add:
if (pane == Pane::Right) {
item.line_number = linenum++;
}
break;
case TextDiffLine::Del:
if (pane == Pane::Left) {
item.line_number = linenum++;
}
break;
default:
item.line_number = linenum; // 行番号は設定するが、インクリメントはしない
break;
}
out->push_back(item);
}
};
SetLineNumber(left, Pane::Left, &m->left_lines);
SetLineNumber(right, Pane::Right, &m->right_lines);
ui->widget_diff_left->setText(&m->left_lines, mainwindow(), diff.blob.a_id, diff.path);
ui->widget_diff_right->setText(&m->right_lines, mainwindow(), diff.blob.b_id, diff.path);
refrectScrollBar();
ui->widget_diff_slider->clear(true);
}
FileViewType FileDiffWidget::setupPreviewWidget()
{
clearDiffView();
QString mimetype_l = mainwindow()->determinFileType(m->init_param_.bytes_a, true);
QString mimetype_r = mainwindow()->determinFileType(m->init_param_.bytes_b, true);
if (misc::isImage(mimetype_l) || misc::isImage(mimetype_r)) { // image
ui->verticalScrollBar->setVisible(false);
ui->horizontalScrollBar->setVisible(false);
ui->widget_diff_slider->setVisible(false);
ui->widget_diff_left->setImage(mimetype_l, m->init_param_.bytes_a, m->init_param_.diff.blob.a_id, m->init_param_.diff.path);
ui->widget_diff_right->setImage(mimetype_r, m->init_param_.bytes_b, m->init_param_.diff.blob.b_id, m->init_param_.diff.path);
return FileViewType::Image;
} else { // text
ui->verticalScrollBar->setVisible(true);
ui->horizontalScrollBar->setVisible(true);
ui->widget_diff_slider->setVisible(true);
setViewType(FileViewType::Text);
return FileViewType::Text;
}
}
void FileDiffWidget::setSingleFile(QByteArray const &ba, QString const &id, QString const &path)
{
m->init_param_ = InitParam_();
m->init_param_.view_style = FileDiffWidget::ViewStyle::SingleFile;
m->init_param_.bytes_a = ba;
m->init_param_.diff.path = path;
m->init_param_.diff.blob.a_id = id;
}
void FileDiffWidget::setOriginalLines_(QByteArray const &ba)
{
m->original_lines.clear();
if (!ba.isEmpty()) {
char const *begin = ba.data();
char const *end = begin + ba.size();
misc::splitLines(begin, end, &m->original_lines, true);
}
}
void FileDiffWidget::setLeftOnly(QByteArray const &ba, Git::Diff const &diff)
{
m->init_param_ = InitParam_();
m->init_param_.view_style = FileDiffWidget::ViewStyle::LeftOnly;
m->init_param_.bytes_a = ba;
m->init_param_.diff = diff;
setOriginalLines_(ba);
if (setupPreviewWidget() == FileViewType::Text) {
TextDiffLineList left_lines;
TextDiffLineList right_lines;
for (std::string const &line : m->original_lines) {
left_lines.push_back(TextDiffLine(line, TextDiffLine::Del));
right_lines.push_back(TextDiffLine());
}
setDiffText(diff, left_lines, right_lines);
}
}
void FileDiffWidget::setRightOnly(QByteArray const &ba, Git::Diff const &diff)
{
m->init_param_ = InitParam_();
m->init_param_.view_style = FileDiffWidget::ViewStyle::RightOnly;
m->init_param_.bytes_b = ba;
m->init_param_.diff = diff;
setOriginalLines_(ba);
if (setupPreviewWidget() == FileViewType::Text) {
TextDiffLineList left_lines;
TextDiffLineList right_lines;
for (std::string const &line : m->original_lines) {
left_lines.push_back(TextDiffLine());
right_lines.push_back(TextDiffLine(line, TextDiffLine::Add));
}
setDiffText(diff, left_lines, right_lines);
}
}
void FileDiffWidget::setSideBySide(QByteArray const &ba, Git::Diff const &diff, bool uncommited, QString const &workingdir)
{
m->init_param_ = InitParam_();
m->init_param_.view_style = FileDiffWidget::ViewStyle::SideBySideText;
m->init_param_.bytes_a = ba;
m->init_param_.diff = diff;
m->init_param_.uncommited = uncommited;
m->init_param_.workingdir = workingdir;
setOriginalLines_(ba);
if (setupPreviewWidget() == FileViewType::Text) {
TextDiffLineList left_lines;
TextDiffLineList right_lines;
makeSideBySideDiffData(diff, m->original_lines, &left_lines, &right_lines);
setDiffText(diff, left_lines, right_lines);
}
}
void FileDiffWidget::setSideBySide_(QByteArray const &ba_a, QByteArray const &ba_b, QString const &workingdir)
{
m->init_param_ = InitParam_();
m->init_param_.view_style = FileDiffWidget::ViewStyle::SideBySideImage;
m->init_param_.bytes_a = ba_a;
m->init_param_.bytes_b = ba_b;
m->init_param_.workingdir = workingdir;
setOriginalLines_(ba_a);
if (setupPreviewWidget() == FileViewType::Text) {
TextDiffLineList left_lines;
TextDiffLineList right_lines;
makeSideBySideDiffData(m->init_param_.diff, m->original_lines, &left_lines, &right_lines);
setDiffText(m->init_param_.diff, left_lines, right_lines);
}
}
QString FileDiffWidget::diffObjects(GitPtr const &g, QString const &a_id, QString const &b_id)
{
if (m->text_codec) {
Git::Object obj_a = mainwindow()->cat_file_(g, a_id);
Git::Object obj_b = mainwindow()->cat_file_(g, b_id);
if (obj_b.type == Git::Object::Type::UNKNOWN) {
obj_b.type = Git::Object::Type::BLOB;
}
if (obj_a.type == Git::Object::Type::BLOB && obj_b.type == Git::Object::Type::BLOB) {
QString path_a = mainwindow()->newTempFilePath();
QString path_b = mainwindow()->newTempFilePath();
QFile file_a(path_a);
QFile file_b(path_b);
if (file_a.open(QFile::WriteOnly) && file_b.open(QFile::WriteOnly)) {
file_a.write(m->text_codec->toUnicode(obj_a.content).toUtf8());
file_b.write(m->text_codec->toUnicode(obj_b.content).toUtf8());
file_a.close();
file_b.close();
QString s = g->diff_file(path_a, path_b);
file_a.remove();
file_b.remove();
return s;
}
}
}
return GitDiff::diffObjects(g, a_id, b_id);
}
bool FileDiffWidget::isValidID_(QString const &id)
{
if (id.startsWith(PATH_PREFIX)) {
return true;
}
return Git::isValidID(id);
}
void FileDiffWidget::updateDiffView(Git::Diff const &info, bool uncommited)
{
GitPtr g = git();
if (!g) return;
if (!g->isValidWorkingCopy()) return;
if (isValidID_(info.blob.a_id) && isValidID_(info.blob.b_id)) {
Git::Object obj_a = cat_file(g, info.blob.a_id);
Git::Object obj_b = cat_file(g, info.blob.b_id);
QString mime_a = mainwindow()->determinFileType(obj_a.content, true);
QString mime_b = mainwindow()->determinFileType(obj_b.content, true);
if (misc::isImage(mime_a) && misc::isImage(mime_b)) {
setSideBySide_(obj_a.content, obj_b.content, g->workingRepositoryDir());
return;
}
}
{
Git::Diff diff;
if (isValidID_(info.blob.a_id) && isValidID_(info.blob.b_id)) {
std::string text = diffObjects(g, info.blob.a_id, info.blob.b_id).toStdString();
GitDiff::parseDiff(text, &info, &diff);
} else {
diff = info;
}
Git::Object obj;
if (isValidID_(diff.blob.a_id)) { // 左が有効
obj = cat_file(g, diff.blob.a_id);
if (isValidID_(diff.blob.b_id)) { // 右が有効
setSideBySide(obj.content, diff, uncommited, g->workingRepositoryDir()); // 通常のdiff表示
} else {
setLeftOnly(obj.content, diff); // 右が無効の時は、削除されたファイル
}
} else if (isValidID_(diff.blob.b_id)) { // 左が無効で右が有効の時は、追加されたファイル
obj = cat_file(g, diff.blob.b_id);
setRightOnly(obj.content, diff);
}
}
}
void FileDiffWidget::updateDiffView(QString const &id_left, QString const &id_right, QString const &path)
{
GitPtr g = git();
if (!g) return;
if (!g->isValidWorkingCopy()) return;
Git::Diff diff;
diff.path = path;
diff.blob.a_id = id_left;
diff.blob.b_id = id_right;
diff.mode = "0";
std::string text = diffObjects(g, diff.blob.a_id, diff.blob.b_id).toStdString();
GitDiff::parseDiff(text, &diff, &diff);
Git::Object obj = cat_file(g, diff.blob.a_id);
setSideBySide(obj.content, diff, false, g->workingRepositoryDir());
ui->widget_diff_slider->clear(false);
resetScrollBarValue();
updateControls();
ui->widget_diff_slider->update();
}
void FileDiffWidget::resizeEvent(QResizeEvent *)
{
refrectScrollBar();
}
void FileDiffWidget::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape) {
event->ignore(); // Escが押されたとき、親ウィジェットに処理させる。(通常、ウィンドウを閉じる、など)
return;
}
if (focusWidget() == ui->widget_diff_left->texteditor()) {
ui->widget_diff_left->write(event);
} else if (focusWidget() == ui->widget_diff_right->texteditor()) {
ui->widget_diff_right->write(event);
}
}
void FileDiffWidget::scrollTo(int value)
{
ui->verticalScrollBar->setValue(value);
}
void FileDiffWidget::onVerticalScrollValueChanged(int)
{
refrectScrollBar();
}
void FileDiffWidget::onHorizontalScrollValueChanged(int)
{
refrectScrollBar();
}
void FileDiffWidget::onDiffWidgetWheelScroll(int lines)
{
while (lines > 0) {
ui->verticalScrollBar->triggerAction(QScrollBar::SliderSingleStepAdd);
lines--;
}
while (lines < 0) {
ui->verticalScrollBar->triggerAction(QScrollBar::SliderSingleStepSub);
lines++;
}
}
void FileDiffWidget::onScrollValueChanged2(int value)
{
ui->verticalScrollBar->setValue(value);
}
void FileDiffWidget::onDiffWidgetResized()
{
updateControls();
}
void FileDiffWidget::on_toolButton_fullscreen_clicked()
{
if (m->init_param_.diff.blob.a_id.isEmpty() && m->init_param_.diff.blob.b_id.isEmpty()) {
return;
}
BigDiffWindow win(mainwindow());
win.setWindowState(Qt::WindowMaximized);
win.init(mainwindow(), m->init_param_);
win.exec();
}
void FileDiffWidget::setFocusAcceptable(Qt::FocusPolicy focuspolicy)
{
// Qt::FocusPolicy focuspolicy = f ? Qt::ClickFocus : Qt::NoFocus;
ui->widget_diff_left->setFocusPolicy(focuspolicy);
ui->widget_diff_right->setFocusPolicy(focuspolicy);
}
void FileDiffWidget::onUpdateSliderBar()
{
int total = m->engine_left->document.lines.size();
int value = ui->verticalScrollBar->value();
int page = ui->verticalScrollBar->pageStep();
ui->widget_diff_slider->setScrollPos(total, value, page);
}
void FileDiffWidget::refrectScrollBar()
{
ui->widget_diff_left->refrectScrollBar();
ui->widget_diff_right->refrectScrollBar();
onUpdateSliderBar();
}
QPixmap FileDiffWidget::makeDiffPixmap(DiffPane pane, int width, int height)
{
auto Do = [&](TextDiffLineList const &lines){
return FileDiffSliderWidget::makeDiffPixmap(width, height, lines, global->theme);
};
if (pane == DiffPane::Left) return Do(m->left_lines);
if (pane == DiffPane::Right) return Do(m->right_lines);
return QPixmap();
}
void FileDiffWidget::onMoved(int cur_row, int cur_col, int scr_row, int scr_col)
{
(void)cur_col;
(void)cur_row;
ui->widget_diff_left->move(-1, -1, scr_row, scr_col, false);
ui->widget_diff_right->move(-1, -1, scr_row, scr_col, false);
refrectScrollBar();
onUpdateSliderBar();
}
void FileDiffWidget::setTextCodec(QTextCodec *codec)
{
m->text_codec = codec;
ui->widget_diff_left->setTextCodec(codec);
ui->widget_diff_right->setTextCodec(codec);
emit textcodecChanged();
}
void FileDiffWidget::setTextCodec(char const *name)
{
QTextCodec *codec = name ? QTextCodec::codecForName(name) : nullptr;
setTextCodec(codec);
}
void FileDiffWidget::on_toolButton_menu_clicked()
{
QMenu menu;
QAction *a_utf8 = menu.addAction("UTF-8");
QAction *a_sjis = menu.addAction("SJIS (CP932)");
QAction *a_eucjp = menu.addAction("EUC-JP");
QAction *a_iso2022jp = menu.addAction("JIS (ISO-2022-JP)");
QAction *a = menu.exec(QCursor::pos() + QPoint(8, -8));
if (a) {
if (a == a_utf8) {
setTextCodec((char const *)nullptr);
return;
}
if (a == a_sjis) {
setTextCodec("Shift_JIS");
return;
}
if (a == a_eucjp) {
setTextCodec("EUC-JP");
return;
}
if (a == a_iso2022jp) {
setTextCodec("ISO-2022-JP");
return;
}
}
}
diff --git a/src/FileDiffWidget.h b/src/FileDiffWidget.h
index 8fb0e52..e685a5d 100644
--- a/src/FileDiffWidget.h
+++ b/src/FileDiffWidget.h
@@ -1,167 +1,167 @@
#ifndef FILEDIFFWIDGET_H
#define FILEDIFFWIDGET_H
#include "FileDiffSliderWidget.h"
#include "FileViewWidget.h"
#include "Git.h"
#include "MainWindow.h"
#include "texteditor/AbstractCharacterBasedApplication.h"
#include <QDialog>
#include <memory>
namespace Ui {
class FileDiffWidget;
}
enum class ViewType {
None,
Left,
Right
};
using TextDiffLine = Document::Line;
using TextDiffLineList = QList<Document::Line>;
struct ObjectContent {
QString id;
QString path;
QByteArray bytes;
TextDiffLineList lines;
};
using ObjectContentPtr = std::shared_ptr<ObjectContent>;
class QTableWidgetItem;
class FileDiffWidget : public QWidget {
Q_OBJECT
friend class BigDiffWindow;
public:
struct DiffData {
ObjectContentPtr left;
ObjectContentPtr right;
std::vector<std::string> original_lines;
DiffData()
{
clear();
}
void clear()
{
left = std::make_shared<ObjectContent>();
right = std::make_shared<ObjectContent>();
original_lines.clear();
}
};
struct DrawData {
int v_scroll_pos = 0;
int h_scroll_pos = 0;
int char_width = 0;
int line_height = 0;
QColor bgcolor_text;
QColor bgcolor_add;
QColor bgcolor_del;
QColor bgcolor_add_dark;
QColor bgcolor_del_dark;
QColor bgcolor_gray;
QWidget *forcus = nullptr;
DrawData();
};
enum ViewStyle {
None,
SingleFile,
LeftOnly,
RightOnly,
SideBySideText,
SideBySideImage,
};
private:
Ui::FileDiffWidget *ui;
struct Private;
Private *m;
struct InitParam_ {
ViewStyle view_style = ViewStyle::None;
QByteArray bytes_a;
QByteArray bytes_b;
Git::Diff diff;
bool uncommited = false;
QString workingdir;
};
ViewStyle viewstyle() const;
GitPtr git();
Git::Object cat_file(const GitPtr &g, QString const &id);
int totalTextLines() const;
void resetScrollBarValue();
void updateSliderCursor();
int fileviewHeight() const;
void setDiffText(const Git::Diff &diff, TextDiffLineList const &left, TextDiffLineList const &right);
void setLeftOnly(QByteArray const &ba, const Git::Diff &diff);
void setRightOnly(QByteArray const &ba, const Git::Diff &diff);
void setSideBySide(QByteArray const &ba, const Git::Diff &diff, bool uncommited, QString const &workingdir);
void setSideBySide_(QByteArray const &ba_a, QByteArray const &ba_b, QString const &workingdir);
bool isValidID_(QString const &id);
FileViewType setupPreviewWidget();
void makeSideBySideDiffData(const Git::Diff &diff, const std::vector<std::string> &original_lines, TextDiffLineList *left_lines, TextDiffLineList *right_lines);
void onUpdateSliderBar();
void refrectScrollBar();
void setOriginalLines_(QByteArray const &ba);
QString diffObjects(const GitPtr &g, QString const &a_id, QString const &b_id);
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
protected:
void resizeEvent(QResizeEvent *) override;
void keyPressEvent(QKeyEvent *event) override;
public:
explicit FileDiffWidget(QWidget *parent = nullptr);
~FileDiffWidget() override;
- void bind(BasicMainWindow *mw);
+ void bind(MainWindow *mw);
void clearDiffView();
void setSingleFile(QByteArray const &ba, QString const &id, QString const &path);
void updateControls();
void scrollToBottom();
void updateDiffView(const Git::Diff &info, bool uncommited);
void updateDiffView(const QString &id_left, const QString &id_right, QString const &path = QString());
void setMaximizeButtonEnabled(bool f);
void setFocusAcceptable(Qt::FocusPolicy focuspolicy);
QPixmap makeDiffPixmap(DiffPane pane, int width, int height);
void setViewType(FileViewType type);
void setTextCodec(QTextCodec *codec);
void setTextCodec(char const *name);
private slots:
void onVerticalScrollValueChanged(int);
void onHorizontalScrollValueChanged(int);
void onDiffWidgetWheelScroll(int lines);
void onScrollValueChanged2(int value);
void onDiffWidgetResized();
void on_toolButton_fullscreen_clicked();
void scrollTo(int value);
void onMoved(int cur_row, int cur_col, int scr_row, int scr_col);
void on_toolButton_menu_clicked();
signals:
// void moveNextItem();
// void movePreviousItem();
void textcodecChanged();
};
#endif // FILEDIFFWIDGET_H
diff --git a/src/FileHistoryWindow.cpp b/src/FileHistoryWindow.cpp
index 9292c58..38e0de2 100644
--- a/src/FileHistoryWindow.cpp
+++ b/src/FileHistoryWindow.cpp
@@ -1,250 +1,250 @@
#include "FileHistoryWindow.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "FileDiffWidget.h"
#include "GitDiff.h"
#include "MyTableWidgetDelegate.h"
#include "common/joinpath.h"
#include "common/misc.h"
#include "ui_FileHistoryWindow.h"
#include <QMenu>
#include <QPainter>
#include <QStyledItemDelegate>
#include <QThread>
struct FileHistoryWindow::Private {
GitPtr g;
QString path;
Git::CommitItemList commit_item_list;
FileDiffWidget::DiffData diff_data;
FileDiffWidget::DrawData draw_data;
};
FileDiffWidget::DiffData *FileHistoryWindow::diffdata()
{
return &m->diff_data;
}
const FileDiffWidget::DiffData *FileHistoryWindow::diffdata() const
{
return &m->diff_data;
}
FileDiffWidget::DrawData *FileHistoryWindow::drawdata()
{
return &m->draw_data;
}
const FileDiffWidget::DrawData *FileHistoryWindow::drawdata() const
{
return &m->draw_data;
}
int FileHistoryWindow::totalTextLines() const
{
return diffdata()->left->lines.size();
}
int FileHistoryWindow::fileviewScrollPos() const
{
return drawdata()->v_scroll_pos;
}
FileHistoryWindow::FileHistoryWindow(BasicMainWindow *parent)
: QDialog(parent)
, ui(new Ui::FileHistoryWindow)
, m(new Private)
{
ui->setupUi(this);
ui->tableWidget_log->setItemDelegate(new MyTableWidgetDelegate(this));
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
flags |= Qt::WindowMaximizeButtonHint;
setWindowFlags(flags);
ui->splitter->setSizes({100, 200});
ui->widget_diff_view->bind(mainwindow());
// connect(ui->widget_diff_view, &FileDiffWidget::moveNextItem, this, &FileHistoryWindow::onMoveNextItem);
// connect(ui->widget_diff_view, &FileDiffWidget::movePreviousItem, this, &FileHistoryWindow::onMovePreviousItem);
}
FileHistoryWindow::~FileHistoryWindow()
{
delete m;
delete ui;
}
-BasicMainWindow *FileHistoryWindow::mainwindow()
+MainWindow *FileHistoryWindow::mainwindow()
{
- return qobject_cast<BasicMainWindow *>(parent());
+ return qobject_cast<MainWindow *>(parent());
}
void FileHistoryWindow::prepare(GitPtr const &g, QString const &path)
{
Q_ASSERT(g);
Q_ASSERT(g->isValidWorkingCopy());
this->m->g = g;
this->m->path = path;
QString reponame = mainwindow()->currentRepositoryName();
QString brname = mainwindow()->currentBranch().name;
QString text = "%1 (%2)";
text = text.arg(reponame).arg(brname);
ui->label_repo->setText(text);
ui->label_path->setText(path);
{
OverrideWaitCursor;
m->commit_item_list = m->g->log_all(m->path, mainwindow()->limitLogCount());
}
collectFileHistory();
updateDiffView();
}
void FileHistoryWindow::collectFileHistory()
{
QStringList cols = {
tr("Commit"),
tr("Date"),
tr("Author"),
tr("Message"),
};
int n = cols.size();
ui->tableWidget_log->setColumnCount(n);
ui->tableWidget_log->setRowCount(0);
for (int i = 0; i < n; i++) {
QString const &text = cols[i];
auto *item = new QTableWidgetItem(text);
ui->tableWidget_log->setHorizontalHeaderItem(i, item);
}
int count = m->commit_item_list.size();
ui->tableWidget_log->setRowCount(count);
for (int row = 0; row < count; row++) {
Git::CommitItem const &commit = m->commit_item_list[row];
int col = 0;
auto AddColumn = [&](QString const &text, QString const &tooltip){
auto *item = new QTableWidgetItem(text);
item->setToolTip(tooltip);
ui->tableWidget_log->setItem(row, col, item);
col++;
};
- QString commit_id = BasicMainWindow::abbrevCommitID(commit);
+ QString commit_id = MainWindow::abbrevCommitID(commit);
QString datetime = misc::makeDateTimeString(commit.commit_date);
AddColumn(commit_id, QString());
AddColumn(datetime, QString());
AddColumn(commit.author, QString());
AddColumn(commit.message, commit.message);
ui->tableWidget_log->setRowHeight(row, 24);
}
ui->tableWidget_log->resizeColumnsToContents();
ui->tableWidget_log->horizontalHeader()->setStretchLastSection(false);
ui->tableWidget_log->horizontalHeader()->setStretchLastSection(true);
ui->tableWidget_log->setFocus();
ui->tableWidget_log->setCurrentCell(0, 0);
}
class FindFileIdThread : public QThread {
private:
- BasicMainWindow *mainwindow;
+ MainWindow *mainwindow;
GitPtr g;
QString commit_id;
QString file;
public:
QString result;
- FindFileIdThread(BasicMainWindow *BasicMainWindow, GitPtr const &g, QString const &commit_id, QString const &file)
+ FindFileIdThread(MainWindow *mw, GitPtr const &g, QString const &commit_id, QString const &file)
{
- this->mainwindow = BasicMainWindow;
+ this->mainwindow = mw;
this->g = g;
this->commit_id = commit_id;
this->file = file;
}
protected:
void run() override
{
result = mainwindow->findFileID(commit_id, file);
}
};
void FileHistoryWindow::updateDiffView()
{
Q_ASSERT(m->g);
Q_ASSERT(m->g->isValidWorkingCopy());
ui->widget_diff_view->clearDiffView();
int row = ui->tableWidget_log->currentRow();
if (row >= 0 && row + 1 < (int)m->commit_item_list.size()) {
Git::CommitItem const &commit_left = m->commit_item_list[row + 1]; // older
Git::CommitItem const &commit_right = m->commit_item_list[row]; // newer
FindFileIdThread left_thread(mainwindow(), m->g->dup(), commit_left.commit_id, m->path);
FindFileIdThread right_thread(mainwindow(), m->g->dup(), commit_right.commit_id, m->path);
left_thread.start();
right_thread.start();
left_thread.wait();
right_thread.wait();
QString id_left = left_thread.result;
QString id_right = right_thread.result;
ui->widget_diff_view->updateDiffView(id_left, id_right, m->path);
} else if (row >= 0 && row < (int)m->commit_item_list.size()) {
Git::CommitItem const &commit = m->commit_item_list[row]; // newer
QString id = mainwindow()->findFileID(commit.commit_id, m->path);
Git::Diff diff(id, m->path, QString());
ui->widget_diff_view->updateDiffView(diff, false);
}
}
void FileHistoryWindow::on_tableWidget_log_currentItemChanged(QTableWidgetItem * /*current*/, QTableWidgetItem * /*previous*/)
{
updateDiffView();
}
//void FileHistoryWindow::onMoveNextItem()
//{
// int row = ui->tableWidget_log->currentRow();
// int count = ui->tableWidget_log->rowCount();
// if (row + 1 < count) {
// ui->tableWidget_log->setCurrentCell(row + 1, 0, QItemSelectionModel::ClearAndSelect);
// }
//}
//void FileHistoryWindow::onMovePreviousItem()
//{
// int row = ui->tableWidget_log->currentRow();
// if (row > 0) {
// ui->tableWidget_log->setCurrentCell(row - 1, 0, QItemSelectionModel::ClearAndSelect);
// }
//}
void FileHistoryWindow::on_tableWidget_log_customContextMenuRequested(const QPoint &pos)
{
(void)pos;
Git::CommitItem const *commit = nullptr;
int row = ui->tableWidget_log->currentRow();
if (row >= 0 && row < (int)m->commit_item_list.size()) {
commit = &m->commit_item_list[row];
}
if (!commit) return;
QMenu menu;
QAction *a_property = mainwindow()->addMenuActionProperty(&menu);
QAction *a = menu.exec(QCursor::pos() + QPoint(8, -8));
if (a) {
if (a == a_property) {
mainwindow()->execCommitPropertyDialog(this, commit);
return;
}
}
}
diff --git a/src/FileHistoryWindow.h b/src/FileHistoryWindow.h
index 433213c..bb19c37 100644
--- a/src/FileHistoryWindow.h
+++ b/src/FileHistoryWindow.h
@@ -1,48 +1,48 @@
#ifndef FILEHISTORYWINDOW_H
#define FILEHISTORYWINDOW_H
#include <QDialog>
#include "Git.h"
#include "BasicMainWindow.h"
#include "FileDiffWidget.h"
namespace Ui {
class FileHistoryWindow;
}
class BasicMainWindow;
class QTableWidgetItem;
class FileHistoryWindow : public QDialog {
Q_OBJECT
private:
struct Private;
Private *m;
FileDiffWidget::DiffData *diffdata();
FileDiffWidget::DiffData const *diffdata() const;
FileDiffWidget::DrawData *drawdata();
FileDiffWidget::DrawData const *drawdata() const;
int totalTextLines() const;
int fileviewScrollPos() const;
public:
explicit FileHistoryWindow(BasicMainWindow *parent);
~FileHistoryWindow() override;
void prepare(const GitPtr &g, QString const &path);
private slots:
void on_tableWidget_log_currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous);
// void onMoveNextItem();
// void onMovePreviousItem();
void on_tableWidget_log_customContextMenuRequested(const QPoint &pos);
private:
Ui::FileHistoryWindow *ui;
void collectFileHistory();
void updateDiffView();
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
};
#endif // FILEHISTORYWINDOW_H
diff --git a/src/FilePropertyDialog.cpp b/src/FilePropertyDialog.cpp
index cd9cf07..17b513d 100644
--- a/src/FilePropertyDialog.cpp
+++ b/src/FilePropertyDialog.cpp
@@ -1,30 +1,30 @@
#include "FilePropertyDialog.h"
#include "MainWindow.h"
#include "ui_FilePropertyDialog.h"
#include "main.h"
FilePropertyDialog::FilePropertyDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::FilePropertyDialog)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
}
FilePropertyDialog::~FilePropertyDialog()
{
delete ui;
}
-void FilePropertyDialog::exec(BasicMainWindow *mw, QString const &path, QString const &id)
+void FilePropertyDialog::exec(MainWindow *mw, QString const &path, QString const &id)
{
mainwindow = mw;
ui->lineEdit_repo->setText(mainwindow->currentRepositoryName());
ui->lineEdit_path->setText(path);
ui->lineEdit_id->setText(id);
QDialog::exec();
}
diff --git a/src/FilePropertyDialog.h b/src/FilePropertyDialog.h
index 11a71b6..2e8974e 100644
--- a/src/FilePropertyDialog.h
+++ b/src/FilePropertyDialog.h
@@ -1,25 +1,25 @@
#ifndef FILEPROPERTYDIALOG_H
#define FILEPROPERTYDIALOG_H
#include <QDialog>
namespace Ui {
class FilePropertyDialog;
}
-class BasicMainWindow;
+class MainWindow;
class FilePropertyDialog : public QDialog {
Q_OBJECT
private:
- BasicMainWindow *mainwindow;
+ MainWindow *mainwindow;
public:
explicit FilePropertyDialog(QWidget *parent = nullptr);
~FilePropertyDialog() override;
- void exec(BasicMainWindow *mw, QString const &path, QString const &id);
+ void exec(MainWindow *mw, QString const &path, QString const &id);
private:
Ui::FilePropertyDialog *ui;
};
#endif // FILEPROPERTYDIALOG_H
diff --git a/src/FileViewWidget.cpp b/src/FileViewWidget.cpp
index bfc4d61..465c799 100644
--- a/src/FileViewWidget.cpp
+++ b/src/FileViewWidget.cpp
@@ -1,170 +1,170 @@
#include "FileViewWidget.h"
#include "common/misc.h"
#include <QMenu>
#include <QPainter>
#include <QStackedWidget>
#include <QVBoxLayout>
FileViewWidget::FileViewWidget(QWidget *parent)
: QWidget(parent)
{
setObjectName(QStringLiteral("FileViewWidget"));
ui_verticalLayout = new QVBoxLayout(this);
ui_verticalLayout->setSpacing(0);
ui_verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
ui_verticalLayout->setContentsMargins(0, 0, 0, 0);
ui_stackedWidget = new QStackedWidget(this);
ui_stackedWidget->setObjectName(QStringLiteral("stackedWidget"));
ui_page_none = new QWidget();
ui_page_none->setObjectName(QStringLiteral("page_none"));
ui_stackedWidget->addWidget(ui_page_none);
ui_page_text = new X_TextEditorWidget();
ui_page_text->setObjectName(QStringLiteral("page_text"));
ui_page_text->setFocusPolicy(Qt::ClickFocus);
ui_stackedWidget->addWidget(ui_page_text);
ui_page_image = new X_ImageViewWidget();
ui_page_image->setObjectName(QStringLiteral("page_image"));
ui_page_image->setFocusPolicy(Qt::ClickFocus);
ui_stackedWidget->addWidget(ui_page_image);
ui_verticalLayout->addWidget(ui_stackedWidget);
setWindowTitle(QApplication::translate("FileViewWidget", "Form", Q_NULLPTR));
ui_stackedWidget->setCurrentIndex(1);
QMetaObject::connectSlotsByName(this);
ui_page_text->setRenderingMode(TextEditorWidget::DecoratedMode);
ui_page_text->setTheme(TextEditorTheme::Light());
ui_page_text->showHeader(false);
ui_page_text->showFooter(false);
ui_page_text->setAutoLayout(true);
ui_page_text->setReadOnly(true);
ui_page_text->setToggleSelectionAnchorEnabled(false);
ui_page_text->setFocusFrameVisible(true);
ui_stackedWidget->setCurrentWidget(ui_page_none);
}
void FileViewWidget::setTextCodec(QTextCodec *codec)
{
ui_page_text->setTextCodec(codec);
}
void FileViewWidget::bind(QMainWindow *mw, FileDiffWidget *fdw, QScrollBar *vsb, QScrollBar *hsb, TextEditorThemePtr const &theme)
{
ui_page_text->bindScrollBar(vsb, hsb);
ui_page_image->bind(mw, fdw, vsb, hsb);
ui_page_text->setTheme(theme);
}
void FileViewWidget::setViewType(FileViewType type)
{
view_type = type;
switch (view_type) {
case FileViewType::Text:
ui_stackedWidget->setCurrentWidget(ui_page_text);
return;
case FileViewType::Image:
ui_stackedWidget->setCurrentWidget(ui_page_image);
return;
default:
ui_stackedWidget->setCurrentWidget(ui_page_none);
return;
}
}
const TextEditorTheme *FileViewWidget::theme() const
{
return ui_page_text->theme();
}
//int FileViewWidget::latin1Width(QString const &s) const
//{
// return ui_page_text->latin1Width(s);
//}
int FileViewWidget::lineHeight() const
{
return ui_page_text->lineHeight();
}
void FileViewWidget::setDiffMode(TextEditorEnginePtr const &editor_engine, QScrollBar *vsb, QScrollBar *hsb)
{
ui_page_text->setTextEditorEngine(editor_engine);
return ui_page_text->bindScrollBar(vsb, hsb);
}
void FileViewWidget::refrectScrollBar()
{
switch (view_type) {
case FileViewType::Text:
ui_page_text->refrectScrollBar();
return;
case FileViewType::Image:
ui_page_image->refrectScrollBar();
return;
}
}
void FileViewWidget::move(int cur_row, int cur_col, int scr_row, int scr_col, bool auto_scroll)
{
return ui_page_text->move(cur_row, cur_col, scr_row, scr_col, auto_scroll);
}
void FileViewWidget::setImage(QString const &mimetype, QByteArray const &ba, QString const &object_id, QString const &path)
{
setViewType(FileViewType::Image);
this->source_id = object_id;
#ifdef APP_GUITAR
ui_page_image->setImage(mimetype, ba, object_id, path);
#else
ui_page_image->setImage(mimetype, ba);
#endif
}
void FileViewWidget::setText(const QList<Document::Line> *source, QMainWindow *mw, QString const &object_id, QString const &object_path)
{
setViewType(FileViewType::Text);
this->source_id = object_id;
#ifdef APP_GUITAR
- ui_page_text->setDocument(source, qobject_cast<BasicMainWindow *>(mw), object_id, object_path);
+ ui_page_text->setDocument(source, qobject_cast<MainWindow *>(mw), object_id, object_path);
scrollToTop();
texteditor()->moveCursorOut(); // 現在行を -1 にして、カーソルを非表示にする。
#else
ui_page_text->setDocument(source);
scrollToTop();
#endif
}
void FileViewWidget::setText(QByteArray const &ba, QMainWindow *mw, QString const &object_id, QString const &object_path)
{
std::vector<std::string> lines;
char const *begin = ba.data();
char const *end = begin + ba.size();
misc::splitLines(begin, end, &lines, true);
QList<Document::Line> source;
source.reserve(lines.size());
int num = 0;
for (std::string const &line : lines) {
Document::Line t(line);
t.line_number = ++num;
source.push_back(t);
}
setText(&source, mw, object_id, object_path);
}
void FileViewWidget::scrollToTop()
{
ui_page_text->scrollToTop();
}
void FileViewWidget::write(QKeyEvent *e)
{
ui_page_text->write(e);
}
TextEditorWidget *FileViewWidget::texteditor()
{
return ui_page_text;
}
diff --git a/src/GitHubAPI.cpp b/src/GitHubAPI.cpp
index 8561746..1771988 100644
--- a/src/GitHubAPI.cpp
+++ b/src/GitHubAPI.cpp
@@ -1,109 +1,109 @@
#include "GitHubAPI.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "MemoryReader.h"
#include "charvec.h"
#include "common/misc.h"
#include "urlencode.h"
#include "webclient.h"
#include <QDebug>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <memory>
using WebClientPtr = GitHubAPI::WebClientPtr;
struct GitHubRequestThread::Private {
- BasicMainWindow *mainwindow = nullptr;
+ MainWindow *mainwindow = nullptr;
WebClientPtr web;
};
GitHubRequestThread::GitHubRequestThread()
: m(new Private)
{
}
GitHubRequestThread::~GitHubRequestThread()
{
delete m;
}
-void GitHubRequestThread::start(BasicMainWindow *mainwindow)
+void GitHubRequestThread::start(MainWindow *mainwindow)
{
m->mainwindow = mainwindow;
m->web = std::make_shared<WebClient>(m->mainwindow->webContext());
QThread::start();
}
void GitHubRequestThread::run()
{
ok = false;
if (web()->get(WebClient::Request(url)) == 200) {
WebClient::Response const &r = web()->response();
if (!r.content.empty()) {
text = to_stdstr(r.content);
ok = true;
if (callback) {
ok = callback(text);
}
}
} else {
std::string msg = web()->error().message();
if (!msg.empty()) {
m->mainwindow->emitWriteLog(QString::fromStdString("Failed to access the site: " + url + '\n').toUtf8());
QString s = QString::fromStdString(msg + '\n');
m->mainwindow->emitWriteLog(s.toUtf8());
}
}
}
GitHubAPI::WebClientPtr GitHubRequestThread::web()
{
return m->web;
}
QList<GitHubAPI::SearchResultItem> GitHubAPI::searchRepository(std::string const &q)
{
QList<GitHubAPI::SearchResultItem> items;
GitHubRequestThread th;
{
OverrideWaitCursor;
th.url = "https://api.github.com/search/repositories?q=" + q;
th.start(mainwindow_);
while (!th.wait(1)) {
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
}
if (th.ok) {
QByteArray ba(th.text.c_str(), th.text.size());
QJsonDocument doc = QJsonDocument::fromJson(ba);
QJsonArray a1 = doc.object().value("items").toArray();
for (QJsonValueRef const &v1 : a1) {
QJsonObject o1 = v1.toObject();
SearchResultItem item;
auto String = [&](QString const &key){
return o1.value(key).toString().toStdString();
};
item.full_name = String("full_name");
if (!item.full_name.empty()) {
item.description = String("description");
item.html_url = String("html_url");
item.ssh_url = String("ssh_url");
item.clone_url = String("clone_url");
item.score = o1.value("score").toDouble();
items.push_back(item);
}
}
}
std::sort(items.begin(), items.end(), [](SearchResultItem const &l, SearchResultItem const &r){
return l.score > r.score; // 降順
});
return items;
}
diff --git a/src/GitHubAPI.h b/src/GitHubAPI.h
index 42583d6..213fc38 100644
--- a/src/GitHubAPI.h
+++ b/src/GitHubAPI.h
@@ -1,63 +1,63 @@
#ifndef GITHUBAPI_H
#define GITHUBAPI_H
#include <QImage>
#include <QThread>
#include <string>
#include <functional>
#include <memory>
-class BasicMainWindow;
+class MainWindow;
class WebContext;
class WebClient;
class GitHubAPI {
public:
using WebClientPtr = std::shared_ptr<WebClient>;
struct User {
std::string login;
std::string avatar_url;
std::string name;
std::string email;
};
struct SearchResultItem {
std::string full_name;
std::string description;
std::string ssh_url;
std::string clone_url;
std::string html_url;
double score = 0;
};
- BasicMainWindow *mainwindow_;
+ MainWindow *mainwindow_;
- GitHubAPI(BasicMainWindow *mainwindow)
+ GitHubAPI(MainWindow *mainwindow)
: mainwindow_(mainwindow)
{
}
QList<GitHubAPI::SearchResultItem> searchRepository(std::string const &q);
};
class GitHubRequestThread : public QThread {
private:
struct Private;
Private *m;
protected:
void run() override;
public:
GitHubAPI::WebClientPtr web();
public:
GitHubRequestThread();
~GitHubRequestThread() override;
std::string url;
bool ok = false;
std::string text;
std::function<bool(std::string const &text)> callback;
- void start(BasicMainWindow *mainwindow);
+ void start(MainWindow *mainwindow);
};
#endif // GITHUBAPI_H
diff --git a/src/ImageViewWidget.cpp b/src/ImageViewWidget.cpp
index a4c54b2..452cb04 100644
--- a/src/ImageViewWidget.cpp
+++ b/src/ImageViewWidget.cpp
@@ -1,373 +1,373 @@
#include "ImageViewWidget.h"
#include "FileDiffSliderWidget.h"
#include "FileDiffWidget.h"
#include "MainWindow.h"
#include "MemoryReader.h"
#include "Photoshop.h"
#include "charvec.h"
#include "common/joinpath.h"
#include "common/misc.h"
#include <QBuffer>
#include <QDebug>
#include <QFileDialog>
#include <QMenu>
#include <QPainter>
#include <QSvgRenderer>
#include <QWheelEvent>
#include <cmath>
#include <functional>
#include <memory>
using SvgRendererPtr = std::shared_ptr<QSvgRenderer>;
struct ImageViewWidget::Private {
QMainWindow *mainwindow = nullptr;
FileDiffWidget *filediffwidget = nullptr;
FileDiffWidget::DrawData *draw_data = nullptr;
QScrollBar *v_scroll_bar = nullptr;
QScrollBar *h_scroll_bar = nullptr;
QString mime_type;
QPixmap pixmap;
SvgRendererPtr svg;
double image_scroll_x = 0;
double image_scroll_y = 0;
double image_scale = 1;
double scroll_origin_x = 0;
double scroll_origin_y = 0;
QPoint mouse_press_pos;
int wheel_delta = 0;
QPointF interest_pos;
int top_margin = 1;
int bottom_margin = 1;
bool draw_left_border = true;
#ifndef APP_GUITAR
QPixmap transparent_pixmap;
#endif
};
ImageViewWidget::ImageViewWidget(QWidget *parent)
: QWidget(parent)
, m(new Private)
{
#if defined(Q_OS_WIN32)
setFont(QFont("MS Gothic"));
#elif defined(Q_OS_LINUX)
setFont(QFont("Monospace"));
#elif defined(Q_OS_MAC)
setFont(QFont("Menlo"));
#endif
setContextMenuPolicy(Qt::DefaultContextMenu);
}
ImageViewWidget::~ImageViewWidget()
{
delete m;
}
void ImageViewWidget::bind(QMainWindow *mainwindow, FileDiffWidget *filediffwidget, QScrollBar *vsb, QScrollBar *hsb)
{
m->mainwindow = mainwindow;
m->filediffwidget = filediffwidget;
m->v_scroll_bar = vsb;
m->h_scroll_bar = hsb;
}
bool ImageViewWidget::hasFocus() const
{
QWidget *w = qApp->focusWidget();
return w && w != m->filediffwidget && w->isAncestorOf(this);
}
void ImageViewWidget::setLeftBorderVisible(bool f)
{
m->draw_left_border = f;
}
void ImageViewWidget::internalScrollImage(double x, double y)
{
m->image_scroll_x = x;
m->image_scroll_y = y;
QSizeF sz = imageScrollRange();
if (m->image_scroll_x < 0) m->image_scroll_x = 0;
if (m->image_scroll_y < 0) m->image_scroll_y = 0;
if (m->image_scroll_x > sz.width()) m->image_scroll_x = sz.width();
if (m->image_scroll_y > sz.height()) m->image_scroll_y = sz.height();
update();
}
void ImageViewWidget::scrollImage(double x, double y)
{
internalScrollImage(x, y);
if (m->h_scroll_bar) {
m->h_scroll_bar->blockSignals(true);
m->h_scroll_bar->setValue((int)m->image_scroll_x);
m->h_scroll_bar->blockSignals(false);
}
if (m->v_scroll_bar) {
m->v_scroll_bar->blockSignals(true);
m->v_scroll_bar->setValue((int)m->image_scroll_y);
m->v_scroll_bar->blockSignals(false);
}
}
void ImageViewWidget::refrectScrollBar()
{
double e = 0.75;
double x = m->h_scroll_bar->value();
double y = m->v_scroll_bar->value();
if (fabs(x - m->image_scroll_x) < e) x = m->image_scroll_x; // 差が小さいときは値を維持する
if (fabs(y - m->image_scroll_y) < e) y = m->image_scroll_y;
internalScrollImage(x, y);
}
void ImageViewWidget::clear()
{
m->mime_type = QString();
m->pixmap = QPixmap();
setMouseTracking(false);
update();
}
QString ImageViewWidget::formatText(Document::Line const &line)
{
QByteArray const &ba = line.text;
if (ba.isEmpty()) return QString();
std::vector<char> vec;
vec.reserve(ba.size() + 100);
char const *begin = ba.data();
char const *end = begin + ba.size();
char const *ptr = begin;
int x = 0;
while (ptr < end) {
if (*ptr == '\t') {
do {
vec.push_back(' ');
x++;
} while ((x % 4) != 0);
ptr++;
} else {
vec.push_back(*ptr);
ptr++;
x++;
}
}
return QString::fromUtf8(&vec[0], vec.size());
}
QSizeF ImageViewWidget::imageScrollRange() const
{
QSize sz = imageSize();
int w = int(sz.width() * m->image_scale);
int h = int(sz.height() * m->image_scale);
return QSize(w, h);
}
void ImageViewWidget::setScrollBarRange(QScrollBar *h, QScrollBar *v)
{
h->blockSignals(true);
v->blockSignals(true);
QSizeF sz = imageScrollRange();
h->setRange(0, (int)sz.width());
v->setRange(0, (int)sz.height());
h->setPageStep(width());
v->setPageStep(height());
h->blockSignals(false);
v->blockSignals(false);
}
void ImageViewWidget::updateScrollBarRange()
{
setScrollBarRange(m->h_scroll_bar, m->v_scroll_bar);
}
QMainWindow *ImageViewWidget::mainwindow()
{
return m->mainwindow;
}
QBrush ImageViewWidget::getTransparentBackgroundBrush()
{
#ifdef APP_GUITAR
- return qobject_cast<BasicMainWindow *>(mainwindow())->getTransparentPixmap();
+ return qobject_cast<MainWindow *>(mainwindow())->getTransparentPixmap();
#else
if (m->transparent_pixmap.isNull()) {
m->transparent_pixmap = QPixmap(":/image/transparent.png");
}
return m->transparent_pixmap;
#endif
}
bool ImageViewWidget::isValidImage() const
{
return !m->pixmap.isNull() || (m->svg && m->svg->isValid());
}
QSize ImageViewWidget::imageSize() const
{
if (!m->pixmap.isNull()) return m->pixmap.size();
if (m->svg && m->svg->isValid()) return m->svg->defaultSize();
return QSize();
}
void ImageViewWidget::paintEvent(QPaintEvent *)
{
QPainter pr(this);
QSize imagesize = imageSize();
if (imagesize.width() > 0 && imagesize.height() > 0) {
pr.save();
if (!m->draw_left_border) {
pr.setClipRect(1, 0, width() - 1, height());
}
double cx = width() / 2.0;
double cy = height() / 2.0;
double x = cx - m->image_scroll_x;
double y = cy - m->image_scroll_y;
QSizeF sz = imageScrollRange();
if (sz.width() > 0 && sz.height() > 0) {
QBrush br = getTransparentBackgroundBrush();
pr.setBrushOrigin((int)x, (int)y);
pr.fillRect((int)x, (int)y, (int)sz.width(), (int)sz.height(), br);
if (!m->pixmap.isNull()) {
pr.drawPixmap((int)x, (int)y, (int)sz.width(), (int)sz.height(), m->pixmap, 0, 0, imagesize.width(), imagesize.height());
} else if (m->svg && m->svg->isValid()) {
m->svg->render(&pr, QRectF(x, y, sz.width(), sz.height()));
}
}
misc::drawFrame(&pr, (int)x - 1, (int)y - 1, (int)sz.width() + 2, (int)sz.height() + 2, Qt::black);
pr.restore();
}
if (m->draw_left_border) {
pr.fillRect(0, 0, 1, height(), QColor(160, 160, 160));
}
if (hasFocus()) {
misc::drawFrame(&pr, 0, 0, width(), height(), QColor(0, 128, 255, 128));
misc::drawFrame(&pr, 1, 1, width() - 2, height() - 2, QColor(0, 128, 255, 64));
}
}
void ImageViewWidget::resizeEvent(QResizeEvent *)
{
updateScrollBarRange();
}
void ImageViewWidget::setImage(QString mimetype, QByteArray const &ba)
{
if (mimetype.isEmpty()) {
mimetype = "image/x-unknown";
}
setMouseTracking(true);
m->pixmap = QPixmap();
m->svg = SvgRendererPtr();
if (!ba.isEmpty()) {
if (misc::isSVG(mimetype)) {
m->svg = std::make_shared<QSvgRenderer>(ba);
} else if (misc::isPSD(mimetype)) {
if (!ba.isEmpty()) {
MemoryReader reader(ba.data(), ba.size());
if (reader.open(QIODevice::ReadOnly)) {
std::vector<char> jpeg;
photoshop::readThumbnail(&reader, &jpeg);
if (!jpeg.empty()) {
m->pixmap.loadFromData((uchar const *)&jpeg[0], jpeg.size());
}
}
}
} else {
m->pixmap.loadFromData(ba);
}
}
QSize sz = imageSize();
double sx = sz.width();
double sy = sz.height();
if (sx > 0 && sy > 0) {
sx = width() / sx;
sy = height() / sy;
m->image_scale = (sx < sy ? sx : sy) * 0.9;
}
updateScrollBarRange();
m->h_scroll_bar->blockSignals(true);
m->v_scroll_bar->blockSignals(true);
m->h_scroll_bar->setValue(m->h_scroll_bar->maximum() / 2);
m->v_scroll_bar->setValue(m->v_scroll_bar->maximum() / 2);
m->h_scroll_bar->blockSignals(false);
m->v_scroll_bar->blockSignals(false);
refrectScrollBar();
}
void ImageViewWidget::mousePressEvent(QMouseEvent *e)
{
if (e->button() == Qt::LeftButton) {
QPoint pos = mapFromGlobal(QCursor::pos());
m->mouse_press_pos = pos;
m->scroll_origin_x = m->image_scroll_x;
m->scroll_origin_y = m->image_scroll_y;
}
}
void ImageViewWidget::mouseMoveEvent(QMouseEvent *e)
{
if (isValidImage()) {
QPoint pos = mapFromGlobal(QCursor::pos());
if ((e->buttons() & Qt::LeftButton) && hasFocus()) {
int delta_x = pos.x() - m->mouse_press_pos.x();
int delta_y = pos.y() - m->mouse_press_pos.y();
scrollImage(m->scroll_origin_x - delta_x, m->scroll_origin_y - delta_y);
}
double cx = width() / 2.0;
double cy = height() / 2.0;
double x = (pos.x() + 0.5 - cx + m->image_scroll_x) / m->image_scale;
double y = (pos.y() + 0.5 - cy + m->image_scroll_y) / m->image_scale;
m->interest_pos = QPointF(x, y);
m->wheel_delta = 0;
}
}
void ImageViewWidget::setImageScale(double scale)
{
if (scale < 1 / 32.0) scale = 1 / 32.0;
if (scale > 32) scale = 32;
m->image_scale = scale;
}
void ImageViewWidget::wheelEvent(QWheelEvent *e)
{
if (isValidImage()) {
double scale = 1;
const double mul = 1.189207115; // sqrt(sqrt(2))
m->wheel_delta += e->delta();
while (m->wheel_delta >= 120) {
m->wheel_delta -= 120;
scale *= mul;
}
while (m->wheel_delta <= -120) {
m->wheel_delta += 120;
scale /= mul;
}
setImageScale(m->image_scale * scale);
updateScrollBarRange();
double cx = width() / 2.0;
double cy = height() / 2.0;
QPoint pos = mapFromGlobal(QCursor::pos());
double dx = m->interest_pos.x() * m->image_scale + cx - (pos.x() + 0.5);
double dy = m->interest_pos.y() * m->image_scale + cy - (pos.y() + 0.5);
scrollImage(dx, dy);
update();
}
}
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index ff43239..3213833 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -1,3114 +1,3193 @@
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "AboutDialog.h"
#include "ApplicationGlobal.h"
#include "AreYouSureYouWantToContinueConnectingDialog.h"
-#include "AvatarLoader.h"
#include "BlameWindow.h"
+#include "CheckoutDialog.h"
+#include "CherryPickDialog.h"
#include "CloneFromGitHubDialog.h"
#include "CommitPropertyDialog.h"
-#include "DeleteBranchDialog.h"
#include "EditGitIgnoreDialog.h"
#include "EditTagsDialog.h"
-#include "FileDiffWidget.h"
#include "FindCommitDialog.h"
#include "GitDiff.h"
#include "JumpDialog.h"
#include "LineEditDialog.h"
+#include "MergeDialog.h"
#include "MySettings.h"
#include "ObjectBrowserDialog.h"
#include "ReflogWindow.h"
-#include "RemoteWatcher.h"
#include "SetGpgSigningDialog.h"
#include "SettingsDialog.h"
#include "StatusLabel.h"
+#include "SubmoduleUpdateDialog.h"
+#include "SubmodulesDialog.h"
#include "TextEditDialog.h"
#include "UserEvent.h"
-#include "common/joinpath.h"
#include "common/misc.h"
-#include "CherryPickDialog.h"
-#include "CloneDialog.h"
-#include "MergeDialog.h"
-#include "SubmoduleUpdateDialog.h"
-#include "SubmodulesDialog.h"
-#include "platform.h"
-#include "webclient.h"
#include <QClipboard>
-#include <QDirIterator>
+#include <QDir>
#include <QElapsedTimer>
#include <QFileDialog>
#include <QFileIconProvider>
#include <QMessageBox>
#include <QMimeData>
#include <QPainter>
#include <QStandardPaths>
#include <QTimer>
FileDiffWidget::DrawData::DrawData()
{
bgcolor_text = QColor(255, 255, 255);
bgcolor_gray = QColor(224, 224, 224);
bgcolor_add = QColor(192, 240, 192);
bgcolor_del = QColor(255, 224, 224);
bgcolor_add_dark = QColor(64, 192, 64);
bgcolor_del_dark = QColor(240, 64, 64);
}
-struct MainWindow::Private {
+struct MainWindow::Private2 {
bool is_online_mode = true;
QTimer interval_10ms_timer;
QImage graph_color;
QPixmap digits;
StatusLabel *status_bar_label;
QObject *last_focused_file_list = nullptr;
QListWidgetItem *last_selected_file_item = nullptr;
bool searching = false;
QString search_text;
- RemoteWatcher remote_watcher;
-
int repos_panel_width = 0;
std::set<QString> ancestors;
QWidget *focused_widget = nullptr;
QList<int> splitter_h_sizes;
};
MainWindow::MainWindow(QWidget *parent)
: BasicMainWindow(parent)
, ui(new Ui::MainWindow)
- , m(new Private)
+ , m1(new Private1)
+ , m2(new Private2)
{
ui->setupUi(this);
+ loadApplicationSettings();
+ m1->starting_dir = QDir::current().absolutePath();
+
+ { // load graphic resources
+ QFileIconProvider icons;
+ m1->folder_icon = icons.icon(QFileIconProvider::Folder);
+ m1->repository_icon = QIcon(":/image/repository.png");
+ m1->signature_good_icon = QIcon(":/image/signature-good.png");
+ m1->signature_bad_icon = QIcon(":/image/signature-bad.png");
+ m1->signature_dubious_icon = QIcon(":/image/signature-dubious.png");
+ m1->transparent_pixmap = QPixmap(":/image/transparent.png");
+ }
+
#ifdef Q_OS_MACX
ui->action_about->setText("About Guitar...");
ui->action_edit_settings->setText("Settings...");
#endif
ui->splitter_v->setSizes({100, 400});
ui->splitter_h->setSizes({200, 100, 200});
- m->status_bar_label = new StatusLabel(this);
- ui->statusBar->addWidget(m->status_bar_label);
+ m2->status_bar_label = new StatusLabel(this);
+ ui->statusBar->addWidget(m2->status_bar_label);
ui->widget_diff_view->bind(this);
qApp->installEventFilter(this);
setShowLabels(appsettings()->show_labels, false);
ui->widget_log->setupForLogWidget(ui->verticalScrollBar_log, ui->horizontalScrollBar_log, themeForTextEditor());
onLogVisibilityChanged();
initNetworking();
showFileList(FilesListType::SingleList);
- m->digits.load(":/image/digits.png");
- m->graph_color = global->theme->graphColorMap();
+ m2->digits.load(":/image/digits.png");
+ m2->graph_color = global->theme->graphColorMap();
prepareLogTableWidget();
#ifdef Q_OS_WIN
{
QFont font;
font = ui->label_repo_name->font();
font.setFamily("Meiryo");
ui->label_repo_name->setFont(font);
font = ui->label_branch_name->font();
font.setFamily("Meiryo");
ui->label_branch_name->setFont(font);
}
#endif
- connect(this, &BasicMainWindow::signalWriteLog, this, &BasicMainWindow::writeLog_);
+ connect(this, &MainWindow::signalWriteLog, this, &MainWindow::writeLog_);
connect(ui->dockWidget_log, &QDockWidget::visibilityChanged, this, &MainWindow::onLogVisibilityChanged);
connect(ui->widget_log, &TextEditorWidget::idle, this, &MainWindow::onLogIdle);
connect(ui->treeWidget_repos, &RepositoriesTreeWidget::dropped, this, &MainWindow::onRepositoriesTreeDropped);
connect((AbstractPtyProcess *)getPtyProcess(), &AbstractPtyProcess::completed, this, &MainWindow::onPtyProcessCompleted);
- connect(this, &BasicMainWindow::remoteInfoChanged, [&](){
+ connect(this, &MainWindow::remoteInfoChanged, [&](){
ui->lineEdit_remote->setText(currentRemoteName());
});
connect(this, &MainWindow::signalSetRemoteChanged, [&](bool f){
setRemoteChanged(f);
updateButton();
});
//
QString path = getBookmarksFilePath();
*getReposPtr() = RepositoryBookmark::load(path);
updateRepositoriesList();
webContext()->set_keep_alive_enabled(true);
getAvatarLoader()->start(this);
connect(getAvatarLoader(), &AvatarLoader::updated, this, &MainWindow::onAvatarUpdated);
*ptrUpdateFilesListCounter() = 0;
connect(ui->widget_diff_view, &FileDiffWidget::textcodecChanged, [&](){ updateDiffView(); });
if (!global->start_with_shift_key && appsettings()->remember_and_restore_window_position) {
Qt::WindowStates state = windowState();
MySettings settings;
settings.beginGroup("MainWindow");
bool maximized = settings.value("Maximized").toBool();
restoreGeometry(settings.value("Geometry").toByteArray());
settings.endGroup();
if (maximized) {
state |= Qt::WindowMaximized;
setWindowState(state);
}
}
ui->action_sidebar->setChecked(true);
startTimers();
}
MainWindow::~MainWindow()
{
stopPtyProcess();
getAvatarLoader()->stop();
- m->remote_watcher.quit();
- m->remote_watcher.wait();
+ deleteTempFiles();
- delete m;
+ delete m2;
+ delete m1;
delete ui;
}
void MainWindow::notifyRemoteChanged(bool f)
{
postUserFunctionEvent([&](QVariant const &v){
setRemoteChanged(v.toBool());
updateButton();
}, QVariant(f));
}
void MainWindow::postStartEvent()
{
QTimer::singleShot(100, [&](){
QApplication::postEvent(this, new StartEvent);
});
}
bool MainWindow::shown()
{
- m->repos_panel_width = ui->stackedWidget_leftpanel->width();
+ m2->repos_panel_width = ui->stackedWidget_leftpanel->width();
ui->stackedWidget_leftpanel->setCurrentWidget(ui->page_repos);
ui->action_repositories_panel->setChecked(true);
{
MySettings settings;
{
settings.beginGroup("Remote");
bool f = settings.value("Online", true).toBool();
settings.endGroup();
setRemoteOnline(f, false);
}
{
settings.beginGroup("MainWindow");
int n = settings.value("FirstColumnWidth", 50).toInt();
if (n < 10) n = 50;
ui->tableWidget_log->setColumnWidth(0, n);
settings.endGroup();
}
}
updateUI();
postStartEvent(); // 開始イベント
return true;
}
bool MainWindow::isUninitialized()
{
return !misc::isExecutable(appsettings()->git_command) || !misc::isExecutable(appsettings()->file_command);
}
void MainWindow::onStartEvent()
{
if (isUninitialized()) { // gitコマンドの有効性チェック
if (!execWelcomeWizardDialog()) { // ようこそダイアログを表示
close(); // キャンセルされたらプログラム終了
}
}
if (isUninitialized()) { // 正しく初期設定されたか
postStartEvent(); // 初期設定されなかったら、もういちどようこそダイアログを出す。
} else {
// 外部コマンド登録
setGitCommand(appsettings()->git_command, false);
setFileCommand(appsettings()->file_command, false);
setGpgCommand(appsettings()->gpg_command, false);
setSshCommand(appsettings()->ssh_command, false);
// メインウィンドウのタイトルを設定
updateWindowTitle(git());
// プログラムバーション表示
writeLog(AboutDialog::appVersion() + '\n');
// gitコマンドバージョン表示
logGitVersion();
}
}
void MainWindow::startTimers()
{
// interval 10ms
- connect(&m->interval_10ms_timer, &QTimer::timeout, [&](){
+ connect(&m2->interval_10ms_timer, &QTimer::timeout, [&](){
const int ms = 10;
auto *p1 = ptrUpdateCommitTableCounter();
if (*p1 > 0) {
if (*p1 > ms) {
*p1 -= ms;
} else {
*p1 = 0;
ui->tableWidget_log->viewport()->update();
}
}
auto *p2 = ptrUpdateFilesListCounter();
if (*p2 > 0) {
if (*p2 > ms) {
*p2 -= ms;
} else {
*p2 = 0;
updateCurrentFilesList();
}
}
});
- m->interval_10ms_timer.setInterval(10);
- m->interval_10ms_timer.start();
+ m2->interval_10ms_timer.setInterval(10);
+ m2->interval_10ms_timer.start();
startTimer(10);
}
void MainWindow::setCurrentLogRow(int row)
{
if (row >= 0 && row < ui->tableWidget_log->rowCount()) {
ui->tableWidget_log->setCurrentCell(row, 2);
ui->tableWidget_log->setFocus();
updateStatusBarText();
}
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
QEvent::Type et = event->type();
if (et == QEvent::KeyPress) {
if (QApplication::activeModalWidget()) {
// thru
} else {
auto *e = dynamic_cast<QKeyEvent *>(event);
Q_ASSERT(e);
int k = e->key();
if (k == Qt::Key_Escape) {
if (centralWidget()->isAncestorOf(qApp->focusWidget())) {
ui->treeWidget_repos->setFocus();
return true;
}
}
if (e->modifiers() & Qt::ControlModifier) {
if (k == Qt::Key_Up || k == Qt::Key_Down) {
int rows = ui->tableWidget_log->rowCount();
int row = ui->tableWidget_log->currentRow();
if (k == Qt::Key_Up) {
if (row > 0) {
row--;
}
} else if (k == Qt::Key_Down) {
if (row + 1 < rows) {
row++;
}
}
ui->tableWidget_log->setCurrentCell(row, 0);
return true;
}
}
if (watched == ui->treeWidget_repos) {
if (k == Qt::Key_Enter || k == Qt::Key_Return) {
openSelectedRepository();
return true;
}
if (!(e->modifiers() & Qt::ControlModifier)) {
if (k >= 0 && k < 128 && QChar((uchar)k).isLetterOrNumber()) {
appendCharToRepoFilter(k);
return true;
}
if (k == Qt::Key_Backspace) {
backspaceRepoFilter();
return true;
}
if (k == Qt::Key_Escape) {
clearRepoFilter();
return true;
}
}
} else if (watched == ui->tableWidget_log) {
if (k == Qt::Key_Home) {
setCurrentLogRow(0);
return true;
}
if (k == Qt::Key_Escape) {
ui->treeWidget_repos->setFocus();
return true;
}
} else if (watched == ui->listWidget_files || watched == ui->listWidget_unstaged || watched == ui->listWidget_staged) {
if (k == Qt::Key_Escape) {
ui->tableWidget_log->setFocus();
return true;
}
}
}
} else if (et == QEvent::FocusIn) {
auto SelectItem = [](QListWidget *w){
int row = w->currentRow();
if (row < 0) {
row = 0;
w->setCurrentRow(row);
}
w->setItemSelected(w->item(row), true);
w->viewport()->update();
};
// ファイルリストがフォーカスを得たとき、diffビューを更新する。(コンテキストメニュー対応)
if (watched == ui->listWidget_unstaged) {
- m->last_focused_file_list = watched;
+ m2->last_focused_file_list = watched;
updateStatusBarText();
updateUnstagedFileCurrentItem();
SelectItem(ui->listWidget_unstaged);
return true;
}
if (watched == ui->listWidget_staged) {
- m->last_focused_file_list = watched;
+ m2->last_focused_file_list = watched;
updateStatusBarText();
updateStagedFileCurrentItem();
SelectItem(ui->listWidget_staged);
return true;
}
if (watched == ui->listWidget_files) {
- m->last_focused_file_list = watched;
+ m2->last_focused_file_list = watched;
SelectItem(ui->listWidget_files);
return true;
}
}
return false;
}
bool MainWindow::event(QEvent *event)
{
QEvent::Type et = event->type();
if (et == QEvent::KeyPress) {
auto *e = dynamic_cast<QKeyEvent *>(event);
Q_ASSERT(e);
int k = e->key();
if (k == Qt::Key_Escape) {
emit onEscapeKeyPressed();
} else if (k == Qt::Key_Delete) {
if (qApp->focusWidget() == ui->treeWidget_repos) {
removeSelectedRepositoryFromBookmark(true);
return true;
}
}
+ } else if (et == (QEvent::Type)EventUserFunction) {
+ if (auto *e = (UserFunctionEvent *)event) {
+ e->func(e->var);
+ return true;
+ }
}
return BasicMainWindow::event(event);
}
void MainWindow::customEvent(QEvent *e)
{
if (e->type() == (QEvent::Type)UserEvent::Start) {
onStartEvent();
return;
}
}
void MainWindow::closeEvent(QCloseEvent *event)
{
MySettings settings;
if (appsettings()->remember_and_restore_window_position) {
setWindowOpacity(0);
Qt::WindowStates state = windowState();
bool maximized = (state & Qt::WindowMaximized) != 0;
if (maximized) {
state &= ~Qt::WindowMaximized;
setWindowState(state);
}
{
settings.beginGroup("MainWindow");
settings.setValue("Maximized", maximized);
settings.setValue("Geometry", saveGeometry());
settings.endGroup();
}
}
{
settings.beginGroup("MainWindow");
settings.setValue("FirstColumnWidth", ui->tableWidget_log->columnWidth(0));
settings.endGroup();
}
QMainWindow::closeEvent(event);
}
void MainWindow::setStatusBarText(QString const &text)
{
- m->status_bar_label->setText(text);
+ m2->status_bar_label->setText(text);
}
void MainWindow::clearStatusBarText()
{
setStatusBarText(QString());
}
void MainWindow::onLogVisibilityChanged()
{
ui->action_window_log->setChecked(ui->dockWidget_log->isVisible());
}
void MainWindow::internalWriteLog(char const *ptr, int len)
{
ui->widget_log->logicalMoveToBottom();
ui->widget_log->write(ptr, len, false);
ui->widget_log->setChanged(false);
setInteractionCanceled(false);
}
void MainWindow::buildRepoTree(QString const &group, QTreeWidgetItem *item, QList<RepositoryItem> *repos)
{
QString name = item->text(0);
if (isGroupItem(item)) {
int n = item->childCount();
for (int i = 0; i < n; i++) {
QTreeWidgetItem *child = item->child(i);
QString sub = group / name;
buildRepoTree(sub, child, repos);
}
} else {
RepositoryItem const *repo = repositoryItem(item);
if (repo) {
RepositoryItem newrepo = *repo;
newrepo.name = name;
newrepo.group = group;
item->setData(0, IndexRole, repos->size());
repos->push_back(newrepo);
}
}
}
void MainWindow::refrectRepositories()
{
QList<RepositoryItem> newrepos;
int n = ui->treeWidget_repos->topLevelItemCount();
for (int i = 0; i < n; i++) {
QTreeWidgetItem *item = ui->treeWidget_repos->topLevelItem(i);
buildRepoTree(QString(), item, &newrepos);
}
*getReposPtr() = std::move(newrepos);
saveRepositoryBookmarks();
}
void MainWindow::onRepositoriesTreeDropped()
{
refrectRepositories();
QTreeWidgetItem *item = ui->treeWidget_repos->currentItem();
if (item) item->setExpanded(true);
}
const QPixmap &MainWindow::digitsPixmap() const
{
- return m->digits;
+ return m2->digits;
}
int MainWindow::digitWidth() const
{
return 5;
}
int MainWindow::digitHeight() const
{
return 7;
}
void MainWindow::drawDigit(QPainter *pr, int x, int y, int n) const
{
int w = digitWidth();
int h = digitHeight();
- pr->drawPixmap(x, y, w, h, m->digits, n * w, 0, w, h);
+ pr->drawPixmap(x, y, w, h, m2->digits, n * w, 0, w, h);
}
-QString BasicMainWindow::defaultWorkingDir() const
+QString MainWindow::defaultWorkingDir() const
{
return appsettings()->default_working_dir;
}
QColor MainWindow::color(unsigned int i)
{
- unsigned int n = m->graph_color.width();
+ unsigned int n = m2->graph_color.width();
if (n > 0) {
n--;
if (i > n) i = n;
- QRgb const *p = (QRgb const *)m->graph_color.scanLine(0);
+ QRgb const *p = (QRgb const *)m2->graph_color.scanLine(0);
return QColor(qRed(p[i]), qGreen(p[i]), qBlue(p[i]));
}
return Qt::black;
}
//QString MainWindow::currentWorkingCopyDir() const
//{
// QString workdir = BasicMainWindow::currentWorkingCopyDir();
// if (workdir.isEmpty()) {
// RepositoryItem const *repo = selectedRepositoryItem();
// if (repo) {
// workdir = repo->local_dir;
// return workdir;
// }
// }
// return workdir;
//}
-RepositoryItem const *BasicMainWindow::findRegisteredRepository(QString *workdir) const
+RepositoryItem const *MainWindow::findRegisteredRepository(QString *workdir) const
{
*workdir = QDir(*workdir).absolutePath();
workdir->replace('\\', '/');
if (Git::isValidWorkingCopy(*workdir)) {
for (RepositoryItem const &item : getRepos()) {
Qt::CaseSensitivity cs = Qt::CaseSensitive;
#ifdef Q_OS_WIN
cs = Qt::CaseInsensitive;
#endif
if (workdir->compare(item.local_dir, cs) == 0) {
return &item;
}
}
}
return nullptr;
}
int MainWindow::repositoryIndex_(QTreeWidgetItem const *item) const
{
if (item) {
int i = item->data(0, IndexRole).toInt();
if (i >= 0 && i < getRepos().size()) {
return i;
}
}
return -1;
}
RepositoryItem const *MainWindow::repositoryItem(QTreeWidgetItem const *item) const
{
int row = repositoryIndex_(item);
QList<RepositoryItem> const &repos = getRepos();
return (row >= 0 && row < repos.size()) ? &repos[row] : nullptr;
}
RepositoryItem const *MainWindow::selectedRepositoryItem() const
{
return repositoryItem(ui->treeWidget_repos->currentItem());
}
static QTreeWidgetItem *newQTreeWidgetItem()
{
auto *item = new QTreeWidgetItem;
item->setSizeHint(0, QSize(20, 20));
return item;
}
QTreeWidgetItem *MainWindow::newQTreeWidgetFolderItem(QString const &name)
{
QTreeWidgetItem *item = newQTreeWidgetItem();
item->setText(0, name);
item->setData(0, IndexRole, GroupItem);
item->setIcon(0, getFolderIcon());
item->setFlags(item->flags() | Qt::ItemIsEditable);
return item;
}
void MainWindow::updateRepositoriesList()
{
QString path = getBookmarksFilePath();
auto *repos = getReposPtr();
*repos = RepositoryBookmark::load(path);
QString filter = getRepositoryFilterText();
ui->treeWidget_repos->clear();
std::map<QString, QTreeWidgetItem *> parentmap;
for (int i = 0; i < repos->size(); i++) {
RepositoryItem const &repo = repos->at(i);
if (!filter.isEmpty() && repo.name.indexOf(filter, 0, Qt::CaseInsensitive) < 0) {
continue;
}
QTreeWidgetItem *parent = nullptr;
{
QString group = repo.group;
if (group.startsWith('/')) {
group = group.mid(1);
}
auto it = parentmap.find(group);
if (it != parentmap.end()) {
parent = it->second;
}
if (!parent) {
QStringList list = group.split('/', QString::SkipEmptyParts);
if (list.isEmpty()) {
list.push_back(tr("Default"));
}
for (QString const &name : list) {
if (name.isEmpty()) continue;
if (!parent) {
auto it = parentmap.find(name);
if (it != parentmap.end()) {
parent = it->second;
} else {
parent = newQTreeWidgetFolderItem(name);
ui->treeWidget_repos->addTopLevelItem(parent);
}
} else {
QTreeWidgetItem *child = newQTreeWidgetFolderItem(name);
parent->addChild(child);
parent = child;
}
parent->setExpanded(true);
}
Q_ASSERT(parent);
parentmap[group] = parent;
}
parent->setData(0, FilePathRole, "");
}
QTreeWidgetItem *child = newQTreeWidgetItem();
child->setText(0, repo.name);
child->setData(0, IndexRole, i);
child->setIcon(0, getRepositoryIcon());
child->setFlags(child->flags() & ~Qt::ItemIsDropEnabled);
parent->addChild(child);
parent->setExpanded(true);
}
}
void MainWindow::showFileList(FilesListType files_list_type)
{
switch (files_list_type) {
case FilesListType::SingleList:
ui->stackedWidget_filelist->setCurrentWidget(ui->page_files);
break;
case FilesListType::SideBySide:
ui->stackedWidget_filelist->setCurrentWidget(ui->page_uncommited);
break;
}
}
void MainWindow::clearFileList()
{
showFileList(FilesListType::SingleList);
ui->listWidget_unstaged->clear();
ui->listWidget_staged->clear();
ui->listWidget_files->clear();
}
void MainWindow::clearDiffView()
{
ui->widget_diff_view->clearDiffView();
}
void MainWindow::clearRepositoryInfo()
{
internalClearRepositoryInfo();
ui->label_repo_name->setText(QString());
ui->label_branch_name->setText(QString());
}
void MainWindow::setRepositoryInfo(QString const &reponame, QString const &brname)
{
ui->label_repo_name->setText(reponame);
ui->label_branch_name->setText(brname);
}
/**
* @brief サブモジュールを更新
* @param id コミットID
*/
-void BasicMainWindow::updateSubmodules(GitPtr g, QString id)
+void MainWindow::updateSubmodules(GitPtr g, QString id)
{
QList<Git::Submodule> submodules;
if (id.isEmpty()) {
submodules = g->submodules();
} else {
GitTreeItemList list;
GitObjectCache objcache;
objcache.setup(g);
GitCommit tree;
GitCommit::parseCommit(&objcache, id, &tree);
parseGitTreeObject(&objcache, tree.tree_id, {}, &list);
for (GitTreeItem const &item : list) {
if (item.type == GitTreeItem::Type::BLOB && item.name == ".gitmodules") {
Git::Object obj = objcache.catFile(item.id);
if (!obj.content.isEmpty()) {
parseGitSubModules(obj.content, &submodules);
}
}
}
for (GitTreeItem const &item : list) {
if (item.type == GitTreeItem::Type::BLOB && item.mode == "160000") {
for (int i = 0; i < submodules.size(); i++) {
if (submodules[i].path == item.name) {
submodules[i].id = item.id;
break;
}
}
}
}
}
// for (Git::Submodule const &m : submodules) {
// qDebug() << m.name << m.path << m.url << m.id;
// }
setSubmodules(submodules);
}
/**
* @brief ファイルリストを更新
* @param id コミットID
* @param wait
*/
void MainWindow::updateFilesList(QString id, bool wait)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
if (!wait) return;
clearFileList();
Git::FileStatusList stats = g->status_s();
setUncommitedChanges(!stats.empty());
FilesListType files_list_type = FilesListType::SingleList;
bool staged = false;
auto AddItem = [&](ObjectData const &data){
auto [header, text] = makeFileItemText(data);
QListWidgetItem *item = new QListWidgetItem(text);
item->setSizeHint(QSize(item->sizeHint().width(), 18));
item->setData(FilePathRole, data.path);
item->setData(DiffIndexRole, data.idiff);
item->setData(HunkIndexRole, -1);
item->setData(HeaderRole, header);
switch (files_list_type) {
case FilesListType::SingleList:
ui->listWidget_files->addItem(item);
break;
case FilesListType::SideBySide:
if (staged) {
ui->listWidget_staged->addItem(item);
} else {
ui->listWidget_unstaged->addItem(item);
}
break;
}
};
if (id.isEmpty()) {
bool uncommited = isThereUncommitedChanges();
if (uncommited) {
files_list_type = FilesListType::SideBySide;
}
bool ok = false;
auto diffs = makeDiffs(uncommited ? QString() : id, &ok);
setDiffResult(diffs);
if (!ok) return;
std::map<QString, int> diffmap;
for (int idiff = 0; idiff < diffResult()->size(); idiff++) {
Git::Diff const &diff = diffResult()->at(idiff);
QString filename = diff.path;
if (!filename.isEmpty()) {
diffmap[filename] = idiff;
}
}
showFileList(files_list_type);
for (Git::FileStatus const &s : stats) {
staged = (s.isStaged() && s.code_y() == ' ');
int idiff = -1;
QString header;
auto it = diffmap.find(s.path1());
Git::Diff const *diff = nullptr;
if (it != diffmap.end()) {
idiff = it->second;
diff = &diffResult()->at(idiff);
}
QString path = s.path1();
if (s.code() == Git::FileStatusCode::Unknown) {
qDebug() << "something wrong...";
} else if (s.code() == Git::FileStatusCode::Untracked) {
// nop
} else if (s.isUnmerged()) {
header += "(unmerged) ";
} else if (s.code() == Git::FileStatusCode::AddedToIndex) {
header = "(add) ";
} else if (s.code_x() == 'D' || s.code_y() == 'D' || s.code() == Git::FileStatusCode::DeletedFromIndex) {
header = "(del) ";
} else if (s.code_x() == 'R' || s.code() == Git::FileStatusCode::RenamedInIndex) {
header = "(ren) ";
path = s.path2(); // renamed newer path
} else if (s.code_x() == 'M' || s.code_y() == 'M') {
header = "(chg) ";
}
ObjectData data;
data.path = path;
data.header = header;
data.idiff = idiff;
if (diff) data.submod = diff->submodule;
if (data.submod) {
GitPtr g = git(data.submod);
g->queryCommit(data.submod.id, &data.submod_commit);
}
AddItem(data);
}
} else {
bool ok = false;
auto diffs = makeDiffs(id, &ok);
setDiffResult(diffs);
if (!ok) return;
showFileList(files_list_type);
addDiffItems(diffResult(), AddItem);
}
for (Git::Diff const &diff : *diffResult()) {
QString key = GitDiff::makeKey(diff);
(*getDiffCacheMap())[key] = diff;
}
}
void MainWindow::updateFilesList(Git::CommitItem const &commit, bool wait)
{
QString id;
if (Git::isUncommited(commit)) {
// empty id for uncommited changes
} else {
id = commit.commit_id;
}
updateFilesList(id, wait);
}
void MainWindow::updateCurrentFilesList()
{
auto logs = getLogs();
QTableWidgetItem *item = ui->tableWidget_log->item(selectedLogIndex(), 0);
if (!item) return;
int index = item->data(IndexRole).toInt();
int count = (int)logs.size();
if (index < count) {
updateFilesList(logs[index], true);
}
}
void MainWindow::prepareLogTableWidget()
{
QStringList cols = {
tr("Graph"),
tr("Commit"),
tr("Date"),
tr("Author"),
tr("Message"),
};
int n = cols.size();
ui->tableWidget_log->setColumnCount(n);
ui->tableWidget_log->setRowCount(0);
for (int i = 0; i < n; i++) {
QString const &text = cols[i];
auto *item = new QTableWidgetItem(text);
ui->tableWidget_log->setHorizontalHeaderItem(i, item);
}
updateCommitGraph(); // コミットグラフを更新
}
void MainWindow::detectGitServerType(GitPtr const &g)
{
setServerType(ServerType::Standard);
*ptrGitHub() = GitHubRepositoryInfo();
QString push_url;
QList<Git::Remote> remotes;
g->getRemoteURLs(&remotes);
for (Git::Remote const &r : remotes) {
if (r.purpose == "push") {
push_url = r.url;
}
}
auto Check = [&](QString const &s){
int i = push_url.indexOf(s);
if (i > 0) return i + s.size();
return 0;
};
// check GitHub
int pos = Check("@github.com:");
if (pos == 0) {
pos = Check("://github.com/");
}
if (pos > 0) {
int end = push_url.size();
{
QString s = ".git";
if (push_url.endsWith(s)) {
end -= s.size();
}
}
QString s = push_url.mid(pos, end - pos);
int i = s.indexOf('/');
if (i > 0) {
auto *p = ptrGitHub();
QString user = s.mid(0, i);
QString repo = s.mid(i + 1);
p->owner_account_name = user;
p->repository_name = repo;
}
setServerType(ServerType::GitHub);
}
}
void MainWindow::clearLog()
{
clearLogs();
clearLabelMap();
setUncommitedChanges(false);
ui->tableWidget_log->clearContents();
ui->tableWidget_log->scrollToTop();
}
void MainWindow::openRepository_(GitPtr g, bool keep_selection)
{
getObjCache()->setup(g);
int scroll_pos = -1;
int select_row = -1;
if (keep_selection) {
scroll_pos = ui->tableWidget_log->verticalScrollBar()->value();
select_row = ui->tableWidget_log->currentRow();
}
if (isValidWorkingCopy(g)) {
bool do_fetch = isOnlineMode() && (getForceFetch() || appsettings()->automatically_fetch_when_opening_the_repository);
setForceFetch(false);
if (do_fetch) {
if (!fetch(g, false)) {
return;
}
}
clearLog();
clearRepositoryInfo();
detectGitServerType(g);
updateFilesList(QString(), true);
bool canceled = false;
ui->tableWidget_log->setEnabled(false);
// ログを取得
setLogs(retrieveCommitLog(g));
// ブランチを取得
queryBranches(g);
// タグを取得
ptrTagMap()->clear();
QList<Git::Tag> tags = g->tags();
for (Git::Tag const &tag : tags) {
Git::Tag t = tag;
t.id = getObjCache()->getCommitIdFromTag(t.id);
(*ptrTagMap())[t.id].push_back(t);
}
ui->tableWidget_log->setEnabled(true);
updateCommitTableLater();
if (canceled) return;
QString branch_name;
if (currentBranch().flags & Git::Branch::HeadDetachedAt) {
branch_name += QString("(HEAD detached at %1)").arg(currentBranchName());
}
if (currentBranch().flags & Git::Branch::HeadDetachedFrom) {
branch_name += QString("(HEAD detached from %1)").arg(currentBranchName());
}
if (branch_name.isEmpty()) {
branch_name = currentBranchName();
}
QString repo_name = currentRepositoryName();
setRepositoryInfo(repo_name, branch_name);
} else {
clearLog();
clearRepositoryInfo();
}
if (!g) return;
updateRemoteInfo();
updateWindowTitle(g);
setHeadId(getObjCache()->revParse("HEAD"));
if (isThereUncommitedChanges()) {
Git::CommitItem item;
item.parent_ids.push_back(currentBranch().id);
item.message = tr("Uncommited changes");
auto p = getLogsPtr();
p->insert(p->begin(), item);
}
prepareLogTableWidget();
auto const &logs = getLogs();
const int count = logs.size();
ui->tableWidget_log->setRowCount(count);
int selrow = 0;
for (int row = 0; row < count; row++) {
Git::CommitItem const *commit = &logs[row];
{
auto *item = new QTableWidgetItem;
item->setData(IndexRole, row);
ui->tableWidget_log->setItem(row, 0, item);
}
int col = 1; // カラム0はコミットグラフなので、その次から
auto AddColumn = [&](QString const &text, bool bold, QString const &tooltip){
auto *item = new QTableWidgetItem(text);
if (!tooltip.isEmpty()) {
QString tt = tooltip;
tt.replace('\n', ' ');
tt = tt.toHtmlEscaped();
tt = "<p style='white-space: pre'>" + tt + "</p>";
item->setToolTip(tt);
}
if (bold) {
QFont font = item->font();
font.setBold(true);
item->setFont(font);
}
ui->tableWidget_log->setItem(row, col, item);
col++;
};
QString commit_id;
QString datetime;
QString author;
QString message;
QString message_ex;
bool isHEAD = (commit->commit_id == getHeadId());
bool bold = false;
{
if (Git::isUncommited(*commit)) { // 未コミットの時
bold = true; // 太字
selrow = row;
} else {
if (isHEAD && !isThereUncommitedChanges()) { // HEADで、未コミットがないとき
bold = true; // 太字
selrow = row;
}
commit_id = abbrevCommitID(*commit);
}
datetime = misc::makeDateTimeString(commit->commit_date);
author = commit->author;
message = commit->message;
message_ex = makeCommitInfoText(row, &(*getLabelMap())[row]);
}
AddColumn(commit_id, false, QString());
AddColumn(datetime, false, QString());
AddColumn(author, false, QString());
AddColumn(message, bold, message + message_ex);
ui->tableWidget_log->setRowHeight(row, 24);
}
int t = ui->tableWidget_log->columnWidth(0);
ui->tableWidget_log->resizeColumnsToContents();
ui->tableWidget_log->setColumnWidth(0, t);
ui->tableWidget_log->horizontalHeader()->setStretchLastSection(false);
ui->tableWidget_log->horizontalHeader()->setStretchLastSection(true);
- m->last_focused_file_list = nullptr;
+ m2->last_focused_file_list = nullptr;
ui->tableWidget_log->setFocus();
if (select_row < 0) {
setCurrentLogRow(selrow);
} else {
setCurrentLogRow(select_row);
ui->tableWidget_log->verticalScrollBar()->setValue(scroll_pos >= 0 ? scroll_pos : 0);
}
- m->remote_watcher.setCurrent(currentRemoteName(), currentBranchName());
-
updateUI();
}
void MainWindow::removeSelectedRepositoryFromBookmark(bool ask)
{
int i = indexOfRepository(ui->treeWidget_repos->currentItem());
removeRepositoryFromBookmark(i, ask);
}
void MainWindow::setNetworkingCommandsEnabled(bool enabled)
{
ui->action_clone->setEnabled(enabled);
ui->toolButton_clone->setEnabled(enabled);
if (!Git::isValidWorkingCopy(currentWorkingCopyDir())) {
enabled = false;
}
bool opened = !currentRepository().name.isEmpty();
ui->action_fetch->setEnabled(enabled || opened);
ui->toolButton_fetch->setEnabled(enabled || opened);
if (isOnlineMode()) {
ui->action_fetch->setText(tr("Fetch"));
ui->toolButton_fetch->setText(tr("Fetch"));
} else {
ui->action_fetch->setText(tr("Update"));
ui->toolButton_fetch->setText(tr("Update"));
}
ui->action_fetch_prune->setEnabled(enabled);
ui->action_pull->setEnabled(enabled);
ui->action_push->setEnabled(enabled);
ui->action_push_u->setEnabled(enabled);
ui->action_push_all_tags->setEnabled(enabled);
ui->toolButton_pull->setEnabled(enabled);
ui->toolButton_push->setEnabled(enabled);
}
void MainWindow::updateUI()
{
setNetworkingCommandsEnabled(isOnlineMode());
ui->toolButton_fetch->setDot(getRemoteChanged());
Git::Branch b = currentBranch();
ui->toolButton_push->setNumber(b.ahead > 0 ? b.ahead : -1);
ui->toolButton_pull->setNumber(b.behind > 0 ? b.behind : -1);
{
bool f = isRepositoryOpened();
ui->toolButton_status->setEnabled(f);
ui->toolButton_terminal->setEnabled(f);
ui->toolButton_explorer->setEnabled(f);
ui->action_repository_status->setEnabled(f);
ui->action_terminal->setEnabled(f);
ui->action_explorer->setEnabled(f);
}
}
void MainWindow::updateStatusBarText()
{
QString text;
QWidget *w = qApp->focusWidget();
if (w == ui->treeWidget_repos) {
RepositoryItem const *repo = selectedRepositoryItem();
if (repo) {
text = QString("%1 : %2")
.arg(repo->name)
.arg(misc::normalizePathSeparator(repo->local_dir))
;
}
} else if (w == ui->tableWidget_log) {
QTableWidgetItem *item = ui->tableWidget_log->item(selectedLogIndex(), 0);
if (item) {
auto const &logs = getLogs();
int row = item->data(IndexRole).toInt();
if (row < (int)logs.size()) {
Git::CommitItem const &commit = logs[row];
if (Git::isUncommited(commit)) {
text = tr("Uncommited changes");
} else {
QString id = commit.commit_id;
text = QString("%1 : %2%3")
.arg(id.mid(0, 7))
.arg(commit.message)
.arg(makeCommitInfoText(row, nullptr))
;
}
}
}
}
setStatusBarText(text);
}
void MainWindow::mergeBranch(QString const &commit, Git::MergeFastForward ff)
{
if (commit.isEmpty()) return;
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
g->mergeBranch(commit, ff);
openRepository(true);
}
void MainWindow::mergeBranch(Git::CommitItem const *commit, Git::MergeFastForward ff)
{
if (!commit) return;
mergeBranch(commit->commit_id, ff);
}
void MainWindow::rebaseBranch(Git::CommitItem const *commit)
{
if (!commit) return;
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
QString text = tr("Are you sure you want to rebase the commit ?");
text += "\n\n";
text += "> git rebase " + commit->commit_id;
int r = QMessageBox::information(this, tr("Rebase"), text, QMessageBox::Ok, QMessageBox::Cancel);
if (r == QMessageBox::Ok) {
g->rebaseBranch(commit->commit_id);
openRepository(true);
}
}
void MainWindow::cherrypick(Git::CommitItem const *commit)
{
if (!commit) return;
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
int n = commit->parent_ids.size();
if (n == 1) {
g->cherrypick(commit->commit_id);
} else if (n > 1) {
Git::CommitItem head;
Git::CommitItem pick;
g->queryCommit(g->rev_parse("HEAD"), &head);
g->queryCommit(commit->commit_id, &pick);
QList<Git::CommitItem> parents;
for (int i = 0; i < n; i++) {
QString id = commit->commit_id + QString("^%1").arg(i + 1);
id = g->rev_parse(id);
Git::CommitItem item;
g->queryCommit(id, &item);
parents.push_back(item);
}
CherryPickDialog dlg(this, head, pick, parents);
if (dlg.exec() == QDialog::Accepted) {
QString cmd = "-m %1 ";
cmd = cmd.arg(dlg.number());
if (dlg.allowEmpty()) {
cmd += "--allow-empty ";
}
cmd += commit->commit_id;
g->cherrypick(cmd);
} else {
return;
}
}
openRepository(true);
}
void MainWindow::merge(Git::CommitItem const *commit)
{
if (isThereUncommitedChanges()) return;
if (!commit) {
int row = selectedLogIndex();
commit = commitItem(row);
if (!commit) return;
}
if (!Git::isValidID(commit->commit_id)) return;
static const char MergeFastForward[] = "MergeFastForward";
QString fastforward;
{
MySettings s;
s.beginGroup("Behavior");
fastforward = s.value(MergeFastForward).toString();
s.endGroup();
}
std::vector<QString> labels;
{
int row = selectedLogIndex();
QList<Label> const *v = label(row);
for (Label const &label : *v) {
if (label.kind == Label::LocalBranch || label.kind == Label::Tag) {
labels.push_back(label.text);
}
}
std::sort(labels.begin(), labels.end());
labels.erase(std::unique(labels.begin(), labels.end()), labels.end());
}
labels.push_back(commit->commit_id);
QString branch_name = currentBranchName();
MergeDialog dlg(fastforward, labels, branch_name, this);
if (dlg.exec() == QDialog::Accepted) {
fastforward = dlg.getFastForwardPolicy();
{
MySettings s;
s.beginGroup("Behavior");
s.setValue(MergeFastForward, fastforward);
s.endGroup();
}
QString from = dlg.mergeFrom();
mergeBranch(from, MergeDialog::ff(fastforward));
}
}
void MainWindow::showStatus()
{
auto g = git();
if (!g->isValidWorkingCopy()) {
msgNoRepositorySelected();
return;
}
QString s = g->status();
TextEditDialog dlg(this);
dlg.setWindowTitle(tr("Status"));
dlg.setText(s, true);
dlg.exec();
}
void MainWindow::on_action_commit_triggered()
{
commit();
}
void MainWindow::on_action_fetch_triggered()
{
if (isOnlineMode()) {
reopenRepository(true, [&](GitPtr g){
fetch(g, false);
});
} else {
updateRepository();
}
}
void MainWindow::on_action_fetch_prune_triggered()
{
if (!isOnlineMode()) return;
reopenRepository(true, [&](GitPtr g){
fetch(g, true);
});
}
void MainWindow::on_action_push_triggered()
{
push();
}
void MainWindow::on_action_pull_triggered()
{
if (!isOnlineMode()) return;
reopenRepository(true, [&](GitPtr g){
setPtyCondition(PtyCondition::Pull);
setPtyProcessOk(true);
g->pull(getPtyProcess());
while (1) {
if (getPtyProcess()->wait(1)) break;
QApplication::processEvents();
}
});
}
void MainWindow::on_toolButton_push_clicked()
{
ui->action_push->trigger();
}
void MainWindow::on_toolButton_pull_clicked()
{
ui->action_pull->trigger();
}
void MainWindow::on_toolButton_status_clicked()
{
showStatus();
}
void MainWindow::on_action_repository_status_triggered()
{
showStatus();
}
void MainWindow::on_treeWidget_repos_currentItemChanged(QTreeWidgetItem * /*current*/, QTreeWidgetItem * /*previous*/)
{
updateStatusBarText();
}
void MainWindow::on_treeWidget_repos_itemDoubleClicked(QTreeWidgetItem * /*item*/, int /*column*/)
{
openSelectedRepository();
}
-void BasicMainWindow::execCommitPropertyDialog(QWidget *parent, Git::CommitItem const *commit)
+void MainWindow::execCommitPropertyDialog(QWidget *parent, Git::CommitItem const *commit)
{
CommitPropertyDialog dlg(parent, this, commit);
dlg.exec();
}
int MainWindow::indexOfRepository(QTreeWidgetItem const *treeitem) const
{
if (!treeitem) return -1;
return treeitem->data(0, IndexRole).toInt();
}
void MainWindow::on_treeWidget_repos_customContextMenuRequested(const QPoint &pos)
{
QTreeWidgetItem *treeitem = ui->treeWidget_repos->currentItem();
if (!treeitem) return;
RepositoryItem const *repo = repositoryItem(treeitem);
int index = indexOfRepository(treeitem);
if (isGroupItem(treeitem)) { // group item
QMenu menu;
QAction *a_add_new_group = menu.addAction(tr("&Add new group"));
QAction *a_delete_group = menu.addAction(tr("&Delete group"));
QAction *a_rename_group = menu.addAction(tr("&Rename group"));
QPoint pt = ui->treeWidget_repos->mapToGlobal(pos);
QAction *a = menu.exec(pt + QPoint(8, -8));
if (a) {
if (a == a_add_new_group) {
QTreeWidgetItem *child = newQTreeWidgetFolderItem(tr("New group"));
treeitem->addChild(child);
child->setFlags(child->flags() | Qt::ItemIsEditable);
ui->treeWidget_repos->setCurrentItem(child);
return;
}
if (a == a_delete_group) {
QTreeWidgetItem *parent = treeitem->parent();
if (parent) {
int i = parent->indexOfChild(treeitem);
delete parent->takeChild(i);
} else {
int i = ui->treeWidget_repos->indexOfTopLevelItem(treeitem);
delete ui->treeWidget_repos->takeTopLevelItem(i);
}
refrectRepositories();
return;
}
if (a == a_rename_group) {
ui->treeWidget_repos->editItem(treeitem);
return;
}
}
} else if (repo) { // repository item
QString open_terminal = tr("Open &terminal");
QString open_commandprompt = tr("Open command promp&t");
QMenu menu;
QAction *a_open = menu.addAction(tr("&Open"));
menu.addSeparator();
#ifdef Q_OS_WIN
QAction *a_open_terminal = menu.addAction(open_commandprompt);
(void)open_terminal;
#else
QAction *a_open_terminal = menu.addAction(open_terminal);
(void)open_commandprompt;
#endif
a_open_terminal->setIcon(QIcon(":/image/terminal.svg"));
QAction *a_open_folder = menu.addAction(tr("Open &folder"));
a_open_folder->setIcon(QIcon(":/image/explorer.svg"));
menu.addSeparator();
QAction *a_remove = menu.addAction(tr("&Remove"));
menu.addSeparator();
QAction *a_properties = addMenuActionProperty(&menu);
QPoint pt = ui->treeWidget_repos->mapToGlobal(pos);
QAction *a = menu.exec(pt + QPoint(8, -8));
if (a) {
if (a == a_open) {
openSelectedRepository();
return;
}
if (a == a_open_folder) {
openExplorer(repo);
return;
}
if (a == a_open_terminal) {
openTerminal(repo);
return;
}
if (a == a_remove) {
removeRepositoryFromBookmark(index, true);
return;
}
if (a == a_properties) {
execRepositoryPropertyDialog(*repo);
return;
}
}
}
}
void MainWindow::on_tableWidget_log_customContextMenuRequested(const QPoint &pos)
{
int row = selectedLogIndex();
Git::CommitItem const *commit = commitItem(row);
if (commit) {
bool is_valid_commit_id = Git::isValidID(commit->commit_id);
QMenu menu;
QAction *a_copy_id_7letters = is_valid_commit_id ? menu.addAction(tr("Copy commit id (7 letters)")) : nullptr;
QAction *a_copy_id_complete = is_valid_commit_id ? menu.addAction(tr("Copy commit id (completely)")) : nullptr;
std::set<QAction *> copy_label_actions;
{
QList<BasicMainWindow::Label> v = sortedLabels(row);
if (!v.isEmpty()) {
auto *copy_lebel_menu = menu.addMenu("Copy label");
for (BasicMainWindow::Label const &l : v) {
QAction *a = copy_lebel_menu->addAction(l.text);
copy_label_actions.insert(copy_label_actions.end(), a);
}
}
}
menu.addSeparator();
QAction *a_checkout = menu.addAction(tr("Checkout/Branch..."));
menu.addSeparator();
QAction *a_edit_message = nullptr;
auto canEditMessage = [&](){
if (commit->has_child) return false; // 子がないこと
if (Git::isUncommited(*commit)) return false; // 未コミットがないこと
bool is_head = false;
bool has_remote_branch = false;
QList<Label> const *labels = label(row);
for (const Label &label : *labels) {
if (label.kind == Label::Head) {
is_head = true;
} else if (label.kind == Label::RemoteBranch) {
has_remote_branch = true;
}
}
return is_head && !has_remote_branch; // HEAD && リモートブランチ無し
};
if (canEditMessage()) {
a_edit_message = menu.addAction(tr("Edit message..."));
}
QAction *a_merge = is_valid_commit_id ? menu.addAction(tr("Merge")) : nullptr;
QAction *a_rebase = is_valid_commit_id ? menu.addAction(tr("Rebase")) : nullptr;
QAction *a_cherrypick = is_valid_commit_id ? menu.addAction(tr("Cherry-pick")) : nullptr;
QAction *a_edit_tags = is_valid_commit_id ? menu.addAction(tr("Edit tags...")) : nullptr;
QAction *a_revert = is_valid_commit_id ? menu.addAction(tr("Revert")) : nullptr;
menu.addSeparator();
QAction *a_delbranch = is_valid_commit_id ? menu.addAction(tr("Delete branch...")) : nullptr;
QAction *a_delrembranch = remoteBranches(commit->commit_id, nullptr).isEmpty() ? nullptr : menu.addAction(tr("Delete remote branch..."));
menu.addSeparator();
QAction *a_explore = is_valid_commit_id ? menu.addAction(tr("Explore")) : nullptr;
QAction *a_properties = addMenuActionProperty(&menu);
QAction *a = menu.exec(ui->tableWidget_log->viewport()->mapToGlobal(pos) + QPoint(8, -8));
if (a) {
if (a == a_copy_id_7letters) {
qApp->clipboard()->setText(commit->commit_id.mid(0, 7));
return;
}
if (a == a_copy_id_complete) {
qApp->clipboard()->setText(commit->commit_id);
return;
}
if (a == a_properties) {
execCommitPropertyDialog(this, commit);
return;
}
if (a == a_edit_message) {
commitAmend();
return;
}
if (a == a_checkout) {
checkout(this, commit);
return;
}
if (a == a_delbranch) {
deleteBranch(commit);
return;
}
if (a == a_delrembranch) {
deleteRemoteBranch(commit);
return;
}
if (a == a_merge) {
merge(commit);
return;
}
if (a == a_rebase) {
rebaseBranch(commit);
return;
}
if (a == a_cherrypick) {
cherrypick(commit);
return;
}
if (a == a_edit_tags) {
ui->action_edit_tags->trigger();
return;
}
if (a == a_revert) {
revertCommit();
return;
}
if (a == a_explore) {
execCommitExploreWindow(this, commit);
return;
}
if (copy_label_actions.find(a) != copy_label_actions.end()) {
QString text = a->text();
QApplication::clipboard()->setText(text);
return;
}
}
}
}
void MainWindow::on_listWidget_files_customContextMenuRequested(const QPoint &pos)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
QMenu menu;
QAction *a_delete = menu.addAction(tr("Delete"));
QAction *a_untrack = menu.addAction(tr("Untrack"));
QAction *a_history = menu.addAction(tr("History"));
QAction *a_blame = menu.addAction(tr("Blame"));
QAction *a_properties = addMenuActionProperty(&menu);
QPoint pt = ui->listWidget_files->mapToGlobal(pos) + QPoint(8, -8);
QAction *a = menu.exec(pt);
if (a) {
QListWidgetItem *item = ui->listWidget_files->currentItem();
if (a == a_delete) {
if (askAreYouSureYouWantToRun("Delete", tr("Delete selected files."))) {
for_each_selected_files([&](QString const &path){
g->removeFile(path);
g->chdirexec([&](){
QFile(path).remove();
return true;
});
});
openRepository(false);
}
} else if (a == a_untrack) {
if (askAreYouSureYouWantToRun("Untrack", tr("rm --cached files"))) {
for_each_selected_files([&](QString const &path){
g->rm_cached(path);
});
openRepository(false);
}
} else if (a == a_history) {
execFileHistory(item);
} else if (a == a_blame) {
blame(item);
} else if (a == a_properties) {
execFilePropertyDialog(item);
}
}
}
void MainWindow::on_listWidget_unstaged_customContextMenuRequested(const QPoint &pos)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
QList<QListWidgetItem *> items = ui->listWidget_unstaged->selectedItems();
if (!items.isEmpty()) {
QMenu menu;
QAction *a_stage = menu.addAction(tr("Stage"));
QAction *a_reset_file = menu.addAction(tr("Reset"));
QAction *a_ignore = menu.addAction(tr("Ignore"));
QAction *a_delete = menu.addAction(tr("Delete"));
QAction *a_untrack = menu.addAction(tr("Untrack"));
QAction *a_history = menu.addAction(tr("History"));
QAction *a_blame = menu.addAction(tr("Blame"));
QAction *a_properties = addMenuActionProperty(&menu);
QPoint pt = ui->listWidget_unstaged->mapToGlobal(pos) + QPoint(8, -8);
QAction *a = menu.exec(pt);
if (a) {
QListWidgetItem *item = ui->listWidget_unstaged->currentItem();
if (a == a_stage) {
for_each_selected_files([&](QString const &path){
g->stage(path);
});
updateCurrentFilesList();
return;
}
if (a == a_reset_file) {
QStringList paths;
for_each_selected_files([&](QString const &path){
paths.push_back(path);
});
resetFile(paths);
return;
}
if (a == a_ignore) {
QString gitignore_path = currentWorkingCopyDir() / ".gitignore";
if (items.size() == 1) {
QString file = getFilePath(items[0]);
EditGitIgnoreDialog dlg(this, gitignore_path, file);
if (dlg.exec() == QDialog::Accepted) {
QString appending = dlg.text();
if (!appending.isEmpty()) {
QString text;
QString path = gitignore_path;
path.replace('/', QDir::separator());
{
QFile file(path);
if (file.open(QFile::ReadOnly)) {
text += QString::fromUtf8(file.readAll());
}
}
size_t n = text.size();
if (n > 0 && text[(int)n - 1] != '\n') {
text += '\n'; // 最後に改行を追加
}
text += appending + '\n';
{
QFile file(path);
if (file.open(QFile::WriteOnly)) {
file.write(text.toUtf8());
}
}
updateCurrentFilesList();
return;
}
} else {
return;
}
}
QString append;
for_each_selected_files([&](QString const &path){
if (path == ".gitignore") {
// skip
} else {
append += path + '\n';
}
});
if (TextEditDialog::editFile(this, gitignore_path, ".gitignore", append)) {
updateCurrentFilesList();
}
return;
}
if (a == a_delete) {
if (askAreYouSureYouWantToRun("Delete", "Delete selected files.")) {
for_each_selected_files([&](QString const &path){
g->removeFile(path);
g->chdirexec([&](){
QFile(path).remove();
return true;
});
});
openRepository(false);
}
return;
}
if (a == a_untrack) {
if (askAreYouSureYouWantToRun("Untrack", "rm --cached")) {
for_each_selected_files([&](QString const &path){
g->rm_cached(path);
});
openRepository(false);
}
return;
}
if (a == a_history) {
execFileHistory(item);
return;
}
if (a == a_blame) {
blame(item);
return;
}
if (a == a_properties) {
execFilePropertyDialog(item);
return;
}
}
}
}
void MainWindow::on_listWidget_staged_customContextMenuRequested(const QPoint &pos)
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
QListWidgetItem *item = ui->listWidget_staged->currentItem();
if (item) {
QString path = getFilePath(item);
QString fullpath = currentWorkingCopyDir() / path;
if (QFileInfo(fullpath).isFile()) {
QMenu menu;
QAction *a_unstage = menu.addAction(tr("Unstage"));
QAction *a_history = menu.addAction(tr("History"));
QAction *a_blame = menu.addAction(tr("Blame"));
QAction *a_properties = addMenuActionProperty(&menu);
QPoint pt = ui->listWidget_staged->mapToGlobal(pos) + QPoint(8, -8);
QAction *a = menu.exec(pt);
if (a) {
QListWidgetItem *item = ui->listWidget_unstaged->currentItem();
if (a == a_unstage) {
g->unstage(path);
openRepository(false);
} else if (a == a_history) {
execFileHistory(item);
} else if (a == a_blame) {
blame(item);
} else if (a == a_properties) {
execFilePropertyDialog(item);
}
}
}
}
}
QStringList MainWindow::selectedFiles_(QListWidget *listwidget) const
{
QStringList list;
QList<QListWidgetItem *> items = listwidget->selectedItems();
for (QListWidgetItem *item : items) {
QString path = getFilePath(item);
list.push_back(path);
}
return list;
}
QStringList MainWindow::selectedFiles() const
{
- if (m->last_focused_file_list == ui->listWidget_files) return selectedFiles_(ui->listWidget_files);
- if (m->last_focused_file_list == ui->listWidget_staged) return selectedFiles_(ui->listWidget_staged);
- if (m->last_focused_file_list == ui->listWidget_unstaged) return selectedFiles_(ui->listWidget_unstaged);
+ if (m2->last_focused_file_list == ui->listWidget_files) return selectedFiles_(ui->listWidget_files);
+ if (m2->last_focused_file_list == ui->listWidget_staged) return selectedFiles_(ui->listWidget_staged);
+ if (m2->last_focused_file_list == ui->listWidget_unstaged) return selectedFiles_(ui->listWidget_unstaged);
return QStringList();
}
void MainWindow::for_each_selected_files(std::function<void(QString const&)> const &fn)
{
for (QString const &path : selectedFiles()) {
fn(path);
}
}
-void BasicMainWindow::execFileHistory(QListWidgetItem *item)
+void MainWindow::execFileHistory(QListWidgetItem *item)
{
if (item) {
QString path = getFilePath(item);
if (!path.isEmpty()) {
execFileHistory(path);
}
}
}
+void MainWindow::checkout(QWidget *parent, const Git::CommitItem *commit, std::function<void ()> accepted_callback)
+{
+ if (!commit) return;
+
+ GitPtr g = git();
+ if (!isValidWorkingCopy(g)) return;
+
+ QStringList tags;
+ QStringList all_local_branches;
+ QStringList local_branches;
+ QStringList remote_branches;
+ {
+ NamedCommitList named_commits = namedCommitItems(Branches | Tags | Remotes);
+ for (NamedCommitItem const &item : named_commits) {
+ QString name = item.name;
+ if (item.id == commit->commit_id) {
+ if (item.type == NamedCommitItem::Type::Tag) {
+ tags.push_back(name);
+ } else if (item.type == NamedCommitItem::Type::BranchLocal || item.type == NamedCommitItem::Type::BranchRemote) {
+ int i = name.lastIndexOf('/');
+ if (i < 0 && name == "HEAD") continue;
+ if (i > 0 && name.mid(i + 1) == "HEAD") continue;
+ if (item.type == NamedCommitItem::Type::BranchLocal) {
+ local_branches.push_back(name);
+ } else if (item.type == NamedCommitItem::Type::BranchRemote) {
+ remote_branches.push_back(name);
+ }
+ }
+ }
+ if (item.type == NamedCommitItem::Type::BranchLocal) {
+ all_local_branches.push_back(name);
+ }
+ }
+ }
+
+ CheckoutDialog dlg(parent, tags, all_local_branches, local_branches, remote_branches);
+ if (dlg.exec() == QDialog::Accepted) {
+ if (accepted_callback) {
+ accepted_callback();
+ }
+ CheckoutDialog::Operation op = dlg.operation();
+ QString name = dlg.branchName();
+ QString id = commit->commit_id;
+ if (id.isEmpty() && !commit->parent_ids.isEmpty()) {
+ id = commit->parent_ids.front();
+ }
+ bool ok = false;
+ setLogEnabled(g, true);
+ if (op == CheckoutDialog::Operation::HeadDetached) {
+ if (!id.isEmpty()) {
+ ok = g->git(QString("checkout \"%1\"").arg(id), true);
+ }
+ } else if (op == CheckoutDialog::Operation::CreateLocalBranch) {
+ if (!name.isEmpty() && !id.isEmpty()) {
+ ok = g->git(QString("checkout -b \"%1\" \"%2\"").arg(name).arg(id), true);
+ }
+ } else if (op == CheckoutDialog::Operation::ExistingLocalBranch) {
+ if (!name.isEmpty()) {
+ ok = g->git(QString("checkout \"%1\"").arg(name), true);
+ }
+ }
+ if (ok) {
+ openRepository(true);
+ }
+ }
+}
+
+void MainWindow::checkout()
+{
+ checkout(this, selectedCommitItem());
+}
+
/**
* @brief コミットログの選択が変化した
*/
void MainWindow::doLogCurrentItemChanged()
{
clearFileList();
int row = selectedLogIndex();
QTableWidgetItem *item = ui->tableWidget_log->item(row, 0);
if (item) {
auto const &logs = getLogs();
int index = item->data(IndexRole).toInt();
if (index < (int)logs.size()) {
updateStatusBarText();
*ptrUpdateFilesListCounter() = 200;
}
} else {
row = -1;
}
updateAncestorCommitMap();
ui->tableWidget_log->viewport()->update();
}
void MainWindow::findNext()
{
- if (m->search_text.isEmpty()) {
+ if (m2->search_text.isEmpty()) {
return;
}
auto const &logs = getLogs();
for (int pass = 0; pass < 2; pass++) {
int row = 0;
if (pass == 0) {
row = selectedLogIndex();
if (row < 0) {
row = 0;
- } else if (m->searching) {
+ } else if (m2->searching) {
row++;
}
}
while (row < (int)logs.size()) {
Git::CommitItem const commit = logs[row];
if (!Git::isUncommited(commit)) {
- if (commit.message.indexOf(m->search_text, 0, Qt::CaseInsensitive) >= 0) {
+ if (commit.message.indexOf(m2->search_text, 0, Qt::CaseInsensitive) >= 0) {
bool b = ui->tableWidget_log->blockSignals(true);
setCurrentLogRow(row);
ui->tableWidget_log->blockSignals(b);
- m->searching = true;
+ m2->searching = true;
return;
}
}
row++;
}
}
}
void MainWindow::findText(QString const &text)
{
- m->search_text = text;
+ m2->search_text = text;
}
bool MainWindow::isAncestorCommit(QString const &id)
{
- auto it = m->ancestors.find(id);
- return it != m->ancestors.end();
+ auto it = m2->ancestors.find(id);
+ return it != m2->ancestors.end();
}
void MainWindow::updateAncestorCommitMap()
{
- m->ancestors.clear();
+ m2->ancestors.clear();
auto const &logs = getLogs();
const size_t LogCount = logs.size();
const size_t index = selectedLogIndex();
if (index < LogCount) {
// ok
} else {
return;
}
auto *logsp = getLogsPtr();
auto LogItem = [&](size_t i)->Git::CommitItem &{ return logsp->at(i); };
std::map<QString, size_t> commit_to_index_map;
size_t end = LogCount;
if (index < end) {
for (size_t i = index; i < end; i++) {
Git::CommitItem const &commit = LogItem(i);
commit_to_index_map[commit.commit_id] = i;
auto *item = ui->tableWidget_log->item(i, 0);
QRect r = ui->tableWidget_log->visualItemRect(item);
if (r.y() >= ui->tableWidget_log->height()) {
end = i + 1;
break;
}
}
}
Git::CommitItem *item = &LogItem(index);
if (item) {
- m->ancestors.insert(m->ancestors.end(), item->commit_id);
+ m2->ancestors.insert(m2->ancestors.end(), item->commit_id);
}
for (size_t i = index; i < end; i++) {
Git::CommitItem *item = &LogItem(i);
if (isAncestorCommit(item->commit_id)) {
for (QString const &parent : item->parent_ids) {
- m->ancestors.insert(m->ancestors.end(), parent);
+ m2->ancestors.insert(m2->ancestors.end(), parent);
}
}
}
}
void MainWindow::on_action_open_existing_working_copy_triggered()
{
QString dir = defaultWorkingDir();
dir = QFileDialog::getExistingDirectory(this, tr("Add existing working copy"), dir);
addWorkingCopyDir(dir, false);
}
void MainWindow::on_action_view_refresh_triggered()
{
openRepository(true);
}
void MainWindow::on_tableWidget_log_currentItemChanged(QTableWidgetItem * /*current*/, QTableWidgetItem * /*previous*/)
{
doLogCurrentItemChanged();
- m->searching = false;
+ m2->searching = false;
}
void MainWindow::on_toolButton_stage_clicked()
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
g->stage(selectedFiles());
updateCurrentFilesList();
}
void MainWindow::on_toolButton_unstage_clicked()
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
g->unstage(selectedFiles());
updateCurrentFilesList();
}
void MainWindow::on_toolButton_select_all_clicked()
{
if (ui->listWidget_unstaged->count() > 0) {
ui->listWidget_unstaged->setFocus();
ui->listWidget_unstaged->selectAll();
} else if (ui->listWidget_staged->count() > 0) {
ui->listWidget_staged->setFocus();
ui->listWidget_staged->selectAll();
}
}
void MainWindow::on_toolButton_commit_clicked()
{
ui->action_commit->trigger();
}
void MainWindow::on_action_edit_global_gitconfig_triggered()
{
QString dir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
QString path = dir / ".gitconfig";
editFile(path, ".gitconfig");
}
void MainWindow::on_action_edit_git_config_triggered()
{
QString dir = currentWorkingCopyDir();
QString path = dir / ".git/config";
editFile(path, ".git/config");
}
void MainWindow::on_action_edit_gitignore_triggered()
{
QString dir = currentWorkingCopyDir();
QString path = dir / ".gitignore";
if (editFile(path, ".gitignore")) {
updateCurrentFilesList();
}
}
int MainWindow::selectedLogIndex() const
{
auto const &logs = getLogs();
int i = ui->tableWidget_log->currentRow();
if (i >= 0 && i < (int)logs.size()) {
return i;
}
return -1;
}
void MainWindow::updateDiffView(QListWidgetItem *item)
{
clearDiffView();
- m->last_selected_file_item = item;
+ m2->last_selected_file_item = item;
if (!item) return;
int idiff = indexOfDiff(item);
if (idiff >= 0 && idiff < diffResult()->size()) {
Git::Diff const &diff = diffResult()->at(idiff);
QString key = GitDiff::makeKey(diff);
auto it = getDiffCacheMap()->find(key);
if (it != getDiffCacheMap()->end()) {
auto const &logs = getLogs();
int row = ui->tableWidget_log->currentRow();
bool uncommited = (row >= 0 && row < (int)logs.size() && Git::isUncommited(logs[row]));
ui->widget_diff_view->updateDiffView(it->second, uncommited);
}
}
}
void MainWindow::updateDiffView()
{
- updateDiffView(m->last_selected_file_item);
+ updateDiffView(m2->last_selected_file_item);
}
void MainWindow::updateUnstagedFileCurrentItem()
{
updateDiffView(ui->listWidget_unstaged->currentItem());
}
void MainWindow::updateStagedFileCurrentItem()
{
updateDiffView(ui->listWidget_staged->currentItem());
}
void MainWindow::on_listWidget_unstaged_currentRowChanged(int /*currentRow*/)
{
updateUnstagedFileCurrentItem();
}
void MainWindow::on_listWidget_staged_currentRowChanged(int /*currentRow*/)
{
updateStagedFileCurrentItem();
}
void MainWindow::on_listWidget_files_currentRowChanged(int /*currentRow*/)
{
updateDiffView(ui->listWidget_files->currentItem());
}
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
if (QApplication::modalWindow()) return;
if (event->mimeData()->hasUrls()) {
event->acceptProposedAction();
event->accept();
}
}
void MainWindow::timerEvent(QTimerEvent *)
{
bool running = getPtyProcess()->isRunning();
if (ui->toolButton_stop_process->isEnabled() != running) {
ui->toolButton_stop_process->setEnabled(running);
ui->action_stop_process->setEnabled(running);
setNetworkingCommandsEnabled(!running);
}
if (!running) {
setInteractionMode(InteractionMode::None);
}
while (1) {
char tmp[1024];
int len = getPtyProcess()->readOutput(tmp, sizeof(tmp));
if (len < 1) break;
writeLog(tmp, len);
}
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
int c = event->key();
if (c == Qt::Key_T && (event->modifiers() & Qt::ControlModifier)) {
test();
return;
}
if (QApplication::focusWidget() == ui->widget_log) {
auto write_char = [&](char c){
if (getPtyProcess()->isRunning()) {
getPtyProcess()->writeInput(&c, 1);
}
};
auto write_text = [&](QString const &str){
std::string s = str.toStdString();
for (char i : s) {
write_char(i);
}
};
if (c == Qt::Key_Return || c == Qt::Key_Enter) {
write_char('\n');
} else {
QString text = event->text();
write_text(text);
}
}
}
void MainWindow::on_action_edit_settings_triggered()
{
SettingsDialog dlg(this);
if (dlg.exec() == QDialog::Accepted) {
ApplicationSettings const &newsettings = dlg.settings();
setAppSettings(newsettings);
setGitCommand(appsettings()->git_command, false);
setFileCommand(appsettings()->file_command, false);
setGpgCommand(appsettings()->gpg_command, false);
- setRemoteMonitoringEnabled(true);
}
}
void MainWindow::onCloneCompleted(bool success, QVariant const &userdata)
{
if (success) {
RepositoryItem r = userdata.value<RepositoryItem>();
saveRepositoryBookmark(r);
setCurrentRepository(r, false);
openRepository(true);
}
}
void MainWindow::onPtyProcessCompleted(bool /*ok*/, QVariant const &userdata)
{
switch (getPtyCondition()) {
case PtyCondition::Clone:
onCloneCompleted(getPtyProcessOk(), userdata);
break;
}
setPtyCondition(PtyCondition::None);
}
void MainWindow::on_action_clone_triggered()
{
clone();
}
void MainWindow::on_action_about_triggered()
{
AboutDialog dlg(this);
dlg.exec();
}
void MainWindow::on_toolButton_clone_clicked()
{
ui->action_clone->trigger();
}
void MainWindow::on_toolButton_fetch_clicked()
{
ui->action_fetch->trigger();
}
void MainWindow::clearRepoFilter()
{
ui->lineEdit_filter->clear();
}
void MainWindow::appendCharToRepoFilter(ushort c)
{
if (QChar(c).isLetter()) {
c = QChar(c).toLower().unicode();
}
ui->lineEdit_filter->setText(getRepositoryFilterText() + c);
}
void MainWindow::backspaceRepoFilter()
{
QString s = getRepositoryFilterText();
int n = s.size();
if (n > 0) {
s = s.mid(0, n - 1);
}
ui->lineEdit_filter->setText(s);
}
void MainWindow::on_lineEdit_filter_textChanged(QString const &text)
{
setRepositoryFilterText(text);
updateRepositoriesList();
}
void MainWindow::on_toolButton_erase_filter_clicked()
{
clearRepoFilter();
ui->lineEdit_filter->setFocus();
}
void MainWindow::deleteTags(QStringList const &tagnames)
{
int row = ui->tableWidget_log->currentRow();
internalDeleteTags(tagnames);
ui->tableWidget_log->selectRow(row);
}
void MainWindow::revertCommit()
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
Git::CommitItem const *commit = selectedCommitItem();
if (commit) {
g->revert(commit->commit_id);
openRepository(false);
}
}
bool MainWindow::addTag(QString const &name)
{
int row = ui->tableWidget_log->currentRow();
bool ok = internalAddTag(name);
ui->tableWidget_log->selectRow(row);
return ok;
}
void MainWindow::on_action_push_all_tags_triggered()
{
reopenRepository(false, [&](GitPtr g){
g->push(true);
});
}
void MainWindow::on_tableWidget_log_itemDoubleClicked(QTableWidgetItem *)
{
Git::CommitItem const *commit = selectedCommitItem();
if (commit) {
execCommitPropertyDialog(this, commit);
}
}
void MainWindow::on_listWidget_unstaged_itemDoubleClicked(QListWidgetItem * item)
{
execFilePropertyDialog(item);
}
void MainWindow::on_listWidget_staged_itemDoubleClicked(QListWidgetItem *item)
{
execFilePropertyDialog(item);
}
void MainWindow::on_listWidget_files_itemDoubleClicked(QListWidgetItem *item)
{
execFilePropertyDialog(item);
}
QListWidgetItem *MainWindow::currentFileItem() const
{
QListWidget *listwidget = nullptr;
if (ui->stackedWidget_filelist->currentWidget() == ui->page_uncommited) {
QWidget *w = qApp->focusWidget();
if (w == ui->listWidget_unstaged) {
listwidget = ui->listWidget_unstaged;
} else if (w == ui->listWidget_staged) {
listwidget = ui->listWidget_staged;
}
} else {
listwidget = ui->listWidget_files;
}
if (listwidget) {
return listwidget->currentItem();
}
return nullptr;
}
void MainWindow::on_action_set_config_user_triggered()
{
Git::User global_user;
Git::User repo_user;
GitPtr g = git();
if (isValidWorkingCopy(g)) {
repo_user = g->getUser(Git::Source::Local);
}
global_user = g->getUser(Git::Source::Global);
execSetUserDialog(global_user, repo_user, currentRepositoryName());
}
void MainWindow::showLogWindow(bool show)
{
ui->dockWidget_log->setVisible(show);
}
void MainWindow::on_action_window_log_triggered(bool checked)
{
showLogWindow(checked);
}
void MainWindow::on_action_repo_jump_triggered()
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
NamedCommitList items = namedCommitItems(Branches | Tags | Remotes);
{
NamedCommitItem head;
head.name = "HEAD";
head.id = getHeadId();
items.push_front(head);
}
JumpDialog dlg(this, items);
if (dlg.exec() == QDialog::Accepted) {
QString text = dlg.text();
if (text.isEmpty()) return;
QString id = g->rev_parse(text);
if (id.isEmpty() && Git::isValidID(text)) {
QStringList list = findGitObject(text);
if (list.isEmpty()) {
QMessageBox::warning(this, tr("Jump"), QString("%1\n\n").arg(text) + tr("No such commit"));
return;
}
ObjectBrowserDialog dlg2(this, list);
if (dlg2.exec() == QDialog::Accepted) {
id = dlg2.text();
if (id.isEmpty()) return;
}
}
if (g->objectType(id) == "tag") {
id = getObjCache()->getCommitIdFromTag(id);
}
int row = rowFromCommitId(id);
if (row < 0) {
QMessageBox::warning(this, tr("Jump"), QString("%1\n(%2)\n\n").arg(text).arg(id) + tr("No such commit"));
} else {
setCurrentLogRow(row);
}
}
}
void MainWindow::on_action_repo_checkout_triggered()
{
checkout();
}
void MainWindow::on_action_delete_branch_triggered()
{
deleteBranch();
}
void MainWindow::on_toolButton_terminal_clicked()
{
openTerminal(nullptr);
}
void MainWindow::on_toolButton_explorer_clicked()
{
openExplorer(nullptr);
}
void MainWindow::on_action_reset_HEAD_1_triggered()
{
GitPtr g = git();
if (!isValidWorkingCopy(g)) return;
g->reset_head1();
openRepository(false);
}
void MainWindow::on_action_create_a_repository_triggered()
{
createRepository(QString());
}
bool MainWindow::isOnlineMode() const
{
- return m->is_online_mode;
+ return m2->is_online_mode;
}
void MainWindow::setRemoteOnline(bool f, bool save)
{
- m->is_online_mode = f;
+ m2->is_online_mode = f;
{
QRadioButton *rb = nullptr;
rb = f ? ui->radioButton_remote_online : ui->radioButton_remote_offline;
rb->blockSignals(true);
rb->click();
rb->blockSignals(false);
ui->action_online->setCheckable(true);
ui->action_offline->setCheckable(true);
ui->action_online->setChecked(f);
ui->action_offline->setChecked(!f);
setNetworkingCommandsEnabled(f);
}
if (save) {
MySettings s;
s.beginGroup("Remote");
s.setValue("Online", f);
s.endGroup();
}
}
void MainWindow::on_radioButton_remote_online_clicked()
{
setRemoteOnline(true, true);
}
void MainWindow::on_radioButton_remote_offline_clicked()
{
setRemoteOnline(false, true);
}
void MainWindow::on_verticalScrollBar_log_valueChanged(int)
{
ui->widget_log->refrectScrollBar();
}
void MainWindow::on_horizontalScrollBar_log_valueChanged(int)
{
ui->widget_log->refrectScrollBar();
}
void MainWindow::on_toolButton_stop_process_clicked()
{
abortPtyProcess();
}
void MainWindow::on_action_stop_process_triggered()
{
abortPtyProcess();
}
void MainWindow::on_action_exit_triggered()
{
close();
}
void MainWindow::on_action_reflog_triggered()
{
GitPtr g = git();
Git::ReflogItemList reflog;
g->reflog(&reflog);
ReflogWindow dlg(this, this, reflog);
dlg.exec();
}
void MainWindow::blame(QListWidgetItem *item)
{
QList<BlameItem> list;
QString path = getFilePath(item);
{
GitPtr g = git();
QByteArray ba = g->blame(path);
if (!ba.isEmpty()) {
char const *begin = ba.data();
char const *end = begin + ba.size();
list = BlameWindow::parseBlame(begin, end);
}
}
if (!list.isEmpty()) {
qApp->setOverrideCursor(Qt::WaitCursor);
BlameWindow win(this, path, list);
qApp->restoreOverrideCursor();
win.exec();
}
}
void MainWindow::blame()
{
blame(currentFileItem());
}
void MainWindow::on_action_repository_property_triggered()
{
execRepositoryPropertyDialog(currentRepository());
}
void MainWindow::on_action_set_gpg_signing_triggered()
{
GitPtr g = git();
QString global_key_id = g->signingKey(Git::Source::Global);
QString repository_key_id;
if (g->isValidWorkingCopy()) {
repository_key_id = g->signingKey(Git::Source::Local);
}
SetGpgSigningDialog dlg(this, currentRepositoryName(), global_key_id, repository_key_id);
if (dlg.exec() == QDialog::Accepted) {
g->setSigningKey(dlg.id(), dlg.isGlobalChecked());
}
}
void MainWindow::execAreYouSureYouWantToContinueConnectingDialog()
{
using TheDlg = AreYouSureYouWantToContinueConnectingDialog;
setInteractionMode(InteractionMode::Busy);
QApplication::restoreOverrideCursor();
TheDlg dlg(this);
if (dlg.exec() == QDialog::Accepted) {
TheDlg::Result r = dlg.result();
if (r == TheDlg::Result::Yes) {
getPtyProcess()->writeInput("yes\n", 4);
} else {
setPtyProcessOk(false); // abort
getPtyProcess()->writeInput("no\n", 3);
QThread::msleep(300);
stopPtyProcess();
}
} else {
ui->widget_log->setFocus();
setInteractionCanceled(true);
}
setInteractionMode(InteractionMode::Busy);
}
void MainWindow::onLogIdle()
{
if (interactionCanceled()) return;
if (interactionMode() != InteractionMode::None) return;
static char const are_you_sure_you_want_to_continue_connecting[] = "Are you sure you want to continue connecting (yes/no)?";
static char const enter_passphrase[] = "Enter passphrase: ";
static char const enter_passphrase_for_key[] = "Enter passphrase for key '";
static char const fatal_authentication_failed_for[] = "fatal: Authentication failed for '";
std::vector<char> vec;
ui->widget_log->retrieveLastText(&vec, 100);
if (!vec.empty()) {
std::string line;
int n = (int)vec.size();
int i = n;
while (i > 0) {
i--;
if (i + 1 < n && vec[i] == '\n') {
i++;
line.assign(&vec[i], n - i);
break;
}
}
if (!line.empty()) {
auto ExecLineEditDialog = [&](QWidget *parent, QString const &title, QString const &prompt, QString const &val, bool password){
LineEditDialog dlg(parent, title, prompt, val, password);
if (dlg.exec() == QDialog::Accepted) {
std::string ret = dlg.text().toStdString();
std::string str = ret + '\n';
getPtyProcess()->writeInput(str.c_str(), str.size());
return ret;
}
abortPtyProcess();
return std::string();
};
auto Match = [&](char const *str){
int n = strlen(str);
if (strncmp(line.c_str(), str, n) == 0) {
char const *p = line.c_str() + n;
while (1) {
if (!*p) return true;
if (!isspace((unsigned char)*p)) break;
p++;
}
}
return false;
};
auto StartsWith = [&](char const *str){
char const *p = line.c_str();
while (*str) {
if (*p != *str) return false;
str++;
p++;
}
return true;
};
if (Match(are_you_sure_you_want_to_continue_connecting)) {
execAreYouSureYouWantToContinueConnectingDialog();
return;
}
if (line == enter_passphrase) {
ExecLineEditDialog(this, "Passphrase", QString::fromStdString(line), QString(), true);
return;
}
if (StartsWith(enter_passphrase_for_key)) {
std::string keyfile;
{
int i = strlen(enter_passphrase_for_key);
char const *p = line.c_str() + i;
char const *q = strrchr(p, ':');
if (q && p + 2 < q && q[-1] == '\'') {
keyfile.assign(p, q - 1);
}
}
if (!keyfile.empty()) {
if (keyfile == sshPassphraseUser() && !sshPassphrasePass().empty()) {
std::string text = sshPassphrasePass() + '\n';
getPtyProcess()->writeInput(text.c_str(), text.size());
} else {
std::string secret = ExecLineEditDialog(this, "Passphrase for key", QString::fromStdString(line), QString(), true);
sshSetPassphrase(keyfile, secret);
}
return;
}
}
char const *begin = line.c_str();
char const *end = line.c_str() + line.size();
auto Input = [&](QString const &title, bool password, std::string *value){
Q_ASSERT(value);
std::string header = QString("%1 for '").arg(title).toStdString();
if (strncmp(begin, header.c_str(), header.size()) == 0) {
QString msg;
if (memcmp(end - 2, "':", 2) == 0) {
msg = QString::fromUtf8(begin, end - begin - 1);
} else if (memcmp(end - 3, "': ", 3) == 0) {
msg = QString::fromUtf8(begin, end - begin - 2);
}
if (!msg.isEmpty()) {
std::string s = ExecLineEditDialog(this, title, msg, value ? QString::fromStdString(*value) : QString(), password);
*value = s;
return true;
}
}
return false;
};
std::string uid = httpAuthenticationUser();
std::string pwd = httpAuthenticationPass();
bool ok = false;
if (Input("Username", false, &uid)) ok = true;
if (Input("Password", true, &pwd)) ok = true;
if (ok) {
httpSetAuthentication(uid, pwd);
return;
}
if (StartsWith(fatal_authentication_failed_for)) {
QMessageBox::critical(this, tr("Authentication Failed"), QString::fromStdString(line));
abortPtyProcess();
return;
}
}
}
}
void MainWindow::on_action_edit_tags_triggered()
{
Git::CommitItem const *commit = selectedCommitItem();
if (commit && Git::isValidID(commit->commit_id)) {
EditTagsDialog dlg(this, commit);
dlg.exec();
}
}
void MainWindow::on_action_push_u_triggered()
{
pushSetUpstream(false);
}
void MainWindow::on_action_delete_remote_branch_triggered()
{
deleteRemoteBranch(selectedCommitItem());
}
void MainWindow::on_action_terminal_triggered()
{
auto const *repo = &currentRepository();
openTerminal(repo);
}
void MainWindow::on_action_explorer_triggered()
{
auto const *repo = &currentRepository();
openExplorer(repo);
}
void MainWindow::on_action_reset_hard_triggered()
{
doGitCommand([&](GitPtr g){
g->reset_hard();
});
}
void MainWindow::on_action_clean_df_triggered()
{
doGitCommand([&](GitPtr g){
g->clean_df();
});
}
void MainWindow::postOpenRepositoryFromGitHub(QString const &username, QString const &reponame)
{
QVariantList list;
list.push_back(username);
list.push_back(reponame);
postUserFunctionEvent([&](QVariant const &v){
QVariantList l = v.toList();
QString uname = l[0].toString();
QString rname = l[1].toString();
CloneFromGitHubDialog dlg(this, uname, rname);
if (dlg.exec() == QDialog::Accepted) {
clone(dlg.url());
}
}, QVariant(list));
}
void MainWindow::on_action_stash_triggered()
{
doGitCommand([&](GitPtr g){
g->stash();
});
}
void MainWindow::on_action_stash_apply_triggered()
{
doGitCommand([&](GitPtr g){
g->stash_apply();
});
}
void MainWindow::on_action_stash_drop_triggered()
{
doGitCommand([&](GitPtr g){
g->stash_drop();
});
}
void MainWindow::on_action_online_triggered()
{
ui->radioButton_remote_online->click();
}
void MainWindow::on_action_offline_triggered()
{
ui->radioButton_remote_offline->click();
}
void MainWindow::on_action_repositories_panel_triggered()
{
bool checked = ui->action_repositories_panel->isChecked();
ui->stackedWidget_leftpanel->setCurrentWidget(checked ? ui->page_repos : ui->page_collapsed);
if (checked) {
- ui->stackedWidget_leftpanel->setFixedWidth(m->repos_panel_width);
+ ui->stackedWidget_leftpanel->setFixedWidth(m2->repos_panel_width);
ui->stackedWidget_leftpanel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
ui->stackedWidget_leftpanel->setMinimumWidth(QWIDGETSIZE_MAX);
ui->stackedWidget_leftpanel->setMaximumWidth(QWIDGETSIZE_MAX);
} else {
- m->repos_panel_width = ui->stackedWidget_leftpanel->width();
+ m2->repos_panel_width = ui->stackedWidget_leftpanel->width();
ui->stackedWidget_leftpanel->setFixedWidth(24);
}
}
void MainWindow::on_action_find_triggered()
{
- m->searching = false;
+ m2->searching = false;
if (getLogs().empty()) {
return;
}
- FindCommitDialog dlg(this, m->search_text);
+ FindCommitDialog dlg(this, m2->search_text);
if (dlg.exec() == QDialog::Accepted) {
- m->search_text = dlg.text();
+ m2->search_text = dlg.text();
ui->tableWidget_log->setFocus();
findNext();
}
}
void MainWindow::on_action_find_next_triggered()
{
- if (m->search_text.isEmpty()) {
+ if (m2->search_text.isEmpty()) {
on_action_find_triggered();
} else {
findNext();
}
}
void MainWindow::on_action_repo_jump_to_head_triggered()
{
QString name = "HEAD";
GitPtr g = git();
QString id = g->rev_parse(name);
int row = rowFromCommitId(id);
if (row < 0) {
qDebug() << "No such commit";
} else {
setCurrentLogRow(row);
}
}
void MainWindow::on_action_repo_merge_triggered()
{
merge();
}
void MainWindow::on_action_expand_commit_log_triggered()
{
ui->splitter_h->setSizes({10000, 1, 1});
}
void MainWindow::on_action_expand_file_list_triggered()
{
ui->splitter_h->setSizes({1, 10000, 1});
}
void MainWindow::on_action_expand_diff_view_triggered()
{
ui->splitter_h->setSizes({1, 1, 10000});
}
void MainWindow::on_action_sidebar_triggered()
{
bool f = ui->stackedWidget_leftpanel->isVisible();
f = !f;
ui->stackedWidget_leftpanel->setVisible(f);
ui->action_sidebar->setChecked(f);
}
#if 0
void MainWindow::on_action_wide_triggered()
{
QWidget *w = focusWidget();
if (w == m->focused_widget) {
ui->splitter_h->setSizes(m->splitter_h_sizes);
m->focused_widget = nullptr;
} else {
m->focused_widget = w;
m->splitter_h_sizes = ui->splitter_h->sizes();
if (w == ui->tableWidget_log) {
ui->splitter_h->setSizes({10000, 1, 1});
} else if (ui->stackedWidget_filelist->isAncestorOf(w)) {
ui->splitter_h->setSizes({1, 10000, 1});
} else if (ui->frame_diff_view->isAncestorOf(w)) {
ui->splitter_h->setSizes({1, 1, 10000});
}
}
}
#endif
void MainWindow::setShowLabels(bool show, bool save)
{
ApplicationSettings *as = appsettings();
as->show_labels = show;
bool b = ui->action_show_labels->blockSignals(true);
ui->action_show_labels->setChecked(show);
ui->action_show_labels->blockSignals(b);
if (save) {
saveApplicationSettings();
}
}
bool MainWindow::isLabelsVisible() const
{
return appsettings()->show_labels;
}
void MainWindow::on_action_show_labels_triggered()
{
bool f = ui->action_show_labels->isChecked();
setShowLabels(f, true);
ui->tableWidget_log->viewport()->update();
}
void MainWindow::test()
{
QElapsedTimer t;
t.start();
{
QPixmap pm(1, 1);
QPainter pr(&pm);
pr.setFont(QFont("MS Gothic", 30));
char tmp[2];
for (int i = 0x20; i < 0x80; i++) {
tmp[0] = i;
tmp[1] = 0;
QString s = tmp;
int w = pr.fontMetrics().size(0, s).width();
qDebug() << w;
}
}
qDebug() << QString("%1ms").arg(t.elapsed());
}
void MainWindow::on_action_submodules_triggered()
{
GitPtr g = git();
QList<Git::Submodule> mods = g->submodules();
std::vector<SubmodulesDialog::Submodule> mods2;
mods2.resize(mods.size());
for (size_t i = 0; i < mods.size(); i++) {
const Git::Submodule mod = mods[i];
mods2[i].submodule = mod;
GitPtr g2 = git(g->workingRepositoryDir() / mod.path, g->sshKey());
g2->queryCommit(mod.id, &mods2[i].head);
}
SubmodulesDialog dlg(this, mods2);
dlg.exec();
}
void MainWindow::on_action_submodule_add_triggered()
{
QString dir = currentRepository().local_dir;
submodule_add({}, dir);
}
void MainWindow::on_action_submodule_update_triggered()
{
SubmoduleUpdateDialog dlg(this);
if (dlg.exec() == QDialog::Accepted) {
GitPtr g = git();
Git::SubmoduleUpdateData data;
data.init = dlg.isInit();
data.recursive = dlg.isRecursive();
g->submodule_update(data, getPtyProcess());
}
}
diff --git a/src/MainWindow.h b/src/MainWindow.h
index ff93a4b..7419815 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -1,243 +1,560 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "BasicMainWindow.h"
+#include "Git.h"
+
+#include "GitHubAPI.h"
+#include "RepositoryData.h"
+#include "MyProcess.h"
+#include "main.h"
+#include "webclient.h"
+#include "AvatarLoader.h"
+#include "GitObjectManager.h"
+#include "Theme.h"
namespace Ui {
class MainWindow;
}
+class QListWidgetItem;
+class QListWidget;
+class QTreeWidgetItem;
class QTableWidgetItem;
class HunkItem {
public:
int hunk_number = -1;
size_t pos, len;
std::vector<std::string> lines;
};
class MainWindow : public BasicMainWindow {
Q_OBJECT
friend class ImageViewWidget;
friend class FileDiffSliderWidget;
friend class FileHistoryWindow;
friend class FileDiffWidget;
friend class AboutDialog;
private:
- struct Private;
- Private *m;
+ struct Private1 {
+ ApplicationSettings appsettings;
+
+ QIcon repository_icon;
+ QIcon folder_icon;
+ QIcon signature_good_icon;
+ QIcon signature_dubious_icon;
+ QIcon signature_bad_icon;
+ QPixmap transparent_pixmap;
+
+ QString starting_dir;
+ Git::Context gcx;
+ RepositoryItem current_repo;
+
+ QList<RepositoryItem> repos;
+ Git::CommitItemList logs;
+ QList<Git::Diff> diff_result;
+ QList<Git::Submodule> submodules;
+
+ QStringList added;
+ QStringList remotes;
+ QString current_remote_name;
+ Git::Branch current_branch;
+ unsigned int temp_file_counter = 0;
+
+ std::string ssh_passphrase_user;
+ std::string ssh_passphrase_pass;
+
+ std::string http_uid;
+ std::string http_pwd;
+
+ std::map<QString, GitHubAPI::User> committer_map; // key is email
+
+ PtyProcess pty_process;
+ bool pty_process_ok = false;
+ PtyCondition pty_condition = PtyCondition::None;
+
+ WebContext webcx;
+
+ AvatarLoader avatar_loader;
+ int update_files_list_counter = 0;
+ int update_commit_table_counter = 0;
+
+ bool interaction_canceled = false;
+ InteractionMode interaction_mode = InteractionMode::None;
+
+ QString repository_filter_text;
+ bool uncommited_changes = false;
+
+ std::map<QString, QList<Git::Branch>> branch_map;
+ std::map<QString, QList<Git::Tag>> tag_map;
+ std::map<int, QList<Label>> label_map;
+ std::map<QString, Git::Diff> diff_cache;
+ GitObjectCache objcache;
+
+ bool remote_changed = false;
+
+ ServerType server_type = ServerType::Standard;
+ GitHubRepositoryInfo github;
+
+ QString head_id;
+ bool force_fetch = false;
+
+ RepositoryItem temp_repo_for_clone_complete;
+ QVariant pty_process_completion_data;
+ };
+ Private1 *m1;
+
+ struct Private2;
+ Private2 *m2;
+
+ struct ObjectData {
+ QString id;
+ QString path;
+ Git::Submodule submod;
+ Git::CommitItem submod_commit;
+ QString header;
+ int idiff;
+ };
+
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
QPixmap const &digitsPixmap() const;
// QString currentWorkingCopyDir() const override;
QColor color(unsigned int i);
- bool isOnlineMode() const override;
+ bool isOnlineMode() const;
private:
Ui::MainWindow *ui;
- void updateFilesList(QString id, bool wait) override;
+ void updateFilesList(QString id, bool wait);
void updateFilesList(Git::CommitItem const &commit, bool wait);
- void updateRepositoriesList() override;
+ void updateRepositoriesList();
- void openRepository_(GitPtr g, bool keep_selection = false) override;
+ void openRepository_(GitPtr g, bool keep_selection = false);
void prepareLogTableWidget();
QStringList selectedFiles_(QListWidget *listwidget) const;
QStringList selectedFiles() const;
void for_each_selected_files(std::function<void (QString const &)> const &fn);
void showFileList(FilesListType files_list_type);
void clearLog();
- void clearFileList() override;
+ void clearFileList();
void clearDiffView();
void clearRepositoryInfo();
int repositoryIndex_(const QTreeWidgetItem *item) const;
RepositoryItem const *repositoryItem(const QTreeWidgetItem *item) const;
QTreeWidgetItem *newQTreeWidgetFolderItem(QString const &name);
void buildRepoTree(QString const &group, QTreeWidgetItem *item, QList<RepositoryItem> *repos);
void refrectRepositories();
void updateDiffView(QListWidgetItem *item);
void updateDiffView();
void updateUnstagedFileCurrentItem();
void updateStagedFileCurrentItem();
- void updateStatusBarText() override;
- void setRepositoryInfo(QString const &reponame, QString const &brname) override;
+ void updateStatusBarText();
+ void setRepositoryInfo(QString const &reponame, QString const &brname);
int indexOfRepository(const QTreeWidgetItem *treeitem) const;
void clearRepoFilter();
void appendCharToRepoFilter(ushort c);
void backspaceRepoFilter();
void revertCommit();
void mergeBranch(const QString &commit, Git::MergeFastForward ff);
void mergeBranch(Git::CommitItem const *commit, Git::MergeFastForward ff);
void rebaseBranch(Git::CommitItem const *commit);
void cherrypick(Git::CommitItem const *commit);
void merge(const Git::CommitItem *commit = nullptr);
void detectGitServerType(const GitPtr &g);
void setRemoteOnline(bool f, bool save);
void startTimers();
void onCloneCompleted(bool success, const QVariant &userdata);
void setNetworkingCommandsEnabled(bool enabled);
void blame(QListWidgetItem *item);
void blame();
QListWidgetItem *currentFileItem() const;
void execAreYouSureYouWantToContinueConnectingDialog();
void deleteRemoteBranch(Git::CommitItem const *commit);
QStringList remoteBranches(QString const &id, QStringList *all);
bool isUninitialized();
void doLogCurrentItemChanged();
void findNext();
void findText(const QString &text);
void showStatus();
void onStartEvent();
void showLogWindow(bool show);
+ QString getObjectID(QListWidgetItem *item);
+ bool isValidRemoteURL(const QString &url, const QString &sshkey);
+ QStringList whichCommand_(const QString &cmdfile1, const QString &cmdfile2 = {});
+ QString selectCommand_(const QString &cmdname, const QStringList &cmdfiles, const QStringList &list, QString path, const std::function<void (const QString &)> &callback);
+ QString selectCommand_(const QString &cmdname, const QString &cmdfile, const QStringList &list, const QString &path, const std::function<void (const QString &)> &callback);
+ const RepositoryItem *findRegisteredRepository(QString *workdir) const;
+ static bool git_callback(void *cookie, const char *ptr, int len);
+ bool execSetGlobalUserDialog();
+ void revertAllFiles();
+ void addWorkingCopyDir(QString dir, QString name, bool open);
+ bool execWelcomeWizardDialog();
+ void execRepositoryPropertyDialog(const RepositoryItem &repo, bool open_repository_menu = false);
+ void execSetUserDialog(const Git::User &global_user, const Git::User &repo_user, const QString &reponame);
+ void setGitCommand(QString path, bool save);
+ void setFileCommand(QString path, bool save);
+ void setGpgCommand(QString path, bool save);
+ void setSshCommand(QString path, bool save);
+ bool checkGitCommand();
+ bool checkFileCommand();
+ bool saveBlobAs(const QString &id, const QString &dstpath);
+ bool saveByteArrayAs(const QByteArray &ba, const QString &dstpath);
+ static QString makeRepositoryName(const QString &loc);
+ bool saveFileAs(const QString &srcpath, const QString &dstpath);
+ QString saveAsTemp(const QString &id);
+ QString executableOrEmpty(const QString &path);
+ bool checkExecutable(const QString &path);
+ void internalSaveCommandPath(const QString &path, bool save, const QString &name);
+ void logGitVersion();
+ void internalClearRepositoryInfo();
+ void checkUser();
+ void openRepository(bool validate, bool waitcursor = true, bool keep_selection = false);
+ void updateRepository();
+ void reopenRepository(bool log, const std::function<void (const GitPtr &)> &callback);
+ void setCurrentRepository(const RepositoryItem &repo, bool clear_authentication);
+ void openSelectedRepository();
+ QList<Git::Diff> makeDiffs(QString id, bool *ok);
+ void queryBranches(const GitPtr &g);
+ void updateRemoteInfo();
+ void queryRemotes(const GitPtr &g);
+ void clone(QString url = {}, QString dir = {});
+ void submodule_add(QString url = {}, QString local_dir = {});
+ const Git::CommitItem *selectedCommitItem() const;
+ void commit(bool amend = false);
+ void commitAmend();
+ void pushSetUpstream(const QString &remote, const QString &branch);
+ bool pushSetUpstream(bool testonly);
+ void push();
+ void deleteBranch(const Git::CommitItem *commit);
+ void deleteBranch();
+ void resetFile(const QStringList &paths);
+ void clearAuthentication();
+ void clearSshAuthentication();
+ void internalDeleteTags(const QStringList &tagnames);
+ bool internalAddTag(const QString &name);
+ void createRepository(const QString &dir);
+ void setLogEnabled(const GitPtr &g, bool f);
+ void doGitCommand(const std::function<void (GitPtr)> &callback);
+ void setWindowTitle_(const Git::User &user);
+ void setUnknownRepositoryInfo();
+ void setCurrentRemoteName(const QString &name);
+ void deleteTags(const Git::CommitItem &commit);
+ bool isAvatarEnabled() const;
+ bool isGitHub() const;
+ QStringList remotes() const;
+ QList<Git::Branch> findBranch(const QString &id);
+ QString tempfileHeader() const;
+ void deleteTempFiles();
+ QString getCommitIdFromTag(const QString &tag);
+ QString newTempFilePath();
+ int limitLogCount() const;
+ Git::Object cat_file_(const GitPtr &g, const QString &id);
+ bool isThereUncommitedChanges() const;
+ void addDiffItems(const QList<Git::Diff> *diff_list, const std::function<void (const ObjectData &)> &add_item);
+ Git::CommitItemList retrieveCommitLog(const GitPtr &g);
+ std::map<QString, QList<Git::Branch> > &branchMapRef();
+ void updateCommitTableLater();
+ void updateWindowTitle(const GitPtr &g);
+ QString makeCommitInfoText(int row, QList<BasicMainWindow::Label> *label_list);
+ void removeRepositoryFromBookmark(int index, bool ask);
+ void openTerminal(const RepositoryItem *repo);
+ void openExplorer(const RepositoryItem *repo);
+ bool askAreYouSureYouWantToRun(const QString &title, const QString &command);
+ bool editFile(const QString &path, const QString &title);
+ void setAppSettings(const ApplicationSettings &appsettings);
+ QIcon getRepositoryIcon() const;
+ QIcon getFolderIcon() const;
+ QIcon getSignatureGoodIcon() const;
+ QIcon getSignatureDubiousIcon() const;
+ QIcon getSignatureBadIcon() const;
+ QPixmap getTransparentPixmap() const;
+ QStringList findGitObject(const QString &id) const;
+ void writeLog(const char *ptr, int len);
+ void writeLog(const QString &str);
+ QList<BasicMainWindow::Label> sortedLabels(int row) const;
+ void saveApplicationSettings();
+ void loadApplicationSettings();
+ void setDiffResult(const QList<Git::Diff> &diffs);
+ const QList<Git::Submodule> &submodules() const;
+ void setSubmodules(const QList<Git::Submodule> &submodules);
+ bool runOnRepositoryDir(const std::function<void (QString)> &callback, const RepositoryItem *repo);
+ NamedCommitList namedCommitItems(int flags);
+ static QString getFilePath(QListWidgetItem *item);
+ static bool isGroupItem(QTreeWidgetItem *item);
+ static int indexOfLog(QListWidgetItem *item);
+ static int indexOfDiff(QListWidgetItem *item);
+ static int getHunkIndex(QListWidgetItem *item);
+ void updateSubmodules(GitPtr g, QString id);
+ void saveRepositoryBookmark(RepositoryItem item);
+ int rowFromCommitId(const QString &id);
+ QList<Git::Tag> findTag(const QString &id);
+ void sshSetPassphrase(const std::string &user, const std::string &pass);
+ std::string sshPassphraseUser() const;
+ std::string sshPassphrasePass() const;
+ void httpSetAuthentication(const std::string &user, const std::string &pass);
+ std::string httpAuthenticationUser() const;
+ std::string httpAuthenticationPass() const;
+// const Git::CommitItemList &getLogs() const;
+ const Git::CommitItem *getLog(int index) const;
+ void updateCommitGraph();
+ void postUserFunctionEvent(const std::function<void(QVariant const &)> &fn, QVariant const &v = QVariant());
+ void initNetworking();
+ bool saveRepositoryBookmarks() const;
+ QString getBookmarksFilePath() const;
+ void stopPtyProcess();
+ void abortPtyProcess();
+ Git::CommitItemList *getLogsPtr();
+ void setLogs(const Git::CommitItemList &logs);
+ void clearLogs();
+ PtyProcess *getPtyProcess();
+ bool getPtyProcessOk() const;
+ BasicMainWindow::PtyCondition getPtyCondition();
+ void setPtyUserData(const QVariant &userdata);
+ void setPtyProcessOk(bool pty_process_ok);
+ bool fetch(const GitPtr &g, bool prune);
+ bool fetch_tags_f(const GitPtr &g);
+ void setPtyCondition(const PtyCondition &ptyCondition);
+ const QList<RepositoryItem> &getRepos() const;
+ QList<RepositoryItem> *getReposPtr();
+ AvatarLoader *getAvatarLoader();
+ const AvatarLoader *getAvatarLoader() const;
+ int *ptrUpdateFilesListCounter();
+ int *ptrUpdateCommitTableCounter();
+ bool interactionCanceled() const;
+ void setInteractionCanceled(bool canceled);
+ BasicMainWindow::InteractionMode interactionMode() const;
+ void setInteractionMode(const InteractionMode &im);
+ QString getRepositoryFilterText() const;
+ void setRepositoryFilterText(const QString &text);
+ void setUncommitedChanges(bool uncommited_changes);
+ QList<Git::Diff> *diffResult();
+ std::map<QString, Git::Diff> *getDiffCacheMap();
+ bool getRemoteChanged() const;
+ void setRemoteChanged(bool remote_changed);
+ void setServerType(const ServerType &server_type);
+ GitHubRepositoryInfo *ptrGitHub();
+ std::map<int, QList<BasicMainWindow::Label> > *getLabelMap();
+ const std::map<int, QList<BasicMainWindow::Label> > *getLabelMap() const;
+ void clearLabelMap();
+ GitObjectCache *getObjCache();
+ bool getForceFetch() const;
+ void setForceFetch(bool force_fetch);
+ std::map<QString, QList<Git::Tag> > *ptrTagMap();
+ QString getHeadId() const;
+ void setHeadId(const QString &head_id);
+ void setPtyProcessCompletionData(const QVariant &value);
+ const QVariant &getTempRepoForCloneCompleteV() const;
+ void msgNoRepositorySelected();
+ bool isRepositoryOpened() const;
+ static std::pair<QString, QString> makeFileItemText(const ObjectData &data);
+ QString gitCommand() const;
+ QPixmap getTransparentPixmap();
protected:
void customEvent(QEvent *);
void dragEnterEvent(QDragEnterEvent *event) override;
void timerEvent(QTimerEvent *) override;
void keyPressEvent(QKeyEvent *event) override;
bool event(QEvent *event) override;
bool eventFilter(QObject *watched, QEvent *event) override;
public:
void drawDigit(QPainter *pr, int x, int y, int n) const;
int digitWidth() const;
int digitHeight() const;
void setStatusBarText(QString const &text);
void clearStatusBarText();
- void setCurrentLogRow(int row) override;
+ void setCurrentLogRow(int row);
bool shown();
- void deleteTags(QStringList const &tagnames) override;
+ void deleteTags(QStringList const &tagnames);
bool addTag(QString const &name);
void updateCurrentFilesList();
void notifyRemoteChanged(bool f);
void postOpenRepositoryFromGitHub(const QString &username, const QString &reponame);
- int selectedLogIndex() const override;
+ int selectedLogIndex() const;
void updateAncestorCommitMap();
bool isAncestorCommit(const QString &id);
void test();
void postStartEvent();
void setShowLabels(bool show, bool save);
bool isLabelsVisible() const;
+ void updateFilesList2(const QString &id, QList<Git::Diff> *diff_list, QListWidget *listwidget);
+ void execCommitViewWindow(const Git::CommitItem *commit);
+ void execCommitPropertyDialog(QWidget *parent, const Git::CommitItem *commit);
+ void execCommitExploreWindow(QWidget *parent, const Git::CommitItem *commit);
+ void execFileHistory(const QString &path);
+ void execFileHistory(QListWidgetItem *item);
+ void execFilePropertyDialog(QListWidgetItem *item);
+ bool testRemoteRepositoryValidity(const QString &url, const QString &sshkey);
+ QString selectGitCommand(bool save);
+ QString selectFileCommand(bool save);
+ QString selectGpgCommand(bool save);
+ QString selectSshCommand(bool save);
+ const Git::Branch &currentBranch() const;
+ void setCurrentBranch(const Git::Branch &b);
+ const RepositoryItem &currentRepository() const;
+ QString currentRepositoryName() const;
+ QString currentRemoteName() const;
+ QString currentBranchName() const;
+ GitPtr git(const QString &dir, const QString &sshkey = {}) const;
+ GitPtr git();
+ GitPtr git(const Git::Submodule &submod);
+ void autoOpenRepository(QString dir);
+ bool queryCommit(const QString &id, Git::CommitItem *out);
+ void checkout(QWidget *parent, const Git::CommitItem *commit, std::function<void ()> accepted_callback = {});
+ void checkout();
+ void jumpToCommit(QString id);
+ Git::Object cat_file(const QString &id);
+ void addWorkingCopyDir(const QString &dir, bool open);
+ bool saveAs(const QString &id, const QString &dstpath);
+ QString determinFileType_(const QString &path, bool mime, const std::function<void (const QString &, QByteArray *)> &callback) const;
+ QString determinFileType(const QString &path, bool mime);
+ QString determinFileType(QByteArray in, bool mime);
+ QList<Git::Tag> queryTagList();
+ TextEditorThemePtr themeForTextEditor();
+ bool isValidWorkingCopy(const GitPtr &g) const;
+ void emitWriteLog(const QByteArray &ba);
+ QString findFileID(const QString &commit_id, const QString &file);
+ const Git::CommitItem *commitItem(int row) const;
+ QIcon committerIcon(int row) const;
+ void changeSshKey(const QString &localdir, const QString &sshkey);
+ static QString abbrevCommitID(const Git::CommitItem &commit);
+ const Git::CommitItemList &getLogs() const;
+ const QList<BasicMainWindow::Label> *label(int row) const;
+ ApplicationSettings *appsettings();
+ const ApplicationSettings *appsettings() const;
+ QString defaultWorkingDir() const;
+ WebContext *webContext();
+ QIcon verifiedIcon(char s) const;
+ QAction *addMenuActionProperty(QMenu *menu);
+ QString currentWorkingCopyDir() const;
+public slots:
+ void writeLog_(QByteArray ba);
private slots:
void updateUI();
void onLogVisibilityChanged();
void onPtyProcessCompleted(bool ok, const QVariant &userdata);
void onRepositoriesTreeDropped();
void on_action_about_triggered();
void on_action_clean_df_triggered();
void on_action_clone_triggered();
void on_action_commit_triggered();
void on_action_create_a_repository_triggered();
void on_action_delete_branch_triggered();
void on_action_delete_remote_branch_triggered();
void on_action_edit_git_config_triggered();
void on_action_edit_gitignore_triggered();
void on_action_edit_global_gitconfig_triggered();
void on_action_edit_settings_triggered();
void on_action_edit_tags_triggered();
void on_action_exit_triggered();
void on_action_explorer_triggered();
void on_action_fetch_triggered();
void on_action_fetch_prune_triggered();
void on_action_find_next_triggered();
void on_action_find_triggered();
void on_action_offline_triggered();
void on_action_online_triggered();
void on_action_open_existing_working_copy_triggered();
void on_action_pull_triggered();
void on_action_push_all_tags_triggered();
void on_action_push_triggered();
void on_action_push_u_triggered();
void on_action_reflog_triggered();
void on_action_repo_checkout_triggered();
void on_action_repo_jump_to_head_triggered();
void on_action_repo_jump_triggered();
void on_action_repositories_panel_triggered();
void on_action_repository_property_triggered();
void on_action_repository_status_triggered();
void on_action_reset_HEAD_1_triggered();
void on_action_reset_hard_triggered();
void on_action_set_config_user_triggered();
void on_action_set_gpg_signing_triggered();
void on_action_stash_apply_triggered();
void on_action_stash_drop_triggered();
void on_action_stash_triggered();
void on_action_stop_process_triggered();
void on_action_terminal_triggered();
void on_action_view_refresh_triggered();
void on_action_window_log_triggered(bool checked);
void on_horizontalScrollBar_log_valueChanged(int);
void on_lineEdit_filter_textChanged(QString const &text);
void on_listWidget_files_currentRowChanged(int currentRow);
void on_listWidget_files_customContextMenuRequested(const QPoint &pos);
void on_listWidget_files_itemDoubleClicked(QListWidgetItem *item);
void on_listWidget_staged_currentRowChanged(int currentRow);
void on_listWidget_staged_customContextMenuRequested(const QPoint &pos);
void on_listWidget_staged_itemDoubleClicked(QListWidgetItem *item);
void on_listWidget_unstaged_currentRowChanged(int currentRow);
void on_listWidget_unstaged_customContextMenuRequested(const QPoint &pos);
void on_listWidget_unstaged_itemDoubleClicked(QListWidgetItem *item);
void on_radioButton_remote_offline_clicked();
void on_radioButton_remote_online_clicked();
void on_tableWidget_log_currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous);
void on_tableWidget_log_customContextMenuRequested(const QPoint &pos);
void on_tableWidget_log_itemDoubleClicked(QTableWidgetItem *);
void on_toolButton_clone_clicked();
void on_toolButton_commit_clicked();
void on_toolButton_erase_filter_clicked();
void on_toolButton_explorer_clicked();
void on_toolButton_fetch_clicked();
void on_toolButton_pull_clicked();
void on_toolButton_push_clicked();
void on_toolButton_select_all_clicked();
void on_toolButton_stage_clicked();
void on_toolButton_status_clicked();
void on_toolButton_stop_process_clicked();
void on_toolButton_terminal_clicked();
void on_toolButton_unstage_clicked();
void on_treeWidget_repos_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
void on_treeWidget_repos_customContextMenuRequested(const QPoint &pos);
void on_treeWidget_repos_itemDoubleClicked(QTreeWidgetItem *item, int column);
void on_verticalScrollBar_log_valueChanged(int);
void on_action_repo_merge_triggered();
void on_action_expand_commit_log_triggered();
void on_action_expand_file_list_triggered();
void on_action_expand_diff_view_triggered();
// void on_action_wide_triggered();
void on_action_sidebar_triggered();
void on_action_show_labels_triggered();
void on_action_submodule_add_triggered();
void on_action_submodules_triggered();
void on_action_submodule_update_triggered();
+ void onAvatarUpdated();
protected:
void closeEvent(QCloseEvent *event) override;
- void internalWriteLog(const char *ptr, int len) override;
- RepositoryItem const *selectedRepositoryItem() const override;
- void removeSelectedRepositoryFromBookmark(bool ask) override;
+ void internalWriteLog(const char *ptr, int len);
+ RepositoryItem const *selectedRepositoryItem() const;
+ void removeSelectedRepositoryFromBookmark(bool ask);
protected slots:
void onLogIdle();
signals:
+ void signalWriteLog(QByteArray ba);
+ void remoteInfoChanged();
void signalSetRemoteChanged(bool f);
void onEscapeKeyPressed();
void updateButton();
};
#endif // MAINWINDOW_H
diff --git a/src/MyTextEditorWidget.cpp b/src/MyTextEditorWidget.cpp
index 67c9780..970fd0f 100644
--- a/src/MyTextEditorWidget.cpp
+++ b/src/MyTextEditorWidget.cpp
@@ -1,57 +1,57 @@
#include "MyTextEditorWidget.h"
#include "MainWindow.h"
#include "common/misc.h"
#include <QMenu>
#include <QFileDialog>
#include "common/joinpath.h"
MyTextEditorWidget::MyTextEditorWidget(QWidget *parent)
: TextEditorWidget(parent)
{
}
-void MyTextEditorWidget::setDocument(const QList<Document::Line> *source, BasicMainWindow *mw, QString const &object_id, QString const &object_path)
+void MyTextEditorWidget::setDocument(const QList<Document::Line> *source, MainWindow *mw, QString const &object_id, QString const &object_path)
{
this->mainwindow = mw;
this->object_id = object_id;
this->object_path = object_path;
TextEditorWidget::setDocument(source);
}
void MyTextEditorWidget::contextMenuEvent(QContextMenuEvent *event)
{
QString id = object_id;
if (id.startsWith(PATH_PREFIX)) {
// pass
} else if (Git::isValidID(id)) {
// pass
} else {
return; // invalid id
}
QMenu menu;
QAction *a_save_as = id.isEmpty() ? nullptr : menu.addAction(tr("Save as..."));
QAction *a_copy = menu.addAction(tr("Copy"));
if (!menu.actions().isEmpty()) {
update();
QAction *a = menu.exec(misc::contextMenuPos(this, event));
if (a) {
if (a == a_save_as) {
QString path = mainwindow->currentWorkingCopyDir() / object_path;
QString dstpath = QFileDialog::getSaveFileName(window(), tr("Save as"), path);
if (!dstpath.isEmpty()) {
mainwindow->saveAs(id, dstpath);
}
update();
return;
}
if (a == a_copy) {
editCopy();
return;
}
}
}
}
diff --git a/src/MyTextEditorWidget.h b/src/MyTextEditorWidget.h
index 616e828..2b78050 100644
--- a/src/MyTextEditorWidget.h
+++ b/src/MyTextEditorWidget.h
@@ -1,20 +1,20 @@
#ifndef MYTEXTEDITORWIDGET_H
#define MYTEXTEDITORWIDGET_H
#include "texteditor/TextEditorWidget.h"
-class BasicMainWindow;
+class MainWindow;
class MyTextEditorWidget : public TextEditorWidget {
private:
- BasicMainWindow *mainwindow;
+ MainWindow *mainwindow;
QString object_id;
QString object_path;
public:
MyTextEditorWidget(QWidget *parent = nullptr);
- void setDocument(const QList<Document::Line> *source, BasicMainWindow *mw, QString const &object_id, QString const &object_path);
+ void setDocument(const QList<Document::Line> *source, MainWindow *mw, QString const &object_id, QString const &object_path);
protected:
void contextMenuEvent(QContextMenuEvent *event) override;
};
#endif // MYTEXTEDITORWIDGET_H
diff --git a/src/ObjectBrowserDialog.cpp b/src/ObjectBrowserDialog.cpp
index d656dd2..3615fc9 100644
--- a/src/ObjectBrowserDialog.cpp
+++ b/src/ObjectBrowserDialog.cpp
@@ -1,124 +1,124 @@
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "ui_ObjectBrowserDialog.h"
#include "ObjectBrowserDialog.h"
#include <QMessageBox>
enum {
IdRole = Qt::UserRole,
TypeRole,
};
-ObjectBrowserDialog::ObjectBrowserDialog(BasicMainWindow *parent, const QStringList &list)
+ObjectBrowserDialog::ObjectBrowserDialog(MainWindow *parent, const QStringList &list)
: QDialog(parent)
, ui(new Ui::ObjectBrowserDialog)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
GitPtr g = git();
QStringList cols = {
tr("ID"),
tr("Type"),
};
auto NewQTableWidgetItem = [](){
auto *item = new QTableWidgetItem();
return item;
};
ui->tableWidget->setColumnCount(cols.size());
for (int i = 0; i < cols.size(); i++) {
QTableWidgetItem *item = NewQTableWidgetItem();
item->setText(cols[i]);
ui->tableWidget->setHorizontalHeaderItem(i, item);
}
ui->tableWidget->setRowCount(list.size());
for (int row = 0; row < list.size(); row++) {
QString const &text = list[row];
QString type = g->objectType(text);
auto *item0 = NewQTableWidgetItem();
item0->setData(IdRole, text);
item0->setData(TypeRole, type);
item0->setText(text);
ui->tableWidget->setItem(row, 0, item0);
auto *item1 = NewQTableWidgetItem();
item1->setText(type);
ui->tableWidget->setItem(row, 1, item1);
}
ui->tableWidget->resizeColumnsToContents();
ui->tableWidget->setCurrentItem(ui->tableWidget->item(0, 0));
}
ObjectBrowserDialog::~ObjectBrowserDialog()
{
delete ui;
}
-BasicMainWindow *ObjectBrowserDialog::mainwindow()
+MainWindow *ObjectBrowserDialog::mainwindow()
{
- return qobject_cast<BasicMainWindow *>(parent());
+ return qobject_cast<MainWindow *>(parent());
}
GitPtr ObjectBrowserDialog::git()
{
return mainwindow()->git();
}
QString ObjectBrowserDialog::text() const
{
int row = ui->tableWidget->currentRow();
auto *item = ui->tableWidget->item(row, 0);
if (item) {
return item->data(IdRole).toString();
}
return QString();
}
void ObjectBrowserDialog::on_tableWidget_itemDoubleClicked(QTableWidgetItem *item)
{
(void)item;
done(QDialog::Accepted);
}
void ObjectBrowserDialog::on_tableWidget_currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous)
{
(void)current;
(void)previous;
// if (current) {
// QString id = current->data(IdRole).toString();
// QString ty = current->data(TypeRole).toString();
// if (Git::isValidID(id) && ty == "commit") {
// }
// }
}
void ObjectBrowserDialog::on_pushButton_inspect_clicked()
{
int row = ui->tableWidget->currentRow();
auto *item = ui->tableWidget->item(row, 0);
if (item) {
GitPtr g = git();
QString id = item->data(IdRole).toString();
QString ty = item->data(TypeRole).toString();
if (Git::isValidID(id) && ty == "commit") {
Git::CommitItem commit;
if (g->queryCommit(id, &commit)) {
mainwindow()->execCommitPropertyDialog(this, &commit);
}
} else {
QMessageBox::information(this, tr("Object Inspection"), id + "\n\n" + ty);
}
}
}
diff --git a/src/ObjectBrowserDialog.h b/src/ObjectBrowserDialog.h
index 6188a15..01fd730 100644
--- a/src/ObjectBrowserDialog.h
+++ b/src/ObjectBrowserDialog.h
@@ -1,31 +1,31 @@
#ifndef OBJECTBROWSERDIALOG_H
#define OBJECTBROWSERDIALOG_H
#include <QDialog>
#include "Git.h"
-class BasicMainWindow;
+class MainWindow;
class QListWidgetItem;
class QTableWidgetItem;
namespace Ui {
class ObjectBrowserDialog;
}
class ObjectBrowserDialog : public QDialog {
Q_OBJECT
private:
Ui::ObjectBrowserDialog *ui;
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
GitPtr git();
public:
- explicit ObjectBrowserDialog(BasicMainWindow *parent, QStringList const &list);
+ explicit ObjectBrowserDialog(MainWindow *parent, QStringList const &list);
~ObjectBrowserDialog() override;
QString text() const;
private slots:
void on_pushButton_inspect_clicked();
void on_tableWidget_currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous);
void on_tableWidget_itemDoubleClicked(QTableWidgetItem *item);
};
#endif // OBJECTBROWSERDIALOG_H
diff --git a/src/RemoteWatcher.cpp b/src/RemoteWatcher.cpp
index d3a9b5d..e69de29 100644
--- a/src/RemoteWatcher.cpp
+++ b/src/RemoteWatcher.cpp
@@ -1,49 +0,0 @@
-#include "RemoteWatcher.h"
-#include "common/joinpath.h"
-#include <QFileInfo>
-
-void RemoteWatcher::start(MainWindow *mw)
-{
- mainwindow_ = mw;
- QThread::start();
- moveToThread(this);
-}
-
-void RemoteWatcher::setCurrent(QString const &remote, QString const &branch)
-{
- remote_ = remote;
- branch_ = branch;
-}
-
-void RemoteWatcher::checkRemoteUpdate()
-{
- QString dir = mainwindow()->currentWorkingCopyDir();
-
- QString refs;
- QString local_id;
-
- if (QFileInfo(dir).isDir()) {
- refs = "refs/remotes" / remote_ / branch_;
- QString head = dir / ".git" / refs;
- QFile file1(head);
- if (file1.open(QFile::ReadOnly)) {
- local_id = file1.readLine().trimmed();
- }
- refs = "refs/heads" / branch_;
- }
- if (local_id.isEmpty()) return;
-
- QString remote_id;
- GitPtr g = mainwindow()->git();
- auto list = g->ls_remote();
- for (auto const &item : list) {
- if (item.name == refs) {
- remote_id = item.commit_id;
- break;
- }
- }
-
- bool changed = remote_id != local_id;
- mainwindow()->notifyRemoteChanged(changed);
-}
-
diff --git a/src/RemoteWatcher.h b/src/RemoteWatcher.h
index 10631ae..e69de29 100644
--- a/src/RemoteWatcher.h
+++ b/src/RemoteWatcher.h
@@ -1,26 +0,0 @@
-#ifndef REMOTEWATCHER_H
-#define REMOTEWATCHER_H
-
-#include <QThread>
-
-#include "MainWindow.h"
-
-class RemoteWatcher : public QThread {
- Q_OBJECT
-private:
- MainWindow *mainwindow_ = nullptr;
- QString remote_;
- QString branch_;
- MainWindow *mainwindow()
- {
- return mainwindow_;
- }
-public:
- RemoteWatcher() = default;
- void start(MainWindow *mw);
- void setCurrent(QString const &remote, QString const &branch);
-public slots:
- void checkRemoteUpdate();
-};
-
-#endif // REMOTEWATCHER_H
diff --git a/src/RepositoryPropertyDialog.cpp b/src/RepositoryPropertyDialog.cpp
index f2e6d96..12446dc 100644
--- a/src/RepositoryPropertyDialog.cpp
+++ b/src/RepositoryPropertyDialog.cpp
@@ -1,168 +1,168 @@
#include "RepositoryPropertyDialog.h"
#include "ui_RepositoryPropertyDialog.h"
#include "MainWindow.h"
#include "common/misc.h"
#include <QClipboard>
#include <QMenu>
#include <QMessageBox>
-RepositoryPropertyDialog::RepositoryPropertyDialog(BasicMainWindow *parent, Git::Context const *gcx, GitPtr const &g, RepositoryItem const &item, bool open_repository_menu)
+RepositoryPropertyDialog::RepositoryPropertyDialog(MainWindow *parent, Git::Context const *gcx, GitPtr const &g, RepositoryItem const &item, bool open_repository_menu)
: BasicRepositoryDialog(parent, g)
, ui(new Ui::RepositoryPropertyDialog)
, gcx(gcx)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
repository = item;
ui->groupBox_remote->setVisible(open_repository_menu);
ui->label_name->setText(repository.name);
ui->lineEdit_local_dir->setText(misc::normalizePathSeparator(repository.local_dir));
updateRemotesTable();
}
RepositoryPropertyDialog::~RepositoryPropertyDialog()
{
delete ui;
}
void RepositoryPropertyDialog::updateRemotesTable()
{
BasicRepositoryDialog::updateRemotesTable(ui->tableWidget);
}
void RepositoryPropertyDialog::toggleRemoteMenuActivity()
{
ui->groupBox_remote->setVisible(!ui->groupBox_remote->isVisible());
}
-void BasicMainWindow::changeSshKey(QString const &localdir, QString const &sshkey)
+void MainWindow::changeSshKey(QString const &localdir, QString const &sshkey)
{
bool changed = false;
QList<RepositoryItem> *repos = getReposPtr();
for (int i = 0; i < repos->size(); i++) {
RepositoryItem *item = &(*repos)[i];
if (item->local_dir == localdir) {
item->ssh_key = sshkey;
changed = true;
}
}
if (changed) {
saveRepositoryBookmarks();
}
}
bool RepositoryPropertyDialog::execEditRemoteDialog(Git::Remote *remote, EditRemoteDialog::Operation op)
{
auto const *list = remotes();
if (op == EditRemoteDialog::RemoteSet) {
int row = ui->tableWidget->currentRow();
if (row >= 0 && row < list->size()) {
*remote = list->at(row);
}
} else {
*remote = Git::Remote();
}
if (remote->name.isEmpty() && list->isEmpty()) {
op = EditRemoteDialog::RemoteAdd;
remote->name = "origin";
}
EditRemoteDialog dlg(mainwindow(), op, gcx);
dlg.setName(remote->name);
dlg.setUrl(remote->url);
dlg.setSshKey(remote->ssh_key);
if (dlg.exec() == QDialog::Accepted) {
remote->name = dlg.name();
remote->url = dlg.url();
remote->ssh_key = dlg.sshKey();
GitPtr g = git();
if (op == EditRemoteDialog::RemoteAdd) {
bool ok = true;
for (Git::Remote const &r : *list) {
if (r.name == remote->name) {
qDebug() << "remote add: Already exists" << remote->name;
ok = false;
break;
}
}
if (ok) {
g->addRemoteURL(*remote);
}
} else if (op == EditRemoteDialog::RemoteSet) {
g->setRemoteURL(*remote);
}
// wip
QString localdir = ui->lineEdit_local_dir->text();
mainwindow()->changeSshKey(localdir, remote->ssh_key);
setSshKey_(remote->ssh_key);
getRemotes_();
updateRemotesTable();
return true;
}
return false;
}
Git::Remote RepositoryPropertyDialog::selectedRemote() const
{
Git::Remote remote;
auto const *list = remotes();
int row = ui->tableWidget->currentRow();
if (row >= 0 && row < list->size()) {
remote = list->at(row);
}
return remote;
}
bool RepositoryPropertyDialog::isRemoteChanged() const
{
return remote_changed;
}
void RepositoryPropertyDialog::on_pushButton_remote_add_clicked()
{
Git::Remote r;
if (execEditRemoteDialog(&r, EditRemoteDialog::RemoteAdd)) {
remote_changed = true;
}
}
void RepositoryPropertyDialog::on_pushButton_remote_edit_clicked()
{
int row = ui->tableWidget->currentRow();
if (row < 0) {
ui->tableWidget->setCurrentCell(0, 0);
}
Git::Remote remote = selectedRemote();
if (execEditRemoteDialog(&remote, EditRemoteDialog::RemoteSet)) {
remote_changed = true;
}
}
void RepositoryPropertyDialog::on_pushButton_remote_remove_clicked()
{
Git::Remote remote = selectedRemote();
if (!remote.name.isEmpty()) {
int r = QMessageBox::warning(this, tr("Confirm Remove"), tr("Are you sure you want to remove the remote '%1' from the repository '%2' ?").arg(remote.name).arg(repository.name), QMessageBox::Ok, QMessageBox::Cancel);
if (r == QMessageBox::Ok) {
GitPtr g = git();
g->removeRemote(remote.name);
updateRemotesTable();
remote_changed = true;
}
}
}
void RepositoryPropertyDialog::on_pushButton_remote_menu_clicked()
{
toggleRemoteMenuActivity();
}
diff --git a/src/RepositoryPropertyDialog.h b/src/RepositoryPropertyDialog.h
index b876fe7..0dfe404 100644
--- a/src/RepositoryPropertyDialog.h
+++ b/src/RepositoryPropertyDialog.h
@@ -1,39 +1,39 @@
#ifndef REPOSITORYPROPERTYDIALOG_H
#define REPOSITORYPROPERTYDIALOG_H
#include "RepositoryData.h"
#include "BasicRepositoryDialog.h"
#include "EditRemoteDialog.h"
#include <QDialog>
#include "Git.h"
-class BasicMainWindow;
+class MainWindow;
namespace Ui {
class RepositoryPropertyDialog;
}
class RepositoryPropertyDialog : public BasicRepositoryDialog {
Q_OBJECT
private:
Ui::RepositoryPropertyDialog *ui;
RepositoryItem repository;
bool remote_changed = false;
Git::Context const *gcx;
void updateRemotesTable();
bool execEditRemoteDialog(Git::Remote *remote, EditRemoteDialog::Operation op);
Git::Remote selectedRemote() const;
void toggleRemoteMenuActivity();
public:
- explicit RepositoryPropertyDialog(BasicMainWindow *parent, const Git::Context *gcx, const GitPtr &g, RepositoryItem const &item, bool open_repository_menu = false);
+ explicit RepositoryPropertyDialog(MainWindow *parent, const Git::Context *gcx, const GitPtr &g, RepositoryItem const &item, bool open_repository_menu = false);
~RepositoryPropertyDialog() override;
bool isRemoteChanged() const;
private slots:
void on_pushButton_remote_add_clicked();
void on_pushButton_remote_edit_clicked();
void on_pushButton_remote_remove_clicked();
void on_pushButton_remote_menu_clicked();
};
#endif // REPOSITORYPROPERTYDIALOG_H
diff --git a/src/SearchFromGitHubDialog.cpp b/src/SearchFromGitHubDialog.cpp
index c1810bc..b065f46 100644
--- a/src/SearchFromGitHubDialog.cpp
+++ b/src/SearchFromGitHubDialog.cpp
@@ -1,167 +1,167 @@
#include "SearchFromGitHubDialog.h"
#include "ui_SearchFromGitHubDialog.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "common/misc.h"
#include "urlencode.h"
#include <QDebug>
#include <QDesktopServices>
#include <QThread>
#include <QUrl>
#include <functional>
using SearchResultItem = GitHubAPI::SearchResultItem;
static QString toQString(std::string const &s)
{
return QString::fromUtf8(s.c_str(), s.size());
}
-SearchFromGitHubDialog::SearchFromGitHubDialog(QWidget *parent, BasicMainWindow *mw)
+SearchFromGitHubDialog::SearchFromGitHubDialog(QWidget *parent, MainWindow *mw)
: QDialog(parent)
, ui(new Ui::SearchFromGitHubDialog)
, mainwindow(mw)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
ui->tableWidget->setItemDelegate(&item_delegate);
connect(ui->label_hyperlink, &HyperLinkLabel::clicked, this, &SearchFromGitHubDialog::onHyperlinkClicked);
ui->pushButton_ok->setEnabled(false);
}
SearchFromGitHubDialog::~SearchFromGitHubDialog()
{
delete ui;
}
QString SearchFromGitHubDialog::url() const
{
return url_;
}
void SearchFromGitHubDialog::on_pushButton_search_clicked()
{
std::string q = ui->lineEdit_keywords->text().trimmed().toStdString();
q = url_encode(q);
if (q.empty()) return;
GitHubAPI github(mainwindow);
items = github.searchRepository(q);
QStringList cols = {
tr("Name"),
tr("Owner"),
tr("Score"),
tr("Description"),
};
ui->tableWidget->setColumnCount(cols.size());
ui->tableWidget->setRowCount(items.size());
for (int col = 0; col < cols.size(); col++) {
auto *p = new QTableWidgetItem();
p->setText(cols[col]);
ui->tableWidget->setHorizontalHeaderItem(col, p);
}
for (int row = 0; row < items.size(); row++) {
SearchResultItem const &item = items[row];
QTableWidgetItem *p;
QString name = QString::fromStdString(item.full_name);
QString owner;
int i = name.indexOf('/');
if (i > 0) {
owner = name.mid(0, i);
name = name.mid(i + 1);
}
int col = 0;
auto AddItem = [&](std::function<void(QTableWidgetItem *)> callback){
p = new QTableWidgetItem();
callback(p);
ui->tableWidget->setItem(row, col, p);
col++;
};
AddItem([&](QTableWidgetItem *p){
p->setData(Qt::UserRole, (int)row);
p->setText(name);
});
AddItem([&](QTableWidgetItem *p){
p->setText(owner);
});
AddItem([&](QTableWidgetItem *p){
char tmp[100];
sprintf(tmp, "%.2f", item.score);
p->setText(tmp);
p->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
});
AddItem([&](QTableWidgetItem *p){
p->setText(toQString(item.description));
});
ui->tableWidget->setRowHeight(row, 24);
}
ui->tableWidget->resizeColumnsToContents();
ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
}
void SearchFromGitHubDialog::updateUI()
{
auto Check = [&](){
if (ui->radioButton_ssh->isChecked()) {
url_ = ui->lineEdit_ssh->text();
if (!url_.isEmpty()) {
return true;
}
}
if (ui->radioButton_http->isChecked()) {
url_ = ui->lineEdit_http->text();
if (!url_.isEmpty()) {
return true;
}
}
url_ = QString();
return false;
};
ui->pushButton_ok->setEnabled(Check());
}
void SearchFromGitHubDialog::on_tableWidget_currentItemChanged(QTableWidgetItem * /*current*/, QTableWidgetItem * /*previous*/)
{
int row = ui->tableWidget->currentRow();
QTableWidgetItem *p = ui->tableWidget->item(row, 0);
if (p) {
int i = p->data(Qt::UserRole).toInt();
if (i < items.size()) {
SearchResultItem const &item = items[i];
ui->lineEdit_ssh->setText(toQString(item.ssh_url));
ui->lineEdit_http->setText(toQString(item.clone_url));
ui->label_hyperlink->setText(toQString(item.html_url));
}
}
updateUI();
}
void SearchFromGitHubDialog::on_radioButton_ssh_clicked()
{
updateUI();
}
void SearchFromGitHubDialog::on_radioButton_http_clicked()
{
updateUI();
}
void SearchFromGitHubDialog::onHyperlinkClicked()
{
QString url = ui->label_hyperlink->text();
QDesktopServices::openUrl(QUrl(url));
}
diff --git a/src/SearchFromGitHubDialog.h b/src/SearchFromGitHubDialog.h
index 4418a1a..521b11d 100644
--- a/src/SearchFromGitHubDialog.h
+++ b/src/SearchFromGitHubDialog.h
@@ -1,40 +1,40 @@
#ifndef SEARCHFROMGITHUBDIALOG_H
#define SEARCHFROMGITHUBDIALOG_H
#include "MyTableWidgetDelegate.h"
#include "GitHubAPI.h"
#include <QDialog>
namespace Ui {
class SearchFromGitHubDialog;
}
class QTableWidgetItem;
-class BasicMainWindow;
+class MainWindow;
class SearchFromGitHubDialog : public QDialog {
Q_OBJECT
private:
Ui::SearchFromGitHubDialog *ui;
QList<GitHubAPI::SearchResultItem> items;
QString url_;
MyTableWidgetDelegate item_delegate;
- BasicMainWindow *mainwindow;
+ MainWindow *mainwindow;
void updateUI();
public:
- explicit SearchFromGitHubDialog(QWidget *parent, BasicMainWindow *mw);
+ explicit SearchFromGitHubDialog(QWidget *parent, MainWindow *mw);
~SearchFromGitHubDialog() override;
QString url() const;
private slots:
void on_pushButton_search_clicked();
void on_tableWidget_currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous);
void on_radioButton_ssh_clicked();
void on_radioButton_http_clicked();
void onHyperlinkClicked();
};
#endif // SEARCHFROMGITHUBDIALOG_H
diff --git a/src/SetUserDialog.cpp b/src/SetUserDialog.cpp
index 582c8ed..b7540bc 100644
--- a/src/SetUserDialog.cpp
+++ b/src/SetUserDialog.cpp
@@ -1,130 +1,130 @@
#include "SetUserDialog.h"
#include "ui_SetUserDialog.h"
#include "AvatarLoader.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "common/misc.h"
struct SetUserDialog::Private {
Git::User global_user;
Git::User repo_user;
AvatarLoader avatar_loader;
};
-SetUserDialog::SetUserDialog(BasicMainWindow *parent, Git::User const &global_user, Git::User const &repo_user, QString const &repo)
+SetUserDialog::SetUserDialog(MainWindow *parent, Git::User const &global_user, Git::User const &repo_user, QString const &repo)
: QDialog(parent)
, ui(new Ui::SetUserDialog)
, m(new Private)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
misc::setFixedSize(this);
m->global_user = global_user;
m->repo_user = repo_user;
if (repo.isEmpty()) {
ui->radioButton_repository->setEnabled(false);
} else {
QString text = tr("Repository");
text += " : ";
text += repo;
ui->radioButton_repository->setText(text);
}
ui->radioButton_global->click();
ui->lineEdit_name->setFocus();
m->avatar_loader.start(mainwindow());
connect(&m->avatar_loader, &AvatarLoader::updated, [&](){
QString email = ui->lineEdit_mail->text();
QIcon icon = m->avatar_loader.fetch(email.toStdString(), false);
setAvatar(icon);
});
}
SetUserDialog::~SetUserDialog()
{
m->avatar_loader.stop();
delete m;
delete ui;
}
-BasicMainWindow *SetUserDialog::mainwindow()
+MainWindow *SetUserDialog::mainwindow()
{
- return qobject_cast<BasicMainWindow *>(parent());
+ return qobject_cast<MainWindow *>(parent());
}
bool SetUserDialog::isGlobalChecked() const
{
return ui->radioButton_global->isChecked();
}
bool SetUserDialog::isRepositoryChecked() const
{
return ui->radioButton_repository->isChecked();
}
Git::User SetUserDialog::user() const
{
Git::User user;
user.name = ui->lineEdit_name->text();
user.email = ui->lineEdit_mail->text();
return user;
}
void SetUserDialog::setAvatar(QIcon const &icon)
{
QPixmap pm = icon.pixmap(QSize(64, 64));
ui->label_avatar->setPixmap(pm);
}
void SetUserDialog::on_radioButton_global_toggled(bool checked)
{
if (checked) {
ui->lineEdit_name->setText(m->global_user.name);
ui->lineEdit_mail->setText(m->global_user.email);
}
}
void SetUserDialog::on_radioButton_repository_toggled(bool checked)
{
if (checked) {
ui->lineEdit_name->setText(m->repo_user.name);
ui->lineEdit_mail->setText(m->repo_user.email);
}
}
void SetUserDialog::on_lineEdit_name_textChanged(QString const &text)
{
if (isGlobalChecked()) {
m->global_user.name = text;
}
if (isRepositoryChecked()) {
m->repo_user.name = text;
}
}
void SetUserDialog::on_lineEdit_mail_textChanged(QString const &text)
{
if (isGlobalChecked()) {
m->global_user.email = text;
}
if (isRepositoryChecked()) {
m->repo_user.email = text;
}
}
void SetUserDialog::on_pushButton_get_icon_clicked()
{
ui->label_avatar->setPixmap(QPixmap());
QString email = ui->lineEdit_mail->text();
if (email.indexOf('@') > 0) {
QIcon icon = m->avatar_loader.fetch(email.toStdString(), true);
if (!icon.isNull()) {
setAvatar(icon);
}
}
}
diff --git a/src/SetUserDialog.h b/src/SetUserDialog.h
index 2d68674..b56949d 100644
--- a/src/SetUserDialog.h
+++ b/src/SetUserDialog.h
@@ -1,39 +1,39 @@
#ifndef SETUSERDIALOG_H
#define SETUSERDIALOG_H
#include "Git.h"
#include <QDialog>
-class BasicMainWindow;
+class MainWindow;
namespace Ui {
class SetUserDialog;
}
class SetUserDialog : public QDialog {
Q_OBJECT
private:
Ui::SetUserDialog *ui;
struct Private;
Private *m;
void setAvatar(const QIcon &icon);
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
public:
- explicit SetUserDialog(BasicMainWindow *parent, Git::User const &global_user, Git::User const &repo_user, QString const &repo);
+ explicit SetUserDialog(MainWindow *parent, Git::User const &global_user, Git::User const &repo_user, QString const &repo);
~SetUserDialog() override;
bool isGlobalChecked() const;
bool isRepositoryChecked() const;
Git::User user() const;
private slots:
void on_radioButton_global_toggled(bool checked);
void on_radioButton_repository_toggled(bool checked);
void on_lineEdit_name_textChanged(QString const &text);
void on_lineEdit_mail_textChanged(QString const &text);
void on_pushButton_get_icon_clicked();
};
#endif // SETUSERDIALOG_H
diff --git a/src/SubmoduleAddDialog.cpp b/src/SubmoduleAddDialog.cpp
index 20b9426..300c9fa 100644
--- a/src/SubmoduleAddDialog.cpp
+++ b/src/SubmoduleAddDialog.cpp
@@ -1,142 +1,142 @@
#include "SubmoduleAddDialog.h"
#include "ui_SubmoduleAddDialog.h"
#include "ApplicationGlobal.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "SearchFromGitHubDialog.h"
#include "common/joinpath.h"
#include "common/misc.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QStandardPaths>
#include <QThread>
enum SearchRepository {
None,
GitHub,
};
struct SubmoduleAddDialog::Private {
QString url;
QString repo_name;
QString default_working_dir;
bool ok = false;
QString errmsg;
};
-SubmoduleAddDialog::SubmoduleAddDialog(BasicMainWindow *parent, QString const &url, QString const &defworkdir, Git::Context const *gcx)
+SubmoduleAddDialog::SubmoduleAddDialog(MainWindow *parent, QString const &url, QString const &defworkdir, Git::Context const *gcx)
: QDialog(parent)
, ui(new Ui::SubmoduleAddDialog)
, m(new Private)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
m->default_working_dir = defworkdir;
ui->lineEdit_working_dir->setText(m->default_working_dir);
ui->lineEdit_repo_location->setText(url);
ui->advanced_option->setSshKeyOverrigingEnabled(!gcx->ssh_command.isEmpty());
#ifdef Q_OS_MACX
ui->comboBox->setMinimumWidth(100);
#endif
ui->lineEdit_repo_location->setFocus();
}
SubmoduleAddDialog::~SubmoduleAddDialog()
{
delete m;
delete ui;
}
-BasicMainWindow *SubmoduleAddDialog::mainwindow()
+MainWindow *SubmoduleAddDialog::mainwindow()
{
- return qobject_cast<BasicMainWindow *>(parent());
+ return qobject_cast<MainWindow *>(parent());
}
QString SubmoduleAddDialog::url()
{
return ui->lineEdit_repo_location->text();
}
QString SubmoduleAddDialog::dir()
{
return ui->lineEdit_working_dir->text();
}
bool SubmoduleAddDialog::isForce() const
{
return ui->checkBox_force->isChecked();
}
void SubmoduleAddDialog::on_lineEdit_repo_location_textChanged(QString const &text)
{
QString path;
int i = text.lastIndexOf('/');
int j = text.lastIndexOf('\\');
if (i < j) i = j;
j = text.size();
if (text.endsWith(".git")) {
j -= 4;
}
if (i >= 0 && i < j) {
path = text.mid(i, j - i);
}
m->repo_name = path;
path = m->default_working_dir / m->repo_name;
path = misc::normalizePathSeparator(path);
ui->lineEdit_working_dir->setText(path);
}
void SubmoduleAddDialog::on_pushButton_test_clicked()
{
mainwindow()->testRemoteRepositoryValidity(url(), overridedSshKey());
}
void SubmoduleAddDialog::on_pushButton_browse_clicked()
{
QString path = ui->lineEdit_working_dir->text();
path = QFileDialog::getExistingDirectory(this, tr("Checkout into"), path);
if (!path.isEmpty()) {
m->default_working_dir = path;
path = m->default_working_dir / m->repo_name;
path = misc::normalizePathSeparator(path);
ui->lineEdit_working_dir->setText(path);
}
}
void SubmoduleAddDialog::on_pushButton_open_existing_clicked()
{
QString dir = mainwindow()->defaultWorkingDir();
dir = QFileDialog::getExistingDirectory(this, tr("Open existing directory"), dir);
if (QFileInfo(dir).isDir()) {
QString url;
GitPtr g = mainwindow()->git(dir);
QList<Git::Remote> vec;
if (g->isValidWorkingCopy()) {
g->getRemoteURLs(&vec);
}
for (Git::Remote const &r : vec) {
if (r.purpose == "push" || url.isEmpty()) {
url = r.url;
}
}
ui->lineEdit_repo_location->setText(url);
ui->lineEdit_working_dir->setText(dir);
done(Accepted);
}
}
QString SubmoduleAddDialog::overridedSshKey() const
{
return ui->advanced_option->sshKey();
}
diff --git a/src/SubmoduleAddDialog.h b/src/SubmoduleAddDialog.h
index a39ce81..13bc579 100644
--- a/src/SubmoduleAddDialog.h
+++ b/src/SubmoduleAddDialog.h
@@ -1,39 +1,39 @@
#ifndef SUBMODULEADDDIALOG_H
#define SUBMODULEADDDIALOG_H
#include <QDialog>
#include <QThread>
#include "Git.h"
namespace Ui {
class SubmoduleAddDialog;
}
-class BasicMainWindow;
+class MainWindow;
class SubmoduleAddDialog : public QDialog {
Q_OBJECT
private:
Ui::SubmoduleAddDialog *ui;
struct Private;
Private *m;
using GitPtr = std::shared_ptr<Git>;
private:
- BasicMainWindow *mainwindow();
+ MainWindow *mainwindow();
public:
- explicit SubmoduleAddDialog(BasicMainWindow *parent, QString const &url, QString const &defworkdir, const Git::Context *gcx);
+ explicit SubmoduleAddDialog(MainWindow *parent, QString const &url, QString const &defworkdir, const Git::Context *gcx);
~SubmoduleAddDialog() override;
QString url();
QString dir();
QString overridedSshKey() const;
bool isForce() const;
private slots:
void on_lineEdit_repo_location_textChanged(QString const &text);
void on_pushButton_test_clicked();
void on_pushButton_browse_clicked();
void on_pushButton_open_existing_clicked();
};
#endif // SUBMODULEADDDIALOG_H
diff --git a/src/SubmodulesDialog.cpp b/src/SubmodulesDialog.cpp
index 1388f95..7de9ae9 100644
--- a/src/SubmodulesDialog.cpp
+++ b/src/SubmodulesDialog.cpp
@@ -1,46 +1,46 @@
#include "SubmodulesDialog.h"
#include "ui_SubmodulesDialog.h"
-#include "BasicMainWindow.h"
+#include "MainWindow.h"
#include "common/misc.h"
SubmodulesDialog::SubmodulesDialog(QWidget *parent, std::vector<Submodule> mods)
: QDialog(parent)
, ui(new Ui::SubmodulesDialog)
{
ui->setupUi(this);
int rows = (int)mods.size();
ui->tableWidget->setColumnCount(5);
ui->tableWidget->setRowCount(rows);
for (int row = 0; row < rows; row++) {
QTableWidgetItem *item;
item = new QTableWidgetItem();
item->setText(mods[row].submodule.path);
ui->tableWidget->setItem(row, 0, item);
item = new QTableWidgetItem();
- item->setText(BasicMainWindow::abbrevCommitID(mods[row].head));
+ item->setText(MainWindow::abbrevCommitID(mods[row].head));
ui->tableWidget->setItem(row, 1, item);
item = new QTableWidgetItem();
item->setText(misc::makeDateTimeString(mods[row].head.commit_date));
ui->tableWidget->setItem(row, 2, item);
item = new QTableWidgetItem();
item->setText(mods[row].head.author);
ui->tableWidget->setItem(row, 3, item);
item = new QTableWidgetItem();
item->setText(mods[row].head.message);
ui->tableWidget->setItem(row, 4, item);
}
ui->tableWidget->resizeColumnsToContents();
ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
}
SubmodulesDialog::~SubmodulesDialog()
{
delete ui;
}
diff --git a/src/WelcomeWizardDialog.cpp b/src/WelcomeWizardDialog.cpp
index aaed083..6d10a4a 100644
--- a/src/WelcomeWizardDialog.cpp
+++ b/src/WelcomeWizardDialog.cpp
@@ -1,216 +1,216 @@
#include "WelcomeWizardDialog.h"
#include "ui_WelcomeWizardDialog.h"
#include <QFileDialog>
#include "MainWindow.h"
#include "common/misc.h"
#include "Git.h"
-WelcomeWizardDialog::WelcomeWizardDialog(BasicMainWindow *parent)
+WelcomeWizardDialog::WelcomeWizardDialog(MainWindow *parent)
: QDialog(parent)
, ui(new Ui::WelcomeWizardDialog)
{
ui->setupUi(this);
Qt::WindowFlags flags = windowFlags();
flags &= ~Qt::WindowContextHelpButtonHint;
setWindowFlags(flags);
mainwindow_ = parent;
pages_.push_back(ui->page_helper_tools);
pages_.push_back(ui->page_global_user_information);
pages_.push_back(ui->page_default_working_folder);
pages_.push_back(ui->page_finish);
ui->stackedWidget->setCurrentWidget(pages_[0]);
on_stackedWidget_currentChanged(0);
avatar_loader_.start(mainwindow_);
connect(&avatar_loader_, &AvatarLoader::updated, [&](){
QString email = ui->lineEdit_user_email->text();
QIcon icon = avatar_loader_.fetch(email.toStdString(), false);
setAvatar(icon);
});
ui->stackedWidget->setCurrentWidget(ui->page_helper_tools);
}
WelcomeWizardDialog::~WelcomeWizardDialog()
{
avatar_loader_.stop();
delete ui;
}
void WelcomeWizardDialog::set_user_name(QString const &v)
{
ui->lineEdit_user_name->setText(v);
}
void WelcomeWizardDialog::set_user_email(QString const &v)
{
ui->lineEdit_user_email->setText(v);
}
void WelcomeWizardDialog::set_default_working_folder(QString const &v)
{
ui->lineEdit_default_working_folder->setText(v);
}
void WelcomeWizardDialog::set_git_command_path(QString const &v)
{
ui->lineEdit_git->setText(v);
}
void WelcomeWizardDialog::set_file_command_path(QString const &v)
{
ui->lineEdit_file->setText(v);
}
QString WelcomeWizardDialog::user_name() const
{
return ui->lineEdit_user_name->text();
}
QString WelcomeWizardDialog::user_email() const
{
return ui->lineEdit_user_email->text();
}
QString WelcomeWizardDialog::default_working_folder() const
{
return ui->lineEdit_default_working_folder->text();
}
QString WelcomeWizardDialog::git_command_path() const
{
return ui->lineEdit_git->text();
}
QString WelcomeWizardDialog::file_command_path() const
{
return ui->lineEdit_file->text();
}
void WelcomeWizardDialog::on_pushButton_prev_clicked()
{
int i = pages_.indexOf(ui->stackedWidget->currentWidget());
if (i == 0) {
done(QDialog::Rejected);
return;
}
if (i > 0) {
i--;
QWidget *w = pages_[i];
ui->stackedWidget->setCurrentWidget(w);
}
}
void WelcomeWizardDialog::on_pushButton_next_clicked()
{
if (ui->stackedWidget->currentWidget() == ui->page_finish) {
done(QDialog::Accepted);
}
int i = pages_.indexOf(ui->stackedWidget->currentWidget());
if (i + 1 < pages_.size()) {
i++;
QWidget *w = pages_[i];
ui->stackedWidget->setCurrentWidget(w);
}
}
void WelcomeWizardDialog::on_stackedWidget_currentChanged(int /*arg1*/)
{
QString prev_text;
QString next_text;
QWidget *w = ui->stackedWidget->currentWidget();
if (w == ui->page_helper_tools) {
prev_text = tr("Cancel");
ui->lineEdit_git->setFocus();
} else if (w == ui->page_global_user_information) {
if (user_name().isEmpty() && user_email().isEmpty()) {
Git::Context gcx;
gcx.git_command = git_command_path();
Git g(gcx, {}, {});
Git::User user = g.getUser(Git::Source::Global);
set_user_name(user.name);
set_user_email(user.email);
}
if (user_name().isEmpty()) {
ui->lineEdit_user_name->setFocus();
} else if (user_email().isEmpty()) {
ui->lineEdit_user_email->setFocus();
} else {
ui->pushButton_next->setFocus();
}
} else if (w == ui->page_default_working_folder) {
ui->lineEdit_default_working_folder->setFocus();
} else if (w == ui->page_finish) {
ui->lineEdit_preview_user->setText(ui->lineEdit_user_name->text());
ui->lineEdit_preview_email->setText(ui->lineEdit_user_email->text());
ui->lineEdit_preview_folder->setText(ui->lineEdit_default_working_folder->text());
ui->lineEdit_preview_git->setText(ui->lineEdit_git->text());
ui->lineEdit_preview_file->setText(ui->lineEdit_file->text());
next_text = tr("Finish");
ui->pushButton_next->setFocus();
}
ui->pushButton_prev->setText(prev_text.isEmpty() ? tr("<< Prev") : prev_text);
ui->pushButton_next->setText(next_text.isEmpty() ? tr("Next >>") : next_text);
ui->pushButton_next->setDefault(true);
}
void WelcomeWizardDialog::on_pushButton_browse_default_workiing_folder_clicked()
{
QString s = ui->lineEdit_default_working_folder->text();
s = QFileDialog::getExistingDirectory(this, tr("Default Working Folder"), s);
s = misc::normalizePathSeparator(s);
ui->lineEdit_default_working_folder->setText(s);
}
void WelcomeWizardDialog::on_pushButton_browse_git_clicked()
{
QString s = mainwindow_->selectGitCommand(false);
ui->lineEdit_git->setText(s);
}
void WelcomeWizardDialog::on_pushButton_browse_file_clicked()
{
QString s = mainwindow_->selectFileCommand(false);
ui->lineEdit_file->setText(s);
}
void WelcomeWizardDialog::setAvatar(QIcon const &icon)
{
QPixmap pm = icon.pixmap(QSize(64, 64));
ui->label_avatar->setPixmap(pm);
}
void WelcomeWizardDialog::on_pushButton_get_icon_clicked()
{
ui->label_avatar->setPixmap(QPixmap());
QString email = ui->lineEdit_user_email->text();
if (email.indexOf('@') > 0) {
QIcon icon = avatar_loader_.fetch(email.toStdString(), true);
if (!icon.isNull()) {
setAvatar(icon);
}
}
}
void WelcomeWizardDialog::on_lineEdit_git_textChanged(const QString &arg1)
{
QString ss;
if (!misc::isExecutable(arg1)) {
ss = "* { background-color: #ffc0c0; }";
}
ui->lineEdit_git->setStyleSheet(ss);
}
void WelcomeWizardDialog::on_lineEdit_file_textChanged(const QString &arg1)
{
QString ss;
if (!misc::isExecutable(arg1)) {
ss = "* { background-color: #ffc0c0; }";
}
ui->lineEdit_file->setStyleSheet(ss);
}
diff --git a/src/WelcomeWizardDialog.h b/src/WelcomeWizardDialog.h
index 69e951b..5036ef0 100644
--- a/src/WelcomeWizardDialog.h
+++ b/src/WelcomeWizardDialog.h
@@ -1,52 +1,52 @@
#ifndef WELCOMEWIZARDDIALOG_H
#define WELCOMEWIZARDDIALOG_H
#include "AvatarLoader.h"
#include <QDialog>
-class BasicMainWindow;
+class MainWindow;
namespace Ui {
class WelcomeWizardDialog;
}
class WelcomeWizardDialog : public QDialog {
Q_OBJECT
private:
- BasicMainWindow *mainwindow_;
+ MainWindow *mainwindow_;
AvatarLoader avatar_loader_;
QList<QWidget *> pages_;
public:
- explicit WelcomeWizardDialog(BasicMainWindow *parent = nullptr);
+ explicit WelcomeWizardDialog(MainWindow *parent = nullptr);
~WelcomeWizardDialog() override;
void set_user_name(QString const &v);
void set_user_email(QString const &v);
void set_default_working_folder(QString const &v);
void set_git_command_path(QString const &v);
void set_file_command_path(QString const &v);
QString user_name() const;
QString user_email() const;
QString default_working_folder() const;
QString git_command_path() const;
QString file_command_path() const;
private slots:
void on_stackedWidget_currentChanged(int arg1);
void on_pushButton_browse_default_workiing_folder_clicked();
void on_pushButton_browse_git_clicked();
void on_pushButton_browse_file_clicked();
void on_pushButton_get_icon_clicked();
void on_pushButton_prev_clicked();
void on_pushButton_next_clicked();
void on_lineEdit_git_textChanged(const QString &arg1);
void on_lineEdit_file_textChanged(const QString &arg1);
private:
Ui::WelcomeWizardDialog *ui;
void setAvatar(const QIcon &icon);
};
#endif // WELCOMEWIZARDDIALOG_H

File Metadata

Mime Type
text/x-diff
Expires
Sat, Feb 7, 7:27 AM (21 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55874
Default Alt Text
(376 KB)

Event Timeline