1 /* time_shift_dialog.cpp
2 *
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "time_shift_dialog.h"
11 #include <ui_time_shift_dialog.h>
12
13 #include "wireshark_application.h"
14
15 #include <ui/time_shift.h>
16 #include <ui/qt/utils/color_utils.h>
17
18 #include <QStyleOption>
19
TimeShiftDialog(QWidget * parent,capture_file * cf)20 TimeShiftDialog::TimeShiftDialog(QWidget *parent, capture_file *cf) :
21 QDialog(parent),
22 ts_ui_(new Ui::TimeShiftDialog),
23 cap_file_(cf),
24 apply_button_(NULL)
25 {
26 ts_ui_->setupUi(this);
27 setWindowTitle(wsApp->windowTitleString(tr("Time Shift")));
28 apply_button_ = ts_ui_->buttonBox->button(QDialogButtonBox::Apply);
29 apply_button_->setDefault(true);
30 connect(apply_button_, SIGNAL(clicked()), this, SLOT(applyTimeShift()));
31
32 QStyleOption style_opt;
33 int rb_label_offset = ts_ui_->shiftAllButton->style()->subElementRect(QStyle::SE_RadioButtonContents, &style_opt).left();
34 int cb_label_offset = ts_ui_->shiftAllButton->style()->subElementRect(QStyle::SE_CheckBoxContents, &style_opt).left();
35 setStyleSheet(QString(
36 "QCheckBox#setTwoCheckBox {"
37 " margin-left: %1px;"
38 "}"
39 "QLabel#extrapolateLabel {"
40 " margin-left: %2px;"
41 "}"
42 )
43 .arg(rb_label_offset)
44 .arg(rb_label_offset + cb_label_offset)
45 );
46
47 if (cap_file_) {
48 if (cap_file_->current_frame) {
49 ts_ui_->setOneFrameLineEdit->setText(QString::number(cap_file_->current_frame->num));
50 } else {
51 ts_ui_->setOneFrameLineEdit->setText(QString::number(cap_file_->first_displayed));
52 }
53 ts_ui_->setTwoFrameLineEdit->setText(QString::number(cap_file_->last_displayed));
54 }
55
56 ts_ui_->shiftAllButton->setChecked(true);
57 ts_ui_->setTwoCheckBox->setChecked(false);
58 enableWidgets();
59 }
60
~TimeShiftDialog()61 TimeShiftDialog::~TimeShiftDialog()
62 {
63 delete ts_ui_;
64 }
65
enableWidgets()66 void TimeShiftDialog::enableWidgets()
67 {
68 bool enable_two = ts_ui_->setOneButton->isChecked();
69 bool enable_apply = false;
70
71 ts_ui_->setTwoCheckBox->setEnabled(enable_two);
72 ts_ui_->setTwoFrameLineEdit->setEnabled(enable_two);
73 ts_ui_->setTwoToLabel->setEnabled(enable_two);
74 ts_ui_->setTwoTimeLineEdit->setEnabled(enable_two);
75 ts_ui_->extrapolateLabel->setEnabled(enable_two && ts_ui_->setTwoCheckBox->isChecked());
76
77 if (ts_ui_->shiftAllButton->isChecked()) {
78 if (ts_ui_->shiftAllTimeLineEdit->syntaxState() == SyntaxLineEdit::Valid)
79 enable_apply = true;
80 } else if (ts_ui_->setOneButton->isChecked()) {
81 bool set_two_valid = false;
82 if (ts_ui_->setTwoCheckBox->isChecked()) {
83 if (ts_ui_->setTwoFrameLineEdit->syntaxState() == SyntaxLineEdit::Valid &&
84 ts_ui_->setTwoTimeLineEdit->syntaxState() == SyntaxLineEdit::Valid) {
85 set_two_valid = true;
86 }
87 } else {
88 set_two_valid = true;
89 }
90 if (set_two_valid &&
91 ts_ui_->setOneFrameLineEdit->syntaxState() == SyntaxLineEdit::Valid &&
92 ts_ui_->setOneTimeLineEdit->syntaxState() == SyntaxLineEdit::Valid) {
93 enable_apply = true;
94 }
95 } else if (ts_ui_->unshiftAllButton->isChecked()) {
96 enable_apply = true;
97 }
98
99 if (syntax_err_.isEmpty()) {
100 ts_ui_->errorLabel->clear();
101 ts_ui_->errorLabel->setStyleSheet(" QLabel { margin-top: 0.5em; }");
102 } else {
103 ts_ui_->errorLabel->setText(syntax_err_);
104 ts_ui_->errorLabel->setStyleSheet(QString(
105 "QLabel {"
106 " margin-top: 0.5em;"
107 " background-color: %2;"
108 "}"
109 )
110 .arg(ColorUtils::warningBackground().name())
111 );
112 }
113 apply_button_->setEnabled(enable_apply);
114 }
115
checkFrameNumber(SyntaxLineEdit & frame_le)116 void TimeShiftDialog::checkFrameNumber(SyntaxLineEdit &frame_le)
117 {
118 bool frame_valid;
119 guint frame_num = frame_le.text().toUInt(&frame_valid);
120
121 syntax_err_.clear();
122 if (frame_le.text().isEmpty()) {
123 frame_le.setSyntaxState(SyntaxLineEdit::Empty);
124 } else if (!frame_valid || !cap_file_ || frame_num < 1 || frame_num > cap_file_->count) {
125 frame_le.setSyntaxState(SyntaxLineEdit::Invalid);
126 if (cap_file_) {
127 syntax_err_ = QString(tr("Frame numbers must be between 1 and %1.").arg(cap_file_->count));
128 } else {
129 syntax_err_ = tr("Invalid frame number.");
130 }
131 } else {
132 frame_le.setSyntaxState(SyntaxLineEdit::Valid);
133 }
134 }
135
checkDateTime(SyntaxLineEdit & time_le)136 void TimeShiftDialog::checkDateTime(SyntaxLineEdit &time_le)
137 {
138 int Y, M, D, h, m;
139 long double s;
140 const gchar *err_str;
141
142 syntax_err_.clear();
143 if (time_le.text().isEmpty()) {
144 time_le.setSyntaxState(SyntaxLineEdit::Empty);
145 } else if ((err_str = time_string_parse(time_le.text().toUtf8().constData(),
146 &Y, &M, &D, NULL, &h, &m, &s)) != NULL) {
147 syntax_err_ = err_str;
148 time_le.setSyntaxState(SyntaxLineEdit::Invalid);
149 } else {
150 time_le.setSyntaxState(SyntaxLineEdit::Valid);
151 }
152 }
153
on_shiftAllButton_toggled(bool)154 void TimeShiftDialog::on_shiftAllButton_toggled(bool)
155 {
156 enableWidgets();
157 }
158
on_setOneButton_toggled(bool)159 void TimeShiftDialog::on_setOneButton_toggled(bool)
160 {
161 enableWidgets();
162 }
163
on_unshiftAllButton_toggled(bool)164 void TimeShiftDialog::on_unshiftAllButton_toggled(bool)
165 {
166 enableWidgets();
167 }
168
on_setTwoCheckBox_toggled(bool)169 void TimeShiftDialog::on_setTwoCheckBox_toggled(bool)
170 {
171 enableWidgets();
172 }
173
on_shiftAllTimeLineEdit_textChanged(const QString & sa_text)174 void TimeShiftDialog::on_shiftAllTimeLineEdit_textChanged(const QString &sa_text)
175 {
176 int h, m;
177 long double s;
178 gboolean neg;
179 const gchar *err_str;
180
181 syntax_err_.clear();
182 if (sa_text.isEmpty()) {
183 ts_ui_->shiftAllTimeLineEdit->setSyntaxState(SyntaxLineEdit::Empty);
184 } else if ((err_str = time_string_parse(sa_text.toUtf8().constData(),
185 NULL, NULL, NULL, &neg, &h, &m, &s)) != NULL) {
186 syntax_err_ = err_str;
187 ts_ui_->shiftAllTimeLineEdit->setSyntaxState(SyntaxLineEdit::Invalid);
188 } else {
189 ts_ui_->shiftAllTimeLineEdit->setSyntaxState(SyntaxLineEdit::Valid);
190 }
191 ts_ui_->shiftAllButton->setChecked(true);
192 enableWidgets();
193 }
194
on_setOneFrameLineEdit_textChanged(const QString &)195 void TimeShiftDialog::on_setOneFrameLineEdit_textChanged(const QString &)
196 {
197 checkFrameNumber(*ts_ui_->setOneFrameLineEdit);
198 ts_ui_->setOneButton->setChecked(true);
199 enableWidgets();
200 }
on_setOneTimeLineEdit_textChanged(const QString &)201 void TimeShiftDialog::on_setOneTimeLineEdit_textChanged(const QString &)
202 {
203 checkDateTime(*ts_ui_->setOneTimeLineEdit);
204 ts_ui_->setOneButton->setChecked(true);
205 enableWidgets();
206 }
207
on_setTwoFrameLineEdit_textChanged(const QString &)208 void TimeShiftDialog::on_setTwoFrameLineEdit_textChanged(const QString &)
209 {
210 checkFrameNumber(*ts_ui_->setTwoFrameLineEdit);
211 if (ts_ui_->setTwoCheckBox->isEnabled())
212 ts_ui_->setTwoCheckBox->setChecked(true);
213 enableWidgets();
214 }
215
on_setTwoTimeLineEdit_textChanged(const QString &)216 void TimeShiftDialog::on_setTwoTimeLineEdit_textChanged(const QString &)
217 {
218 checkDateTime(*ts_ui_->setTwoTimeLineEdit);
219 if (ts_ui_->setTwoCheckBox->isEnabled())
220 ts_ui_->setTwoCheckBox->setChecked(true);
221 enableWidgets();
222 }
223
applyTimeShift()224 void TimeShiftDialog::applyTimeShift()
225 {
226 const gchar *err_str = NULL;
227
228 if (!cap_file_ || cap_file_->state == FILE_CLOSED) return;
229
230 syntax_err_.clear();
231 if (cap_file_->state == FILE_READ_IN_PROGRESS) {
232 syntax_err_ = tr("Time shifting is not available capturing packets.");
233 } else if (ts_ui_->shiftAllButton->isChecked()) {
234 err_str = time_shift_all(cap_file_,
235 ts_ui_->shiftAllTimeLineEdit->text().toUtf8().constData());
236 } else if (ts_ui_->setOneButton->isChecked()) {
237 if (!ts_ui_->setTwoCheckBox->isChecked()) {
238 err_str = time_shift_settime(cap_file_,
239 ts_ui_->setOneFrameLineEdit->text().toUInt(),
240 ts_ui_->setOneTimeLineEdit->text().toUtf8().constData()
241 );
242 } else {
243 err_str = time_shift_adjtime(cap_file_,
244 ts_ui_->setOneFrameLineEdit->text().toUInt(),
245 ts_ui_->setOneTimeLineEdit->text().toUtf8().constData(),
246 ts_ui_->setTwoFrameLineEdit->text().toUInt(),
247 ts_ui_->setTwoTimeLineEdit->text().toUtf8().constData()
248 );
249 }
250 } else if (ts_ui_->unshiftAllButton->isChecked()) {
251 err_str = time_shift_undo(cap_file_);
252 }
253
254 if (err_str) {
255 syntax_err_ = err_str;
256 } else {
257 emit timeShifted();
258 }
259
260 enableWidgets();
261 }
262
on_buttonBox_helpRequested()263 void TimeShiftDialog::on_buttonBox_helpRequested()
264 {
265 wsApp->helpTopicAction(HELP_TIME_SHIFT_DIALOG);
266 }
267