Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
41 changes: 39 additions & 2 deletions capa/ida/plugin/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
CAPA_SETTINGS_RULEGEN_AUTHOR = "rulegen_author"
CAPA_SETTINGS_RULEGEN_SCOPE = "rulegen_scope"
CAPA_SETTINGS_ANALYZE = "analyze"
CAPA_SETTINGS_FONT = "font"


CAPA_OFFICIAL_RULESET_URL = f"https://github.com/mandiant/capa-rules/releases/tag/v{capa.version.__version__}"
Expand Down Expand Up @@ -304,6 +305,39 @@ def load_interface(self):

# load parent view
self.load_view_parent()
self.load_font()

def load_font(self):
"""load the user-configured font or fall back to the system fixed font"""
font_str = settings.user.get(CAPA_SETTINGS_FONT, "")
font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)
if font_str:
font.fromString(font_str)
self.update_fonts(font)
Comment thread
vee1e marked this conversation as resolved.
Outdated

def slot_font(self):
"""launch the font dialog and apply the chosen font"""
font_str = settings.user.get(CAPA_SETTINGS_FONT, "")
current_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)
if font_str:
current_font.fromString(font_str)
font, ok = QtWidgets.QFontDialog.getFont(current_font, self.parent, "Select Plugin Font")
if ok:
settings.user[CAPA_SETTINGS_FONT] = font.toString()
self.update_fonts(font)
Comment thread
vee1e marked this conversation as resolved.
Outdated

def update_fonts(self, font: QtGui.QFont):
"""propagate the selected font throughout the plugin UI"""
if hasattr(self, "model_data") and self.model_data:
self.model_data.update_font(font)
if hasattr(self, "view_tree") and self.view_tree:
self.view_tree.update_font(font)
if hasattr(self, "view_rulegen_preview") and self.view_rulegen_preview:
self.view_rulegen_preview.update_font(font)
if hasattr(self, "view_rulegen_editor") and self.view_rulegen_editor:
self.view_rulegen_editor.update_font(font)
if hasattr(self, "view_rulegen_features") and self.view_rulegen_features:
self.view_rulegen_features.update_font(font)
Comment thread
vee1e marked this conversation as resolved.
Outdated
Comment thread
vee1e marked this conversation as resolved.
Outdated

def load_view_tabs(self):
"""load tabs"""
Expand Down Expand Up @@ -345,22 +379,26 @@ def load_view_buttons(self):
reset_button = QtWidgets.QPushButton("Reset Selections")
save_button = QtWidgets.QPushButton("Save")
settings_button = QtWidgets.QPushButton("Settings")
font_button = QtWidgets.QPushButton("Font...")

analyze_button.clicked.connect(self.slot_analyze)
reset_button.clicked.connect(self.slot_reset)
save_button.clicked.connect(self.slot_save)
settings_button.clicked.connect(self.slot_settings)
font_button.clicked.connect(self.slot_font)

layout = QtWidgets.QHBoxLayout()
layout.addWidget(analyze_button)
layout.addWidget(reset_button)
layout.addWidget(settings_button)
layout.addWidget(font_button)
layout.addStretch(3)
layout.addWidget(save_button, alignment=QtCore.Qt.AlignRight)

self.view_analyze_button = analyze_button
self.view_reset_button = reset_button
self.view_settings_button = settings_button
self.view_font_button = font_button
self.view_save_button = save_button
self.view_buttons = layout

Expand Down Expand Up @@ -416,9 +454,8 @@ def load_view_rulegen_tab(self):
left = QtWidgets.QWidget()
left.setLayout(layout2)

font = QtGui.QFont()
font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)
font.setBold(True)
Comment thread
vee1e marked this conversation as resolved.
Outdated
font.setPointSize(11)

label1 = QtWidgets.QLabel()
label1.setAlignment(QtCore.Qt.AlignLeft)
Expand Down
14 changes: 12 additions & 2 deletions capa/ida/plugin/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ def __init__(self, parent=None):
super().__init__(parent)
# root node does not have parent, contains header columns
self.root_node = CapaExplorerDataItem(None, ["Rule Information", "Address", "Details"])
self.current_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)

def update_font(self, font: QtGui.QFont):
"""update the font used to render items"""
self.current_font = font
self.layoutChanged.emit()

def reset(self):
"""reset UI elements (e.g. checkboxes, IDA color highlights)
Expand Down Expand Up @@ -134,7 +140,8 @@ def data(self, model_index, role):
CapaExplorerDataModel.COLUMN_INDEX_DETAILS,
):
# set font for virtual address and details columns
font = QtGui.QFont("Courier", weight=QtGui.QFont.Medium)
font = QtGui.QFont(self.current_font)
font.setWeight(QtGui.QFont.Medium)
if column == CapaExplorerDataModel.COLUMN_INDEX_VIRTUAL_ADDRESS:
font.setBold(True)
return font
Expand All @@ -156,10 +163,13 @@ def data(self, model_index, role):
and column == CapaExplorerDataModel.COLUMN_INDEX_RULE_INFORMATION
):
# set bold font for important items
font = QtGui.QFont()
font = QtGui.QFont(self.current_font)
font.setBold(True)
return font

if role == QtCore.Qt.FontRole:
return QtGui.QFont(self.current_font)

if role == QtCore.Qt.ForegroundRole and column == CapaExplorerDataModel.COLUMN_INDEX_VIRTUAL_ADDRESS:
# set color for virtual address column
return QtGui.QColor(37, 147, 215)
Expand Down
55 changes: 47 additions & 8 deletions capa/ida/plugin/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,20 @@ def __init__(self, parent=None):
""" """
super().__init__(parent)

self.setFont(QtGui.QFont("Courier", weight=QtGui.QFont.Bold))
self.current_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)
font = QtGui.QFont(self.current_font)
font.setBold(True)
self.setFont(font)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.setAcceptRichText(False)

def update_font(self, font: QtGui.QFont):
self.current_font = font
preview_font = QtGui.QFont(self.current_font)
preview_font.setBold(True)
self.setFont(preview_font)

def reset_view(self):
""" """
self.clear()
Expand Down Expand Up @@ -347,6 +356,7 @@ def __init__(self, preview, parent=None):
self.reset_view()

self.is_editing = False
self.current_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)

@staticmethod
def get_column_feature_index():
Expand Down Expand Up @@ -498,6 +508,20 @@ def slot_item_double_clicked(self, o, column):
o.setFlags(o.flags() & ~QtCore.Qt.ItemIsEditable)
self.is_editing = True

def update_font(self, font: QtGui.QFont):
"""apply a new font to the editor and restyle existing nodes"""
self.current_font = font
self.setFont(font)
self.header().setFont(font)
for node in iterate_tree(self):
if getattr(node, "capa_type", None) == CapaExplorerRulegenEditor.get_node_type_expression():
self.style_expression_node(node)
elif getattr(node, "capa_type", None) == CapaExplorerRulegenEditor.get_node_type_feature():
self.style_feature_node(node)
elif getattr(node, "capa_type", None) == CapaExplorerRulegenEditor.get_node_type_comment():
self.style_comment_node(node)
self.slot_resize_columns_to_content()

def update_preview(self):
""" """
rule_text = self.preview.toPlainText()
Expand Down Expand Up @@ -577,17 +601,16 @@ def load_custom_context_menu_expression(self, pos):

def style_expression_node(self, o):
""" """
font = QtGui.QFont()
font = QtGui.QFont(self.current_font)
font.setBold(True)

o.setFont(CapaExplorerRulegenEditor.get_column_feature_index(), font)

def style_feature_node(self, o):
""" """
font = QtGui.QFont()
font = QtGui.QFont(self.current_font)
brush = QtGui.QBrush()

font.setFamily("Courier")
font.setWeight(QtGui.QFont.Medium)
brush.setColor(QtGui.QColor(*COLOR_GREEN_RGB))

Expand All @@ -596,9 +619,8 @@ def style_feature_node(self, o):

def style_comment_node(self, o):
""" """
font = QtGui.QFont()
font = QtGui.QFont(self.current_font)
font.setBold(True)
font.setFamily("Courier")

o.setFont(CapaExplorerRulegenEditor.get_column_feature_index(), font)

Expand Down Expand Up @@ -814,6 +836,7 @@ def __init__(self, editor, parent=None):

self.parent_items = {}
self.editor = editor
self.current_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)

self.setHeaderLabels(["Feature", "Address"])
self.setStyleSheet("QTreeView::item {padding-right: 15 px;padding-bottom: 2 px;}")
Expand Down Expand Up @@ -972,14 +995,15 @@ def show_item_and_parents(_o):

def style_parent_node(self, o):
""" """
font = QtGui.QFont()
font = QtGui.QFont(self.current_font)
font.setBold(True)

o.setFont(CapaExplorerRulegenFeatures.get_column_feature_index(), font)

def style_leaf_node(self, o):
""" """
font = QtGui.QFont("Courier", weight=QtGui.QFont.Bold)
font = QtGui.QFont(self.current_font)
font.setBold(True)
brush = QtGui.QBrush()

o.setFont(CapaExplorerRulegenFeatures.get_column_feature_index(), font)
Expand All @@ -990,6 +1014,17 @@ def style_leaf_node(self, o):

brush.setColor(QtGui.QColor(*COLOR_BLUE_RGB))
o.setForeground(CapaExplorerRulegenFeatures.get_column_address_index(), brush)
def update_font(self, font: QtGui.QFont):
"""apply a new font to the feature tree and restyle nodes"""
self.current_font = font
self.setFont(font)
self.header().setFont(font)
for node in iterate_tree(self):
if getattr(node, "capa_type", None) == CapaExplorerRulegenFeatures.get_node_type_parent():
self.style_parent_node(node)
elif getattr(node, "capa_type", None) == CapaExplorerRulegenFeatures.get_node_type_leaf():
self.style_leaf_node(node)
self.slot_resize_columns_to_content()

def set_parent_node(self, o):
""" """
Expand Down Expand Up @@ -1133,6 +1168,10 @@ def __init__(self, model, parent=None):

self.setStyleSheet("QTreeView::item {padding-right: 15 px;padding-bottom: 2 px;}")

def update_font(self, font: QtGui.QFont):
self.setFont(font)
self.header().setFont(font)
Comment thread
vee1e marked this conversation as resolved.
Outdated

def reset_ui(self, should_sort=True):
"""reset user interface changes

Expand Down
Loading