#include "svnrevertdialog.h"
// Tnz6 includes
#include "tapp.h"
// TnzQt includes
#include "toonzqt/gutil.h"
// TnzLib includes
#include "toonz/txshsimplelevel.h"
// TnzCore includes
#include "tfilepath.h"
#include "tsystem.h"
// Qt includes
#include <QPushButton>
#include <QTreeWidget>
#include <QHeaderView>
#include <QCheckBox>
#include <QMovie>
#include <QLabel>
#include <QDir>
#include <QRegExp>
#include <QMainWindow>
//=============================================================================
// SVNRevertDialog
//-----------------------------------------------------------------------------
SVNRevertDialog::SVNRevertDialog(QWidget *parent, const QString &workingDir,
const QStringList &files, bool folderOnly,
int sceneIconAdded)
: Dialog(TApp::instance()->getMainWindow(), true, false)
, m_workingDir(workingDir)
, m_files(files)
, m_revertSceneContentsCheckBox(0)
, m_folderOnly(folderOnly)
, m_sceneIconAdded(sceneIconAdded) {
setModal(false);
setMinimumSize(300, 150);
setAttribute(Qt::WA_DeleteOnClose, true);
setWindowTitle(tr("Version Control: Revert changes"));
QWidget *container = new QWidget;
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->setAlignment(Qt::AlignHCenter);
mainLayout->setMargin(0);
QHBoxLayout *hLayout = new QHBoxLayout;
m_waitingLabel = new QLabel;
QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
waitingMove->setParent(this);
m_waitingLabel->setMovie(waitingMove);
waitingMove->setCacheMode(QMovie::CacheAll);
waitingMove->start();
m_textLabel = new QLabel(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);
if (!m_folderOnly) {
mainLayout->addSpacing(10);
QHBoxLayout *checkBoxLayout = new QHBoxLayout;
checkBoxLayout->setMargin(0);
m_revertSceneContentsCheckBox = new QCheckBox(this);
connect(m_revertSceneContentsCheckBox, SIGNAL(toggled(bool)), this,
SLOT(onRevertSceneContentsToggled(bool)));
m_revertSceneContentsCheckBox->setChecked(false);
m_revertSceneContentsCheckBox->hide();
m_revertSceneContentsCheckBox->setText(tr("Revert Scene Contents"));
checkBoxLayout->addStretch();
checkBoxLayout->addWidget(m_revertSceneContentsCheckBox);
checkBoxLayout->addStretch();
mainLayout->addLayout(checkBoxLayout);
}
container->setLayout(mainLayout);
beginHLayout();
addWidget(container, false);
endHLayout();
m_revertButton = new QPushButton(tr("Revert"));
m_revertButton->setEnabled(false);
connect(m_revertButton, SIGNAL(clicked()), this,
SLOT(onRevertButtonClicked()));
m_cancelButton = new QPushButton(tr("Cancel"));
connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
addButtonBarWidget(m_revertButton, m_cancelButton);
// 0. Connect for svn errors (that may occurs everythings)
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);
}
//-----------------------------------------------------------------------------
void SVNRevertDialog::onStatusRetrieved(const QString &xmlResponse) {
SVNStatusReader sr(xmlResponse);
m_status = sr.getStatus();
checkFiles();
int fileSize = m_filesToRevert.size();
for (int i = 0; i < fileSize; i++) {
if (m_filesToRevert.at(i).endsWith(".tnz")) {
if (m_revertSceneContentsCheckBox) m_revertSceneContentsCheckBox->show();
break;
}
}
initTreeWidget();
if (m_filesToRevert.size() == 0) {
QString msg = QString(tr("No items to revert."));
m_textLabel->setText(msg);
switchToCloseButton();
} else {
QString msg = QString(tr("%1 items to revert."))
.arg(m_filesToRevert.size() == 1
? 1
: m_filesToRevert.size() - m_sceneIconAdded);
m_textLabel->setText(msg);
m_waitingLabel->hide();
m_revertButton->setEnabled(true);
m_thread.disconnect(SIGNAL(statusRetrieved(const QString &)));
}
}
//-----------------------------------------------------------------------------
void SVNRevertDialog::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 != "normal" && s.m_item != "unversioned") {
if (m_folderOnly || m_files.contains(s.m_path))
m_filesToRevert.append(s.m_path);
}
}
}
//-----------------------------------------------------------------------------
void SVNRevertDialog::initTreeWidget() {
int filesSize = m_filesToRevert.size();
bool itemAdded = false;
for (int i = 0; i < filesSize; i++) {
QString fileName = m_filesToRevert.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_filesToRevert.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 SVNRevertDialog::switchToCloseButton() {
m_waitingLabel->hide();
m_treeWidget->hide();
m_revertButton->disconnect();
m_revertButton->setText("Close");
m_revertButton->setEnabled(true);
m_cancelButton->hide();
connect(m_revertButton, SIGNAL(clicked()), this, SLOT(close()));
}
//-----------------------------------------------------------------------------
void SVNRevertDialog::onRevertButtonClicked() {
m_revertButton->setEnabled(false);
revertFiles();
}
//-----------------------------------------------------------------------------
void SVNRevertDialog::revertFiles() {
m_treeWidget->hide();
if (m_revertSceneContentsCheckBox) m_revertSceneContentsCheckBox->hide();
m_waitingLabel->show();
int fileToRevertSize = m_filesToRevert.size();
int sceneResourceToRevertSize = m_sceneResources.size();
int totalFilesToRevert = fileToRevertSize + sceneResourceToRevertSize;
if (totalFilesToRevert > 0) {
m_textLabel->setText(tr("Reverting %1 items...")
.arg(totalFilesToRevert == 1
? 1
: totalFilesToRevert - m_sceneIconAdded));
QStringList args;
args << "revert";
for (int i = 0; i < fileToRevertSize; i++) args << m_filesToRevert.at(i);
for (int i = 0; i < sceneResourceToRevertSize; i++)
args << m_sceneResources.at(i);
connect(&m_thread, SIGNAL(done(const QString &)), SLOT(onRevertDone()));
m_thread.executeCommand(m_workingDir, "svn", args);
} else
onRevertDone();
}
//-----------------------------------------------------------------------------
void SVNRevertDialog::onRevertDone() {
m_textLabel->setText(tr("Revert done successfully."));
QStringList files;
for (int i = 0; i < m_filesToRevert.size(); i++)
files.append(m_filesToRevert.at(i));
emit done(files);
switchToCloseButton();
}
//-----------------------------------------------------------------------------
void SVNRevertDialog::onError(const QString &errorString) {
m_textLabel->setText(errorString);
switchToCloseButton();
update();
}
//-----------------------------------------------------------------------------
void SVNRevertDialog::onRevertSceneContentsToggled(bool checked) {
if (!checked)
m_sceneResources.clear();
else {
VersionControl *vc = VersionControl::instance();
int fileSize = m_filesToRevert.count();
for (int i = 0; i < fileSize; i++) {
QString fileName = m_filesToRevert.at(i);
if (fileName.endsWith(".tnz")) {
if (m_filesToRevert.contains(fileName))
m_sceneResources.append(vc->getSceneContents(m_workingDir, fileName));
}
}
}
m_textLabel->setText(
tr("%1 items to revert.")
.arg(m_filesToRevert.size() + m_sceneResources.size() == 1
? 1
: m_filesToRevert.size() + m_sceneResources.size() -
m_sceneIconAdded));
}
//=============================================================================
// SVNRevertFrameRangeDialog
//-----------------------------------------------------------------------------
SVNRevertFrameRangeDialog::SVNRevertFrameRangeDialog(
QWidget *parent, const QString &workingDir, const QString &file,
const QString &tempFileName)
: Dialog(TApp::instance()->getMainWindow(), true, false)
, m_workingDir(workingDir)
, m_file(file)
, m_tempFileName(tempFileName) {
setModal(false);
setMinimumSize(300, 150);
setAttribute(Qt::WA_DeleteOnClose, true);
setWindowTitle(tr("Version Control: Revert Frame Range changes"));
beginVLayout();
m_waitingLabel = new QLabel;
QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
waitingMove->setParent(this);
m_waitingLabel->setMovie(waitingMove);
waitingMove->setCacheMode(QMovie::CacheAll);
waitingMove->start();
m_waitingLabel->hide();
m_textLabel = new QLabel(tr("1 item to revert."));
addWidgets(m_waitingLabel, m_textLabel);
endVLayout();
m_revertButton = new QPushButton(tr("Revert"));
connect(m_revertButton, SIGNAL(clicked()), this,
SLOT(onRevertButtonClicked()));
m_cancelButton = new QPushButton(tr("Cancel"));
connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
addButtonBarWidget(m_revertButton, m_cancelButton);
}
//-----------------------------------------------------------------------------
void SVNRevertFrameRangeDialog::switchToCloseButton() {
m_waitingLabel->hide();
m_revertButton->disconnect();
m_revertButton->setText("Close");
m_revertButton->setEnabled(true);
m_cancelButton->hide();
connect(m_revertButton, SIGNAL(clicked()), this, SLOT(close()));
}
//-----------------------------------------------------------------------------
void SVNRevertFrameRangeDialog::onRevertButtonClicked() {
m_revertButton->setEnabled(false);
revertFiles();
}
//-----------------------------------------------------------------------------
void SVNRevertFrameRangeDialog::revertFiles() {
m_waitingLabel->show();
m_textLabel->setText(tr("Reverting 1 item..."));
try {
TFilePath pathToRemove = TFilePath(m_tempFileName.toStdWString());
if (TSystem::doesExistFileOrLevel(pathToRemove))
TSystem::removeFileOrLevel(TFilePath(m_tempFileName.toStdWString()));
if (pathToRemove.getType() == "tlv") {
pathToRemove = pathToRemove.withType("tpl");
if (TSystem::doesExistFileOrLevel(pathToRemove))
TSystem::removeFileOrLevel(pathToRemove);
}
TFilePath hookFilePath =
pathToRemove.withName(pathToRemove.getName() + "_hooks")
.withType("xml");
if (TSystem::doesExistFileOrLevel(hookFilePath))
TSystem::removeFileOrLevel(hookFilePath);
} catch (...) {
m_textLabel->setText(tr("It is not possible to revert the file."));
switchToCloseButton();
return;
}
TFilePath path =
TFilePath(m_workingDir.toStdWString()) + m_file.toStdWString();
if (path.getDots() == "..") {
TFilePath dir = path.getParentDir();
QDir qDir(QString::fromStdWString(dir.getWideString()));
QString levelName =
QRegExp::escape(QString::fromStdWString(path.getWideName()));
QString levelType = QString::fromStdString(path.getType());
QString exp(levelName + ".[0-9]{1,4}." + levelType);
QRegExp regExp(exp);
QStringList list = qDir.entryList(QDir::Files);
m_files = list.filter(regExp);
// 0. Connect for svn errors (that may occurs everythings)
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, m_files);
} else {
m_textLabel->setText(tr("Revert done successfully."));
QStringList files;
files.append(m_file);
emit done(files);
switchToCloseButton();
}
}
//-----------------------------------------------------------------------------
void SVNRevertFrameRangeDialog::onStatusRetrieved(const QString &xmlResponse) {
SVNStatusReader sr(xmlResponse);
m_status = sr.getStatus();
checkFiles();
int fileToRevertCount = m_filesToRevert.size();
if (fileToRevertCount == 0) {
m_textLabel->setText(tr("Revert done successfully."));
switchToCloseButton();
} else {
m_thread.disconnect(SIGNAL(statusRetrieved(const QString &)));
m_textLabel->setText(
tr("Reverting %1 items...").arg(QString::number(fileToRevertCount)));
QStringList args;
args << "revert";
for (int i = 0; i < fileToRevertCount; i++) args << m_filesToRevert.at(i);
connect(&m_thread, SIGNAL(done(const QString &)), SLOT(onRevertDone()));
m_thread.executeCommand(m_workingDir, "svn", args);
}
}
//-----------------------------------------------------------------------------
void SVNRevertFrameRangeDialog::onError(const QString &errorString) {
m_textLabel->setText(errorString);
switchToCloseButton();
update();
}
//-----------------------------------------------------------------------------
void SVNRevertFrameRangeDialog::checkFiles() {
int statusCount = m_status.size();
for (int i = 0; i < statusCount; i++) {
SVNStatus s = m_status.at(i);
if (s.m_item != "normal" && s.m_item != "unversioned") {
if (m_files.contains(s.m_path)) m_filesToRevert.append(s.m_path);
}
}
}
//-----------------------------------------------------------------------------
void SVNRevertFrameRangeDialog::onRevertDone() {
m_textLabel->setText(tr("Revert done successfully."));
QStringList files;
for (int i = 0; i < m_filesToRevert.size(); i++)
files.append(m_filesToRevert.at(i));
emit done(files);
switchToCloseButton();
}