1 #include "sendinghandler.h"
2 #include "utils.h"
3 #include "emuthread.h"
4 #include "../../core/link.h"
5 #include "archive/extractor.h"
6 
7 #include <QtWidgets/QMessageBox>
8 #include <QtWidgets/QApplication>
9 #include <QtWidgets/QToolButton>
10 #include <QtCore/QFileInfo>
11 #include <QtCore/QMimeData>
12 #include <QtGui/QDragEnterEvent>
13 
14 SendingHandler *sendingHandler = Q_NULLPTR;
15 
16 static const QStringList valid_suffixes = { QStringLiteral("8xp"),
17                                             QStringLiteral("8xv"),
18                                             QStringLiteral("8xl"),
19                                             QStringLiteral("8xn"),
20                                             QStringLiteral("8xm"),
21                                             QStringLiteral("8xy"),
22                                             QStringLiteral("8xg"),
23                                             QStringLiteral("8xs"),
24                                             QStringLiteral("8xd"),
25                                             QStringLiteral("8xw"),
26                                             QStringLiteral("8xc"),
27                                             QStringLiteral("8xz"),
28                                             QStringLiteral("8xt"),
29                                             QStringLiteral("8ca"),
30                                             QStringLiteral("8cg"),
31                                             QStringLiteral("8ci"), };
32 
pathHasBundleExtension(const QString & filepath)33 static inline bool pathHasBundleExtension(const QString& filepath) {
34     return filepath.endsWith("b84", Qt::CaseInsensitive) || filepath.endsWith("b83", Qt::CaseInsensitive);
35 }
36 
37 static QStringList bundleList;
checkValidFile(const char * path)38 static bool checkValidFile(const char *path) {
39     QString npath(path);
40     foreach (const QString &str, valid_suffixes) {
41         if (npath.endsWith(str, Qt::CaseInsensitive)) {
42             bundleList.append(path);
43             return true;
44         }
45     }
46     return false;
47 }
48 
getValidFilesFromArchive(const QString & archivePath)49 QStringList SendingHandler::getValidFilesFromArchive(const QString& archivePath) {
50     if (!m_tempDir.isValid()) {
51         QMessageBox::critical(Q_NULLPTR, tr("Transfer error"), tr("Could not create the temporary directory to extract the archive.\nFile: ") + archivePath);
52         return {};
53     }
54 
55     bundleList.clear();
56     extractor(archivePath.toStdString().c_str(), m_tempDir.path().toStdString().c_str(), checkValidFile);
57     return bundleList;
58 }
59 
SendingHandler(QObject * parent,QProgressBar * bar,QTableWidget * table)60 SendingHandler::SendingHandler(QObject *parent, QProgressBar *bar, QTableWidget *table) : QObject{parent} {
61     m_progressBar = bar;
62     m_table = table;
63 
64     bar->setMinimum(0);
65     bar->setMinimumWidth(0);
66     bar->setMaximumWidth(200);
67     bar->setTextVisible(false);
68     bar->setValue(0);
69     bar->setVisible(false);
70     m_iconSend.addPixmap(QPixmap(":/icons/resources/icons/variables.png"));
71     m_iconCheck.addPixmap(QPixmap(":/icons/resources/icons/check.png"));
72     m_iconCheckGray.addPixmap(QPixmap(":/icons/resources/icons/checkgray.png"));
73 }
74 
dropOccured(QDropEvent * e,int location)75 void SendingHandler::dropOccured(QDropEvent *e, int location) {
76     if (guiSend || guiReceive || guiDebug) {
77         e->ignore();
78         return;
79     }
80 
81     const QMimeData* mime_data = e->mimeData();
82     if (!mime_data->hasUrls()) {
83         return;
84     }
85 
86     QStringList files;
87     for(auto &&url : mime_data->urls()) {
88         const QString filePath = url.toLocalFile();
89         files.append(filePath);
90     }
91 
92     sendFiles(files, location);
93 }
94 
resendSelected()95 void SendingHandler::resendSelected() {
96     QStringList files;
97 
98     for (int row = 0; row < m_table->rowCount(); row++) {
99         if (static_cast<QAbstractButton *>(m_table->cellWidget(row, RECENT_SELECT_COL))->isChecked()) {
100             files.append(m_table->item(row, RECENT_PATH_COL)->text());
101         }
102     }
103 
104     sendFiles(files, LINK_FILE);
105 }
106 
resendPressed()107 void SendingHandler::resendPressed() {
108     QStringList files;
109 
110     for (int row = 0; row < m_table->rowCount(); row++){
111         if (sender() == m_table->cellWidget(row, RECENT_RESEND_COL)) {
112             files.append(m_table->item(row, RECENT_PATH_COL)->text());
113             break;
114         }
115     }
116 
117     sendFiles(files, LINK_FILE);
118 }
119 
removeRow()120 void SendingHandler::removeRow() {
121     for (int row = 0; row < m_table->rowCount(); row++){
122         if (sender() == m_table->cellWidget(row, RECENT_REMOVE_COL)) {
123             m_table->removeRow(row);
124             break;
125         }
126     }
127 }
128 
dragOccured(QDragEnterEvent * e)129 bool SendingHandler::dragOccured(QDragEnterEvent *e) {
130     if (guiSend || guiReceive || guiDebug) {
131         e->ignore();
132         return false;
133     }
134 
135     for (QUrl &url : e->mimeData()->urls()) {
136         QFileInfo file(url.fileName());
137         QString fileExtension = file.suffix().toLower();
138         if (!pathHasBundleExtension(fileExtension) && !valid_suffixes.contains(fileExtension)) {
139             e->ignore();
140             return false;
141         }
142     }
143 
144     e->accept();
145     return true;
146 }
147 
sentFile(const QString & file,int ok)148 void SendingHandler::sentFile(const QString &file, int ok) {
149 
150     static int result = LINK_GOOD;
151     result |= ok;
152 
153     // Send null to complete sending
154     if (file.isEmpty()) {
155         if (result & LINK_ERR) {
156             QMessageBox::critical(Q_NULLPTR, QObject::tr("Transfer error"), QObject::tr("Transfer Error, see console for information."));
157         }
158         else if (result & LINK_WARN) {
159             QMessageBox::warning(Q_NULLPTR, QObject::tr("Transfer warning"), QObject::tr("Transfer Warning, see console for information."));
160         }
161         result = LINK_GOOD;
162         m_progressBar->setValue(m_progressBar->maximum());
163         guiDelay(100);
164         if (m_progressBar) {
165             m_progressBar->setVisible(false);
166             m_progressBar->setValue(0);
167         }
168         guiSend = false;
169         return;
170     }
171 
172     QFileInfo fi(file);
173     QString directory = fi.absolutePath();
174 
175     // check for sending of equate file
176     if (m_sendEquates) {
177         if (!m_dirs.contains(directory)) {
178             m_dirs.append(directory);
179             checkDirForEquateFiles(directory);
180         }
181     }
182 
183     // don't add temp files (created by bundles)
184     if (directory != m_tempDir.path()) {
185         addFile(file, true);
186     }
187 
188     if (m_progressBar) {
189         m_progressBar->setValue(m_progressBar->value() + 1);
190     }
191 }
192 
193 
addFile(const QString & file,bool select)194 void SendingHandler::addFile(const QString &file, bool select) {
195     int j, rows = m_table->rowCount();
196 
197     for (j = 0; j < rows; j++) {
198         if (!m_table->item(j, RECENT_PATH_COL)->text().compare(file, Qt::CaseInsensitive)) {
199             return;
200         }
201     }
202 
203     m_table->setSortingEnabled(false);
204 
205     m_table->setRowCount(rows + 1);
206     QTableWidgetItem *remove = new QTableWidgetItem;
207     QTableWidgetItem *resend = new QTableWidgetItem;
208     QTableWidgetItem *selected = new QTableWidgetItem;
209     QTableWidgetItem *path = new QTableWidgetItem(file);
210 
211     QIcon removeIcon(QPixmap(QStringLiteral(":/icons/resources/icons/exit.png")));
212     QToolButton *btnRemove = new QToolButton;
213     btnRemove->setIcon(removeIcon);
214 
215     QToolButton *btnResend = new QToolButton;
216     btnResend->setIcon(m_iconSend);
217 
218     QToolButton *btnSelect = new QToolButton;
219     btnSelect->setIcon(select ? m_iconCheck : m_iconCheckGray);
220     btnSelect->setCheckable(true);
221     btnSelect->setChecked(select);
222 
223     connect(btnResend, &QToolButton::clicked, this, &SendingHandler::resendPressed);
224     connect(btnRemove, &QToolButton::clicked, this, &SendingHandler::removeRow);
225     connect(btnSelect, &QToolButton::clicked, [this, btnSelect](bool checked) { btnSelect->setIcon(checked ? m_iconCheck : m_iconCheckGray); });
226 
227     m_table->setItem(rows, RECENT_REMOVE_COL, remove);
228     m_table->setItem(rows, RECENT_RESEND_COL, resend);
229     m_table->setItem(rows, RECENT_SELECT_COL, selected);
230     m_table->setItem(rows, RECENT_PATH_COL, path);
231     m_table->setCellWidget(rows, RECENT_REMOVE_COL, btnRemove);
232     m_table->setCellWidget(rows, RECENT_RESEND_COL, btnResend);
233     m_table->setCellWidget(rows, RECENT_SELECT_COL, btnSelect);
234 
235     m_table->setVisible(false);
236     m_table->resizeColumnsToContents();
237     m_table->setVisible(true);
238     m_table->setSortingEnabled(true);
239 }
240 
sendFiles(const QStringList & fileNames,int location)241 void SendingHandler::sendFiles(const QStringList &fileNames, int location) {
242     QStringList list = fileNames;
243 
244     if (guiSend || guiReceive || guiDebug || !list.size()) {
245         return;
246     }
247 
248     guiSend = true;
249     m_dirs.clear();
250 
251     foreach(const QString &str, fileNames) {
252         if (pathHasBundleExtension(str)) {
253             list.removeOne(str);
254             list.append(getValidFilesFromArchive(str));
255             addFile(str, true);
256         }
257     }
258 
259     if (m_progressBar) {
260         m_progressBar->setVisible(true);
261         m_progressBar->setMaximum(list.size());
262     }
263 
264     emit send(list, location);
265 }
266 
setLoadEquates(bool state)267 void SendingHandler::setLoadEquates(bool state) {
268     m_sendEquates = state;
269 }
270 
checkDirForEquateFiles(QString & dirPath)271 void SendingHandler::checkDirForEquateFiles(QString &dirPath) {
272     QDirIterator dirIt(dirPath, QDirIterator::NoIteratorFlags);
273     while (dirIt.hasNext()) {
274         dirIt.next();
275         QString dirItFile = dirIt.filePath();
276         if (QFileInfo(dirItFile).isFile()) {
277             QString suffix = QFileInfo(dirItFile).suffix();
278             if (suffix == QStringLiteral("map") ||
279                 suffix == QStringLiteral("inc") ||
280                 suffix == QStringLiteral("lab")) {
281                 emit loadEquateFile(dirItFile);
282             }
283         }
284     }
285 }
286