mainwindow.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #include <include/mainwindow.h>
  2. #include "ui_mainwindow.h"
  3. #include <QDebug>
  4. #include <QTextEdit>
  5. #include <QTextStream>
  6. #include <QString>
  7. #include <QLayout>
  8. #include <headers/ktextedit.hpp>
  9. #include <QDateTime>
  10. #include <vector>
  11. #include <headers/util.hpp>
  12. void infoMessageBox(QString text, QString title = "KYGUI") {
  13. QMessageBox box;
  14. box.setWindowTitle(title);
  15. box.setText(text);
  16. box.setButtonText(0, "Close");
  17. box.exec();
  18. }
  19. QString getTime() {
  20. return QDateTime::currentDateTime().toString("hh:mm:ss");
  21. }
  22. /**
  23. * @brief MainWindow::MainWindow
  24. * @param argc
  25. * @param argv
  26. * @param parent
  27. */
  28. MainWindow::MainWindow(int argc, char** argv, QWidget *parent) :
  29. QMainWindow(parent),
  30. cli_argc(argc),
  31. cli_argv(argv),
  32. ui(new Ui::MainWindow),
  33. arg_ui(new ArgDialog),
  34. q_client(nullptr) {
  35. m_process_model = new QStandardItemModel(this);
  36. m_event_model = new QStandardItemModel(this);
  37. q_client = new Client(this, cli_argc, cli_argv);
  38. ui->setupUi(this);
  39. this->setWindowTitle("KYGUI");
  40. QPushButton *button = this->findChild<QPushButton*>("connect");
  41. button->setMaximumSize(700, 900);
  42. button->setMinimumSize(700, 900);
  43. connect(button, &QPushButton::clicked, this, &MainWindow::connectClient);
  44. ui->processList->setModel(m_process_model);
  45. ui->eventList->setModel(m_event_model);
  46. }
  47. /**
  48. * @brief MainWindow::~MainWindow
  49. */
  50. MainWindow::~MainWindow()
  51. {
  52. delete q_client;
  53. delete ui;
  54. }
  55. /**
  56. * @brief MainWindow::buttonClicked
  57. */
  58. void MainWindow::connectClient() {
  59. ui->connect->hide();
  60. qDebug() << "Connecting to KServer";
  61. QObject::connect(q_client, &Client::messageReceived, this, &MainWindow::updateMessages);
  62. QObject::connect(q_client, &Client::startTimer, this, &MainWindow::startTimer);
  63. QProgressBar* progressBar = ui->progressBar;
  64. q_client->start();
  65. for (int i = 1; i < 101; i++) {
  66. progressBar->setValue(i);
  67. }
  68. KTextEdit* send_message_box = reinterpret_cast<KTextEdit*>(ui->inputText);
  69. send_message_box->show();
  70. QPushButton* send_message_button = this->findChild<QPushButton*>("sendMessage");
  71. // Handle mouse
  72. QObject::connect(send_message_button, &QPushButton::clicked, this, [this, send_message_box]() {
  73. QString msg = escapeText(send_message_box->toPlainText());
  74. qDebug() << "Sending message: " << msg;
  75. q_client->sendMessage(escapeText(send_message_box->toPlainText()));
  76. send_message_box->clear();
  77. });
  78. QObject::connect(ui->appList, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this]() {
  79. QString app_name = ui->appList->currentText();
  80. // TODO: I know, it's awful. Fix this
  81. q_client->setSelectedApp(std::vector<QString>{{app_name}});
  82. });
  83. QPushButton* disconnect_button = this->findChild<QPushButton*>("disconnect");
  84. QObject::connect(disconnect_button, &QPushButton::clicked, this, [this, progressBar]() {
  85. q_client->closeConnection();
  86. QApplication::exit(9);
  87. });
  88. QObject::connect(ui->execute, &QPushButton::clicked, this, [this]() {
  89. q_client->execute();
  90. });
  91. QObject::connect(ui->addArgs, &QPushButton::clicked, this, [this]() {
  92. if (ui->appList->count() == 0) {
  93. QMessageBox::warning(this, tr("Args"), tr("Please connect to the KServer and retrieve a list of available processes."));
  94. } else {
  95. arg_ui->show();
  96. }
  97. });
  98. QObject::connect(arg_ui, &ArgDialog::uploadFiles, this, [this](QVector<KFileData> files) {
  99. m_timer->stop();
  100. q_client->sendFiles(files);
  101. });
  102. QObject::connect(arg_ui, &ArgDialog::taskRequestReady, this, [this](Task task, bool file_pending) {
  103. // TODO: Maybe this should be handled by the Client class directly
  104. auto mask = q_client->getSelectedApp();
  105. if (mask > -1) {
  106. if (q_client->getAppName(mask) == "Instagram") {
  107. auto datetime = task.args.at(0);
  108. auto current_datetime = QDateTime::currentDateTime().toTime_t();
  109. auto seconds_diff = std::stoi(datetime) - current_datetime;
  110. // qDebug() << "Time difference: " << seconds_diff;
  111. // if (seconds_diff > 3600) {
  112. qDebug() << "Scheduling a task";
  113. task.args.push_back(std::to_string(mask));
  114. q_client->scheduleTask(task.args, file_pending);
  115. // }
  116. }
  117. }
  118. });
  119. QObject::connect(ui->tasks, &QPushButton::clicked, this, [this]() {
  120. // TODO: Change this to a complete implementation
  121. q_client->sendMessage("scheduler");
  122. });
  123. QObject::connect(ui->viewConsole, &QPushButton::clicked, this, [this]() {
  124. console_ui.show();
  125. });
  126. // TODO: Handle enter key
  127. // QObject::connect(static_cast<KTextEdit*>(ui->inputText), &KTextEdit::textInputEnter, this, &MainWindow::handleInputEnterKey);
  128. QObject::connect(static_cast<KTextEdit*>(ui->inputText), &KTextEdit::textInputEnter, this, &MainWindow::handleKey);
  129. QObject::connect(ui->processList, &QListView::clicked, this, [this](const QModelIndex &index) {
  130. auto process = m_processes.at(index.row());
  131. QString process_info_text = m_processes.at(index.row()).name.toUtf8() + "\n";
  132. process_info_text += "Execution requested at " + process.start.toUtf8() + "\n" +
  133. "Is currently in a state of: " + ProcessNames[process.state - 1].toUtf8();
  134. if (process.end.size() > 0 || process.id == "Scheduled task") {
  135. process_info_text += "\n\nResult: \n" + process.result;
  136. }
  137. infoMessageBox(process_info_text, "Process");
  138. });
  139. QObject::connect(ui->eventList, &QListView::clicked, this, [this](const QModelIndex &index) {
  140. auto event = m_events.at(index.row());
  141. infoMessageBox(event, "Event");
  142. });
  143. m_timer = new QTimer(this);
  144. connect(m_timer, &QTimer::timeout, q_client, &Client::ping);
  145. m_timer->start(30000);
  146. }
  147. void MainWindow::handleKey() {
  148. q_client->sendMessage(ui->inputText->toPlainText());
  149. ui->inputText->clear();
  150. }
  151. QString MainWindow::parseMessage(const QString& message, StringVec v) {
  152. QString simplified_message{};
  153. if (isMessage(message.toUtf8())) {
  154. simplified_message += "Message: " + getMessage(message.toUtf8());
  155. } else if (isEvent(message.toUtf8())) {
  156. simplified_message += "Event: " + getEvent(message.toUtf8());
  157. } else if (isOperation(message.toUtf8())) {
  158. simplified_message += "Operation: ";
  159. simplified_message += getOperation(message.toUtf8()).c_str();
  160. }
  161. return simplified_message;
  162. }
  163. QStandardItem* createProcessListItem(Process process) {
  164. return new QStandardItem(QString("%0 requested for execution. ID: %1\nStatus: %2\nTime: %3 Done: %4").arg(process.name).arg(process.id).arg(ProcessNames[process.state - 1]).arg(process.start).arg(process.end));
  165. }
  166. QStandardItem* createEventListItem(QString event) {
  167. return new QStandardItem(event);
  168. }
  169. /**
  170. * @brief MainWindow::updateMessages
  171. * @param s
  172. */
  173. void MainWindow::updateMessages(int t, const QString& message, StringVec v) {
  174. QString timestamp_prefix = QDateTime::currentDateTime().toString("hh:mm:ss") + " - ";
  175. if (t == MESSAGE_UPDATE_TYPE) {
  176. qDebug() << "Updating message area";
  177. auto simple_message = timestamp_prefix + parseMessage(message, v);
  178. ui->messages->append(simple_message);
  179. console_ui.updateText(message);
  180. } else if (t == COMMANDS_UPDATE_TYPE) {
  181. if (message == "New Session") {
  182. ui->led->setState(true);
  183. }
  184. qDebug() << "Updating commands";
  185. QComboBox* app_list = ui->appList;
  186. app_list->clear();
  187. for (const auto& s : v) {
  188. app_list->addItem(s);
  189. }
  190. } else if (t == PROCESS_REQUEST_TYPE) {
  191. qDebug() << "Updating process list";
  192. m_processes.push_back(Process{ .name=v.at(1), .state=ProcessState::PENDING, .start=getTime(), .id=v.at(2) });
  193. int row = 0;
  194. for (const auto& process : m_processes) {
  195. m_process_model->setItem(row, createProcessListItem(process));
  196. row++;
  197. }
  198. } else if (t == EVENT_UPDATE_TYPE) {
  199. QString event_message{timestamp_prefix};
  200. if (!v.empty()) {
  201. // TODO: extract process result handling from here. This should handle any event
  202. if (v.size() == 1) {
  203. event_message += message + "\n" + v.at(0);
  204. } else {
  205. event_message += message;
  206. if (message == "Process Result") {
  207. event_message += "\n";
  208. auto app_name = q_client->getAppName(std::stoi(v.at(0).toUtf8().constData()));
  209. if (v.at(1).length() > 0) {
  210. updateProcessResult(v.at(1), v.at(2));
  211. } else { // new process, from scheduled task
  212. Process new_process{ .name=app_name, .state=ProcessState::SUCCEEDED, .start=getTime(), .id="Scheduled task" };
  213. if (v.count() > 2 && !v.at(2).isEmpty()) {
  214. new_process.result = v.at(2);
  215. new_process.end = new_process.start;
  216. }
  217. m_processes.push_back(new_process);
  218. m_process_model->setItem(m_process_model->rowCount(), createProcessListItem(new_process));
  219. }
  220. event_message += app_name;
  221. event_message += ": ";
  222. event_message += v.at(2);
  223. } else {
  224. event_message += ": ";
  225. event_message += v.at(1);
  226. }
  227. }
  228. } else {
  229. event_message += message;
  230. }
  231. m_events.push_back(event_message);
  232. m_event_model->setItem(m_event_model->rowCount(), createEventListItem(event_message));
  233. } else {
  234. qDebug() << "Unknown update type. Cannot update UI";
  235. }
  236. }
  237. void MainWindow::startTimer() {
  238. if (m_timer != nullptr) {
  239. m_timer->start(30000);
  240. }
  241. }
  242. void MainWindow::updateProcessResult(QString id, QString result) { // We need to start matching processes with a unique identifier
  243. for (int i = m_processes.size() - 1; i >= 0; i--) {
  244. if (m_processes.at(i).id == id) {
  245. m_processes.at(i).end = getTime();
  246. m_processes.at(i).state = ProcessState::SUCCEEDED;
  247. m_processes.at(i).result = result;
  248. m_process_model->setItem(i, 0, createProcessListItem(m_processes.at(i)));
  249. return;
  250. }
  251. }
  252. }
  253. void MainWindow::keyPressEvent(QKeyEvent *e) {
  254. qDebug() << "Key press: " << e->key();
  255. if(e->key()==Qt::Key_0)
  256. {
  257. qDebug() << "Ok";
  258. }
  259. }