2022-02-27 12:14:47 +13:00
|
|
|
import re
|
2022-03-10 08:47:52 +13:00
|
|
|
import shutil
|
2022-02-27 12:14:47 +13:00
|
|
|
from logging import getLogger
|
2023-08-22 05:33:27 +12:00
|
|
|
from typing import Dict, Optional
|
2022-02-27 12:14:47 +13:00
|
|
|
|
2023-02-19 06:36:49 +13:00
|
|
|
from PyQt5.QtCore import pyqtSignal, QSettings, QSize, Qt, QMimeData, pyqtSlot, QCoreApplication
|
2023-08-17 05:55:41 +12:00
|
|
|
from PyQt5.QtGui import QDrag, QDropEvent, QDragEnterEvent, QDragMoveEvent, QFont, QMouseEvent
|
2023-02-19 06:36:49 +13:00
|
|
|
from PyQt5.QtWidgets import (
|
|
|
|
QHBoxLayout,
|
|
|
|
QLabel,
|
|
|
|
QInputDialog,
|
|
|
|
QFrame,
|
|
|
|
QMessageBox,
|
|
|
|
QSizePolicy,
|
|
|
|
QWidget,
|
|
|
|
QScrollArea,
|
2023-08-22 05:22:54 +12:00
|
|
|
QAction,
|
|
|
|
QToolButton,
|
|
|
|
QMenu,
|
2023-02-19 06:36:49 +13:00
|
|
|
)
|
|
|
|
|
|
|
|
from rare.shared import RareCore
|
2022-03-19 05:03:14 +13:00
|
|
|
from rare.ui.components.tabs.settings.widgets.wrapper import Ui_WrapperSettings
|
2022-02-27 12:14:47 +13:00
|
|
|
from rare.utils import config_helper
|
2022-07-27 02:58:17 +12:00
|
|
|
from rare.utils.misc import icon
|
2022-02-27 12:14:47 +13:00
|
|
|
|
2023-02-19 06:36:49 +13:00
|
|
|
logger = getLogger("WrapperSettings")
|
2022-02-27 12:14:47 +13:00
|
|
|
|
|
|
|
extra_wrapper_regex = {
|
|
|
|
"proton": "\".*proton\" run", # proton
|
|
|
|
"mangohud": "mangohud" # mangohud
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-08-14 01:35:22 +12:00
|
|
|
class Wrapper:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2022-03-02 10:20:45 +13:00
|
|
|
class WrapperWidget(QFrame):
|
2023-08-17 21:33:49 +12:00
|
|
|
update_wrapper = pyqtSignal(str, str)
|
2022-02-27 12:14:47 +13:00
|
|
|
delete_wrapper = pyqtSignal(str)
|
|
|
|
|
2022-03-14 05:20:55 +13:00
|
|
|
def __init__(self, text: str, show_text=None, parent=None):
|
2022-03-12 11:08:36 +13:00
|
|
|
super(WrapperWidget, self).__init__(parent=parent)
|
2022-03-14 05:20:55 +13:00
|
|
|
if not show_text:
|
2023-08-17 21:33:49 +12:00
|
|
|
show_text = text.split()[0]
|
2022-03-14 05:20:55 +13:00
|
|
|
|
2022-03-20 03:32:46 +13:00
|
|
|
self.setFrameShape(QFrame.StyledPanel)
|
|
|
|
self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
|
|
|
|
|
2022-02-27 12:14:47 +13:00
|
|
|
self.text = text
|
2023-08-21 09:59:10 +12:00
|
|
|
self.setToolTip(text)
|
2023-08-22 05:22:54 +12:00
|
|
|
|
|
|
|
unmanaged = show_text in extra_wrapper_regex.keys()
|
|
|
|
|
|
|
|
text_lbl = QLabel(show_text, parent=self)
|
|
|
|
text_lbl.setFont(QFont("monospace"))
|
|
|
|
text_lbl.setDisabled(unmanaged)
|
|
|
|
|
|
|
|
image_lbl = QLabel(parent=self)
|
|
|
|
image_lbl.setPixmap(icon("mdi.drag-vertical").pixmap(QSize(20, 20)))
|
|
|
|
|
|
|
|
edit_action = QAction("Edit", parent=self)
|
|
|
|
edit_action.triggered.connect(self.__edit)
|
|
|
|
delete_action = QAction("Delete", parent=self)
|
|
|
|
delete_action.triggered.connect(self.__delete)
|
|
|
|
|
|
|
|
manage_menu = QMenu(parent=self)
|
|
|
|
manage_menu.addActions([edit_action, delete_action])
|
|
|
|
|
|
|
|
manage_button = QToolButton(parent=self)
|
|
|
|
manage_button.setIcon(icon("mdi.menu"))
|
|
|
|
manage_button.setMenu(manage_menu)
|
|
|
|
manage_button.setPopupMode(QToolButton.InstantPopup)
|
|
|
|
manage_button.setDisabled(unmanaged)
|
|
|
|
if unmanaged:
|
|
|
|
manage_button.setToolTip(self.tr("Manage through settings"))
|
2023-08-17 05:55:41 +12:00
|
|
|
else:
|
2023-08-22 05:22:54 +12:00
|
|
|
manage_button.setToolTip(self.tr("Manage"))
|
2022-02-27 12:14:47 +13:00
|
|
|
|
2023-08-17 05:55:41 +12:00
|
|
|
layout = QHBoxLayout(self)
|
2022-03-20 03:32:46 +13:00
|
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
2023-08-22 05:22:54 +12:00
|
|
|
layout.addWidget(image_lbl)
|
|
|
|
layout.addWidget(text_lbl)
|
|
|
|
layout.addWidget(manage_button)
|
2022-03-20 03:32:46 +13:00
|
|
|
self.setLayout(layout)
|
|
|
|
|
|
|
|
# lk: set object names for the stylesheet
|
|
|
|
self.setObjectName(type(self).__name__)
|
2023-08-22 05:22:54 +12:00
|
|
|
manage_button.setObjectName(f"{self.objectName()}Button")
|
2022-03-10 08:47:52 +13:00
|
|
|
|
2023-08-21 09:59:10 +12:00
|
|
|
@pyqtSlot()
|
|
|
|
def __delete(self):
|
2022-02-27 12:14:47 +13:00
|
|
|
self.delete_wrapper.emit(self.text)
|
|
|
|
|
2023-08-21 09:59:10 +12:00
|
|
|
def __edit(self) -> None:
|
|
|
|
dialog = QInputDialog(self)
|
|
|
|
dialog.setWindowTitle(f"{self.tr('Edit wrapper')} - {QCoreApplication.instance().applicationName()}")
|
|
|
|
dialog.setLabelText(self.tr("Edit wrapper command"))
|
|
|
|
dialog.setTextValue(self.text)
|
|
|
|
accepted = dialog.exec()
|
|
|
|
wrapper = dialog.textValue()
|
|
|
|
dialog.deleteLater()
|
2023-08-22 05:22:54 +12:00
|
|
|
if accepted and wrapper:
|
2023-08-21 09:59:10 +12:00
|
|
|
self.update_wrapper.emit(self.text, wrapper)
|
|
|
|
|
2023-08-17 21:33:49 +12:00
|
|
|
def mouseMoveEvent(self, a0: QMouseEvent) -> None:
|
|
|
|
if a0.buttons() == Qt.LeftButton:
|
|
|
|
a0.accept()
|
2022-03-10 08:47:52 +13:00
|
|
|
drag = QDrag(self)
|
|
|
|
mime = QMimeData()
|
|
|
|
drag.setMimeData(mime)
|
|
|
|
drag.exec_(Qt.MoveAction)
|
|
|
|
|
2022-02-27 12:14:47 +13:00
|
|
|
|
2023-08-22 05:33:27 +12:00
|
|
|
class WrapperSettings(QWidget):
|
2022-02-27 12:14:47 +13:00
|
|
|
def __init__(self):
|
2022-03-10 08:47:52 +13:00
|
|
|
super(WrapperSettings, self).__init__()
|
2023-08-22 05:33:27 +12:00
|
|
|
self.ui = Ui_WrapperSettings()
|
|
|
|
self.ui.setupUi(self)
|
2022-03-20 03:32:46 +13:00
|
|
|
|
2023-01-29 23:50:37 +13:00
|
|
|
self.wrappers: Dict[str, WrapperWidget] = {}
|
2023-08-22 05:33:27 +12:00
|
|
|
self.app_name: str = "default"
|
2023-01-29 23:50:37 +13:00
|
|
|
|
2023-08-22 05:33:27 +12:00
|
|
|
self.wrapper_scroll = QScrollArea(self.ui.widget_stack)
|
2022-03-20 03:32:46 +13:00
|
|
|
self.wrapper_scroll.setWidgetResizable(True)
|
|
|
|
self.wrapper_scroll.setSizeAdjustPolicy(QScrollArea.AdjustToContents)
|
|
|
|
self.wrapper_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
|
|
self.wrapper_scroll.setProperty("no_kinetic_scroll", True)
|
2022-03-12 11:08:36 +13:00
|
|
|
self.scroll_content = WrapperContainer(
|
2022-03-20 03:32:46 +13:00
|
|
|
save_cb=self.save, parent=self.wrapper_scroll
|
2022-03-14 05:20:55 +13:00
|
|
|
)
|
2022-03-20 03:32:46 +13:00
|
|
|
self.wrapper_scroll.setWidget(self.scroll_content)
|
2023-08-22 05:33:27 +12:00
|
|
|
self.ui.widget_stack.insertWidget(0, self.wrapper_scroll)
|
2022-03-10 08:47:52 +13:00
|
|
|
|
2023-02-19 06:36:49 +13:00
|
|
|
self.core = RareCore.instance().core()
|
2022-02-27 12:14:47 +13:00
|
|
|
|
2023-08-22 05:33:27 +12:00
|
|
|
self.ui.add_button.clicked.connect(self.add_button_pressed)
|
2022-03-07 07:48:35 +13:00
|
|
|
self.settings = QSettings()
|
2022-02-27 12:14:47 +13:00
|
|
|
|
2022-03-20 03:32:46 +13:00
|
|
|
self.wrapper_scroll.horizontalScrollBar().rangeChanged.connect(self.adjust_scrollarea)
|
|
|
|
|
|
|
|
# lk: set object names for the stylesheet
|
|
|
|
self.setObjectName(type(self).__name__)
|
2023-08-22 05:33:27 +12:00
|
|
|
self.ui.no_wrapper_label.setObjectName(f"{self.objectName()}Label")
|
2022-03-20 03:32:46 +13:00
|
|
|
self.wrapper_scroll.setObjectName(f"{self.objectName()}Scroll")
|
|
|
|
self.wrapper_scroll.horizontalScrollBar().setObjectName(
|
|
|
|
f"{self.wrapper_scroll.objectName()}Bar")
|
|
|
|
self.wrapper_scroll.verticalScrollBar().setObjectName(
|
|
|
|
f"{self.wrapper_scroll.objectName()}Bar")
|
|
|
|
|
|
|
|
@pyqtSlot(int, int)
|
|
|
|
def adjust_scrollarea(self, min: int, max: int):
|
2023-01-29 23:50:37 +13:00
|
|
|
wrapper_widget = self.scroll_content.findChild(WrapperWidget)
|
|
|
|
if not wrapper_widget:
|
|
|
|
return
|
2022-03-20 03:32:46 +13:00
|
|
|
# lk: when the scrollbar is not visible, min and max are 0
|
|
|
|
if max > min:
|
|
|
|
self.wrapper_scroll.setMaximumHeight(
|
|
|
|
wrapper_widget.sizeHint().height()
|
|
|
|
+ self.wrapper_scroll.rect().height() // 2
|
|
|
|
- self.wrapper_scroll.contentsRect().height() // 2
|
|
|
|
+ self.scroll_content.layout().spacing()
|
|
|
|
+ self.wrapper_scroll.horizontalScrollBar().sizeHint().height()
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self.wrapper_scroll.setMaximumHeight(
|
|
|
|
wrapper_widget.sizeHint().height()
|
|
|
|
+ self.wrapper_scroll.rect().height()
|
|
|
|
- self.wrapper_scroll.contentsRect().height()
|
|
|
|
)
|
2022-03-10 08:47:52 +13:00
|
|
|
|
2022-02-27 12:14:47 +13:00
|
|
|
def get_wrapper_string(self):
|
2022-03-07 07:48:35 +13:00
|
|
|
return " ".join(self.get_wrapper_list())
|
|
|
|
|
|
|
|
def get_wrapper_list(self):
|
2023-08-14 01:35:22 +12:00
|
|
|
wrappers = list(self.wrappers.values())
|
|
|
|
wrappers.sort(key=lambda x: self.scroll_content.layout().indexOf(x))
|
|
|
|
return [w.text for w in wrappers]
|
2022-02-27 12:14:47 +13:00
|
|
|
|
|
|
|
def add_button_pressed(self):
|
2023-08-17 21:33:49 +12:00
|
|
|
dialog = QInputDialog(self)
|
|
|
|
dialog.setWindowTitle(f"{self.tr('Add wrapper')} - {QCoreApplication.instance().applicationName()}")
|
|
|
|
dialog.setLabelText(self.tr("Enter wrapper command"))
|
|
|
|
accepted = dialog.exec()
|
|
|
|
wrapper = dialog.textValue()
|
|
|
|
dialog.deleteLater()
|
|
|
|
if accepted:
|
|
|
|
self.add_wrapper(wrapper)
|
|
|
|
|
|
|
|
def add_wrapper(self, text: str, position: int = -1, from_load: bool = False):
|
2022-03-14 05:20:55 +13:00
|
|
|
if text == "mangohud" and self.wrappers.get("mangohud"):
|
|
|
|
return
|
2023-08-17 05:55:41 +12:00
|
|
|
show_text = ""
|
2022-02-27 12:14:47 +13:00
|
|
|
for key, extra_wrapper in extra_wrapper_regex.items():
|
|
|
|
if re.match(extra_wrapper, text):
|
2022-03-14 05:20:55 +13:00
|
|
|
show_text = key
|
2023-08-17 05:55:41 +12:00
|
|
|
if not show_text:
|
|
|
|
show_text = text.split()[0]
|
2022-03-10 08:47:52 +13:00
|
|
|
|
|
|
|
# validate
|
|
|
|
if not text.strip(): # is empty
|
2022-03-02 10:20:45 +13:00
|
|
|
return
|
2022-03-10 08:47:52 +13:00
|
|
|
if not from_load:
|
|
|
|
if self.wrappers.get(text):
|
2023-08-17 05:55:41 +12:00
|
|
|
QMessageBox.warning(
|
2023-08-23 05:57:54 +12:00
|
|
|
self, self.tr("Warning"), self.tr("Wrapper <b>{0}</b> is already in the list").format(text)
|
2023-08-17 05:55:41 +12:00
|
|
|
)
|
2022-03-10 08:47:52 +13:00
|
|
|
return
|
|
|
|
|
2022-03-14 05:20:55 +13:00
|
|
|
if show_text != "proton" and not shutil.which(text.split()[0]):
|
2023-08-23 05:57:54 +12:00
|
|
|
if (
|
|
|
|
QMessageBox.question(
|
|
|
|
self,
|
|
|
|
self.tr("Warning"),
|
|
|
|
self.tr("Wrapper <b>{0}</b> is not in $PATH. Add it anyway?").format(show_text),
|
|
|
|
QMessageBox.Yes | QMessageBox.No,
|
|
|
|
QMessageBox.No,
|
|
|
|
)
|
|
|
|
== QMessageBox.No
|
|
|
|
):
|
2022-03-10 08:47:52 +13:00
|
|
|
return
|
2022-03-02 10:20:45 +13:00
|
|
|
|
2022-03-14 05:20:55 +13:00
|
|
|
if text == "proton":
|
2023-08-17 05:55:41 +12:00
|
|
|
QMessageBox.warning(
|
2023-08-23 05:57:54 +12:00
|
|
|
self,
|
|
|
|
self.tr("Warning"),
|
|
|
|
self.tr("Do not insert <b>proton</b> manually. Add it through Proton settings"),
|
2023-08-17 05:55:41 +12:00
|
|
|
)
|
2022-03-14 05:20:55 +13:00
|
|
|
return
|
|
|
|
|
2023-08-22 05:33:27 +12:00
|
|
|
self.ui.widget_stack.setCurrentIndex(0)
|
2022-03-02 10:20:45 +13:00
|
|
|
|
2022-03-23 09:48:20 +13:00
|
|
|
if widget := self.wrappers.get(show_text, None):
|
|
|
|
widget.deleteLater()
|
|
|
|
|
2022-03-14 05:20:55 +13:00
|
|
|
widget = WrapperWidget(text, show_text, self.scroll_content)
|
2023-08-17 21:33:49 +12:00
|
|
|
if position < 0:
|
|
|
|
self.scroll_content.layout().addWidget(widget)
|
|
|
|
else:
|
|
|
|
self.scroll_content.layout().insertWidget(position, widget)
|
2022-03-20 03:32:46 +13:00
|
|
|
self.adjust_scrollarea(
|
|
|
|
self.wrapper_scroll.horizontalScrollBar().minimum(),
|
2023-08-23 05:57:54 +12:00
|
|
|
self.wrapper_scroll.horizontalScrollBar().maximum(),
|
2022-03-20 03:32:46 +13:00
|
|
|
)
|
2023-08-17 21:33:49 +12:00
|
|
|
widget.update_wrapper.connect(self.update_wrapper)
|
2022-02-27 12:14:47 +13:00
|
|
|
widget.delete_wrapper.connect(self.delete_wrapper)
|
2023-08-17 21:33:49 +12:00
|
|
|
|
2022-03-14 05:20:55 +13:00
|
|
|
self.wrappers[show_text] = widget
|
2022-03-10 09:45:02 +13:00
|
|
|
|
2022-03-10 08:47:52 +13:00
|
|
|
if not from_load:
|
|
|
|
self.save()
|
2022-02-27 12:14:47 +13:00
|
|
|
|
2023-08-17 21:33:49 +12:00
|
|
|
@pyqtSlot(str)
|
2022-02-27 12:14:47 +13:00
|
|
|
def delete_wrapper(self, text: str):
|
2023-08-17 21:33:49 +12:00
|
|
|
text = text.split()[0]
|
2022-02-27 12:14:47 +13:00
|
|
|
widget = self.wrappers.get(text, None)
|
2022-03-14 05:20:55 +13:00
|
|
|
if widget:
|
2022-02-27 12:14:47 +13:00
|
|
|
self.wrappers.pop(text)
|
2022-03-14 05:20:55 +13:00
|
|
|
widget.deleteLater()
|
2022-02-27 12:14:47 +13:00
|
|
|
|
2022-03-02 10:20:45 +13:00
|
|
|
if not self.wrappers:
|
2023-08-22 05:33:27 +12:00
|
|
|
self.wrapper_scroll.setMaximumHeight(self.ui.label_page.sizeHint().height())
|
|
|
|
self.ui.widget_stack.setCurrentIndex(1)
|
2022-03-02 10:20:45 +13:00
|
|
|
|
2022-02-27 12:14:47 +13:00
|
|
|
self.save()
|
|
|
|
|
2023-08-17 21:33:49 +12:00
|
|
|
@pyqtSlot(str, str)
|
|
|
|
def update_wrapper(self, old: str, new: str):
|
|
|
|
key = old.split()[0]
|
|
|
|
idx = self.scroll_content.layout().indexOf(self.wrappers[key])
|
|
|
|
self.delete_wrapper(key)
|
|
|
|
self.add_wrapper(new, position=idx)
|
|
|
|
|
2022-02-27 12:14:47 +13:00
|
|
|
def save(self):
|
2022-03-07 07:48:35 +13:00
|
|
|
# save wrappers twice, to support wrappers with spaces
|
2022-03-14 05:20:55 +13:00
|
|
|
if len(self.wrappers) == 0:
|
2022-03-02 09:16:45 +13:00
|
|
|
config_helper.remove_option(self.app_name, "wrapper")
|
2022-03-07 07:48:35 +13:00
|
|
|
self.settings.remove(f"{self.app_name}/wrapper")
|
2022-03-02 09:16:45 +13:00
|
|
|
else:
|
|
|
|
config_helper.add_option(self.app_name, "wrapper", self.get_wrapper_string())
|
2022-03-07 07:48:35 +13:00
|
|
|
self.settings.setValue(f"{self.app_name}/wrapper", self.get_wrapper_list())
|
2022-02-27 12:14:47 +13:00
|
|
|
|
2022-03-07 07:48:35 +13:00
|
|
|
def load_settings(self, app_name: str):
|
2022-02-27 12:14:47 +13:00
|
|
|
self.app_name = app_name
|
|
|
|
for i in self.wrappers.values():
|
|
|
|
i.deleteLater()
|
|
|
|
self.wrappers.clear()
|
|
|
|
|
2022-03-07 07:48:35 +13:00
|
|
|
wrappers = self.settings.value(f"{self.app_name}/wrapper", [], str)
|
|
|
|
|
|
|
|
if not wrappers and (cfg := self.core.lgd.config.get(self.app_name, "wrapper", fallback="")):
|
|
|
|
logger.info("Loading wrappers from legendary config")
|
|
|
|
# no qt wrapper, but legendary wrapper, to have backward compatibility
|
|
|
|
pattern = re.compile(r'''((?:[^ "']|"[^"]*"|'[^']*')+)''')
|
|
|
|
wrappers = pattern.split(cfg)[1::2]
|
|
|
|
|
|
|
|
for wrapper in wrappers:
|
2023-08-17 21:33:49 +12:00
|
|
|
self.add_wrapper(wrapper, from_load=True)
|
2022-03-07 07:48:35 +13:00
|
|
|
|
|
|
|
if not self.wrappers:
|
2023-08-22 05:33:27 +12:00
|
|
|
self.wrapper_scroll.setMaximumHeight(self.ui.label_page.sizeHint().height())
|
|
|
|
self.ui.widget_stack.setCurrentIndex(1)
|
2022-02-27 12:14:47 +13:00
|
|
|
else:
|
2023-08-22 05:33:27 +12:00
|
|
|
self.ui.widget_stack.setCurrentIndex(0)
|
2022-03-14 05:20:55 +13:00
|
|
|
|
2022-03-10 08:47:52 +13:00
|
|
|
self.save()
|
|
|
|
|
2022-03-12 11:08:36 +13:00
|
|
|
|
|
|
|
class WrapperContainer(QWidget):
|
|
|
|
|
|
|
|
def __init__(self, save_cb, parent=None):
|
|
|
|
super(WrapperContainer, self).__init__(parent=parent)
|
|
|
|
self.setAcceptDrops(True)
|
|
|
|
self.save = save_cb
|
2022-03-20 03:32:46 +13:00
|
|
|
layout = QHBoxLayout()
|
|
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
layout.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
|
|
|
self.setLayout(layout)
|
|
|
|
|
2023-08-22 05:33:27 +12:00
|
|
|
self.drag_widget: Optional[QWidget] = None
|
|
|
|
|
2022-03-20 03:32:46 +13:00
|
|
|
# lk: set object names for the stylesheet
|
|
|
|
self.setObjectName(type(self).__name__)
|
2022-03-12 11:08:36 +13:00
|
|
|
|
2022-03-10 08:47:52 +13:00
|
|
|
def dragEnterEvent(self, e: QDragEnterEvent):
|
|
|
|
widget = e.source()
|
|
|
|
self.drag_widget = widget
|
|
|
|
e.accept()
|
|
|
|
|
|
|
|
def _get_drop_index(self, x):
|
2022-03-12 11:08:36 +13:00
|
|
|
drag_idx = self.layout().indexOf(self.drag_widget)
|
|
|
|
|
|
|
|
if drag_idx > 0:
|
|
|
|
prev_widget = self.layout().itemAt(drag_idx - 1).widget()
|
|
|
|
if x < self.drag_widget.x() - prev_widget.width() // 2:
|
|
|
|
return drag_idx - 1
|
|
|
|
if drag_idx < self.layout().count() - 1:
|
|
|
|
next_widget = self.layout().itemAt(drag_idx + 1).widget()
|
|
|
|
if x > self.drag_widget.x() + self.drag_widget.width() + next_widget.width() // 2:
|
|
|
|
return drag_idx + 1
|
|
|
|
|
|
|
|
return drag_idx
|
2022-03-10 08:47:52 +13:00
|
|
|
|
|
|
|
def dragMoveEvent(self, e: QDragMoveEvent) -> None:
|
|
|
|
i = self._get_drop_index(e.pos().x())
|
2022-03-12 11:08:36 +13:00
|
|
|
self.layout().insertWidget(i, self.drag_widget)
|
2022-03-10 08:47:52 +13:00
|
|
|
|
|
|
|
def dropEvent(self, e: QDropEvent):
|
|
|
|
pos = e.pos()
|
|
|
|
widget = e.source()
|
|
|
|
index = self._get_drop_index(pos.x())
|
2022-03-12 11:08:36 +13:00
|
|
|
self.layout().insertWidget(index, widget)
|
2022-03-10 08:47:52 +13:00
|
|
|
self.drag_widget = None
|
|
|
|
e.accept()
|
|
|
|
self.save()
|