#include "svnlockdialog.h"
// Tnz6 includes
#include "tapp.h"
// TnzQt includes
#include "toonzqt/gutil.h"
// TnzLib includes
#include "toonz/txshsimplelevel.h"
// TnzCore includes
#include "tsystem.h"
// Qt includes
#include <QWidget>
#include <QBoxLayout>
#include <QFormLayout>
#include <QMovie>
#include <QPushButton>
#include <QLabel>
#include <QPlainTextEdit>
#include <QTime>
#include <QCheckBox>
#include <QHeaderView>
#include <QTreeWidget>
#include <QTextStream>
#include <QMainWindow>
//=============================================================================
// SVNLockDialog
//-----------------------------------------------------------------------------
SVNLockDialog::SVNLockDialog(QWidget *parent, const QString &workingDir,
const QStringList &files, bool lock,
int sceneIconAdded)
: Dialog(TApp::instance()->getMainWindow(), true, false)
, m_editSceneContentsCheckBox(0)
, m_workingDir(workingDir)
, m_files(files)
, m_lock(lock)
, m_hasError(false)
, m_sceneIconAdded(sceneIconAdded)
, m_targetTempFile(0) {
setModal(false);
setAttribute(Qt::WA_DeleteOnClose, true);
if (m_lock)
setWindowTitle(tr("Version Control: Edit"));
else
setWindowTitle(tr("Version Control: Unlock"));
setMinimumSize(300, 150);
QWidget *container = new QWidget;
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->setAlignment(Qt::AlignHCenter);
mainLayout->setMargin(0);
QHBoxLayout *hLayout = new QHBoxLayout;
m_waitingLabel = new QLabel;
m_waitingLabel->setMaximumHeight(55);
QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
waitingMove->setParent(this);
m_waitingLabel->setMovie(waitingMove);
waitingMove->setCacheMode(QMovie::CacheAll);
waitingMove->start();
m_textLabel = new QLabel;
m_textLabel->setText(tr("Getting repository status..."));
hLayout->addStretch();
hLayout->addWidget(m_waitingLabel);
hLayout->addWidget(m_textLabel);
hLayout->addStretch();
mainLayout->addLayout(hLayout);
m_treeWidget = new QTreeWidget;
m_treeWidget->setStyleSheet("QTreeWidget { border: 1px solid gray; }");
m_treeWidget->header()->hide();
m_treeWidget->hide();
mainLayout->addWidget(m_treeWidget);
QFormLayout *formLayout = new QFormLayout;
formLayout->setLabelAlignment(Qt::AlignRight);
formLayout->setFormAlignment(Qt::AlignHCenter | Qt::AlignTop);
formLayout->setSpacing(10);
formLayout->setMargin(0);
m_commentTextEdit = new QPlainTextEdit;
m_commentTextEdit->setMaximumHeight(50);
m_commentLabel = new QLabel(tr("Comment:"));
m_commentLabel->setFixedWidth(55);
if (!m_lock) {
m_commentTextEdit->hide();
m_commentLabel->hide();
}
formLayout->addRow(m_commentLabel, m_commentTextEdit);
m_editSceneContentsCheckBox = new QCheckBox(this);
m_editSceneContentsCheckBox->setChecked(false);
if (m_lock)
m_editSceneContentsCheckBox->setText(tr("Edit Scene Contents"));
else
m_editSceneContentsCheckBox->setText(tr("Unlock Scene Contents"));
m_editSceneContentsCheckBox->hide();
connect(m_editSceneContentsCheckBox, SIGNAL(toggled(bool)), this,
SLOT(onEditSceneContentsToggled(bool)));
int fileSize = m_files.size();
for (int i = 0; i < fileSize; i++) {
if (m_files.at(i).endsWith(".tnz")) {
m_editSceneContentsCheckBox->show();
break;
}
}
formLayout->addRow("", m_editSceneContentsCheckBox);
mainLayout->addLayout(formLayout);
container->setLayout(mainLayout);
beginHLayout();
addWidget(container, false);
endHLayout();
m_lockButton = new QPushButton();
if (m_lock)
m_lockButton->setText(tr("Edit"));
else
m_lockButton->setText(tr("Unlock"));
m_lockButton->hide();
connect(m_lockButton, SIGNAL(clicked()), this, SLOT(onLockButtonClicked()));
m_cancelButton = new QPushButton(tr("Cancel"));
connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
addButtonBarWidget(m_lockButton, m_cancelButton);
// 0. Connect for svn errors (that may occur every time)
connect(&m_thread, SIGNAL(error(const QString &)), this,
SLOT(onError(const QString &)));
// 1. Getting status
connect(&m_thread, SIGNAL(statusRetrieved(const QString &)), this,
SLOT(onStatusRetrieved(const QString &)));
m_thread.getSVNStatus(m_workingDir, true);
}
//-----------------------------------------------------------------------------
void SVNLockDialog::onStatusRetrieved(const QString &xmlResponse) {
SVNStatusReader sr(xmlResponse);
m_status = sr.getStatus();
m_thread.disconnect(SIGNAL(statusRetrieved(const QString &)));
checkFiles();
initTreeWidget();
if (m_filesToEdit.size() == 0) {
if (m_lock) {
m_textLabel->setText(tr("No items to edit."));
m_commentTextEdit->show();
m_commentLabel->show();
} else
m_textLabel->setText(tr("No items to unlock."));
switchToCloseButton();
} else {
int height = m_lock ? 160 : 50;
if (m_treeWidget->isVisible())
height += (m_filesToEdit.size() * (m_lock ? 25 : 50));
setMinimumSize(300, std::min(height, 350));
m_waitingLabel->hide();
if (m_lock)
m_textLabel->setText(
tr("%1 items to edit.")
.arg(m_filesToEdit.size() == 1 ? 1 : m_filesToEdit.size() -
m_sceneIconAdded));
else
m_textLabel->setText(
tr("%1 items to unlock.")
.arg(m_filesToEdit.size() == 1 ? 1 : m_filesToEdit.size() -
m_sceneIconAdded));
m_lockButton->show();
}
}
//-----------------------------------------------------------------------------
void SVNLockDialog::onSceneResourcesStatusRetrieved(
const QString &xmlResponse) {
SVNStatusReader sr(xmlResponse);
m_status = sr.getStatus();
m_thread.disconnect(SIGNAL(statusRetrieved(const QString &)));
int statusCount = m_status.size();
for (int i = 0; i < statusCount; i++) {
SVNStatus s = m_status.at(i);
if (s.m_path == "." || s.m_path == "..") continue;
if (s.m_item != "unversioned" && s.m_item != "missing") {
if (m_lock && !s.m_isLocked) m_filesToEdit.append(s.m_path);
if (!m_lock && s.m_isLocked) m_filesToEdit.append(s.m_path);
}
}
executeCommand();
}
//-----------------------------------------------------------------------------
void SVNLockDialog::onError(const QString &errorString) {
if (m_targetTempFile) {
QFile::remove(m_targetTempFile->fileName());
delete m_targetTempFile;
m_targetTempFile = 0;
}
m_textLabel->setText(errorString);
switchToCloseButton();
update();
m_hasError = true;
}
//-----------------------------------------------------------------------------
void SVNLockDialog::onLockButtonClicked() {
m_waitingLabel->show();
m_commentLabel->hide();
m_commentTextEdit->hide();
m_treeWidget->hide();
m_editSceneContentsCheckBox->hide();
// Check the status of sceneResources
if (!m_sceneResources.empty()) {
m_thread.disconnect(SIGNAL(done(const QString &)));
connect(&m_thread, SIGNAL(statusRetrieved(const QString &)), this,
SLOT(onSceneResourcesStatusRetrieved(const QString &)));
m_thread.getSVNStatus(m_workingDir, m_sceneResources);
return;
} else
executeCommand();
}
//-----------------------------------------------------------------------------
void SVNLockDialog::executeCommand() {
if (m_lock)
m_textLabel->setText(
tr("Editing %1 items...")
.arg(m_filesToEdit.size() == 1 ? 1 : m_filesToEdit.size() -
m_sceneIconAdded));
else
m_textLabel->setText(
tr("Unlocking %1 items...")
.arg(m_filesToEdit.size() == 1 ? 1 : m_filesToEdit.size() -
m_sceneIconAdded));
QStringList args;
if (m_lock)
args << "lock";
else
args << "unlock";
// Use a temporary file to store all the files list
m_targetTempFile = new QFile(m_workingDir + "/" + "tempLockFile");
if (m_targetTempFile->open(QFile::WriteOnly | QFile::Truncate)) {
QTextStream out(m_targetTempFile);
int fileCount = m_filesToEdit.size();
for (int i = 0; i < fileCount; i++) {
QString path = m_filesToEdit.at(i);
;
out << path + "\n";
}
}
m_targetTempFile->close();
args << "--targets";
args << "tempLockFile";
if (m_lock) {
if (!m_commentTextEdit->toPlainText().isEmpty())
args << QString("-m").append(TSystem::getHostName() + ":" +
m_commentTextEdit->toPlainText());
else
args << QString("-m").append(TSystem::getHostName() + ":" +
VersionControl::instance()->getUserName() +
" edit files.");
}
m_thread.disconnect(SIGNAL(done(const QString &)));
connect(&m_thread, SIGNAL(done(const QString &)), SLOT(onLockDone()));
m_thread.executeCommand(m_workingDir, "svn", args);
}
//-----------------------------------------------------------------------------
void SVNLockDialog::onLockDone() {
if (m_targetTempFile) {
QFile::remove(m_targetTempFile->fileName());
delete m_targetTempFile;
m_targetTempFile = 0;
}
if (!m_hasError) {
QStringList files;
int fileCount = m_files.size();
for (int i = 0; i < fileCount; i++) files.append(m_files.at(i));
emit done(files);
close();
}
}
//-----------------------------------------------------------------------------
void SVNLockDialog::initTreeWidget() {
int filesSize = m_filesToEdit.size();
bool itemAdded = false;
for (int i = 0; i < filesSize; i++) {
QString fileName = m_filesToEdit.at(i);
TFilePath fp =
TFilePath(m_workingDir.toStdWString()) + fileName.toStdWString();
TFilePathSet fpset;
TXshSimpleLevel::getFiles(fp, fpset);
QStringList linkedFiles;
TFilePathSet::iterator it;
for (it = fpset.begin(); it != fpset.end(); ++it) {
QString fn = toQString((*it).withoutParentDir());
if (m_filesToEdit.contains(fn)) linkedFiles.append(fn);
}
if (!linkedFiles.isEmpty()) {
itemAdded = true;
QTreeWidgetItem *twi = new QTreeWidgetItem(m_treeWidget);
twi->setText(0, fileName);
twi->setFirstColumnSpanned(false);
twi->setFlags(Qt::NoItemFlags);
for (int i = 0; i < linkedFiles.size(); i++) {
QTreeWidgetItem *child = new QTreeWidgetItem(twi);
child->setText(0, linkedFiles.at(i));
child->setFlags(Qt::NoItemFlags);
}
twi->setExpanded(true);
}
}
if (itemAdded) m_treeWidget->show();
}
//-----------------------------------------------------------------------------
void SVNLockDialog::checkFiles() {
int statusCount = m_status.size();
for (int i = 0; i < statusCount; i++) {
SVNStatus s = m_status.at(i);
if (s.m_path == "." || s.m_path == "..") continue;
if (s.m_item != "unversioned" && s.m_item != "missing") {
if (m_files.contains(s.m_path)) {
if (m_lock && !s.m_isLocked) m_filesToEdit.append(s.m_path);
if (!m_lock && s.m_isLocked) m_filesToEdit.append(s.m_path);
}
}
}
}
//-----------------------------------------------------------------------------
void SVNLockDialog::switchToCloseButton() {
m_editSceneContentsCheckBox->hide();
m_commentLabel->hide();
m_commentTextEdit->hide();
m_treeWidget->hide();
m_waitingLabel->hide();
m_lockButton->disconnect();
m_lockButton->setText("Close");
m_lockButton->setEnabled(true);
m_lockButton->show();
m_cancelButton->hide();
connect(m_lockButton, SIGNAL(clicked()), this, SLOT(close()));
}
//-----------------------------------------------------------------------------
void SVNLockDialog::onEditSceneContentsToggled(bool checked) {
if (!checked)
m_sceneResources.clear();
else {
VersionControl *vc = VersionControl::instance();
int fileSize = m_files.count();
for (int i = 0; i < fileSize; i++) {
QString fileName = m_files.at(i);
if (fileName.endsWith(".tnz"))
m_sceneResources.append(vc->getSceneContents(m_workingDir, fileName));
}
}
if (m_lock)
m_textLabel->setText(
tr("%1 items to edit.")
.arg(m_filesToEdit.size() + m_sceneResources.size() == 1
? 1
: m_filesToEdit.size() + m_sceneResources.size() -
m_sceneIconAdded));
else
m_textLabel->setText(
tr("%1 items to unlock.")
.arg(m_filesToEdit.size() + m_sceneResources.size() == 1
? 1
: m_filesToEdit.size() + m_sceneResources.size() -
m_sceneIconAdded));
}
//=============================================================================
// SVNLockInfoDialog
//-----------------------------------------------------------------------------
SVNLockInfoDialog::SVNLockInfoDialog(QWidget *parent, const SVNStatus &status)
: Dialog(TApp::instance()->getMainWindow(), true, false), m_status(status) {
setModal(false);
setAttribute(Qt::WA_DeleteOnClose, true);
setWindowTitle(tr("Version Control: Edit Info"));
setMinimumSize(300, 150);
QFormLayout *mainLayout = new QFormLayout;
mainLayout->setMargin(0);
mainLayout->setLabelAlignment(Qt::AlignLeft);
mainLayout->addRow(tr("<b>Edited By:</b>"), new QLabel(m_status.m_lockOwner));
mainLayout->addRow(tr("<b>Host:</b>"), new QLabel(m_status.m_lockHostName));
mainLayout->addRow(tr("<b>Comment:</b>"), new QLabel(m_status.m_lockComment));
QDate d = QDate::fromString(m_status.m_lockDate.left(10), "yyyy-MM-dd");
int dayCount = d.daysTo(QDate::currentDate());
QString dateString;
if (dayCount == 0) {
QString timeString = m_status.m_lockDate.split("T").at(1);
timeString = timeString.left(5);
// Convert the current time, to UTC
QDateTime currentTime = QDateTime::currentDateTime().toUTC();
QTime t = QTime::fromString(timeString, "hh:mm");
QTime now = QTime::fromString(currentTime.toString("hh:mm"), "hh:mm");
int seconds = t.secsTo(now);
int minute = seconds / 60;
dateString += QString::number(minute) + " minutes ago.";
} else
dateString += QString::number(dayCount) + " days ago.";
mainLayout->addRow(tr("<b>Date:</b>"), new QLabel(dateString)),
// container->setLayout(mainLayout);
beginHLayout();
addLayout(mainLayout, false);
endHLayout();
QPushButton *closeButton = new QPushButton(tr("Close"));
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
addButtonBarWidget(closeButton);
}