mainwindow.cpp 11 KB

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