From 2c4a24b6570d33c59b726dcda63c1b4dfe6cc7bb Mon Sep 17 00:00:00 2001
From: Daniel Kratzert <dkratzert@gmx.de>
Date: Sun, 26 Nov 2023 14:53:20 +0100
Subject: [PATCH] Adds edit button for edit fields

---
 finalcif/gui/custom_classes.py |  4 +--
 finalcif/gui/edit_button.py    | 66 ++++++++++++++++++++++++++++++++++
 finalcif/gui/plaintextedit.py  | 60 ++++++++++++++++++++++++++++---
 3 files changed, 124 insertions(+), 6 deletions(-)
 create mode 100644 finalcif/gui/edit_button.py

diff --git a/finalcif/gui/custom_classes.py b/finalcif/gui/custom_classes.py
index 541efc8c..0b34f716 100644
--- a/finalcif/gui/custom_classes.py
+++ b/finalcif/gui/custom_classes.py
@@ -11,12 +11,13 @@
 from finalcif.cif.text import retranslate_delimiter
 from finalcif.gui.combobox import MyComboBox
 from finalcif.gui.dialogs import show_keyword_help
+from finalcif.gui.edit_button import FloatingButtonWidget
 from finalcif.gui.mixins import ItemTextMixin
 from finalcif.gui.plaintextedit import MyQPlainTextEdit
 
 white = QColor(255, 255, 255)
 light_green = QColor(217, 255, 201)
-light_blue = QColor(220, 232, 247)
+light_blue = QColor(249, 249, 249)
 blue = QColor(102, 150, 179)
 yellow = QColor(250, 247, 150)  # #faf796
 
@@ -25,7 +26,6 @@ class Column(IntEnum):
     CIF = 0
     DATA = 1
     EDIT = 2
-    BUTTON = 3
 
 
 DEBUG = False
diff --git a/finalcif/gui/edit_button.py b/finalcif/gui/edit_button.py
new file mode 100644
index 00000000..26303bdf
--- /dev/null
+++ b/finalcif/gui/edit_button.py
@@ -0,0 +1,66 @@
+# Create a QTextedit widget with a button to open a file dialog
+# to select a file to be inserted into the QTextedit widget
+# The file dialog is opened by pressing the button.
+# The button should be placed above the QTextedit widget and appear on mouse over.
+
+from PyQt5 import QtWidgets, QtCore, QtGui
+import os
+import sys
+
+
+class FloatingButtonWidget(QtWidgets.QPushButton):
+    floatingButtonClicked = QtCore.pyqtSignal()
+
+    def __init__(self, parent=None, *args, **kwargs):
+        super().__init__(parent=parent, *args, **kwargs)
+        self.setText('edit')
+        self.paddingLeft = 2
+        self.paddingTop = 2
+        self.setFixedSize(24, 16)
+        self.setFlat(True)
+        self.setStyleSheet(f'''QPushButton {{background-color: {QtGui.QColor(220, 232, 247).name()};
+                                            padding-bottom: 1px;
+                                            border-radius: 5px; 
+                                            font-size: 11px; 
+                                            border: 1px solid {QtGui.QColor(170, 172, 177).name()};
+                                            }} 
+                                            ''')
+
+    def update_position(self):
+        """Update the position of the button to be placed in the bottom right corner of the parent widget.
+        """
+        self.move(self.parent().width() - self.width() - self.paddingLeft,
+                  self.parent().height() - self.height() - self.paddingTop)
+
+    def mousePressEvent(self, event):
+        self.floatingButtonClicked.emit()
+
+
+class OverlayTestEdit(QtWidgets.QTextEdit):
+
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self.edit_button = FloatingButtonWidget(parent=self)
+        # The button should be placed over the QTextedit widget as overlay and appear on mouse over.
+        self.edit_button.hide()
+        self.edit_button.update_position()
+
+    def resizeEvent(self, event):
+        self.edit_button.update_position()
+        super().resizeEvent(event)
+
+    def enterEvent(self, a0):
+        print('enter')
+        self.edit_button.show()
+
+    def leaveEvent(self, a0):
+        print('leave')
+        self.edit_button.hide()
+
+
+if __name__ == '__main__':
+    app = QtWidgets.QApplication(sys.argv)
+    window = OverlayTestEdit()
+    window.resize(130, 30)
+    window.show()
+    sys.exit(app.exec_())
diff --git a/finalcif/gui/plaintextedit.py b/finalcif/gui/plaintextedit.py
index c94c5f8d..f854b0b5 100644
--- a/finalcif/gui/plaintextedit.py
+++ b/finalcif/gui/plaintextedit.py
@@ -3,10 +3,13 @@
 from functools import cache
 from typing import TYPE_CHECKING
 
+from PyQt5 import QtCore
 from PyQt5.QtCore import pyqtSignal, Qt, QObject, QEvent, QSize
 from PyQt5.QtGui import QTextOption, QFontMetrics, QContextMenuEvent, QFont, QColor
 from PyQt5.QtWidgets import QPlainTextEdit, QFrame, QApplication, QAbstractScrollArea
+from numpy import random
 
+from finalcif.gui.edit_button import FloatingButtonWidget
 from finalcif.gui.new_key_dialog import NewKey
 
 if TYPE_CHECKING:
@@ -17,7 +20,6 @@ class Column(IntEnum):
     CIF = 0
     DATA = 1
     EDIT = 2
-    BUTTON = 3
 
 
 class MyQPlainTextEdit(QPlainTextEdit):
@@ -33,9 +35,9 @@ def __init__(self, parent=None, *args, **kwargs):
         """
         Plaintext edit field for most of the table cells.
         """
-        super().__init__(parent, *args, **kwargs)
-        self.setParent(parent)
+        super().__init__(parent=parent, *args, **kwargs)
         self.cif_key = ''
+        self.edit_button = None
         font = QFont()
         font.setPointSize(self.document().defaultFont().pointSize() + 1)
         self.setFont(font)
@@ -91,7 +93,11 @@ def copy_vhead_item(self, row):
 
     @property
     def row(self) -> int:
-        return self.parent.vheaderitems.index(self.cif_key)
+        return self.parent.indexAt(self.pos()).row()
+
+    @property
+    def column(self) -> int:
+        return self.parent.indexAt(self.pos()).column()
 
     def setBackground(self, color: QColor) -> None:
         """
@@ -126,6 +132,25 @@ def eventFilter(self, widget: QObject, event: QEvent):
             return True
         return QObject.eventFilter(self, widget, event)
 
+    def resizeEvent(self, event):
+        super().resizeEvent(event)
+        if self.edit_button and self.column == Column.EDIT:
+            self.edit_button.update_position()
+
+    def enterEvent(self, a0):
+        super().enterEvent(a0)
+        if self.column == Column.EDIT:
+            if not self.edit_button:
+                self.edit_button = FloatingButtonWidget(parent=self)
+                self.edit_button.floatingButtonClicked.connect(self._on_create_template)
+                self.edit_button.update_position()
+            self.edit_button.show()
+
+    def leaveEvent(self, a0):
+        super().leaveEvent(a0)
+        if self.edit_button and self.column == Column.EDIT:
+            self.edit_button.hide()
+
     def getText(self):
         return self.toPlainText()
 
@@ -198,3 +223,30 @@ def sizeHint(self) -> QSize:
             # Prevent extreme height for long text:
             size = QSize(100, 300)
         return size
+
+
+if __name__ == '__main__':
+    import sys
+    from PyQt5.QtWidgets import QApplication, QTableWidget, QTableWidgetItem
+
+    app = QApplication(sys.argv)
+    window = QTableWidget()
+    window.setColumnCount(3)
+    window.setRowCount(10)
+    # stretch the last table colum:
+    window.horizontalHeader().setStretchLastSection(True)
+    window.setHorizontalHeaderLabels(['CIF', 'Data', 'Edit'])
+    for row in range(10):
+        for col in range(3):
+            window.setCellWidget(row, col, MyQPlainTextEdit(window))
+            w = window.cellWidget(row, col)
+            if col == 2:
+                w.setText(f'Hello World {random.randint(0, 10000)} {random.randint(0, 10000)}')
+            w.setMinimumHeight(50)
+            w.setMinimumWidth(150)
+    window.resizeRowsToContents()
+    window.resizeColumnsToContents()
+    window.show()
+    window.setMinimumSize(600, 400)
+
+    sys.exit(app.exec_())