1 /* funnel_text_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
10 #include "funnel_text_dialog.h"
11 #include <ui_funnel_text_dialog.h>
13 #include <QPushButton>
14 #include <QRegularExpression>
15 #include <QTextCharFormat>
16 #include <QTextCursor>
18 #include <ui/qt/utils/qt_ui_utils.h>
19 #include "main_application.h"
22 // - Add "Find next" to highlighting.
23 // - Add rich text support?
26 static QHash
<QObject
*, funnel_bt_t
*> text_button_to_funnel_button_
;
28 FunnelTextDialog::FunnelTextDialog(QWidget
*parent
, const QString
&title
) :
29 GeometryStateDialog(parent
),
30 ui(new Ui::FunnelTextDialog
),
35 if (!title
.isEmpty()) {
36 loadGeometry(0, 0, QStringLiteral("Funnel %1").arg(title
));
38 setWindowTitle(mainApp
->windowTitleString(title
));
40 funnel_text_window_
.funnel_text_dialog
= this;
42 ui
->textEdit
->setFont(mainApp
->monospaceFont());
43 ui
->textEdit
->setReadOnly(true);
44 ui
->textEdit
->setAcceptRichText(false);
47 FunnelTextDialog::~FunnelTextDialog()
52 void FunnelTextDialog::reject()
57 close_cb_(close_cb_data_
);
60 for (const auto& button
: ui
->buttonBox
->buttons()) {
61 funnel_bt_t
*funnel_button
= text_button_to_funnel_button_
.take(qobject_cast
<QObject
*>(button
));
62 if (funnel_button
!= nullptr) {
63 if (funnel_button
->free_data_fcn
) {
64 funnel_button
->free_data_fcn(funnel_button
->data
);
66 if (funnel_button
->free_fcn
) {
67 funnel_button
->free_fcn(funnel_button
);
76 struct _funnel_text_window_t
*FunnelTextDialog::textWindowNew(QWidget
*parent
, const QString title
)
78 FunnelTextDialog
*ftd
= new FunnelTextDialog(parent
, title
);
80 return &ftd
->funnel_text_window_
;
83 void FunnelTextDialog::setText(const QString text
)
85 ui
->textEdit
->setText(text
);
88 void FunnelTextDialog::appendText(const QString text
)
90 ui
->textEdit
->moveCursor(QTextCursor::End
);
91 ui
->textEdit
->insertPlainText(text
);
94 void FunnelTextDialog::prependText(const QString text
)
96 ui
->textEdit
->moveCursor(QTextCursor::Start
);
97 ui
->textEdit
->insertPlainText(text
);
100 void FunnelTextDialog::clearText()
102 ui
->textEdit
->clear();
105 const char *FunnelTextDialog::getText()
107 return qstring_strdup(ui
->textEdit
->toPlainText());
110 void FunnelTextDialog::setCloseCallback(text_win_close_cb_t close_cb
, void *close_cb_data
)
112 close_cb_
= close_cb
;
113 close_cb_data_
= close_cb_data
;
116 void FunnelTextDialog::setTextEditable(bool editable
)
118 ui
->textEdit
->setReadOnly(!editable
);
121 void FunnelTextDialog::addButton(funnel_bt_t
*funnel_button
, QString label
)
123 // Use "&&" to get a real ampersand in the button.
124 label
.replace('&', "&&");
126 QPushButton
*button
= new QPushButton(label
);
127 ui
->buttonBox
->addButton(button
, QDialogButtonBox::ActionRole
);
128 text_button_to_funnel_button_
[button
] = funnel_button
;
129 connect(button
, &QPushButton::clicked
, this, &FunnelTextDialog::buttonClicked
);
132 void FunnelTextDialog::buttonClicked()
134 if (text_button_to_funnel_button_
.contains(sender())) {
135 funnel_bt_t
*funnel_button
= text_button_to_funnel_button_
[sender()];
137 funnel_button
->func(&funnel_text_window_
, funnel_button
->data
);
142 void FunnelTextDialog::on_findLineEdit_textChanged(const QString
&pattern
)
144 QRegularExpression
re(pattern
, QRegularExpression::CaseInsensitiveOption
|
145 QRegularExpression::UseUnicodePropertiesOption
);
146 QTextCharFormat plain_fmt
, highlight_fmt
;
147 highlight_fmt
.setBackground(Qt::yellow
);
148 QTextCursor
csr(ui
->textEdit
->document());
149 int position
= csr
.position();
151 setUpdatesEnabled(false);
153 // Reset highlighting
154 csr
.movePosition(QTextCursor::Start
);
155 csr
.movePosition(QTextCursor::End
, QTextCursor::KeepAnchor
);
156 csr
.setCharFormat(plain_fmt
);
158 // Apply new highlighting
159 if (!pattern
.isEmpty() && re
.isValid()) {
160 QRegularExpressionMatchIterator iter
= re
.globalMatch(ui
->textEdit
->toPlainText());
161 while (iter
.hasNext()) {
162 QRegularExpressionMatch match
= iter
.next();
163 csr
.setPosition(static_cast<int>(match
.capturedStart()), QTextCursor::MoveAnchor
);
164 csr
.setPosition(static_cast<int>(match
.capturedEnd()), QTextCursor::KeepAnchor
);
165 csr
.setCharFormat(highlight_fmt
);
169 // Restore cursor and anchor
170 csr
.setPosition(position
, QTextCursor::MoveAnchor
);
171 setUpdatesEnabled(true);
174 void text_window_set_text(funnel_text_window_t
*ftw
, const char* text
)
177 ftw
->funnel_text_dialog
->setText(text
);
181 void text_window_append(funnel_text_window_t
* ftw
, const char* text
)
184 ftw
->funnel_text_dialog
->appendText(text
);
188 void text_window_prepend(funnel_text_window_t
*ftw
, const char* text
)
191 ftw
->funnel_text_dialog
->prependText(text
);
195 void text_window_clear(funnel_text_window_t
* ftw
)
198 ftw
->funnel_text_dialog
->clearText();
202 const char *text_window_get_text(funnel_text_window_t
*ftw
)
205 return ftw
->funnel_text_dialog
->getText();
210 void text_window_set_close_cb(funnel_text_window_t
*ftw
, text_win_close_cb_t close_cb
, void *close_cb_data
)
213 ftw
->funnel_text_dialog
->setCloseCallback(close_cb
, close_cb_data
);
217 void text_window_set_editable(funnel_text_window_t
*ftw
, bool editable
)
220 ftw
->funnel_text_dialog
->setTextEditable(editable
);
224 void text_window_destroy(funnel_text_window_t
*ftw
)
227 ftw
->funnel_text_dialog
->close();
231 void text_window_add_button(funnel_text_window_t
*ftw
, funnel_bt_t
*funnel_button
, const char *label
)
234 ftw
->funnel_text_dialog
->addButton(funnel_button
, label
);