@@ -426,6 +426,34 @@ def start(self) -> None:
426426 clear_select_action .setToolTip ("Esc" )
427427 edit_menu .addAction (clear_select_action )
428428
429+ self .copy_buffer : dict = {"fields" : [], "tags" : []}
430+
431+ self .copy_fields_action = QAction (menu_bar )
432+ Translations .translate_qobject (self .copy_fields_action , "edit.copy_fields" )
433+ self .copy_fields_action .triggered .connect (self .copy_fields_action_callback )
434+ self .copy_fields_action .setShortcut (
435+ QtCore .QKeyCombination (
436+ QtCore .Qt .KeyboardModifier (QtCore .Qt .KeyboardModifier .ControlModifier ),
437+ QtCore .Qt .Key .Key_C ,
438+ )
439+ )
440+ self .copy_fields_action .setToolTip ("Ctrl+C" )
441+ self .copy_fields_action .setEnabled (False )
442+ edit_menu .addAction (self .copy_fields_action )
443+
444+ self .paste_fields_action = QAction (menu_bar )
445+ Translations .translate_qobject (self .paste_fields_action , "edit.paste_fields" )
446+ self .paste_fields_action .triggered .connect (self .paste_fields_action_callback )
447+ self .paste_fields_action .setShortcut (
448+ QtCore .QKeyCombination (
449+ QtCore .Qt .KeyboardModifier (QtCore .Qt .KeyboardModifier .ControlModifier ),
450+ QtCore .Qt .Key .Key_V ,
451+ )
452+ )
453+ self .paste_fields_action .setToolTip ("Ctrl+V" )
454+ self .paste_fields_action .setEnabled (False )
455+ edit_menu .addAction (self .paste_fields_action )
456+
429457 self .add_tag_to_selected_action = QAction (menu_bar )
430458 Translations .translate_qobject (
431459 self .add_tag_to_selected_action , "select.add_tag_to_selected"
@@ -814,7 +842,9 @@ def select_all_action_callback(self):
814842 item .thumb_button .set_selected (True )
815843
816844 self .set_macro_menu_viability ()
845+ self .set_clipboard_menu_viability ()
817846 self .set_add_to_selected_visibility ()
847+
818848 self .preview_panel .update_widgets (update_preview = False )
819849
820850 def clear_select_action_callback (self ):
@@ -824,6 +854,7 @@ def clear_select_action_callback(self):
824854 item .thumb_button .set_selected (False )
825855
826856 self .set_macro_menu_viability ()
857+ self .set_clipboard_menu_viability ()
827858 self .preview_panel .update_widgets ()
828859
829860 def add_tags_to_selected_callback (self , tag_ids : list [int ]):
@@ -1100,6 +1131,36 @@ def _init_thumb_grid(self):
11001131 sa .setWidgetResizable (True )
11011132 sa .setWidget (self .flow_container )
11021133
1134+ def copy_fields_action_callback (self ):
1135+ if len (self .selected ) > 0 :
1136+ entry = self .lib .get_entry_full (self .selected [0 ])
1137+ if entry :
1138+ self .copy_buffer ["fields" ] = entry .fields
1139+ self .copy_buffer ["tags" ] = [tag .id for tag in entry .tags ]
1140+ self .set_clipboard_menu_viability ()
1141+
1142+ def paste_fields_action_callback (self ):
1143+ for id in self .selected :
1144+ entry = self .lib .get_entry_full (id , with_fields = True , with_tags = False )
1145+ if not entry :
1146+ continue
1147+ existing_fields = entry .fields
1148+ for field in self .copy_buffer ["fields" ]:
1149+ exists = False
1150+ for e in existing_fields :
1151+ if field .type_key == e .type_key and field .value == e .value :
1152+ exists = True
1153+ if not exists :
1154+ self .lib .add_field_to_entry (id , field_id = field .type_key , value = field .value )
1155+ self .lib .add_tags_to_entry (id , self .copy_buffer ["tags" ])
1156+ if len (self .selected ) > 1 :
1157+ if TAG_ARCHIVED in self .copy_buffer ["tags" ]:
1158+ self .update_badges ({BadgeType .ARCHIVED : True }, origin_id = 0 , add_tags = False )
1159+ if TAG_FAVORITE in self .copy_buffer ["tags" ]:
1160+ self .update_badges ({BadgeType .FAVORITE : True }, origin_id = 0 , add_tags = False )
1161+ else :
1162+ self .preview_panel .update_widgets ()
1163+
11031164 def toggle_item_selection (self , item_id : int , append : bool , bridge : bool ):
11041165 """Toggle the selection of an item in the Thumbnail Grid.
11051166
@@ -1170,12 +1231,24 @@ def toggle_item_selection(self, item_id: int, append: bool, bridge: bool):
11701231 it .thumb_button .set_selected (False )
11711232
11721233 self .set_macro_menu_viability ()
1234+ self .set_clipboard_menu_viability ()
11731235 self .set_add_to_selected_visibility ()
1236+
11741237 self .preview_panel .update_widgets ()
11751238
11761239 def set_macro_menu_viability (self ):
11771240 self .autofill_action .setDisabled (not self .selected )
11781241
1242+ def set_clipboard_menu_viability (self ):
1243+ if len (self .selected ) == 1 :
1244+ self .copy_fields_action .setEnabled (True )
1245+ else :
1246+ self .copy_fields_action .setEnabled (False )
1247+ if self .selected and (self .copy_buffer ["fields" ] or self .copy_buffer ["tags" ]):
1248+ self .paste_fields_action .setEnabled (True )
1249+ else :
1250+ self .paste_fields_action .setEnabled (False )
1251+
11791252 def set_add_to_selected_visibility (self ):
11801253 if not self .add_tag_to_selected_action :
11811254 return
0 commit comments