# -*- coding: utf-8 -*-
"""
Copyright (C) Korcan Karaokçu <korcankaraokcu@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PyQt6.QtWidgets import (
QWidget,
QScrollBar,
QTableWidget,
QTableWidgetItem,
QTreeWidget,
QTreeWidgetItem,
QListWidget,
QListWidgetItem,
QComboBox,
QMenu,
QLayout,
)
from PyQt6.QtCore import QObject, QRegularExpression
from PyQt6.QtGui import QShortcut, QRegularExpressionValidator
from libpince import utils, typedefs, regexes
from tr.tr import TranslationConstants as tr
from typing import overload
validator_map: dict[str, QRegularExpressionValidator | None] = {
"int": QRegularExpressionValidator(QRegularExpression(regexes.decimal_number.pattern)), # integers
"int_hex": QRegularExpressionValidator(QRegularExpression(regexes.hex_number_gui.pattern)), # hexadecimals
"float": QRegularExpressionValidator(QRegularExpression(regexes.float_number.pattern)), # floats
"bytearray": QRegularExpressionValidator(QRegularExpression(regexes.bytearray_input.pattern)), # array of bytes
"string": None,
}
[docs]
def get_icons_directory():
"""Gets the directory of the icons
Returns:
str: Path to the icons directory
"""
return utils.get_script_directory() + "/media/icons"
[docs]
def center(window: QWidget):
"""Center the given window to desktop
Args:
window (QWidget): The window that'll be centered to desktop
"""
window.frameGeometry().moveCenter(window.screen().availableGeometry().center())
[docs]
def center_to_parent(window: QWidget):
"""Center the given window to its parent
Args:
window (QWidget): The window that'll be centered to its parent
"""
parent: QWidget = window.parent()
window.move(parent.frameGeometry().center() - window.rect().center())
[docs]
def resize_to_contents(tablewidget: QTableWidget):
"""Resizes the columns of the given QTableWidget to its contents
This also fixes the stretch problem of the last column
Args:
tablewidget (QTableWidget): Self-explanatory
"""
tablewidget.resizeColumnsToContents()
default_size = tablewidget.horizontalHeader().defaultSectionSize()
tablewidget.horizontalHeader().resizeSection(tablewidget.columnCount() - 1, default_size)
[docs]
def fill_value_combobox(combobox: QComboBox, current_index: int = typedefs.VALUE_INDEX.INT32):
"""Fills the given QComboBox with value_index strings
Args:
combobox (QComboBox): The combobox that'll be filled
current_index (int): Can be a member of typedefs.VALUE_INDEX
"""
for key in typedefs.index_to_text_dict:
combobox.addItem(typedefs.index_to_text_dict[key])
combobox.setCurrentIndex(current_index)
[docs]
def fill_endianness_combobox(combobox: QComboBox, current_index: int = typedefs.ENDIANNESS.HOST):
"""Fills the given QComboBox with endianness strings
Args:
combobox (QComboBox): The combobox that'll be filled
current_index (int): Can be a member of typedefs.ENDIANNESS
"""
endianness_text = [
(typedefs.ENDIANNESS.HOST, tr.HOST),
(typedefs.ENDIANNESS.LITTLE, tr.LITTLE),
(typedefs.ENDIANNESS.BIG, tr.BIG),
]
for endian, text in endianness_text:
combobox.addItem(text, endian)
combobox.setCurrentIndex(current_index)
[docs]
def get_current_row(tablewidget: QTableWidget):
r"""Returns the currently selected row index for the given QTableWidget
If you try to use only selectionModel().currentIndex().row() for this purpose, you'll get the last selected row even
if it was unselected afterwards. This is why this function exists, it checks the selection state before returning
the selected row
Args:
tablewidget (QTableWidget): Self-explanatory
Returns:
int: Currently selected row. Returns -1 if nothing is selected
Note:
This function doesn't work properly when used within signals such as currentItemChanged, currentIndexChanged,
currentChanged and currentRowChanged. Use the row, item, QModelIndex or whatever the signal provides instead.
This bug occurs because those signals only update the changed row, not the selectionModel. This causes
selectionModel().selectedRows() to return None and this function to behave improperly
For developers: You can use the regex \.current.*\.connect to search signals if a cleanup is needed
"""
if tablewidget.selectionModel().selectedRows():
return tablewidget.selectionModel().currentIndex().row()
return -1
@overload
def get_current_item(listwidget: QListWidget) -> QListWidgetItem | None: ...
@overload
def get_current_item(tablewidget: QTableWidget) -> QTableWidgetItem | None: ...
@overload
def get_current_item(treewidget: QTreeWidget) -> QTreeWidgetItem | None: ...
[docs]
def get_current_item(widget: QListWidget | QTableWidget | QTreeWidget):
r"""Returns the currently selected item for the given widget
If you try to use only selectionModel().currentItem() for this purpose, you'll get the last selected item even
if it was unselected afterwards. This is why this function exists, it checks the selection state before returning
the selected item. Unlike get_current_row, this function can be used with QTreeWidget
Args:
widget (QListWidget | QTableWidget | QTreeWidget): Self-explanatory
Returns:
Any: Currently selected item. Returns None if nothing is selected
Note:
This function doesn't work properly when used within signals such as currentItemChanged, currentIndexChanged,
currentChanged and currentRowChanged. Use the row, item, QModelIndex or whatever the signal provides instead.
This bug occurs because those signals only update the changed row, not the selectionModel. This causes
selectionModel().selectedRows() to return None and this function to behave improperly
For developers: You can use the regex \.current.*\.connect to search signals if a cleanup is needed
"""
if widget.selectionModel().selectedRows():
return widget.currentItem()
# TODO: This is a really bad design pattern, remove this function after moving classes to their own files
[docs]
def search_parents_by_function(qt_object: QObject, func_name: str):
"""Search for func_name in the parents of given QObject. Once function is found, parent that possesses func_name
is returned
Args:
qt_object (QObject): The object that'll be searched for it's parents
func_name (str): The name of the function that'll be searched
"""
while qt_object is not None:
qt_object = qt_object.parent()
if func_name in dir(qt_object):
return qt_object
[docs]
def contains_reference_mark(string: str):
"""Checks if given string contains the reference mark
Args:
string (str): String that'll be checked for the reference mark
Returns:
bool: True if given string contains the reference mark, False otherwise
"""
return True if regexes.reference_mark.search(string) else False