Skip to content

Commit

Permalink
Merge branch 'developer_1'
Browse files Browse the repository at this point in the history
added custom_delegets.py to check an duplicate list in listViewWidget, It is being called in CustomLabelWidget class, When user will click on any item in list for edit, it will check duplicate entry, if exits it will show a msg & revert back to origional state. - 2. in main.py two changes: a) enable edit, save, clear, delete btn when save directory loaded and it find an label for corresponding image_index. b) added one function refresh list to directly reflect the updated_modified_object list from by user from CustomLabelWidget Class. -3 in list_widget.py added custom_delegets as attribute in CustomLabelWidget class and refresh_list method in CustomObjectListWidget class
  • Loading branch information
amish0 committed Aug 17, 2024
2 parents 5404c5f + ddff12a commit 7dac6fa
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 22 deletions.
75 changes: 75 additions & 0 deletions labelvim/labelvim/widgets/custom_delegets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from PyQt5.QtWidgets import QStyledItemDelegate, QMessageBox, QLineEdit
from PyQt5.QtCore import Qt

"""
CustomDelegate: Now checks for duplicates in the QStringList
Model and handles committing data appropriately.
The setModelData method iterates through the string list to
check for duplicates and updates the model if the new text is valid.
CustomObjectListWidget: Uses QStringListModel for the list data.
add_item: Appends new items to the list.
This setup integrates QStringListModel with the custom delegate,
allowing you to edit list items and ensure that no duplicates are added.
"""

class CustomDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super().__init__(parent)
self.parent_view = parent

def createEditor(self, parent, option, index):
"""
Create and return a new editor widget for the item.
Args:
parent (QWidget): The parent widget.
option (QStyleOptionViewItem): The option for the item.
index (QModelIndex): The index of the item.
Returns:
QLineEdit: The editor widget.
"""
editor = QLineEdit(parent)
return editor

def setEditorData(self, editor, index):
"""
Set the data for the editor widget.
Args:
editor (QWidget): The editor widget.
index (QModelIndex): The index of the item.
"""
data = index.model().data(index, Qt.EditRole)
editor.setText(data)

def setModelData(self, editor, model, index):
"""
Retrieve the data from the editor widget and set it in the model.
Args:
editor (QWidget): The editor widget.
model (QAbstractItemModel): The model.
index (QModelIndex): The index of the item.
"""
new_text = editor.text()
# Check if the new text already exists in the model
for row in range(model.rowCount()):
item_text = model.data(model.index(row, 0), Qt.DisplayRole)
if item_text == new_text and model.index(row, 0) != index:
QMessageBox.warning(self.parent_view, 'Validation Error', 'The entered text already exists in the list.')
return

model.setData(index, new_text, Qt.EditRole)

def commitData(self, editor):
"""
Validate and commit the edited data.
Args:
editor (QWidget): The editor widget.
"""
super().commitData(editor)
99 changes: 82 additions & 17 deletions labelvim/labelvim/widgets/list_widgets.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from PyQt5 import QtWidgets
from PyQt5.QtCore import QStringListModel, Qt, QRect, pyqtSignal
from PyQt5.QtCore import QStringListModel, Qt, QRect, pyqtSignal, QModelIndex, pyqtSlot
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QInputDialog, QMessageBox, QMenu, QAction

# External imports
from labelvim.utils.config import ANNOTATION_TYPE, OBJECT_LIST_ACTION
from labelvim.widgets.custom_delegets import CustomDelegate
from enum import Enum

class CustomListViewWidget(QtWidgets.QListView):
Expand Down Expand Up @@ -62,7 +63,7 @@ def set_label_list(self, label_list=[]):
Args:
label_list (list, optional): A list of label names to display. Defaults to an empty list.
"""
print(f"Label List in set label list: {label_list}")
# print(f"Label List in set label list: {label_list}")
if isinstance(label_list, list) and len(label_list) > 0:
self.model.clear() # Clear the model before updating
self.label_list = label_list
Expand Down Expand Up @@ -176,8 +177,8 @@ def mousePressEvent(self, event):
event (QMouseEvent): The mouse event object.
"""
index = self.indexAt(event.pos())
print(f"Index: {index.row()}")
print(f"model row count {self.model.rowCount()}")
# print(f"Index: {index.row()}")
# print(f"model row count {self.model.rowCount()}")
if index.isValid():
item = self.model.itemFromIndex(index)
print(f"Item: {item.text()}")
Expand Down Expand Up @@ -230,6 +231,8 @@ def __init__(self, parent=None):
# Set the geometry, model
self.set_geometry()
self.set_model()
self.delegate = CustomDelegate(self)
self.setItemDelegate(self.delegate)
# Set the annotation type to None
self.annotation_type = "Rectangle"
# Connect the signals
Expand Down Expand Up @@ -387,6 +390,7 @@ def edit_label(self, index):
# Start editing the item at the specified index
self.edit(index)


def on_data_changed(self, topLeft, bottomRight, roles):
"""
Slot that is triggered when the data in the model is changed.
Expand Down Expand Up @@ -438,7 +442,7 @@ def __init__(self, parent=None):
self.set_label_list(self.label_list)
# Connect the signals
self.object_list_slot_receiver.connect(self.__receiver_action) # Connect the signal to update the label list
# self.model.dataChanged.connect(self.on_data_changed) # Connect the dataChanged signal
# self.model.dataChanged.connect(self.handle_data_changed) # Connect the dataChanged signal

def set_geometry(self):
"""
Expand All @@ -455,7 +459,7 @@ def set_model(self):
self.setModel(self.model)
self.setUpdatesEnabled(True)
# # Set the edit triggers to NoEditTriggers
# self.setEditTriggers(QtWidgets.QListView.NoEditTriggers)
self.setEditTriggers(QtWidgets.QListView.NoEditTriggers)

def __receiver_action(self, data: any, action: Enum):
data = data[0]
Expand Down Expand Up @@ -493,15 +497,15 @@ def set_label_list(self, category_id: list = [], object_id: list = []):
label_list (list, optional): A list of label names to display. Defaults to an empty list.
"""
# Check if the label list is a non-empty list
if isinstance(category_id, list) and len(category_id) > 0 and isinstance(object_id, list) and len(object_id) > 0:
# if isinstance(category_id, list) and len(category_id) > 0 and isinstance(object_id, list) and len(object_id) > 0:
# Clear the model before updating
self.clear_list()
# Update the label list and model
self.category_id = category_id
self.object_id = object_id
object_list = [f"{self.label_list[id]}" for id in category_id]
# update the model
self.model.setStringList(object_list)
self.clear_list()
# Update the label list and model
self.category_id = category_id
self.object_id = object_id
object_list = [f"{self.label_list[id]}" for id in category_id]
# update the model
self.model.setStringList(object_list)

def clear_list(self):
"""
Expand Down Expand Up @@ -534,6 +538,7 @@ def remove_label(self, data: list):
Args:
label (str): The label to remove.
"""
print(f"Data To Be remoed: {data}")
category_id = [label["category_id"] for label in data]
object_id = [label['id'] for label in data]
self.object = {label['id']: label['category_id'] for label in data}
Expand All @@ -555,6 +560,14 @@ def edit_label(self, object_id, category_id):
object_list = [f"{self.label_list[id]}" for id in self.category_id]
self.model.setStringList(object_list)

def refresh_list(self, label_list: list):
"""
Refresh the list view
"""
self.label_list = label_list
object_list = [f"{self.label_list[id]}" for id in self.category_id]
self.model.setStringList(object_list)

def on_item_clicked(self, index):
"""
Emits the signal with the currently selected item's text.
Expand All @@ -563,8 +576,8 @@ def on_item_clicked(self, index):
index (QModelIndex): The index of the current item.
"""
# Emit the signal with the selected item's text
print(f"Index: {index.row()}")
print(f"Item: {self.model.data(index, Qt.DisplayRole)}")
# print(f"Index: {index.row()}")
# print(f"Item: {self.model.data(index, Qt.DisplayRole)}")
id = self.object_id[index.row()]
self.object_selection_notification_slot.emit(id)

Expand All @@ -580,4 +593,56 @@ def mousePressEvent(self, event) -> None:
print("Clearing selection")
self.object_selection_notification_slot.emit(-1)
# Call the parent class's mousePressEvent to handle normal clicks
super().mousePressEvent(event)
super().mousePressEvent(event)

# def contextMenuEvent(self, event):
# """
# Handles the context menu event, providing an option to edit the selected item.

# Args:
# event (QContextMenuEvent): The context menu event object.
# """
# # Get the index at the mouse position
# index = self.indexAt(event.pos())
# # Check if the index is valid
# if index.isValid():
# # Create a context menu
# menu = QMenu(self)
# # Create an action to edit the item
# edit_action = QAction('Edit', self)
# # Connect the action to the edit_label method
# edit_action.triggered.connect(lambda: self.edit_label_at_index(index))
# # Add the action to the menu
# menu.addAction(edit_action)
# # Show the context menu at the mouse position
# menu.exec_(event.globalPos())

# def edit_label_at_index(self, index):
# """
# Triggers inline editing for the selected item.

# Args:
# index (QModelIndex): The index of the item to be edited.
# """
# # Start editing the item at the specified index
# self.edit(index)

# @pyqtSlot(QModelIndex, QModelIndex)
# def handle_data_changed(self, top_left: QModelIndex, bottom_right: QModelIndex):
# """
# Slot to handle data changes in the list view.

# Args:
# top_left (QModelIndex): The top-left index of the changed data.
# bottom_right (QModelIndex): The bottom-right index of the changed data.
# """
# row = top_left.row()
# # get index of the item and old data





# new_data = self.model.data(top_left, Qt.EditRole)
# print(f"Item at row {row} was changed to '{new_data}'")
# # Optionally, you can update your data model or UI here
21 changes: 16 additions & 5 deletions labelvim/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,10 @@ def __save_directory(self):

# Emit the annotation data to the display
self.Display.annotation_data_slot_receiver.emit(self.annotaion_data['annotations'])

self.SaveBtn.setEnabled(True)
self.DeleteAnnotationBtn.setEnabled(True)
self.EditObjectBtn.setEnabled(True)
self.ClearAnnotationBtn.setEnabled(True)
def __delete_file(self):
"""
Deletes the currently selected file from the list. Removes the file from
Expand Down Expand Up @@ -353,10 +356,16 @@ def __create_object(self):

# Enable the save button
self.SaveBtn.setEnabled(True)
self.DeleteAnnotationBtn.setEnabled(True)
self.EditObjectBtn.setEnabled(True)
self.ClearAnnotationBtn.setEnabled(True)
else:
# Display a message dialog if save directory is not selected
self.msg_dialog("Save Directory Not Selected", "Please select the save directory first.")
self.SaveBtn.setEnabled(False)
self.DeleteAnnotationBtn.setEnabled(False)
self.EditObjectBtn.setEnabled(False)
self.ClearAnnotationBtn.setEnabled(False)

def __edit_object(self):
print("Edit Object")
Expand Down Expand Up @@ -439,16 +448,18 @@ def msg_dialog(self, title, msg):

## Signal and Slot
def update_label_list_to_Display(self, label_list):
print(f"update_label_list: {label_list}")
# print(f"update_label_list: {label_list}")
self.label_list_manager.update(label_list)
self.Display.update_label_list_slot_receiver.emit(label_list)
self.ObjectLabelListWidget.label_list = label_list # Update the label list in the object list widget
self.ObjectLabelListWidget.refresh_list(label_list) # Update the label list in the object list widget
# self.ObjectLabelListWidget.label_list = label_list

def update_label_list_to_Label_Widget(self, label_list):
print(f"update_label_list: {label_list}")
# print(f"update_label_list: {label_list}")
self.label_list_manager.update(label_list)
self.LabelWidget.update_label_list_slot_receiver.emit(label_list)
self.ObjectLabelListWidget.label_list = label_list # Update the label list in the object list widget
self.ObjectLabelListWidget.refresh_list(label_list) # Update the label list in the object list widget
# self.ObjectLabelListWidget.label_list = label_list # Update the label list in the object list widget

def update_data_to_ObjectListWidget(self, data, action):
print(f"update_data_to_ObjectListWidget: {data}")
Expand Down

0 comments on commit 7dac6fa

Please sign in to comment.