diff --git a/gui/dropper.py b/gui/dropper.py new file mode 100644 --- /dev/null +++ b/gui/dropper.py @@ -0,0 +1,145 @@ +from PyQt5 import QtGui, QtCore, QtWidgets +from PyQt5.QtWidgets import QSizePolicy + +from cdemu import CDEmuException +from .device_menu import QDeviceMenu +from mount import mount +from urllib.parse import unquote + +class KCDEmuDevice(QtWidgets.QLabel): + def __init__(self, device, width=32, height=32): + super().__init__() + self.setAcceptDrops(True) + self.device = None + self.empty_icon = ':/dropper_empty.png' + self.full_icon = ':/dropper_full.png' + self.refresh(device) + self.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) + self.setAlignment(QtCore.Qt.AlignCenter) + self.setMinimumSize(width, height) + self.setBaseSize(width, height) + self.setMaximumSize(width, height) + self.ctx_menu = QDeviceMenu(device) + + def set_size(self, width, height): + self.setMinimumSize(width, height) + self.setBaseSize(width, height) + self.setMaximumSize(width, height) + self.adjustSize() + + def set_icons(self, empty_icon, full_icon): + self.empty_icon = empty_icon + self.full_icon = full_icon + self.refresh() + + def refresh(self, device=None): + if device is not None: + if self.device and self.device != device: + self.device.remove_handler('change') + if self.device != device: + self.device = device + self.device.add_handler('change', self.refresh) + self.setText( + ''.format( + self.full_icon if self.device.get_img() else self.empty_icon)) + if self.device.get_img(): + self.setToolTip('Click to unload "{}"'.format(self.device.get_img())) + else: + self.setToolTip('Click to load') + + def dragEnterEvent(self, event): + if event.mimeData().hasFormat('text/plain'): + text = event.mimeData().text() + if text.startswith('file://'): + event.acceptProposedAction() + + def dragLeaveEvent(self, event): + pass + + def dropEvent(self, event): + if event.mimeData().hasFormat('text/plain'): + text = event.mimeData().text() + if text.startswith('file://'): + text = unquote(text.replace('file://', '').replace('\n', '').replace('\r', '')) + self.device.load(text) + + def mousePressEvent(self, event): + if event.button() == QtCore.Qt.RightButton: + self.ctx_menu.popup(QtCore.QPoint(event.globalX(), event.globalY())) + elif event.button() == QtCore.Qt.LeftButton: + if self.device.get_img(): + try: + self.device.unload() + except Exception as e: + QtWidgets.QMessageBox.critical(None, 'Error', str(e)) + else: + fd = QtWidgets.QFileDialog(self) + fd.setAcceptMode(QtWidgets.QFileDialog.AcceptOpen) + if fd.exec() == QtWidgets.QDialog.Accepted: + self.device.load(fd.selectedFiles()[0]) + +class KCDEmuDropperWidget(QtWidgets.QWidget): + changed = QtCore.pyqtSignal() + + def __init__(self, cdemu, config): + """ + :type cdemu: cdemu.CDEmu + :type config: config.config.ConfigFile + """ + super().__init__(None, QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint) + self.config = config + self.setWindowTitle('KCDEmu') + self.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)) + layout = QtWidgets.QHBoxLayout(self) + layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize) + layout.setContentsMargins(0,0,0,0) + layout.setSpacing(0) + self.setLayout(layout) + self.cdemu = cdemu + self.devices = [] + + self.cdemu.add_handler('devices_changed', self.on_devices_changed) + self.cdemu.add_handler('daemon_stopped', self.on_daemon_stopped) + self.cdemu.add_handler('daemon_started', self.on_daemon_started) + self.config.add_handler('changed', self.reload_config) + self.reload_config() + + if self.cdemu.is_daemon_ready(): + self.on_devices_changed() + + def on_devices_changed(self, number=None): + devices = self.cdemu.get_devices() + while len(self.devices) > len(devices): + dev = self.devices.pop() + self.layout().removeWidget(dev) + dev.hide() + for index, device in enumerate(devices): + if len(self.devices) <= index: + icon_size = self.config.get_icon_size() + dev = KCDEmuDevice(device, icon_size[0], icon_size[1]) + dev.set_icons(self.config.get_empty_icon(), self.config.get_full_icon()) + self.devices.append(dev) + self.layout().addWidget(dev) + else: + self.devices[index].refresh(device) + self.updateGeometry() + + def resizeEvent(self, event): + print(self.sizeHint().width()) + self.changed.emit() + + def on_daemon_stopped(self): + while len(self.devices) > 0: + dev = self.devices.pop() + self.layout().removeWidget(dev) + + def on_daemon_started(self): + self.on_devices_changed() + + def reload_config(self): + for i in range(self.layout().count()): + widget = self.layout().itemAt(i).widget() + if widget: + icon_size = self.config.get_icon_size() + widget.set_size(icon_size[0], icon_size[1]) + widget.set_icons(self.config.get_empty_icon(), self.config.get_full_icon())