1
2
3 #include "svndeletedialog.h"
4
5 // Tnz6 includes
6 #include "tapp.h"
7 #include "tsystem.h"
8 #include "tfilepath.h"
9 #include "filebrowser.h"
10 #include "fileselection.h"
11
12 // TnzQt includes
13 #include "toonzqt/tselectionhandle.h"
14 #include "toonzqt/gutil.h"
15
16 // TnzLib includes
17 #include "toonz/txshsimplelevel.h"
18
19 // Qt includes
20 #include <QWidget>
21 #include <QLabel>
22 #include <QMovie>
23 #include <QCheckBox>
24 #include <QPlainTextEdit>
25 #include <QPushButton>
26 #include <QBoxLayout>
27 #include <QFormLayout>
28 #include <QTreeWidget>
29 #include <QHeaderView>
30 #include <QTextStream>
31 #include <QDir>
32 #include <QMainWindow>
33
34 //=============================================================================
35 // SVNDeleteDialog
36 //-----------------------------------------------------------------------------
37
SVNDeleteDialog(QWidget * parent,const QString & workingDir,const QStringList & files,bool isFolder,int sceneIconAdded)38 SVNDeleteDialog::SVNDeleteDialog(QWidget *parent, const QString &workingDir,
39 const QStringList &files, bool isFolder,
40 int sceneIconAdded)
41 : Dialog(TApp::instance()->getMainWindow(), true, false)
42 , m_deleteSceneContentsCheckBox(0)
43 , m_workingDir(workingDir)
44 , m_files(files)
45 , m_targetTempFile(0)
46 , m_isFolder(isFolder)
47 , m_sceneIconAdded(sceneIconAdded) {
48 setModal(false);
49 setAttribute(Qt::WA_DeleteOnClose, true);
50
51 setWindowTitle(tr("Version Control: Delete"));
52
53 setMinimumSize(300, 180);
54
55 QWidget *container = new QWidget;
56
57 QVBoxLayout *mainLayout = new QVBoxLayout;
58 mainLayout->setAlignment(Qt::AlignHCenter);
59 mainLayout->setMargin(0);
60
61 QHBoxLayout *hLayout = new QHBoxLayout;
62
63 m_waitingLabel = new QLabel;
64 QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
65 waitingMove->setParent(this);
66 m_waitingLabel->hide();
67
68 m_waitingLabel->setMovie(waitingMove);
69 waitingMove->setCacheMode(QMovie::CacheAll);
70 waitingMove->start();
71
72 m_textLabel = new QLabel;
73
74 if (m_isFolder) {
75 QDir dir(m_workingDir + "/" + m_files.at(0));
76 int filesCount = dir.entryList(QDir::Files | QDir::Dirs).count();
77 if (filesCount > 0)
78 m_textLabel->setText(tr("Delete folder that contains %1 items.")
79 .arg(filesCount - m_sceneIconAdded));
80 else
81 m_textLabel->setText(tr("Delete empty folder."));
82 } else
83 m_textLabel->setText(
84 tr("Delete %1 items.").arg(m_files.size() - m_sceneIconAdded));
85
86 hLayout->addStretch();
87 hLayout->addWidget(m_waitingLabel);
88 hLayout->addWidget(m_textLabel);
89 hLayout->addStretch();
90
91 mainLayout->addLayout(hLayout);
92
93 m_treeWidget = new QTreeWidget;
94 m_treeWidget->setStyleSheet("QTreeWidget { border: 1px solid gray; }");
95 m_treeWidget->header()->hide();
96 m_treeWidget->hide();
97 mainLayout->addWidget(m_treeWidget);
98
99 QFormLayout *formLayout = new QFormLayout;
100 formLayout->setLabelAlignment(Qt::AlignRight);
101 formLayout->setFormAlignment(Qt::AlignHCenter | Qt::AlignTop);
102 formLayout->setSpacing(10);
103 formLayout->setMargin(0);
104
105 m_commentTextEdit = new QPlainTextEdit;
106 m_commentTextEdit->setMaximumHeight(50);
107
108 m_commentLabel = new QLabel(tr("Comment:"));
109 m_commentLabel->setFixedWidth(55);
110
111 m_commentTextEdit->hide();
112 m_commentLabel->hide();
113
114 formLayout->addRow(m_commentLabel, m_commentTextEdit);
115
116 if (!m_isFolder) {
117 m_deleteSceneContentsCheckBox = new QCheckBox(this);
118 connect(m_deleteSceneContentsCheckBox, SIGNAL(toggled(bool)), this,
119 SLOT(onDeleteSceneContentsToggled(bool)));
120 m_deleteSceneContentsCheckBox->setChecked(false);
121 m_deleteSceneContentsCheckBox->hide();
122 m_deleteSceneContentsCheckBox->setText(tr("Delete Scene Contents"));
123
124 formLayout->addRow("", m_deleteSceneContentsCheckBox);
125
126 int fileSize = m_files.size();
127 for (int i = 0; i < fileSize; i++) {
128 if (m_files.at(i).endsWith(".tnz")) {
129 m_deleteSceneContentsCheckBox->show();
130 break;
131 }
132 }
133 }
134
135 m_keepLocalCopyCheckBox = new QCheckBox(tr(" Keep Local Copy"));
136 m_keepLocalCopyCheckBox->setChecked(true);
137 m_keepLocalCopyCheckBox->hide();
138
139 formLayout->addRow("", m_keepLocalCopyCheckBox);
140
141 mainLayout->addLayout(formLayout);
142
143 container->setLayout(mainLayout);
144
145 beginHLayout();
146 addWidget(container, false);
147 endHLayout();
148
149 m_deleteLocalButton = new QPushButton();
150 m_deleteLocalButton->setText(tr("Delete Local Copy "));
151 connect(m_deleteLocalButton, SIGNAL(clicked()), this,
152 SLOT(onDeleteLocalButtonClicked()));
153
154 m_deleteServerButton = new QPushButton();
155 m_deleteServerButton->setText(tr("Delete on Server "));
156 connect(m_deleteServerButton, SIGNAL(clicked()), this,
157 SLOT(onDeleteServerButtonClicked()));
158
159 m_cancelButton = new QPushButton(tr("Cancel"));
160 connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
161
162 addButtonBarWidget(m_deleteLocalButton, m_deleteServerButton, m_cancelButton);
163
164 // 0. Connect for svn errors (that may occurs)
165 connect(&m_thread, SIGNAL(error(const QString &)), this,
166 SLOT(onError(const QString &)));
167 }
168
169 //-----------------------------------------------------------------------------
170
showEvent(QShowEvent * e)171 void SVNDeleteDialog::showEvent(QShowEvent *e) {
172 if (!m_isFolder) {
173 initTreeWidget();
174
175 int height = 50;
176 if (m_treeWidget->isVisible()) height += (m_files.size() * 50);
177
178 setMinimumSize(300, std::min(height, 350));
179 }
180 QDialog::showEvent(e);
181 }
182
183 //-----------------------------------------------------------------------------
184
onError(const QString & errorString)185 void SVNDeleteDialog::onError(const QString &errorString) {
186 if (m_targetTempFile) {
187 QFile::remove(m_targetTempFile->fileName());
188 delete m_targetTempFile;
189 m_targetTempFile = 0;
190 }
191
192 m_textLabel->setText(errorString);
193 switchToCloseButton();
194 update();
195 }
196
197 //-----------------------------------------------------------------------------
198
switchToCloseButton()199 void SVNDeleteDialog::switchToCloseButton() {
200 if (m_deleteSceneContentsCheckBox) m_deleteSceneContentsCheckBox->hide();
201 m_commentTextEdit->hide();
202 m_commentLabel->hide();
203 m_waitingLabel->hide();
204 m_treeWidget->hide();
205 m_keepLocalCopyCheckBox->hide();
206 m_deleteLocalButton->disconnect();
207 m_deleteLocalButton->setText("Close");
208 m_deleteLocalButton->show();
209 m_cancelButton->hide();
210 m_deleteServerButton->hide();
211 connect(m_deleteLocalButton, SIGNAL(clicked()), this, SLOT(close()));
212 }
213
214 //-----------------------------------------------------------------------------
215
onDeleteLocalButtonClicked()216 void SVNDeleteDialog::onDeleteLocalButtonClicked() {
217 // Delete files locally
218 int fileCount = m_files.size();
219 m_waitingLabel->show();
220 m_textLabel->setText(
221 tr("Deleting %1 items...")
222 .arg(fileCount + m_sceneResources.size() - m_sceneIconAdded));
223 m_textLabel->show();
224
225 for (int i = 0; i < fileCount; i++) {
226 TFilePath fp((m_workingDir + "/" + m_files.at(i)).toStdWString());
227 TSystem::moveFileOrLevelToRecycleBin(fp);
228 }
229
230 int sceneResourcesCount = m_sceneResources.size();
231 for (int i = 0; i < sceneResourcesCount; i++) {
232 TFilePath fp(m_sceneResources.at(i).toStdWString());
233 TSystem::moveFileOrLevelToRecycleBin(fp);
234 }
235
236 updateFileBrowser();
237
238 emit done(m_files);
239
240 m_waitingLabel->hide();
241 m_textLabel->hide();
242
243 close();
244 }
245
246 //-----------------------------------------------------------------------------
247
updateFileBrowser()248 void SVNDeleteDialog::updateFileBrowser() {
249 // Reset the selection
250 TSelection *selection =
251 TApp::instance()->getCurrentSelection()->getSelection();
252 FileSelection *fileSelection = dynamic_cast<FileSelection *>(selection);
253 if (fileSelection) fileSelection->selectNone();
254
255 TFilePath fp((m_workingDir + "/" + m_files.at(0)).toStdWString());
256
257 // Refresh FileBrowser
258 FileBrowser::refreshFolder(fp.getParentDir());
259 }
260
261 //-----------------------------------------------------------------------------
262
onDeleteServerButtonClicked()263 void SVNDeleteDialog::onDeleteServerButtonClicked() {
264 m_deleteLocalButton->hide();
265
266 disconnect(m_deleteServerButton, SIGNAL(clicked()), this,
267 SLOT(onDeleteServerButtonClicked()));
268 m_deleteServerButton->setText(tr("Delete"));
269 connect(m_deleteServerButton, SIGNAL(clicked()), this, SLOT(deleteFiles()));
270
271 int height = 175;
272 if (m_treeWidget->isVisible()) height += (m_files.size() * 50);
273 setMinimumSize(300, std::min(height, 350));
274
275 m_textLabel->setText(
276 tr("You are deleting items also on repository. Are you sure ?"));
277 m_commentLabel->show();
278 m_commentTextEdit->show();
279 m_keepLocalCopyCheckBox->show();
280 }
281
282 //-----------------------------------------------------------------------------
283
deleteFiles()284 void SVNDeleteDialog::deleteFiles() {
285 m_waitingLabel->show();
286 m_textLabel->setText(
287 tr("Deleting %1 items...")
288 .arg(QString::number(m_files.size() + m_sceneResources.size() -
289 m_sceneIconAdded)));
290 m_commentLabel->hide();
291 m_commentTextEdit->hide();
292 m_treeWidget->hide();
293 m_keepLocalCopyCheckBox->hide();
294 if (m_deleteSceneContentsCheckBox) m_deleteSceneContentsCheckBox->hide();
295 m_deleteServerButton->hide();
296 m_cancelButton->hide();
297
298 QStringList args;
299 args << "delete";
300
301 if (m_keepLocalCopyCheckBox->isChecked()) args << "--keep-local";
302
303 // Use a temporary file to store all the files list
304 m_targetTempFile = new QFile(m_workingDir + "/" + "tempDeleteFile");
305 if (m_targetTempFile->open(QFile::WriteOnly | QFile::Truncate)) {
306 QTextStream out(m_targetTempFile);
307
308 int filesCount = m_files.count();
309 for (int i = 0; i < filesCount; i++) out << m_files.at(i) + "\n";
310
311 int sceneResourcesCount = m_sceneResources.size();
312 for (int i = 0; i < sceneResourcesCount; i++)
313 out << m_sceneResources.at(i) + "\n";
314 }
315 m_targetTempFile->close();
316
317 args << "--targets";
318 args << "tempDeleteFile";
319
320 m_thread.disconnect(SIGNAL(done(const QString &)));
321 connect(&m_thread, SIGNAL(done(const QString &)), SLOT(commitDeletedFiles()));
322 m_thread.executeCommand(m_workingDir, "svn", args, false);
323 }
324
325 //-----------------------------------------------------------------------------
326
commitDeletedFiles()327 void SVNDeleteDialog::commitDeletedFiles() {
328 updateFileBrowser();
329 QStringList args;
330 args << "commit";
331 args << "--targets";
332 args << "tempDeleteFile";
333
334 if (!m_commentTextEdit->toPlainText().isEmpty())
335 args << QString("-m").append(m_commentTextEdit->toPlainText());
336 else
337 args << QString("-m").append(VersionControl::instance()->getUserName() +
338 " delete files.");
339 m_thread.disconnect(SIGNAL(done(const QString &)));
340 connect(&m_thread, SIGNAL(done(const QString &)), SLOT(onCommitDone()));
341 m_thread.executeCommand(m_workingDir, "svn", args);
342 }
343
344 //-----------------------------------------------------------------------------
345
onCommitDone()346 void SVNDeleteDialog::onCommitDone() {
347 if (m_targetTempFile) {
348 QFile::remove(m_targetTempFile->fileName());
349 delete m_targetTempFile;
350 m_targetTempFile = 0;
351 }
352
353 emit done(m_files);
354 close();
355 }
356
357 //-----------------------------------------------------------------------------
358
initTreeWidget()359 void SVNDeleteDialog::initTreeWidget() {
360 int filesSize = m_files.size();
361 bool itemAdded = false;
362
363 for (int i = 0; i < filesSize; i++) {
364 QString fileName = m_files.at(i);
365 TFilePath fp =
366 TFilePath(m_workingDir.toStdWString()) + fileName.toStdWString();
367 TFilePathSet fpset;
368 TXshSimpleLevel::getFiles(fp, fpset);
369
370 QStringList linkedFiles;
371
372 TFilePathSet::iterator it;
373 for (it = fpset.begin(); it != fpset.end(); ++it) {
374 QString fn = toQString((*it).withoutParentDir());
375
376 if (m_files.contains(fn)) linkedFiles.append(fn);
377 }
378
379 if (!linkedFiles.isEmpty()) {
380 itemAdded = true;
381 QTreeWidgetItem *twi = new QTreeWidgetItem(m_treeWidget);
382 twi->setText(0, fileName);
383 twi->setFirstColumnSpanned(false);
384 twi->setFlags(Qt::NoItemFlags);
385
386 for (int i = 0; i < linkedFiles.size(); i++) {
387 QTreeWidgetItem *child = new QTreeWidgetItem(twi);
388 child->setText(0, linkedFiles.at(i));
389 child->setFlags(Qt::NoItemFlags);
390 }
391 twi->setExpanded(true);
392 }
393 }
394
395 if (itemAdded) m_treeWidget->show();
396 }
397
398 //-----------------------------------------------------------------------------
399
onDeleteSceneContentsToggled(bool checked)400 void SVNDeleteDialog::onDeleteSceneContentsToggled(bool checked) {
401 if (!checked)
402 m_sceneResources.clear();
403 else {
404 VersionControl *vc = VersionControl::instance();
405
406 int fileSize = m_files.count();
407 for (int i = 0; i < fileSize; i++) {
408 QString fileName = m_files.at(i);
409 if (fileName.endsWith(".tnz")) {
410 if (m_files.contains(fileName))
411 m_sceneResources.append(vc->getSceneContents(m_workingDir, fileName));
412 }
413 }
414 }
415 m_textLabel->setText(
416 tr("Delete %1 items.")
417 .arg(m_files.size() - m_sceneIconAdded + m_sceneResources.size()));
418 }
419