diff --git a/src/airunner/data/managers.py b/src/airunner/data/managers.py index 2baa0cd21..e15514556 100644 --- a/src/airunner/data/managers.py +++ b/src/airunner/data/managers.py @@ -1,10 +1,9 @@ from contextlib import contextmanager -from typing import Any, Iterator +from typing import Iterator from sqlalchemy.orm import joinedload from PyQt6.QtCore import QObject, pyqtSignal from airunner.utils import Logger - from airunner.data.session_scope import ( models_scope, session_scope, @@ -125,13 +124,6 @@ def loras(self, search_filter=None): loras = session.query(Lora).options(joinedload('*')).all() yield loras - @contextmanager - def layers(self): - from airunner.data.models import Layer - with session_scope() as session: - layers = session.query(Layer).options(joinedload('*')).all() - yield layers - @contextmanager def document(self): from airunner.data.models import Document diff --git a/src/airunner/data/models.py b/src/airunner/data/models.py index 3b3837392..86d440a4b 100644 --- a/src/airunner/data/models.py +++ b/src/airunner/data/models.py @@ -204,40 +204,3 @@ class ImageFilterValue(BaseModel): min_value = Column(Integer, default=0) max_value = Column(Integer, default=100) - -class Layer(BaseModel): - __tablename__ = 'layers' - - @property - def image(self): - # convert base64 image to pil image - if self.base_64_image: - decoded_image = base64.b64decode(self.base_64_image) - bytes_image = io.BytesIO(decoded_image) - # convert bytes to PIL iamge: - image = Image.open(bytes_image) - image = image.convert("RGBA") - return image - return None - - @image.setter - def image(self, value): - # convert to base 64 - if value: - buffered = io.BytesIO() - value.save(buffered, format="PNG") - self.base_64_image = base64.b64encode(buffered.getvalue()) - else: - self.base_64_image = "" - - name = Column(String) - visible = Column(Boolean, default=True) - opacity = Column(Integer, default=10000) - position = Column(Integer, default=0) - base_64_image = Column(String, default="") - pos_x = Column(Integer, default=0) - pos_y = Column(Integer, default=0) - pivot_point_x = Column(Integer, default=0) - pivot_point_y = Column(Integer, default=0) - root_point_x = Column(Integer, default=0) - root_point_y = Column(Integer, default=0) diff --git a/src/airunner/widgets/canvas_plus/canvas_plus_widget.py b/src/airunner/widgets/canvas_plus/canvas_plus_widget.py index 974a4bb90..3a228ddc9 100644 --- a/src/airunner/widgets/canvas_plus/canvas_plus_widget.py +++ b/src/airunner/widgets/canvas_plus/canvas_plus_widget.py @@ -45,18 +45,20 @@ class CanvasPlusWidget(CanvasBaseWidget): @property def image_pivot_point(self): - with self.layer_container_widget.current_layer() as layer: - try: - return QPoint(layer.pivot_x, layer.pivot_y) - except Exception as e: - pass - return QPoint(0, 0) + try: + layer = self.app.current_layer() + return QPoint(layer["pivot_x"], layer["pivot_y"]) + except Exception as e: + self.logger.error(e) + return QPoint(0, 0) @image_pivot_point.setter def image_pivot_point(self, value): - with self.layer_container_widget.current_layer() as layer: - layer.pivot_x = value.x() - layer.pivot_y = value.y() + layer = self.app.current_layer() + self.app.update_current_layer({ + "pivot_x": value.x(), + "pivot_y": value.y() + }) @property def brush_size(self): @@ -79,21 +81,11 @@ def active_grid_area_rect(self): @property def current_active_image(self): - with self.layer_container_widget.current_layer() as layer: - return layer.image + return self.app.get_image_from_current_layer() @current_active_image.setter def current_active_image(self, value): - with self.layer_container_widget.current_layer() as layer: - layer.image = value - - @property - def current_layer_index(self): - return self.layer_container_widget.current_layer_index - - @current_layer_index.setter - def current_layer_index(self, value): - self.layer_container_widget.current_layer_index = value + self.app.add_image_to_current_layer(value) @property def layer_container_widget(self): @@ -105,14 +97,12 @@ def canvas_container(self): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - #self.app.settings_manager.changed_signal.connect(self.handle_changed_signal) self.app.application_settings_changed_signal.connect(self.handle_changed_signal) - with session_scope() as session: - self.ui.central_widget.resizeEvent = self.resizeEvent - self.app.add_image_to_canvas_signal.connect(self.handle_add_image_to_canvas) - self.app.image_data.connect(self.handle_image_data) - self.app.load_image.connect(self.load_image_from_path) - self.app.load_image_object.connect(self.add_image_to_scene) + self.ui.central_widget.resizeEvent = self.resizeEvent + self.app.add_image_to_canvas_signal.connect(self.handle_add_image_to_canvas) + self.app.image_data.connect(self.handle_image_data) + self.app.load_image.connect(self.load_image_from_path) + self.app.load_image_object.connect(self.add_image_to_scene) self.app.loaded.connect(self.handle_loaded) self._zoom_level = 1 self.canvas_container.resizeEvent = self.window_resized @@ -331,46 +321,27 @@ def set_canvas_color(self): self.scene.setBackgroundBrush(QBrush(QColor(self.canvas_color))) def draw_layers(self): - with self.app.settings_manager.layers() as layers: - for layer in layers: - image = layer.image - if image is None: - continue - - image = apply_opacity_to_image( - image, - layer.opacity / 100.0 - ) - - if layer.id in self.layers: - if not layer.visible: - if self.layers[layer.id] in self.scene.items(): - self.scene.removeItem(self.layers[layer.id]) - elif layer.visible: - if not self.layers[layer.id] in self.scene.items(): - self.scene.addItem(self.layers[layer.id]) - self.layers[layer.id].pixmap.convertFromImage(ImageQt(image)) - continue - - draggable_pixmap = None - if layer.id in self.layers: - self.layers[layer.id].pixmap.convertFromImage(ImageQt(image)) - draggable_pixmap = self.layers[layer.id] - self.scene.removeItem(draggable_pixmap) - - if not draggable_pixmap: - draggable_pixmap = DraggablePixmap(self, QPixmap.fromImage(ImageQt(image))) - self.layers[layer.id] = draggable_pixmap - - if layer.visible: - self.scene.addItem(draggable_pixmap) - - pos = QPoint(layer.pos_x, layer.pos_y) - canvas_settings = self.app.settings["canvas_settings"] - draggable_pixmap.setPos(QPointF( - canvas_settings["pos_x"] + pos.x(), - canvas_settings["pos_y"] + pos.y() - )) + layers = self.app.settings["layers"] + for layer in layers: + image = self.app.get_image_from_layer(layer) + if image is None: + continue + + image = apply_opacity_to_image( + image, + layer["opacity"] / 100.0 + ) + + if not layer["visible"]: + if layer["pixmap"] in self.scene.items(): + self.scene.removeItem(layer["pixmap"]) + elif layer["visible"]: + if type(layer["pixmap"]) is not DraggablePixmap or layer["pixmap"] not in self.scene.items(): + layer["pixmap"].convertFromImage(ImageQt(image)) + layer["pixmap"] = DraggablePixmap(self, layer["pixmap"]) + self.app.update_layer(layer) + self.scene.addItem(layer["pixmap"]) + continue def set_scene_rect(self): self.scene.setSceneRect(0, 0, self.view_size.width(), self.view_size.height()) @@ -487,8 +458,8 @@ def handle_outpaint(self, outpaint_box_rect, outpainted_image, action=None): pivot_point = self.image_pivot_point root_point = QPoint(0, 0) - with self.layer_container_widget.current_layer() as layer: - current_image_position = QPoint(layer.pos_x, layer.pos_y) + layer = self.app.current_layer() + current_image_position = QPoint(layer["pos_x"], layer["pos_y"]) is_drawing_left = outpaint_box_rect.x() < current_image_position.x() is_drawing_right = outpaint_box_rect.x() > current_image_position.x() @@ -546,11 +517,8 @@ def load_image(self, image_path): self.add_image_to_scene(image) def current_draggable_pixmap(self): - with self.layer_container_widget.current_layer() as layer: - index = layer + 1 - if index in self.layers: - return self.layers[index] - + self.app.current_draggable_pixmap() + def copy_image(self, image:Image=None) -> DraggablePixmap: pixmap = self.current_pixmap() if image is None else QPixmap.fromImage(ImageQt(image)) return self.move_pixmap_to_clipboard(pixmap) @@ -561,9 +529,7 @@ def cut_image(self): if not draggable_pixmap: return self.scene.removeItem(draggable_pixmap) - with self.layer_container_widget.current_layer() as layer: - if layer.id in self.layers: - del self.layers[layer.id] + self.app.delete_current_layer() self.update() def delete_image(self): @@ -636,7 +602,7 @@ def add_layer(self): return self.app.ui.layer_widget.add_layer() def switch_to_layer(self, layer_index): - self.current_layer_index = layer_index + self.app.switch_layer(layer_index) def add_image_to_scene(self, image, is_outpaint=False, image_root_point=None): #self.image_adder = ImageAdder(self, image, is_outpaint, image_root_point) diff --git a/src/airunner/widgets/canvas_plus/draggables.py b/src/airunner/widgets/canvas_plus/draggables.py index 9ac62ce89..ac224adbb 100644 --- a/src/airunner/widgets/canvas_plus/draggables.py +++ b/src/airunner/widgets/canvas_plus/draggables.py @@ -15,10 +15,9 @@ def __init__(self, parent, pixmap): self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True) def snap_to_grid(self): - cell_size = self.parent.cell_size - grid_size = cell_size - x = round(self.x() / grid_size) * grid_size - y = round(self.y() / grid_size) * grid_size + cell_size = self.parent.app.settings["grid_settings"]["cell_size"] + x = round(self.x() / cell_size) * cell_size + y = round(self.y() / cell_size) * cell_size x += self.parent.last_pos.x() y += self.parent.last_pos.y() self.setPos(x, y) diff --git a/src/airunner/widgets/layers/layer_container_widget.py b/src/airunner/widgets/layers/layer_container_widget.py index 333b3d2f6..3c0ca5d30 100644 --- a/src/airunner/widgets/layers/layer_container_widget.py +++ b/src/airunner/widgets/layers/layer_container_widget.py @@ -4,7 +4,6 @@ from contextlib import contextmanager from airunner.aihandler.logger import Logger -from airunner.data.models import Layer from airunner.models.layerdata import LayerData from airunner.data.session_scope import session_scope from airunner.widgets.base_widget import BaseWidget @@ -18,23 +17,13 @@ class LayerContainerWidget(BaseWidget): layers = [] selected_layers = {} - @contextmanager - def current_layer(self): - with self.app.settings_manager.layers() as layers: - if len(layers) == 0: - self.add_layer() - try: - yield layers[self.current_layer_index] - except IndexError: - self.logger.error(f"No current layer for index {self.current_layer_index}") - def initialize(self): - with self.current_layer() as current_layer: - self.ui.scrollAreaWidgetContents.layout().addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)) - # set the current_value property of the slider - self.ui.opacity_slider_widget.set_slider_and_spinbox_values(current_layer.opacity) - self.ui.opacity_slider_widget.initialize_properties() - self.set_layer_opacity(current_layer.opacity) + current_layer = self.app.current_layer() + self.ui.scrollAreaWidgetContents.layout().addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)) + # set the current_value property of the slider + self.ui.opacity_slider_widget.set_slider_and_spinbox_values(current_layer["opacity"]) + self.ui.opacity_slider_widget.initialize_properties() + self.set_layer_opacity(current_layer["opacity"]) def action_clicked_button_add_new_layer(self): self.add_layer() @@ -58,32 +47,11 @@ def add_layers(self): self.add_layer_widget(layer, layer.position) def add_layer(self): - self.app.history.add_event({ - "event": "new_layer", - "layers": self.get_layers_copy(), - "layer_index": self.current_layer_index - }) return self.create_layer() def create_layer(self): - with self.app.settings_manager.document() as document: - with self.app.settings_manager.layers() as layers: - layer_data = Layer( - name=f"Layer {len(layers) + 1}", - document=document, - position=len(layers) + 1, - visible=True - ) - - with session_scope() as session: - session.add(layer_data) - - # layer_name = f"Layer {len(self.layers) + 1}" - index = 0 - with self.app.settings_manager.layers() as layers: - layers.insert(index, layer_data) - self.set_current_layer(index) - self.add_layer_widget(layer_data, index) + index = self.app.add_layer() + self.app.switch_layer(index) return index def add_layer_widget(self, layer_data, index): @@ -96,32 +64,14 @@ def add_layer_widget(self, layer_data, index): layer_widget.reset_position() def move_layer_up(self): - with self.app.settings_manager.layers() as layers: - with self.current_layer() as current_layer: - layer = current_layer - index = layers.index(layer) - if index == 0: - return - # track the current layer order - self.app.canvas.track_layer_move_history() - layers.remove(layer) - layers.insert(index - 1, layer) - self.current_layer_index = index - 1 - self.show_layers() - self.app.canvas.update() + self.app.move_layer_up() + self.show_layers() + self.app.canvas.update() def move_layer_down(self): - with self.app.settings_manager.layers() as layers: - with self.current_layer() as layer: - index = layers.index(layer) - if index == len(layers) - 1: - return - self.app.canvas.track_layer_move_history() - layers.remove(layer) - layers.insert(index + 1, layer) - self.current_layer_index = index + 1 - self.show_layers() - self.app.canvas.update() + self.app.move_layer_down() + self.show_layers() + self.app.canvas.update() def merge_selected_layers(self): with self.current_layer() as current_layer: @@ -180,19 +130,10 @@ def merge_selected_layers(self): self.show_layers() self.app.canvas.update() - def get_layers_copy(self): - with self.app.settings_manager.layers() as layers: - return [layer for layer in layers] - selected_layers = {} def delete_selected_layers(self): self.logger.info("Deleting selected layers") - self.app.history.add_event({ - "event": "delete_layer", - "layers": self.get_layers_copy(), - "layer_index": self.current_layer_index - }) for index, layer in self.selected_layers.items(): self.delete_layer(index=index, layer=layer) self.selected_layers = {} @@ -200,45 +141,13 @@ def delete_selected_layers(self): self.app.standard_image_panel.canvas_widget.do_draw() def delete_layer(self, _value=False, index=None, layer=None): - self.logger.info(f"delete_layer requested index {index}") - with self.app.settings_manager.layers() as layers: - current_index = index - if layer and current_index is None: - for layer_index, layer_object in enumerate(layers): - if layer_object is layer: - current_index = layer_index - self.logger.info(f"current_index={current_index}") - if current_index is None: - current_index = self.current_layer_index - self.logger.info(f"Deleting layer {current_index}") - self.app.standard_image_panel.canvas_widget.delete_image() - self.app.history.add_event({ - "event": "delete_layer", - "layers": self.get_layers_copy(), - "layer_index": current_index - }) - try: - with session_scope() as session: - session.delete(layers[current_index]) - with self.app.settings_manager.layers() as layers: - layer = layers.pop(current_index) - layer.layer_widget.deleteLater() - except IndexError as e: - self.logger.error(f"Could not delete layer {current_index}. Error: {e}") - if len(layers) == 0: - layers = [LayerData(0, "Layer 1")] - self.show_layers() - self.update() + self.app.delete_layer(index, layer) def clear_layers(self): - # delete all widgets from self.container.layout() - with self.app.settings_manager.layers() as layers: - for index, layer in enumerate(layers): - if not layer.layer_widget: - continue - layer.layer_widget.deleteLater() - layers = [LayerData(0, "Layer 1")] - self.current_layer_index = 0 + self.app.clear_layers() + + def set_current_layer(self, index): + self.app.set_current_layer(index) def handle_layer_click(self, layer, index, event): self.logger.info(f"handle_layer_click index={index}") @@ -263,46 +172,17 @@ def handle_layer_click(self, layer, index, event): self.set_current_layer(index) self.selected_layers = {} - def set_current_layer(self, index): - self.logger.info(f"set_current_layer current_layer_index={index}") - self.current_layer_index = index - if not hasattr(self, "container"): - return - if self.app.canvas.container: - item = self.app.canvas.container.layout().itemAt(self.current_layer_index) - if item: - item.widget().frame.setStyleSheet(self.app.css("layer_normal_style")) - self.current_layer_index = index - if self.app.canvas.container: - item = self.app.canvas.container.layout().itemAt(self.current_layer_index) - if item: - item.widget().frame.setStyleSheet(self.app.css("layer_highlight_style")) - # change the layer opacity - # self.app.tool_menu_widget.set_opacity_slider( - # int(self.current_layer.opacity * 100) - # ) - def track_layer_move_history(self): - with self.app.settings_manager.layers() as layers: - layer_order = [] - for layer in layers: - layer_order.append(layer.uuid) - self.app.history.add_event({ - "event": "move_layer", - "layer_order": layer_order, - "layer_index": self.current_layer_index - }) - - def get_layers_copy(self): - with self.app.settings_manager.layers() as layers: - return [layer for layer in layers] + layers = self.app.settings["layers"] + layer_order = [] + for layer in layers: + layer_order.append(layer["uuid"]) def get_index_by_layer(self, layer): - with self.app.settings_manager.layers() as layers: - for index, layer_object in enumerate(layers): - if layer is layer_object: - return index - return 0 + for index, layer_object in enumerate(self.app.settings["layers"]): + if layer is layer_object: + return index + return 0 def toggle_layer_visibility(self, layer, layer_obj): # change the eye icon of the visible_button on the layer @@ -346,17 +226,19 @@ def handle_move_layer(self, event): point.setX(int(point.x() - int(rect.width() / 2))) point.setY(int(point.y() - int(rect.height() / 2))) - with self.app.settings_manager.layers() as layers: - layers[self.current_layer_index].offset = point + self.app.update_current_layer({ + "offset": point + }) self.app.canvas.update() def get_layer_opacity(self, index): - with self.app.settings_manager.layers() as layers: - return layers[index].opacity + layers = self.app.settings["layers"] + return layers[index]["opacity"] def set_layer_opacity(self, opacity: int): - with self.current_layer() as current_layer: - current_layer.opacity = opacity + self.app.update_current_layer({ + "opacity": opacity + }) def show_layers(self): pass \ No newline at end of file diff --git a/src/airunner/windows/main/main_window.py b/src/airunner/windows/main/main_window.py index 52523caea..8b172a38f 100644 --- a/src/airunner/windows/main/main_window.py +++ b/src/airunner/windows/main/main_window.py @@ -1,9 +1,12 @@ +import base64 +import io import os import queue import pickle import platform import subprocess import sys +import uuid import webbrowser from functools import partial @@ -13,6 +16,9 @@ from PyQt6.QtWidgets import QApplication, QFileDialog, QMainWindow from PyQt6 import QtGui from PyQt6.QtCore import QSettings +from PyQt6.QtGui import QPixmap + +from PIL import Image from airunner.resources_light_rc import * from airunner.resources_dark_rc import * @@ -38,12 +44,10 @@ from airunner.widgets.brushes.brushes_container import BrushesContainer from airunner.workers.image_data_worker import ImageDataWorker -logger = Logger(prefix="MainWindow") - - class MainWindow( QMainWindow ): + logger = Logger(prefix="MainWindow") # signals show_grid_toggled = pyqtSignal(bool) cell_size_changed_signal = pyqtSignal(int) @@ -122,18 +126,19 @@ def handle_key_press(self, key): print("generate_image_key PRESSED") def key_matches(self, key_name, keyboard_key): - if not key_name in self.app.settings["shortcut_key_settings"]: + if not key_name in self.settings["shortcut_key_settings"]: return False - return self.app.settings["shortcut_key_settings"][key_name]["key"] == keyboard_key + return self.settings["shortcut_key_settings"][key_name]["key"] == keyboard_key def key_text(self, key_name): - if not key_name in self.app.settings["shortcut_key_settings"]: + if not key_name in self.settings["shortcut_key_settings"]: return "" - return self.app.settings["shortcut_key_settings"][key_name]["text"] + return self.settings["shortcut_key_settings"][key_name]["text"] @property def settings(self): return self.application_settings.value("settings", dict( + current_layer_index=0, ocr_enabled=False, tts_enabled=False, stt_enabled=False, @@ -472,13 +477,186 @@ def settings(self): ), ], saved_prompts=[], + layers=[] ), type=dict) + + def add_layer(self): + settings = self.settings + total_layers = len(self.settings['layers']) + name=f"Layer {total_layers + 1}" + settings["layers"].append(dict( + name=name, + visible=True, + opacity=100, + position=total_layers, + base_64_image="", + pos_x="", + pos_y="", + pivot_point_x=0, + pivot_point_y=0, + root_point_x=0, + root_point_y=0, + uuid=str(uuid.uuid4()), + pixmap=QPixmap(), + )) + self.settings = settings + return total_layers + + def current_draggable_pixmap(self): + return self.current_layer()["pixmap"] + + def delete_layer(self, index, layer): + self.logger.info(f"delete_layer requested index {index}") + layers = self.settings["layers"] + current_index = index + if layer and current_index is None: + for layer_index, layer_object in enumerate(layers): + if layer_object is layer: + current_index = layer_index + self.logger.info(f"current_index={current_index}") + if current_index is None: + current_index = self.settings["current_layer_index"] + self.logger.info(f"Deleting layer {current_index}") + self.standard_image_panel.canvas_widget.delete_image() + try: + layer = layers.pop(current_index) + layer.layer_widget.deleteLater() + except IndexError as e: + self.logger.error(f"Could not delete layer {current_index}. Error: {e}") + if len(layers) == 0: + self.add_layer() + self.switch_layer(0) + settings = self.settings + settings["layers"] = layers + self.settings = settings + self.show_layers() + self.update() + + def clear_layers(self): + # delete all widgets from self.container.layout() + layers = self.settings["layers"] + for index, layer in enumerate(layers): + if not layer.layer_widget: + continue + layer.layer_widget.deleteLater() + self.add_layer() + settings = self.settings + settings["layers"] = layers + self.settings = settings + self.switch_layer(0) + + def set_current_layer(self, index): + self.logger.info(f"set_current_layer current_layer_index={index}") + self.current_layer_index = index + if not hasattr(self, "container"): + return + if self.canvas.container: + item = self.canvas.container.layout().itemAt(self.current_layer_index) + if item: + item.widget().frame.setStyleSheet(self.css("layer_normal_style")) + self.current_layer_index = index + if self.canvas.container: + item = self.canvas.container.layout().itemAt(self.current_layer_index) + if item: + item.widget().frame.setStyleSheet(self.css("layer_highlight_style")) + + def move_layer_up(self): + layer = self.current_layer() + settings = self.settings + index = self.settings["current_layer_index"] + if index == 0: + return + layers = settings["layers"] + layers.remove(layer) + layers.insert(index - 1, layer) + self.settings["current_layer_index"] = index - 1 + settings["layers"] = layers + self.settings = settings + + def move_layer_down(self): + layer = self.current_layer() + settings = self.settings + index = self.settings["current_layer_index"] + if index == len(settings["layers"]) - 1: + return + layers = settings["layers"] + layers.remove(layer) + layers.insert(index + 1, layer) + self.settings["current_layer_index"] = index + 1 + settings["layers"] = layers + self.settings = settings + + def current_layer(self): + if len(self.settings["layers"]) == 0: + self.add_layer() + try: + return self.settings["layers"][self.settings["current_layer_index"]] + except IndexError: + self.logger.error(f"Unable to get current layer with index {self.settings['current_layer_index']}") + + def update_current_layer(self, data): + settings = self.settings + layer = settings["layers"][settings["current_layer_index"]] + for k, v in data.items(): + layer[k] = v + settings["layers"][settings["current_layer_index"]] = layer + self.settings = settings + + def update_layer(self, data): + uuid = data["uuid"] + settings = self.settings + for index, layer in enumerate(settings["layers"]): + if layer["uuid"] == uuid: + for k, v in data.items(): + layer[k] = v + settings["layers"][index] = layer + self.settings = settings + return + self.logger.error(f"Unable to find layer with uuid {uuid}") + + + def switch_layer(self, layer_index): + settings = self.settings + settings["current_layer_index"] = layer_index + self.settings = settings + + def delete_current_layer(self): + self.delete_layer(self.settings["current_layer_index"], None) + + def get_image_from_current_layer(self): + layer = self.current_layer() + return self.get_image_from_layer(layer) + + def get_image_from_layer(self, layer): + if layer["base_64_image"]: + decoded_image = base64.b64decode(layer["base_64_image"]) + bytes_image = io.BytesIO(decoded_image) + # convert bytes to PIL iamge: + image = Image.open(bytes_image) + image = image.convert("RGBA") + return image + return None + + def add_image_to_current_layer(self, value): + self.add_image_to_layer(self.settings["current_layer_index"], value) + + def add_image_to_layer(self, layer_index, value): + if value: + buffered = io.BytesIO() + value.save(buffered, format="PNG") + base_64_image = base64.b64encode(buffered.getvalue()) + else: + base_64_image = "" + + settings = self.settings + settings["layers"][layer_index]["base_64_image"] = base_64_image + self.settings = settings def load_saved_stablediffuion_prompt(self, index): try: saved_prompt = self.settings["saved_prompts"][index] except KeyError: - logger.error(f"Unable to load prompt at index {index}") + self.logger.error(f"Unable to load prompt at index {index}") saved_prompt = None if saved_prompt: @@ -495,7 +673,7 @@ def update_saved_stablediffusion_prompt(self, index, prompt, negative_prompt): negative_prompt=negative_prompt, ) except KeyError: - logger.error(f"Unable to update prompt at index {index}") + self.logger.error(f"Unable to update prompt at index {index}") self.settings = settings def save_stablediffusion_prompt(self): @@ -659,7 +837,7 @@ def message_handler(self, response: dict): try: code = response["code"] except TypeError: - # logger.error(f"Invalid response message: {response}") + # self.logger.error(f"Invalid response message: {response}") # traceback.print_exc() return message = response["message"] @@ -672,7 +850,7 @@ def message_handler(self, response: dict): }.get(code, lambda *args: None)(message) def __init__(self, settings_manager, *args, **kwargs): - logger.info("Starting AI Runnner") + self.logger.info("Starting AI Runnner") self.ui = Ui_MainWindow() self.application_settings = QSettings("Capsize Games", "AI Runner") self.application_settings.clear() @@ -703,7 +881,7 @@ def __init__(self, settings_manager, *args, **kwargs): self.register_keypress() if not self.testing: - logger.info("Executing window") + self.logger.info("Executing window") self.display() self.set_window_state() self.is_started = True @@ -1055,7 +1233,7 @@ def toggle_fullscreen(self): self.showFullScreen() def quit(self): - logger.info("Quitting") + self.logger.info("Quitting") self.image_data_worker.stop() self.client.stop() self.save_state() @@ -1084,7 +1262,7 @@ def v2t_button_toggled(self, val): self.settings = new_settings def save_state(self): - logger.info("Saving window state") + self.logger.info("Saving window state") settings = self.settings settings["window_settings"] = dict( main_splitter=self.ui.main_splitter.saveState(), @@ -1228,7 +1406,7 @@ def show_update_popup(self): self.update_popup = UpdateWindow(self.settings_manager, app=self) def reset_settings(self): - logger.info("MainWindow: Resetting settings") + self.logger.info("MainWindow: Resetting settings") self.canvas_widget.reset_settings() def on_state_changed(self, state): @@ -1244,7 +1422,7 @@ def set_stylesheet(self): """ Sets the stylesheet for the application based on the current theme """ - logger.info("MainWindow: Setting stylesheets") + self.logger.info("MainWindow: Setting stylesheets") theme_name = "dark_theme" if self.settings["dark_mode_enabled"] else "light_theme" here = os.path.dirname(os.path.realpath(__file__)) with open(os.path.join(here, "..", "..", "styles", theme_name, "styles.qss"), "r") as f: @@ -1320,7 +1498,7 @@ def initialize_mixins(self): pass def connect_signals(self): - logger.info("MainWindow: Connecting signals") + self.logger.info("MainWindow: Connecting signals") #self.canvas_widget._is_dirty.connect(self.set_window_title) for signal, handler in self.registered_settings_handlers: @@ -1430,7 +1608,7 @@ def initialize_window(self): self.set_window_title() def initialize_stable_diffusion(self): - logger.info("Initializing stable diffusion") + self.logger.info("Initializing stable diffusion") self.client = OfflineClient( app=self, message_var=self.message_var, @@ -1441,7 +1619,7 @@ def save_settings(self): self.settings_manager.save_settings() def display(self): - logger.info("Displaying window") + self.logger.info("Displaying window") self.set_stylesheet() if not self.testing: self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowType.Window) @@ -1560,7 +1738,7 @@ def handle_progress(self, message): self.generator_tab_widget.set_progress_bar_value(tab_section, action, int(current * 100)) def handle_unknown(self, message): - logger.error(f"Unknown message code: {message}") + self.logger.error(f"Unknown message code: {message}") def clear_status_message(self): self.set_status_label("")