1 #include "cleandialog.h"
2 #include "ui_cleandialog.h"
3
4 #include "configmanager.h"
5 #include "utilsUI.h"
6
7 QString CleanDialog::defaultExtensions = "log,aux,dvi,lof,lot,bit,idx,glo,bbl,bcf,ilg,toc,ind,out,blg,fdb_latexmk,fls,run.xml";
8 QString CleanDialog::currentExtensions = CleanDialog::defaultExtensions;
9 int CleanDialog::scopeID = 0;
10
11 static const int AbsFilePathRole = Qt::UserRole;
12
CleanDialog(QWidget * parent)13 CleanDialog::CleanDialog(QWidget *parent) :
14 QDialog(parent),
15 ui(new Ui::CleanDialog)
16 {
17 ui->setupUi(this);
18 UtilsUi::resizeInFontHeight(this, 38, 22);
19
20 ConfigManagerInterface *config = ConfigManager::getInstance();
21 config->registerOption("CleanDialog/Extensions", ¤tExtensions, defaultExtensions);
22 config->registerOption("CleanDialog/Scope", &scopeID, 0);
23 if (scopeID < 0 || scopeID >= MAX_SCOPE) scopeID = 0;
24
25 QString allowedChars = "[^\\\\/\\?\\%\\*:|\"<>\\s,;]";
26 QRegularExpressionValidator *rxValExtensionList = new QRegularExpressionValidator(QRegularExpression(QString("(%1+\\.)*%1+(,(%1+\\.)*%1+)*").arg(allowedChars)), this);
27 int dummyPos;
28 if (rxValExtensionList->validate(currentExtensions, dummyPos) == QValidator::Acceptable) {
29 ui->leExtensions->setText(currentExtensions);
30 } else {
31 UtilsUi::txsWarning("Invalid extension list found. Resetting to default.");
32 currentExtensions = defaultExtensions;
33 ui->leExtensions->setText(currentExtensions);
34 }
35 ui->leExtensions->setValidator(rxValExtensionList);
36
37 ui->pbResetExtensions->setIcon(getRealIcon("edit-undo"));
38
39 connect(ui->pbResetExtensions, SIGNAL(clicked()), SLOT(resetExtensions()));
40 connect(ui->cbScope, SIGNAL(currentIndexChanged(int)), SLOT(updateFilesToRemove()));
41 connect(ui->leExtensions, SIGNAL(editingFinished()), SLOT(updateFilesToRemove()));
42 connect(ui->buttonBox, SIGNAL(accepted()), SLOT(onAccept()));
43 connect(ui->buttonBox, SIGNAL(rejected()), SLOT(onReject()));
44 }
45
~CleanDialog()46 CleanDialog::~CleanDialog() {
47 delete ui;
48 }
49
50 /* internally sets up possible clean variants. Call before exec()
51 Returns true, if at least one variant can be applied. */
checkClean(const LatexDocuments & docs)52 bool CleanDialog::checkClean(const LatexDocuments &docs) {
53 bool somethingToClean = false;
54 ui->cbScope->blockSignals(true); // don't emit currentIndexChanged while populating the combo box
55 if (docs.masterDocument) {
56 masterFile = docs.masterDocument->getFileName();
57 ui->cbScope->addItem(tr("Project (Master file folder and all subfolders)"), CleanDialog::Project);
58 if (scopeID == CleanDialog::Project) ui->cbScope->setCurrentIndex(ui->cbScope->count()-1);
59 somethingToClean = true;
60 }
61 if (docs.currentDocument && docs.currentDocument->getFileInfo().suffix().toLower() == "tex") {
62 currentTexFile = docs.currentDocument->getFileName();
63 ui->cbScope->addItem(tr("Current File"), CleanDialog::CurrentTexFile);
64 if (scopeID == CleanDialog::CurrentTexFile) ui->cbScope->setCurrentIndex(ui->cbScope->count()-1);
65 ui->cbScope->addItem(tr("Current File Folder"), CleanDialog::CurrentFileFolder);
66 if (scopeID == CleanDialog::CurrentFileFolder) ui->cbScope->setCurrentIndex(ui->cbScope->count()-1);
67 somethingToClean = true;
68 }
69 foreach (LatexDocument *doc, docs.documents) {
70 if (doc->getFileInfo().suffix().toLower() == "tex") openTexFiles.append(doc->getFileName());
71 }
72 if (!openTexFiles.isEmpty()) {
73 ui->cbScope->addItem(tr("Open Files"), CleanDialog::OpenTexFiles);
74 if (scopeID == CleanDialog::OpenTexFiles) ui->cbScope->setCurrentIndex(ui->cbScope->count()-1);
75 somethingToClean = true;
76 }
77 ui->cbScope->blockSignals(false);
78
79 if (somethingToClean)
80 updateFilesToRemove();
81 return somethingToClean;
82 }
83
resetExtensions()84 void CleanDialog::resetExtensions() {
85 ui->leExtensions->setText(defaultExtensions);
86 }
87
onAccept()88 void CleanDialog::onAccept() {
89 for (int i=0; i<ui->lwFiles->count(); i++) {
90 QFile::remove(ui->lwFiles->item(i)->data(AbsFilePathRole).toString());
91 }
92 accept();
93 }
94
onReject()95 void CleanDialog::onReject() {
96 reject();
97 }
98
updateFilesToRemove()99 void CleanDialog::updateFilesToRemove() {
100 scopeID = ui->cbScope->itemData(ui->cbScope->currentIndex()).toInt();
101 Scope scope = (Scope) scopeID;
102 #if (QT_VERSION>=QT_VERSION_CHECK(5,14,0))
103 QStringList extList(ui->leExtensions->text().split(',', Qt::SkipEmptyParts));
104 #else
105 QStringList extList(ui->leExtensions->text().split(',', QString::SkipEmptyParts));
106 #endif
107 QStringList forbiddenExtensions = QStringList() << "tex" << "lytex";
108 QStringList found;
109 foreach (const QString &ext, forbiddenExtensions) {
110 if (extList.contains(ext))
111 found << ext;
112 }
113 if (!found.isEmpty()) {
114 UtilsUi::txsWarning(tr("For your own safety clean will not delete the files with the following extensions:") + QString("\n") + extList.join(", "));
115 foreach (QString ext, found)
116 extList.removeAll(ext);
117 }
118 currentExtensions = extList.join(",");
119 ui->leExtensions->setText(currentExtensions);
120
121 QStringList files;
122 files << filesToRemove(scope, extList);
123 ui->lwFiles->clear();
124
125 foreach (const QString &absName, files) {
126 QFileInfo f(absName);
127 QListWidgetItem *item = new QListWidgetItem(f.fileName());
128 item->setData(AbsFilePathRole, absName);
129 item->setToolTip(absName);
130 ui->lwFiles->addItem(item);
131 }
132 }
133
filesToRemove(CleanDialog::Scope scope,const QStringList & extensionFilter)134 QStringList CleanDialog::filesToRemove(CleanDialog::Scope scope, const QStringList &extensionFilter) {
135 QStringList files;
136 switch (scope) {
137 case Project:
138 {
139 QStringList filterList;
140 foreach (const QString &ext, extensionFilter) filterList << "*." + ext;
141 files << filesToRemoveFromDir(QFileInfo(masterFile).absoluteDir(), filterList);
142 }
143 break;
144 case CurrentTexFile:
145 {
146 QFileInfo fi(currentTexFile);
147 QString basename=fi.absolutePath()+"/"+fi.completeBaseName();
148 foreach(const QString& ext, extensionFilter) {
149 QFileInfo f(basename + "." + ext);
150 if (f.exists())
151 files << f.absoluteFilePath();
152 }
153 }
154 break;
155 case CurrentFileFolder:
156 {
157 QStringList filterList;
158 foreach (const QString &ext, extensionFilter) filterList << "*." + ext;
159 files << filesToRemoveFromDir(QFileInfo(currentTexFile).absoluteDir(), filterList);
160 }
161 break;
162 case OpenTexFiles:
163 {
164 foreach(const QString& finame, openTexFiles){
165 QFileInfo fi(finame);
166 QString basename=fi.absolutePath()+"/"+fi.completeBaseName();
167 foreach(const QString& ext, extensionFilter) {
168 QFileInfo f(basename + "." + ext);
169 if (f.exists())
170 files << f.absoluteFilePath();
171 }
172 }
173 }
174 break;
175 case None:
176 break;
177 default:
178 break;
179 }
180 return files;
181 }
182
filesToRemoveFromDir(const QDir & dir,const QStringList & extensionFilter,bool recursive)183 QStringList CleanDialog::filesToRemoveFromDir(const QDir &dir, const QStringList &extensionFilter, bool recursive) {
184 QStringList files;
185 foreach (const QFileInfo &fi, dir.entryInfoList(extensionFilter, QDir::Files)) {
186 files << fi.absoluteFilePath();
187 }
188 if (recursive) {
189 foreach (const QFileInfo &fi, dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
190 if(fi.fileName().startsWith("."))
191 continue; // filter directories starting with . (e.g. .git) since they are not automatiocally hidden on windows
192 files << filesToRemoveFromDir(fi.absoluteFilePath(), extensionFilter, recursive);
193 }
194 }
195 return files;
196 }
197