@@ -85,6 +85,38 @@ QString WorkbenchPage::sendEncodingKey() const
8585 : AppTextEncoding::defaultKey ());
8686}
8787
88+ QString WorkbenchPage::frameBreakModeKey () const
89+ {
90+ const QString mode = m_frameModeCombo ? m_frameModeCombo->currentData ().toString () : QStringLiteral (" timeout" );
91+ if (mode == QStringLiteral (" header" ) || mode == QStringLiteral (" tail" ) || mode == QStringLiteral (" length" )) {
92+ return mode;
93+ }
94+ return QStringLiteral (" timeout" );
95+ }
96+
97+ QByteArray WorkbenchPage::frameBoundaryPattern (bool *ok) const
98+ {
99+ if (ok) {
100+ *ok = false ;
101+ }
102+ if (!m_framePatternEdit) {
103+ return {};
104+ }
105+ const QString patternText = m_framePatternEdit->text ().trimmed ();
106+ if (patternText.isEmpty ()) {
107+ return {};
108+ }
109+
110+ const HexParseResult result = parseHexPayload (patternText);
111+ if (!result.ok || result.bytes .isEmpty ()) {
112+ return {};
113+ }
114+ if (ok) {
115+ *ok = true ;
116+ }
117+ return result.bytes ;
118+ }
119+
88120QString WorkbenchPage::currentDisplayMode () const
89121{
90122 return m_displayModeSegment ? m_displayModeSegment->currentItem () : QStringLiteral (" text" );
@@ -195,15 +227,140 @@ bool WorkbenchPage::recordMatchesTerminalFilter(const SessionRecord &record) con
195227 record.displayText .contains (searchText, Qt::CaseInsensitive);
196228}
197229
198- void WorkbenchPage::appendRecord (RecordDirection direction, const QByteArray &data)
230+ void WorkbenchPage::handleReceivedData (const QByteArray &data)
231+ {
232+ if (data.isEmpty ()) {
233+ return ;
234+ }
235+
236+ if (!m_autoFrameBreakCheck || !m_autoFrameBreakCheck->isChecked () ||
237+ frameBreakModeKey () == QStringLiteral (" timeout" )) {
238+ appendRecord (RecordDirection::Rx, data);
239+ return ;
240+ }
241+
242+ recordReceivedBytes (data);
243+ processBufferedFrameData (data);
244+ }
245+
246+ void WorkbenchPage::recordReceivedBytes (const QByteArray &data)
247+ {
248+ if (data.isEmpty ()) {
249+ return ;
250+ }
251+
252+ m_rxCount += data.size ();
253+ if (m_saveReceiveCheck && m_saveReceiveCheck->isChecked ()) {
254+ if (!m_receiveCaptureFile.isOpen ()) {
255+ updateReceiveCapture (true );
256+ }
257+ if (m_receiveCaptureFile.isOpen ()) {
258+ m_receiveCaptureFile.write (data);
259+ m_receiveCaptureFile.flush ();
260+ }
261+ }
262+ updateCounters ();
263+ }
264+
265+ void WorkbenchPage::processBufferedFrameData (const QByteArray &data)
266+ {
267+ const QString mode = frameBreakModeKey ();
268+ if (mode == QStringLiteral (" length" )) {
269+ const int frameLength = m_frameFixedLengthSpin ? qBound (1 , m_frameFixedLengthSpin->value (), 65536 ) : 1 ;
270+ m_rxFrameBuffer.append (data);
271+ while (m_rxFrameBuffer.size () >= frameLength) {
272+ appendRecord (RecordDirection::Rx, m_rxFrameBuffer.left (frameLength), false );
273+ m_rxFrameBuffer.remove (0 , frameLength);
274+ }
275+ return ;
276+ }
277+
278+ bool patternOk = false ;
279+ const QByteArray pattern = frameBoundaryPattern (&patternOk);
280+ if (!patternOk || pattern.isEmpty ()) {
281+ appendRecord (RecordDirection::Rx, data, false );
282+ return ;
283+ }
284+
285+ m_rxFrameBuffer.append (data);
286+ if (mode == QStringLiteral (" tail" )) {
287+ while (true ) {
288+ const int index = m_rxFrameBuffer.indexOf (pattern);
289+ if (index < 0 ) {
290+ break ;
291+ }
292+ const int frameEnd = index + pattern.size ();
293+ appendRecord (RecordDirection::Rx, m_rxFrameBuffer.left (frameEnd), false );
294+ m_rxFrameBuffer.remove (0 , frameEnd);
295+ }
296+ } else if (mode == QStringLiteral (" header" )) {
297+ while (true ) {
298+ const int firstHeader = m_rxFrameBuffer.indexOf (pattern);
299+ if (firstHeader < 0 ) {
300+ const int keepBytes = qMin (pattern.size () - 1 , m_rxFrameBuffer.size ());
301+ const int emitBytes = m_rxFrameBuffer.size () - keepBytes;
302+ if (emitBytes > 0 ) {
303+ appendRecord (RecordDirection::Rx, m_rxFrameBuffer.left (emitBytes), false );
304+ m_rxFrameBuffer.remove (0 , emitBytes);
305+ }
306+ break ;
307+ }
308+ if (firstHeader > 0 ) {
309+ appendRecord (RecordDirection::Rx, m_rxFrameBuffer.left (firstHeader), false );
310+ m_rxFrameBuffer.remove (0 , firstHeader);
311+ }
312+
313+ const int nextHeader = m_rxFrameBuffer.indexOf (pattern, pattern.size ());
314+ if (nextHeader < 0 ) {
315+ break ;
316+ }
317+ appendRecord (RecordDirection::Rx, m_rxFrameBuffer.left (nextHeader), false );
318+ m_rxFrameBuffer.remove (0 , nextHeader);
319+ }
320+ }
321+
322+ if (m_rxFrameBuffer.size () > MaxFrameBufferBytes) {
323+ flushRxFrameBuffer ();
324+ }
325+ }
326+
327+ void WorkbenchPage::flushRxFrameBuffer ()
328+ {
329+ if (m_rxFrameBuffer.isEmpty ()) {
330+ return ;
331+ }
332+ const QByteArray data = m_rxFrameBuffer;
333+ m_rxFrameBuffer.clear ();
334+ appendRecord (RecordDirection::Rx, data, false );
335+ }
336+
337+ void WorkbenchPage::updateFrameControlState ()
338+ {
339+ const bool enabled = m_autoFrameBreakCheck && m_autoFrameBreakCheck->isChecked ();
340+ const QString mode = frameBreakModeKey ();
341+ if (m_frameModeCombo) {
342+ m_frameModeCombo->setEnabled (true );
343+ }
344+ if (m_framePatternEdit) {
345+ m_framePatternEdit->setEnabled (enabled && (mode == QStringLiteral (" header" ) || mode == QStringLiteral (" tail" )));
346+ }
347+ if (m_frameFixedLengthSpin) {
348+ m_frameFixedLengthSpin->setEnabled (enabled && mode == QStringLiteral (" length" ));
349+ }
350+ if (m_frameBreakIntervalSpin) {
351+ m_frameBreakIntervalSpin->setEnabled (enabled && mode == QStringLiteral (" timeout" ));
352+ }
353+ }
354+
355+ void WorkbenchPage::appendRecord (RecordDirection direction, const QByteArray &data, bool updateStats)
199356{
200357 if (data.isEmpty ()) {
201358 return ;
202359 }
203360
204361 const QDateTime now = QDateTime::currentDateTime ();
205362 if (direction == RecordDirection::Rx && m_autoFrameBreakCheck && m_autoFrameBreakCheck->isChecked () &&
206- m_lastRxTimestamp.isValid ()) {
363+ frameBreakModeKey () == QStringLiteral ( " timeout " ) && m_lastRxTimestamp.isValid ()) {
207364 const int thresholdMs = m_frameBreakIntervalSpin ? m_frameBreakIntervalSpin->value () : 20 ;
208365 if (m_lastRxTimestamp.msecsTo (now) >= thresholdMs) {
209366 SessionRecord separator;
@@ -225,7 +382,7 @@ void WorkbenchPage::appendRecord(RecordDirection direction, const QByteArray &da
225382 m_records.append (record);
226383 m_pendingRecordIndexes.append (m_records.size () - 1 );
227384
228- if (direction == RecordDirection::Rx) {
385+ if (direction == RecordDirection::Rx && updateStats ) {
229386 m_lastRxTimestamp = now;
230387 m_rxCount += data.size ();
231388 if (m_saveReceiveCheck && m_saveReceiveCheck->isChecked ()) {
@@ -237,7 +394,7 @@ void WorkbenchPage::appendRecord(RecordDirection direction, const QByteArray &da
237394 m_receiveCaptureFile.flush ();
238395 }
239396 }
240- } else {
397+ } else if (direction == RecordDirection::Tx && updateStats) {
241398 m_txCount += data.size ();
242399 }
243400
0 commit comments