PySide6Plot 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,259 @@
1
+ from qfluentwidgets import (
2
+ FluentIcon,
3
+ Action,
4
+ Flyout,
5
+ FlyoutAnimationType,
6
+ TableWidget,
7
+ CommandBarView,
8
+ TableItemDelegate,
9
+ )
10
+ from PySide6.QtWidgets import QTableView, QTableWidgetItem
11
+ from PySide6.QtCore import Qt, Signal, QEvent, QModelIndex
12
+ from PySide6.QtGui import QCursor
13
+ from PySide6.QtWidgets import QWidget, QStyleOptionViewItem
14
+
15
+
16
+ # https://forum.qt.io/topic/97628/qlistwidget-item-editing/13
17
+ class JEditableListStyledItemDelegate(TableItemDelegate):
18
+ # class variable for "editStarted" signal, with QModelIndex parameter
19
+ editStarted = Signal(QModelIndex, name="editStarted")
20
+ # class variable for "editFinished" signal, with QModelIndex parameter
21
+ editFinished = Signal(QModelIndex, name="editFinished")
22
+
23
+ def __init__(self, parent: QTableView):
24
+ super().__init__(parent)
25
+ self.edit_created = False
26
+
27
+ def createEditor(self, parent: QWidget, option: QStyleOptionViewItem, index: QModelIndex):
28
+ editor = super().createEditor(parent, option, index)
29
+ self.edit_created = True
30
+ if editor is not None:
31
+ self.editStarted.emit(index)
32
+ return editor
33
+
34
+ def destroyEditor(self, editor: QWidget, index: QModelIndex):
35
+ if self.edit_created:
36
+ self.editFinished.emit(index)
37
+ self.edit_created = False
38
+ return super().destroyEditor(editor, index)
39
+
40
+
41
+ class RemovableTable(TableWidget):
42
+ sigAcceptClicked = Signal(int)
43
+ sigRowClicked = Signal(int)
44
+ sigDeleteClicked = Signal(int)
45
+ sigMoveUpClicked = Signal(int)
46
+ sigMoveDownClicked = Signal(int)
47
+ sigNameEdited = Signal(int, str)
48
+
49
+ def __init__(
50
+ self,
51
+ parent=None,
52
+ show_row_index=False,
53
+ resize_columns_to_contents=True,
54
+ show_move_up_down_buttons=True,
55
+ show_delete_button=True,
56
+ show_rename_button=True,
57
+ accept_name="Select",
58
+ accept_icon=FluentIcon.ACCEPT,
59
+ link_default_slot=True,
60
+ ):
61
+ super().__init__(parent)
62
+ self.setBorderVisible(True)
63
+ self.setBorderRadius(8)
64
+ self.setWordWrap(False)
65
+ self.viewport().installEventFilter(self)
66
+ styledItemDelegate = JEditableListStyledItemDelegate(self)
67
+ styledItemDelegate.editFinished.connect(self.__on_name_changed)
68
+ self.setItemDelegate(styledItemDelegate)
69
+ self.current_item = None
70
+ self.show_row_index = show_row_index
71
+ self.resize_columns_to_contents = resize_columns_to_contents
72
+ self.show_move_up_down_buttons = show_move_up_down_buttons
73
+ self.show_delete_button = show_delete_button
74
+ self.show_rename_button = show_rename_button
75
+ self.accept_name = accept_name
76
+ self.accept_icon = accept_icon
77
+ self.act_from_self = False
78
+ if not self.show_row_index:
79
+ self.verticalHeader().hide()
80
+ if link_default_slot:
81
+ self.sigAcceptClicked.connect(self.accept_row_data)
82
+ self.sigDeleteClicked.connect(self.delete_row_data)
83
+ self.sigMoveUpClicked.connect(self.move_up_row_data)
84
+ self.sigMoveDownClicked.connect(self.move_down_row_data)
85
+
86
+ def show_menu_bar(self):
87
+ """
88
+ Show the menu bar with various actions such as accept, rename, move up, move down, and delete.
89
+ NOTE: Must specify the current item before calling this method.
90
+ """
91
+ self.command_bar = CommandBarView(self)
92
+ select_action = Action(self.accept_icon, self.accept_name)
93
+ select_action.triggered.connect(self.__on_accept_clicked)
94
+ self.command_bar.addAction(select_action)
95
+ if self.show_rename_button:
96
+ edit_action = Action(FluentIcon.FONT, "Rename")
97
+ edit_action.triggered.connect(self.__on_edit_row_clicked)
98
+ self.command_bar.addAction(edit_action)
99
+ if self.show_move_up_down_buttons:
100
+ if self.current_item.row() > 0:
101
+ move_up_action = Action(FluentIcon.UP, "Move up")
102
+ move_up_action.triggered.connect(self.__on_move_up_row_clicked)
103
+ self.command_bar.addAction(move_up_action)
104
+ if self.current_item.row() < self.rowCount() - 1:
105
+ move_down_action = Action(FluentIcon.DOWN, "Move down")
106
+ move_down_action.triggered.connect(self.__on_move_down_row_clicked)
107
+ self.command_bar.addAction(move_down_action)
108
+ if self.show_delete_button:
109
+ delete_action = Action(FluentIcon.DELETE, "Delete")
110
+ delete_action.triggered.connect(self.__on_delete_row_clicked)
111
+ self.command_bar.addAction(delete_action)
112
+ self.command_bar.resizeToSuitableWidth()
113
+ self.shown_cbar = Flyout.make(self.command_bar, QCursor.pos(), self, FlyoutAnimationType.FADE_IN, True)
114
+
115
+ def accept_row_data(self, row_index):
116
+ pass
117
+
118
+ def __on_accept_clicked(self):
119
+ if self.current_item is not None:
120
+ self.clearSelection()
121
+ self.shown_cbar.close()
122
+ self.sigAcceptClicked.emit(self.current_item.row())
123
+ self.current_item = None
124
+
125
+ def delete_row_data(self, row_index):
126
+ """
127
+ Delete a row of data from the table.
128
+
129
+ Args:
130
+ row_index (int): The index of the row to be deleted.
131
+ """
132
+ self.removeRow(row_index)
133
+
134
+ def __on_delete_row_clicked(self):
135
+ if self.current_item is not None:
136
+ self.clearSelection()
137
+ self.shown_cbar.close()
138
+ self.sigDeleteClicked.emit(self.current_item.row())
139
+ self.current_item = None
140
+
141
+ def move_up_row_data(self, row_index):
142
+ """
143
+ Moves the data in the specified row up by one row.
144
+
145
+ Args:
146
+ row_index (int): The index of the row to move up.
147
+
148
+ Returns:
149
+ None
150
+ """
151
+ for j in range(self.columnCount()):
152
+ temple = self.item(row_index, j).text()
153
+ self.item(row_index, j).setText(self.item(row_index - 1, j).text())
154
+ self.item(row_index - 1, j).setText(temple)
155
+
156
+ def __on_move_up_row_clicked(self):
157
+ if self.current_item is not None:
158
+ self.clearSelection()
159
+ self.shown_cbar.close()
160
+ self.sigMoveUpClicked.emit(self.current_item.row())
161
+ self.current_item = None
162
+
163
+ def move_down_row_data(self, row_index, mute_signal=False):
164
+ """
165
+ Move the data in the specified row down by one row.
166
+
167
+ Args:
168
+ row_index (int): The index of the row to move down.
169
+ mute_signal (bool, optional): Whether to mute the signal emitted during the move. Defaults to False.
170
+ """
171
+ for j in range(self.columnCount()):
172
+ temple = self.item(row_index, j).text()
173
+ self.item(row_index, j).setText(self.item(row_index + 1, j).text())
174
+ self.item(row_index + 1, j).setText(temple)
175
+
176
+ def __on_move_down_row_clicked(self):
177
+ if self.current_item is not None:
178
+ self.clearSelection()
179
+ self.shown_cbar.close()
180
+ self.sigMoveDownClicked.emit(self.current_item.row())
181
+ self.current_item = None
182
+
183
+ def rename(self, row_index):
184
+ self.editItem(self.item(row_index, 0))
185
+
186
+ def __on_edit_row_clicked(self):
187
+ if self.current_item is not None:
188
+ self.rename(self.current_item.row())
189
+ self.shown_cbar.close()
190
+
191
+ def __on_name_changed(self, index):
192
+ self.sigNameEdited.emit(index.row(), index.data())
193
+
194
+ def set_header_labels(self, labels):
195
+ """
196
+ Set the header labels for the table.
197
+
198
+ Args:
199
+ labels (list): A list of strings representing the header labels.
200
+
201
+ Returns:
202
+ None
203
+ """
204
+ self.setColumnCount(len(labels))
205
+ self.setHorizontalHeaderLabels(labels)
206
+ if self.resize_columns_to_contents:
207
+ self.resizeColumnsToContents()
208
+
209
+ def set_row_data_item(self, row_index, col_index, item):
210
+ """
211
+ Sets the data item for a specific row and column in the table.
212
+
213
+ Parameters:
214
+ row_index (int): The index of the row.
215
+ col_index (int): The index of the column.
216
+ item (QWidget or any): The item to be set in the table.
217
+
218
+ Returns:
219
+ None
220
+ """
221
+ if isinstance(item, QWidget):
222
+ item_text = " "
223
+ self.setItem(row_index, col_index, QTableWidgetItem(item_text))
224
+ self.setCellWidget(row_index, col_index, item)
225
+ else:
226
+ item = QTableWidgetItem(str(item))
227
+ if col_index != 0:
228
+ item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsEditable)
229
+ self.setItem(row_index, col_index, item)
230
+
231
+ def add_row_data(self, data_i):
232
+ """
233
+ Add a new row to the table and populate it with the given data.
234
+
235
+ Args:
236
+ data_i (list): The data to be added to the new row.
237
+
238
+ Returns:
239
+ None
240
+ """
241
+ row_count = self.rowCount()
242
+ self.setRowCount(row_count + 1)
243
+ for j, content in enumerate(data_i):
244
+ self.set_row_data_item(row_count, j, content)
245
+ if self.resize_columns_to_contents:
246
+ self.resizeColumnsToContents()
247
+
248
+ def eventFilter(self, source, event):
249
+ if event.type() == QEvent.Type.MouseButtonPress:
250
+ item = self.itemAt(event.pos())
251
+ if item is not None:
252
+ self.current_item = item
253
+ self.clearSelection()
254
+ self.selectRow(self.current_item.row())
255
+ if event.button() == Qt.MouseButton.LeftButton:
256
+ self.sigRowClicked.emit(self.current_item.row())
257
+ elif event.button() == Qt.MouseButton.RightButton:
258
+ self.show_menu_bar()
259
+ return super().eventFilter(source, event)
@@ -0,0 +1,69 @@
1
+ from PySide6.QtCore import QEvent, QObject
2
+ from qfluentwidgets import TransparentPushButton, LineEdit
3
+ from PySide6.QtWidgets import QWidget, QVBoxLayout
4
+ from PySide6.QtCore import Signal, Qt
5
+
6
+
7
+ class TransparentLineEdit(QWidget):
8
+ sigTextEditFinished = Signal()
9
+
10
+ def __init__(self, parent=None):
11
+ super().__init__(parent=parent)
12
+ self.main_layout = QVBoxLayout()
13
+ self.main_layout.setContentsMargins(0, 0, 0, 0)
14
+ self.main_layout.setSpacing(0)
15
+ self.line_edit = LineEdit(parent=self)
16
+ self.push_button = TransparentPushButton(parent=self)
17
+ self.main_layout.addWidget(self.line_edit)
18
+ self.main_layout.addWidget(self.push_button)
19
+ self.line_edit.setVisible(False)
20
+ self.setLayout(self.main_layout)
21
+ self.push_button.clicked.connect(self.__show_line_edit)
22
+ self.line_edit.installEventFilter(self)
23
+
24
+ def set_text(self, text):
25
+ self.line_edit.setText(text)
26
+ self.push_button.setText(text)
27
+
28
+ def get_text(self):
29
+ return self.line_edit.text()
30
+
31
+ def __show_line_edit(self):
32
+ self.push_button.setVisible(False)
33
+ self.line_edit.setVisible(True)
34
+ self.line_edit.setFocus()
35
+
36
+ def __finish_edit(self):
37
+ self.sigTextEditFinished.emit()
38
+ self.push_button.setText(self.line_edit.text())
39
+ self.line_edit.setVisible(False)
40
+ self.push_button.setVisible(True)
41
+
42
+ def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
43
+ if a0 == self.line_edit:
44
+ if a1.type() == QEvent.Type.FocusOut:
45
+ self.__finish_edit()
46
+ return False
47
+ if a1.type() == QEvent.Type.KeyPress:
48
+ if a1.key() in (Qt.Key.Key_Enter, Qt.Key.Key_Return):
49
+ self.__finish_edit()
50
+ return False
51
+ elif a1.key() == Qt.Key.Key_Escape:
52
+ self.line_edit.setVisible(False)
53
+ self.push_button.setVisible(True)
54
+ return False
55
+ return super().eventFilter(a0, a1)
56
+
57
+
58
+ if __name__ == "__main__":
59
+ from PySide6.QtWidgets import QApplication
60
+ import sys
61
+
62
+ if __name__ == "__main__":
63
+ app = QApplication(sys.argv)
64
+ window = QWidget()
65
+ widget = TransparentLineEdit()
66
+ window.setLayout(QVBoxLayout())
67
+ window.layout().addWidget(widget)
68
+ window.show()
69
+ sys.exit(app.exec())
@@ -0,0 +1,208 @@
1
+ from qfluentwidgets import (
2
+ TransparentDropDownPushButton,
3
+ Action,
4
+ FluentIcon,
5
+ CheckableMenu,
6
+ ColorDialog,
7
+ MenuIndicatorType,
8
+ )
9
+ from qfluentwidgets.common.icon import toQIcon
10
+ from PySide6.QtGui import QColor, QPixmap, QIcon
11
+ from PySide6.QtCore import Signal
12
+ from PySide6.QtWidgets import QApplication
13
+ import sys
14
+
15
+ TRADITIONAL_COLORS = {
16
+ "Black": QColor(45, 45, 45),
17
+ "White": QColor(255, 255, 255),
18
+ "Red": QColor(255, 0, 0),
19
+ "Green": QColor(0, 255, 0),
20
+ "Blue": QColor(0, 0, 255),
21
+ "Yellow": QColor(255, 255, 0),
22
+ "Cyan": QColor(0, 255, 255),
23
+ "Magenta": QColor(255, 0, 255),
24
+ "Gray": QColor(128, 128, 128),
25
+ "Dark gray": QColor(64, 64, 64),
26
+ "Light gray": QColor(192, 192, 192),
27
+ "Orange": QColor(255, 165, 0),
28
+ "Purple": QColor(128, 0, 128),
29
+ "Brown": QColor(165, 42, 42),
30
+ }
31
+
32
+ SCIENTIFIC_COLORS = {
33
+ "Black": QColor(0, 0, 0),
34
+ "Red": QColor("#FF1F5B"),
35
+ "Blue": QColor("#009ADE"),
36
+ "Yellow": QColor("#FFC61E"),
37
+ "Purple": QColor("#AF58BA"),
38
+ "Orange": QColor("#F28522"),
39
+ "Green": QColor("#00CD6C"),
40
+ "Brown": QColor("#A6761D"),
41
+ }
42
+
43
+ DEFAULT_LINE_WIDTHS = {
44
+ "0.25 pt": 0.25 * 2,
45
+ "0.5 pt": 0.5 * 2,
46
+ "0.75 pt": 0.75 * 2,
47
+ "1 pt": 1 * 2,
48
+ "1.5 pt": 1.5 * 2,
49
+ "2.25 pt": 2.25 * 2,
50
+ "3 pt": 3 * 2,
51
+ "4.5 pt": 4.5 * 2,
52
+ "6 pt": 6 * 2,
53
+ }
54
+
55
+ DEFAULT_DASH_TYPE = {
56
+ "——————": [],
57
+ "—— —— ": [5, 5],
58
+ "⋅⋅⋅⋅⋅⋅⋅⋅": [1, 1],
59
+ "- ⋅ ": [3, 5, 1, 5],
60
+ "- ⋅ ⋅": [3, 5, 1, 5, 1, 5],
61
+ "———— ": [10, 3],
62
+ "—— ": [5, 10],
63
+ "- ⋅": [3, 10, 1, 10],
64
+ "- ⋅ ⋅": [3, 10, 1, 10, 1, 10],
65
+ "- ⋅ ⋅": [3, 1, 1, 1, 1, 1],
66
+ }
67
+
68
+
69
+ class TransparentSelector(TransparentDropDownPushButton):
70
+ item_selected = Signal(str)
71
+
72
+ def __init__(self, items: dict, allow_custom=True, default_index=0, *args, **kwargs):
73
+ super().__init__(*args, **kwargs)
74
+ self.allow_custom = allow_custom
75
+ self.items = items
76
+ self.item_menu_actions = []
77
+
78
+ def generate_item_select_action(item_name):
79
+ item_action = Action(item_name)
80
+ item_action.setCheckable(True)
81
+ item_action.setChecked(False)
82
+ item_action.triggered.connect(lambda: self.on_item_menu_action_clicked(item_action))
83
+ return item_action
84
+
85
+ self.item_menu_actions = [
86
+ {"name": item_name, "value": value, "action": generate_item_select_action(item_name)}
87
+ for item_name, value in self.items.items()
88
+ ]
89
+ if self.allow_custom:
90
+ self.customized_item = None
91
+ self.item_menu_actions.append(
92
+ {
93
+ "name": "customized",
94
+ "value": self.customized_item,
95
+ "action": generate_item_select_action("customized"),
96
+ }
97
+ )
98
+ self.item_menu_actions[default_index]["action"].setChecked(True)
99
+ self.current_item = self.item_menu_actions[default_index]["value"]
100
+ self.default_item = self.item_menu_actions[default_index]["value"]
101
+ self.item_menu = CheckableMenu(indicatorType=MenuIndicatorType.RADIO)
102
+ self.item_menu.addActions([item["action"] for item in self.item_menu_actions])
103
+ self.setMenu(self.item_menu)
104
+ self.setText(self.item_menu_actions[default_index]["action"].text())
105
+
106
+ def on_item_menu_action_clicked(self, action, emit=True):
107
+ if self.allow_custom and action.text() == "customized":
108
+ if self.get_custom_item():
109
+ self.current_item = self.customized_item
110
+ else:
111
+ self.set_item(self.current_item)
112
+ return False
113
+ else:
114
+ self.current_item = self.items[action.text()]
115
+ self.setText(action.text())
116
+ if emit:
117
+ self.item_selected.emit(action.text())
118
+ for other_action in self.item_menu_actions:
119
+ other_action["action"].setChecked(False)
120
+ action.setChecked(True)
121
+ return True
122
+
123
+ def set_item(self, item):
124
+ for action in self.item_menu_actions:
125
+ if action["value"] == item:
126
+ self.on_item_menu_action_clicked(action["action"], emit=False)
127
+ return 0
128
+ if self.allow_custom:
129
+ self.customized_item = item
130
+ self.current_item = item
131
+ action = self.item_menu_actions[-1]["action"]
132
+ self.setText(action.text())
133
+ for other_action in self.item_menu_actions:
134
+ other_action["action"].setChecked(False)
135
+ action.setChecked(True)
136
+ return 1
137
+ else:
138
+ raise ValueError("No such item in the menu")
139
+
140
+ def get_value(self, selected_text):
141
+ for action in self.item_menu_actions:
142
+ if action["name"] == selected_text:
143
+ return action["value"]
144
+ raise ValueError("No such item in the menu")
145
+
146
+ def get_custom_item(self):
147
+ return True
148
+
149
+
150
+ class TransparentColorSelector(TransparentSelector):
151
+ def __init__(self, color_icon_width=24, color_icon_height=8, colors=SCIENTIFIC_COLORS, *args, **kwargs):
152
+ super().__init__(*args, items=colors, allow_custom=True, **kwargs)
153
+ self.color_icon_width = color_icon_width
154
+ self.color_icon_height = color_icon_height
155
+ for action in self.item_menu_actions[0:-1]:
156
+ action["action"].setIcon(self.__color_icon(colors[action["name"]]))
157
+ self.item_menu_actions[-1]["action"].setIcon(toQIcon(FluentIcon.PALETTE))
158
+ self.setIcon(self.__color_icon(self.current_item))
159
+
160
+ def on_item_menu_action_clicked(self, action, emit=True):
161
+ re = super().on_item_menu_action_clicked(action, emit)
162
+ if re:
163
+ self.setIcon(action.icon())
164
+ return re
165
+
166
+ def __color_icon(self, color):
167
+ pixmap = QPixmap(self.color_icon_width, self.color_icon_height)
168
+ pixmap.fill(color)
169
+ return QIcon(pixmap)
170
+
171
+ def set_item(self, item):
172
+ re = super().set_item(item)
173
+ if re == 1:
174
+ icon = toQIcon(self.__color_icon(item))
175
+ self.setIcon(icon)
176
+ self.item_menu_actions[-1]["action"].setIcon(icon)
177
+ return re
178
+
179
+ def get_custom_item(self):
180
+ if self.customized_item is not None:
181
+ default_color = self.customized_item
182
+ else:
183
+ default_color = self.current_item
184
+ w = ColorDialog(default_color, "Select Color", self.window())
185
+ if w.exec():
186
+ self.customized_item = w.color
187
+ self.item_menu_actions[-1]["value"] = self.customized_item
188
+ self.item_menu_actions[-1]["action"].setIcon(self.__color_icon(self.customized_item))
189
+ return True
190
+ else:
191
+ return False
192
+
193
+
194
+ class TransparentLineWidthSelector(TransparentSelector):
195
+ def __init__(self, *args, **kwargs):
196
+ super().__init__(*args, items=DEFAULT_LINE_WIDTHS, default_index=3, allow_custom=False, **kwargs)
197
+
198
+
199
+ class TransparentDashTypeSelector(TransparentSelector):
200
+ def __init__(self, *args, **kwargs):
201
+ super().__init__(*args, items=DEFAULT_DASH_TYPE, default_index=0, allow_custom=False, **kwargs)
202
+
203
+
204
+ if __name__ == "__main__":
205
+ app = QApplication(sys.argv)
206
+ widget = TransparentColorSelector()
207
+ widget.show()
208
+ sys.exit(app.exec())