1 /************************************************************************
2 **
3 ** Copyright (C) 2020-2021 Kevin B. Hendricks, Stratford Ontario Canada
4 **
5 ** This file is part of Sigil.
6 **
7 ** Sigil is free software: you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation, either version 3 of the License, or
10 ** (at your option) any later version.
11 **
12 ** Sigil is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with Sigil. If not, see <http://www.gnu.org/licenses/>.
19 **
20 *************************************************************************/
21 #include <QString>
22 #include <QList>
23 #include <QDir>
24 #include <QFile>
25 #include <QFileInfo>
26 #include <QTableWidgetItem>
27 #include <QMessageBox>
28 #include <QApplication>
29 #include <QtConcurrent>
30 #include <QFuture>
31
32 #include <QDebug>
33
34 #include "Misc/Utility.h"
35 #include "Misc/SettingsStore.h"
36 #include "EmbedPython/PythonRoutines.h"
37 #include "Dialogs/RepoLog.h"
38 #include "Dialogs/ManageRepos.h"
39
40 static const QString SETTINGS_GROUP = "manage_repos";
41
ManageRepos(QWidget * parent)42 ManageRepos::ManageRepos(QWidget *parent)
43 : QDialog(parent),
44 m_repoList(QStringList())
45 {
46 ui.setupUi(this);
47 ReadSettings();
48 InitializeTable();
49 ConnectSignalsToSlots();
50 }
51
~ManageRepos()52 ManageRepos::~ManageRepos()
53 {
54 WriteSettings();
55 }
56
SetRepoList()57 void ManageRepos::SetRepoList()
58 {
59 QDir d(Utility::DefinePrefsDir() + "/repo");
60 if (!d.exists()) {
61 return;
62 }
63 // get the directory names in this directory that start with "epub_"
64 m_repoList = d.entryList(QStringList("epub_*"), QDir::Dirs|QDir::NoDotAndDotDot);
65 }
66
GetBookInfo(const QString & reponame)67 QStringList ManageRepos::GetBookInfo(const QString& reponame)
68 {
69 QStringList bookinfo;
70 QString infopath = Utility::DefinePrefsDir() + "/repo/" + reponame + "/.bookinfo";
71 QFileInfo fi(infopath);
72 if (fi.exists() && fi.isFile() && fi.isReadable()) {
73 QString data = Utility::ReadUnicodeTextFile(infopath);
74 bookinfo = data.split("\n");
75 }
76 return bookinfo;
77 }
78
InitializeTable()79 void ManageRepos::InitializeTable()
80 {
81 m_repoList.clear();
82 SetRepoList();
83 int nrows = 0;
84 // clear out the table but do NOT clear out column headings
85 while (ui.repoTable->rowCount() > 0) {
86 ui.repoTable->removeRow(0);
87 }
88 foreach(QString rp, m_repoList) {
89 QStringList fields = GetBookInfo(rp);
90 if (!fields.isEmpty() && (fields.count() >= 5)) {
91 ui.repoTable->insertRow(nrows);
92 SetRepoTableRow(fields,nrows);
93 nrows++;
94 }
95 }
96 ui.repoTable->resizeColumnsToContents();
97 ui.repoTable->setSortingEnabled(true);
98 }
99
WriteSettings()100 void ManageRepos::WriteSettings()
101 {
102 SettingsStore settings;
103 settings.beginGroup(SETTINGS_GROUP);
104 settings.setValue("geometry", saveGeometry());
105 settings.endGroup();
106 }
107
SetRepoTableRow(const QStringList & fields,int row)108 void ManageRepos::SetRepoTableRow(const QStringList &fields, int row)
109 {
110 bool sortingOn = ui.repoTable->isSortingEnabled();
111 ui.repoTable->setSortingEnabled(false);
112 ui.repoTable->setItem(row,ManageRepos::FileField, new QTableWidgetItem(fields.at(ManageRepos::FileField)));
113 ui.repoTable->setItem(row,ManageRepos::TitleField, new QTableWidgetItem(fields.at(ManageRepos::TitleField)));
114 ui.repoTable->setItem(row,ManageRepos::ModifiedField, new QTableWidgetItem(fields.at(ManageRepos::ModifiedField)));
115 ui.repoTable->setItem(row,ManageRepos::VersionField, new QTableWidgetItem(fields.at(ManageRepos::VersionField)));
116 ui.repoTable->setItem(row,ManageRepos::UUIDField, new QTableWidgetItem(fields.at(ManageRepos::UUIDField)));
117 ui.repoTable->setSortingEnabled(sortingOn);
118 }
119
ReadSettings()120 void ManageRepos::ReadSettings()
121 {
122 SettingsStore settings;
123 settings.beginGroup(SETTINGS_GROUP);
124 QByteArray geometry = settings.value("geometry").toByteArray();
125 if (!geometry.isNull()) {
126 restoreGeometry(geometry);
127 }
128 settings.endGroup();
129 }
130
RepoSelected(int row,int col)131 void ManageRepos::RepoSelected(int row, int col)
132 {
133 ui.repoTable->setCurrentCell(row, col);
134 }
135
ShowLog()136 void ManageRepos::ShowLog()
137 {
138 // limited to work with one selection at a time to prevent row mixup upon removal
139 QList<QTableWidgetItem *> itemlist = ui.repoTable->selectedItems();
140 if (itemlist.isEmpty()) {
141 Utility::DisplayStdWarningDialog(tr("Nothing is Selected."));
142 return;
143 }
144 int row = ui.repoTable->row(itemlist.at(0));
145 QString bookid = ui.repoTable->item(row, ManageRepos::UUIDField)->text();
146 QString localRepo = Utility::DefinePrefsDir() + "/repo/";
147
148 QApplication::setOverrideCursor(Qt::WaitCursor);
149
150 // generate the repo log using python in a separate thread since this
151 // may take a while depending on the speed of the filesystem
152 PythonRoutines pr;
153 QFuture<QString> future = QtConcurrent::run(&pr,
154 &PythonRoutines::GenerateRepoLogSummaryInPython,
155 localRepo,
156 bookid);
157 future.waitForFinished();
158 QString logData = future.result();
159
160 QApplication::restoreOverrideCursor();
161
162 RepoLog log(tr("Repository Log"), logData, this);
163 log.exec();
164 }
165
166
RemoveRepo()167 void ManageRepos::RemoveRepo()
168 {
169 // limited to work with one selection at a time to prevent row mixup upon removal
170 QList<QTableWidgetItem *> itemlist = ui.repoTable->selectedItems();
171 if (itemlist.isEmpty()) {
172 Utility::DisplayStdWarningDialog(tr("Nothing is Selected."));
173 return;
174 }
175 ui.repoTable->setSortingEnabled(false);
176 int row = ui.repoTable->row(itemlist.at(0));
177 QString bookid = ui.repoTable->item(row, ManageRepos::UUIDField)->text();
178 QString reponame = "epub_" + bookid;
179 QString repopath = Utility::DefinePrefsDir() + "/repo/" + reponame;
180 bool success = Utility::removeDir(repopath);
181 if (success) {
182 m_repoList.removeOne(reponame);
183 ui.repoTable->removeRow(row);
184 } else {
185 qDebug() << "Error removing Repo: " << repopath;
186 }
187 ui.repoTable->resizeColumnsToContents();
188 ui.repoTable->setSortingEnabled(true);
189 }
190
RemoveAllRepos()191 void ManageRepos::RemoveAllRepos()
192 {
193 QMessageBox msgBox;
194
195 msgBox.setIcon(QMessageBox::Warning);
196 msgBox.setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint);
197 msgBox.setWindowTitle(tr("Remove All Repositories"));
198 msgBox.setText(tr("Are you sure sure you want to remove all checkpoint repositories?"));
199 QPushButton *yesButton = msgBox.addButton(QMessageBox::Yes);
200 QPushButton *noButton = msgBox.addButton(QMessageBox::No);
201 msgBox.setDefaultButton(noButton);
202 msgBox.exec();
203 if (msgBox.clickedButton() == yesButton) {
204 foreach(QString reponame, m_repoList) {
205 QString repopath = Utility::DefinePrefsDir() + "/repo/" + reponame;
206 Utility::removeDir(repopath);
207 }
208 InitializeTable();
209 }
210 }
211
ConnectSignalsToSlots()212 void ManageRepos::ConnectSignalsToSlots()
213 {
214 connect(ui.logButton, SIGNAL(clicked()), this, SLOT(ShowLog()));
215 connect(ui.removeButton, SIGNAL(clicked()), this, SLOT(RemoveRepo()));
216 connect(ui.removeAllButton, SIGNAL(clicked()), this, SLOT(RemoveAllRepos()));
217 connect(ui.repoTable, SIGNAL(cellDoubleClicked(int,int)), this, SLOT(RepoSelected(int,int)));
218 }
219