summaryrefslogtreecommitdiffstats
path: root/ui/qt/io_console_dialog.cpp
blob: 92d4c542685bcae2c20d1348e8b7bb5973bb0164 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * io_console_dialog.c
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include <config.h>
#define WS_LOG_DOMAIN LOG_DOMAIN_QTUI
#include "io_console_dialog.h"
#include <ui_io_console_dialog.h>

#include "main_application.h"

extern "C" {
static void print_function(const char *str, void *ptr);
}

static void print_function(const char *str, void *print_data)
{
    IOConsoleDialog *dialog = static_cast<IOConsoleDialog *>(print_data);
    dialog->appendOutputText(QString(str));
}

IOConsoleDialog::IOConsoleDialog(QWidget &parent,
                                QString title,
                                funnel_console_eval_cb_t eval_cb,
                                funnel_console_open_cb_t open_cb,
                                funnel_console_close_cb_t close_cb,
                                void *callback_data = nullptr) :
    GeometryStateDialog(&parent),
    ui(new Ui::IOConsoleDialog),
    eval_cb_(eval_cb),
    open_cb_(open_cb),
    close_cb_(close_cb),
    callback_data_(callback_data)
{
    ui->setupUi(this);

    if (title.isEmpty())
        title = QString("Console");

    loadGeometry(0, 0, title);
    setWindowTitle(mainApp->windowTitleString(title));

    QPushButton *eval_button = ui->buttonBox->addButton(tr("Evaluate"), QDialogButtonBox::ActionRole);
    eval_button->setDefault(true);
    eval_button->setShortcut(QKeySequence("Ctrl+Return"));
    connect(eval_button, &QPushButton::clicked, this, &IOConsoleDialog::acceptInput);

    QPushButton *clear_button = ui->buttonBox->addButton(tr("Clear"), QDialogButtonBox::ActionRole);
    connect(clear_button, &QPushButton::clicked, this, &IOConsoleDialog::on_clearActivated);

    ui->inputTextEdit->setFont(mainApp->monospaceFont());
    ui->inputTextEdit->setPlaceholderText(QString(tr("Use %1 to evaluate."))
            .arg(eval_button->shortcut().toString(QKeySequence::NativeText)));

    ui->outputTextEdit->setFont(mainApp->monospaceFont());
    ui->outputTextEdit->setReadOnly(true);

    ui->hintLabel->clear();

    // Install print
    open_cb_(print_function, this, callback_data_);
}

IOConsoleDialog::~IOConsoleDialog()
{
    delete ui;
    // Remove print
    close_cb_(callback_data_);
}

void IOConsoleDialog::setHintText(const QString &text)
{
    ui->hintLabel->setText(QString("<small><i>%1.</i></small>").arg(text));
}

void IOConsoleDialog::clearHintText()
{
    ui->hintLabel->clear();
}

void IOConsoleDialog::clearSuccessHint()
{
    // Text changed so we no longer have a success.
    ui->hintLabel->clear();
    // Disconnect this slot until the next success.
    disconnect(ui->inputTextEdit, &QTextEdit::textChanged, this, &IOConsoleDialog::clearSuccessHint);
}

void IOConsoleDialog::acceptInput()
{
    clearHintText();

    QString text = ui->inputTextEdit->toPlainText();
    if (text.isEmpty())
        return;

    char *error_str = nullptr;
    char *error_hint = nullptr;
    int result = eval_cb_(qUtf8Printable(text), &error_str, &error_hint, callback_data_);
    if (result != 0) {
        if (error_hint) {
            QString hint(error_hint);
            setHintText(hint.at(0).toUpper() + hint.mid(1));
            g_free(error_hint);
        }
        else if (result < 0) {
            setHintText("Error loading string");
        }
        else {
            setHintText("Error running chunk");
        }
        if (error_str) {
            appendOutputText(QString(error_str));
            g_free(error_str);
        }
    }
    else {
        setHintText("Code evaluated successfully");
        connect(ui->inputTextEdit, &QTextEdit::textChanged, this, &IOConsoleDialog::clearSuccessHint);
    }
}

void IOConsoleDialog::appendOutputText(const QString &text)
{
    ui->outputTextEdit->append(text);
}

void IOConsoleDialog::on_clearActivated()
{
    ui->inputTextEdit->clear();
    ui->outputTextEdit->clear();
    ui->hintLabel->clear();
}