Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add alignment action in analysis #458

Merged
merged 19 commits into from
Jun 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ __Import announcement if you build URH manually__: Cython is now a __required__
- [#470](https://github.com/jopohl/urh/pull/470) - improve conditional compiling of native device extensions
- [#469](https://github.com/jopohl/urh/pull/469) - improve device selection in options, use a table instead of a list view
- [#468](https://github.com/jopohl/urh/pull/468) - improve python2 interpreter settings for GNU Radio backend with empty ``` urh.ini ```
- [#458](https://github.com/jopohl/urh/pull/458) - add alignment action to analysis
![alignment image](https://i.imgur.com/xQt7H7Y.png)

---

Expand Down
39 changes: 23 additions & 16 deletions data/ui/analysis.ui
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="16">
<item row="0" column="17">
<widget class="QToolButton" name="btnSaveProto">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
Expand Down Expand Up @@ -543,7 +543,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="11">
<item row="0" column="12">
<widget class="QLabel" name="label_2">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The &lt;span style=&quot; font-weight:600;&quot;&gt;Received Signal Strength Indicator&lt;/span&gt; indicates the average signal power of the current message.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
Expand All @@ -553,7 +553,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="6">
<item row="0" column="7">
<widget class="QLabel" name="lSlash">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
Expand All @@ -569,14 +569,14 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="3">
<item row="0" column="4">
<widget class="QLabel" name="lblShownRows">
<property name="text">
<string>shown: 42/108</string>
</property>
</widget>
</item>
<item row="0" column="15">
<item row="0" column="16">
<widget class="QLabel" name="lTime">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
Expand All @@ -598,7 +598,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="5">
<item row="0" column="6">
<widget class="QLabel" name="lSearchCurrent">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
Expand All @@ -617,7 +617,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="12">
<item row="0" column="13">
<widget class="QLabel" name="lblRSSI">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
Expand Down Expand Up @@ -645,14 +645,14 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
<bool>false</bool>
</property>
<property name="placeholderText">
<string>Search Pattern</string>
<string>Enter pattern here</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="8">
<item row="0" column="9">
<widget class="QToolButton" name="btnNextSearch">
<property name="enabled">
<bool>false</bool>
Expand All @@ -672,7 +672,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="4">
<item row="0" column="5">
<widget class="QToolButton" name="btnPrevSearch">
<property name="enabled">
<bool>false</bool>
Expand All @@ -692,7 +692,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="7">
<item row="0" column="8">
<widget class="QLabel" name="lSearchTotal">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
Expand All @@ -711,7 +711,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="14">
<item row="0" column="15">
<widget class="QLabel" name="label_3">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The &lt;span style=&quot; font-weight:600;&quot;&gt;Message Start&lt;/span&gt; is the point in time when a protocol message begins. Additionally the relative time (+ ...) from the previous message is shown.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
Expand All @@ -724,7 +724,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="13">
<item row="0" column="14">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
Expand Down Expand Up @@ -760,7 +760,7 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="9">
<item row="0" column="10">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
Expand All @@ -776,14 +776,14 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</spacer>
</item>
<item row="0" column="10">
<item row="0" column="11">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="17">
<item row="0" column="18">
<widget class="QToolButton" name="btnLoadProto">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
Expand All @@ -803,6 +803,13 @@ image: url(:/icons/icons/splitter_handle_vertical.svg);
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="lblClearAlignment">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;reset_alignment&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Reset alignment&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
Expand Down
81 changes: 61 additions & 20 deletions src/urh/controller/CompareFrameController.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ def __init__(self, plugin_manager: PluginManager, project_manager: ProjectManage
self.__active_group_ids = [0]
self.selected_protocols = set()

self.search_select_search_menu = QMenu()
self.search_action = self.search_select_search_menu.addAction(self.tr("Search"))
self.select_action = self.search_select_search_menu.addAction(self.tr("Select all"))
self.filter_action = self.search_select_search_menu.addAction(self.tr("Filter"))
self.ui.btnSearchSelectFilter.setMenu(self.search_select_search_menu)
self.search_select_filter_align_menu = QMenu()
self.search_action = self.search_select_filter_align_menu.addAction(self.tr("Search"))
self.select_action = self.search_select_filter_align_menu.addAction(self.tr("Select all"))
self.filter_action = self.search_select_filter_align_menu.addAction(self.tr("Filter"))
self.align_action = self.search_select_filter_align_menu.addAction(self.tr("Align"))
self.ui.btnSearchSelectFilter.setMenu(self.search_select_filter_align_menu)

self.analyze_menu = QMenu()
self.assign_participants_action = self.analyze_menu.addAction(self.tr("Assign participants"))
Expand All @@ -85,6 +86,7 @@ def __init__(self, plugin_manager: PluginManager, project_manager: ProjectManage
self.ui.btnAnalyze.setMenu(self.analyze_menu)

self.ui.lblShownRows.hide()
self.ui.lblClearAlignment.hide()

self.protocol_model = ProtocolTableModel(self.proto_analyzer, project_manager.participants,
self) # type: ProtocolTableModel
Expand Down Expand Up @@ -265,7 +267,9 @@ def create_connects(self):
self.search_action.triggered.connect(self.on_search_action_triggered)
self.select_action.triggered.connect(self.on_select_action_triggered)
self.filter_action.triggered.connect(self.on_filter_action_triggered)
self.align_action.triggered.connect(self.on_align_action_triggered)
self.ui.lblShownRows.linkActivated.connect(self.on_label_shown_link_activated)
self.ui.lblClearAlignment.linkActivated.connect(self.on_label_clear_alignment_link_activated)

self.protocol_label_list_model.protolabel_visibility_changed.connect(self.on_protolabel_visibility_changed)
self.protocol_label_list_model.protocol_label_name_edited.connect(self.label_value_model.update)
Expand Down Expand Up @@ -589,23 +593,20 @@ def restore_selection(self, old_view: int, sel_cols, sel_rows):
if len(sel_cols) == 0 or len(sel_rows) == 0:
return

startCol, endCol = numpy.min(sel_cols), numpy.max(sel_cols)
startRow, endRow = numpy.min(sel_rows), numpy.max(sel_rows)
start_col, end_col = numpy.min(sel_cols), numpy.max(sel_cols)
start_row, end_row = numpy.min(sel_rows), numpy.max(sel_rows)
new_view = self.ui.cbProtoView.currentIndex()

message = self.proto_analyzer.messages[endRow]
startCol = message.convert_index(startCol, old_view, new_view, True)[0]
endCol = message.convert_index(endCol, old_view, new_view, True)[1]
message = self.proto_analyzer.messages[end_row]
start_col = message.convert_index(start_col, old_view, new_view, True)[0]
end_col = message.convert_index(end_col, old_view, new_view, True)[1]

endCol = endCol if endCol < len(self.protocol_model.display_data[endRow]) else len(
self.protocol_model.display_data[endRow]) - 1

startindex = self.protocol_model.index(startRow, startCol)
endindex = self.protocol_model.index(endRow, endCol)
mid_index = self.protocol_model.index(int((startRow + endRow) / 2), int((startCol + endCol) / 2))
start_index = self.protocol_model.index(start_row, start_col)
end_index = self.protocol_model.index(end_row, end_col)
mid_index = self.protocol_model.index(int((start_row + end_row) / 2), int((start_col + end_col) / 2))

sel = QItemSelection()
sel.select(startindex, endindex)
sel.select(start_index, end_index)

self.ui.tblViewProtocol.selectionModel().select(sel, QItemSelectionModel.ClearAndSelect)
self.ui.tblViewProtocol.scrollTo(mid_index)
Expand Down Expand Up @@ -715,6 +716,31 @@ def __set_shown_rows_status_label(self):
else:
self.ui.lblShownRows.hide()

def align_messages(self, pattern=None):
pattern = self.ui.lineEditSearch.text() if pattern is None else pattern
self.proto_analyzer.align_messages(pattern, view_type=self.ui.cbProtoView.currentIndex())
self.ui.lblClearAlignment.setVisible(any(msg.alignment_offset != 0 for msg in self.proto_analyzer.messages))
self.protocol_model.update()

row = column = 0
for i, message in enumerate(self.proto_analyzer.messages):
if self.ui.tblViewProtocol.isRowHidden(i):
continue

data = message.view_to_string(self.ui.cbProtoView.currentIndex(), decoded=True)
try:
row = i
column = data.index(pattern) + len(pattern) + self.protocol_model.get_alignment_offset_at(i) - 1
break
except ValueError:
pass

self.ui.tblViewProtocol.scrollTo(self.protocol_model.index(row, column))

self.show_all_cols()
for lbl in filter(lambda l: not l.show, self.proto_analyzer.protocol_labels):
self.set_protocol_label_visibility(lbl)

def next_search_result(self):
index = int(self.ui.lSearchCurrent.text())
self.ui.lSearchTotal.setText((str(len(self.protocol_model.search_results))))
Expand Down Expand Up @@ -775,9 +801,8 @@ def clear_search(self):

def set_protocol_label_visibility(self, lbl: ProtocolLabel, message: Message = None):
try:
message = message if message else next(
msg for msg in self.proto_analyzer.messages if lbl in msg.message_type)
start, end = message.get_label_range(lbl, self.ui.cbProtoView.currentIndex(), True)
message = message if message else next(m for m in self.proto_analyzer.messages if lbl in m.message_type)
start, end = message.get_label_range(lbl, self.ui.cbProtoView.currentIndex(), True, consider_alignment=True)

for i in range(start, end):
self.ui.tblViewProtocol.setColumnHidden(i, not lbl.show)
Expand Down Expand Up @@ -1146,6 +1171,17 @@ def on_filter_action_triggered(self):
self.ui.btnSearchSelectFilter.clicked.disconnect()
self.ui.btnSearchSelectFilter.clicked.connect(self.filter_search_results)

@pyqtSlot()
def on_align_action_triggered(self):
def on_btn_search_select_filter_clicked():
self.align_messages()

self.ui.btnSearchSelectFilter.setText("Align")
self.ui.btnSearchSelectFilter.setIcon(QIcon.fromTheme("align-horizontal-left"))
self.set_search_ui_visibility(False)
self.ui.btnSearchSelectFilter.clicked.disconnect()
self.ui.btnSearchSelectFilter.clicked.connect(on_btn_search_select_filter_clicked)

@pyqtSlot(bool)
def on_writeable_changed(self, writeable_status: bool):
hidden_rows = {i for i in range(self.protocol_model.row_count) if self.ui.tblViewProtocol.isRowHidden(i)}
Expand Down Expand Up @@ -1434,6 +1470,11 @@ def on_label_shown_link_activated(self, link: str):
self.ui.lineEditSearch.clear()
self.show_all_rows()

@pyqtSlot(str)
def on_label_clear_alignment_link_activated(self, link: str):
if link == "reset_alignment":
self.align_messages(pattern="")

@pyqtSlot()
def on_protocol_updated(self):
self.set_shown_protocols()
Expand Down
10 changes: 7 additions & 3 deletions src/urh/models/ProtocolTableModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ class ProtocolTableModel(TableModel):
def __init__(self, proto_analyzer: ProtocolAnalyzer, participants, controller, parent=None):
super().__init__(participants=participants, parent=parent)

self.controller = controller
""":type: urh.controller.CompareFrameController.CompareFrameController"""
self.controller = controller # type: urh.controller.CompareFrameController.CompareFrameController

self.protocol = proto_analyzer
self.active_group_ids = [0]
Expand All @@ -36,7 +35,8 @@ def refindex(self, refindex):
self.ref_index_changed.emit(self._refindex)

def addProtoLabel(self, start, end, messagenr):
self.controller.add_protocol_label(start=start, end=end, messagenr=messagenr, proto_view=self.proto_view)
a = self.get_alignment_offset_at(messagenr)
self.controller.add_protocol_label(start=start-a, end=end-a, messagenr=messagenr, proto_view=self.proto_view)

def refresh_fonts(self):
self.bold_fonts.clear()
Expand All @@ -61,6 +61,10 @@ def delete_range(self, min_row: int, max_row: int, start: int, end: int):

def flags(self, index: QModelIndex):
if index.isValid():
alignment_offset = self.get_alignment_offset_at(index.row())
if index.column() < alignment_offset:
return Qt.ItemIsSelectable | Qt.ItemIsEnabled

if self.is_writeable:
return Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable
else:
Expand Down
Loading