import random import time import os from pathlib import Path from datetime import datetime, timedelta from human_id import generate_id from krita import Krita, Selection, Extension, ManagedColor from PyQt5.QtGui import QColor, QIcon, QPixmap from PyQt5.QtCore import QByteArray dt_fmt = "%Y-%m-%d-%H-%M-%S" ccolors = ['#ffb482', '#a1c9f4', '#8de5a1', '#ff9f9b', '#d0bbff', '#debb9b', '#fab0e4', '#fffea3', '#b9f2f0'] history = {} FOLDERS = "grey studies animations sfw pieces sketches lineart doodles ideas comics lo".split() def fill_color(app, doc, view, x, y, w, h, color): newSelection = Selection() opacity = 255 newSelection.select(x, y, w, h, opacity) doc.setSelection(newSelection) mColor = ManagedColor.fromQColor(color) view.setForeGroundColor(mColor) doc.waitForDone() app.action('fill_selection_foreground_color').trigger() doc.waitForDone() mColor = ManagedColor.fromQColor(QColor(0, 0, 0)) view.setForeGroundColor(mColor) #TODO: write date on page using text tool def write_text(app, doc, view, x, y, w, h, text): newSelection = Selection() opacity = 255 newSelection.select(x, y, w, h, opacity) doc.setSelection(newSelection) app.action('SvgTextTool').trigger() doc.waitForDone() mColor = ManagedColor.fromQColor(QColor(0, 0, 0)) view.setForeGroundColor(mColor) def create_new_page2(path: Path): print(path) app = Krita.instance() win = app.activeWindow() view = win.activeView() base = path.joinpath("base.kra.tmpl").as_posix() now = datetime.now() w, h = 5000, 5000 new = Path(path).joinpath(f"{now.strftime(dt_fmt)}.kra").as_posix() os.system(f"""cp '{base}' '{new}'""") doc = app.openDocument(new) app.activeWindow().addView(doc) random.seed(time.time()) square_size = 200 randcolor2 = QColor(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) black = QColor(35, 7, 33) border = 15 fill_color(app, doc, view, w-square_size-100-border, h-square_size-100-border, square_size+(border*2), square_size+(border*2), black) fill_color(app, doc, view, w-square_size-100, h-square_size-100, square_size, square_size, randcolor2) app.action('merge_layer').trigger() doc.waitForDone() app.action('deselect').trigger() doc.waitForDone() newLayer2 = doc.createNode("PaintLayer", "paintlayer") doc.rootNode().addChildNode(newLayer2, None) doc.save() app.action('deselect').trigger() doc.waitForDone() # def create_new_page(path: Path): # raise Exception("This function should never be called.") # app = Krita.instance() # win = app.activeWindow() # view = win.activeView() # w = 3840 # h = 2160 # square_size = 200 # now = datetime.now() # now_str = now.strftime(dt_fmt) # colorspace = "GRAYA" if path.name in ["grey", "lineart"] else "RGBA" # doc = app.createDocument(w, h, now_str, colorspace, "U8", "", 100.0) # v = win.addView(doc) # newLayer = doc.createNode("PaintLayer", "paintlayer") # doc.rootNode().addChildNode(newLayer, None) # doc.setAnnotation(f'sketchbook_page', f"Sketchbook Page Number", QByteArray(now_str.encode())) # doc.waitForDone() # doc.setFileName(path.joinpath(f"{now_str}.kra").as_posix()) # doc.setName(generate_id(seed=now_str, separator='-', word_count=3)) # doc.waitForDone() # # random.seed(time.time()) # if path.name == "sketches": # t = int(w/3) # fill_color(app, doc, view, 0 , 0, t, h, QColor(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))) # fill_color(app, doc, view, t , 0, 2*t, h, QColor(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))) # fill_color(app, doc, view, 2*t, 0, 3*t, h, QColor(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))) # elif path.name == "lineart": # fill_color(app, doc, view, 0, 0, w, h, QColor(100, 100, 100)) # elif path.name == "doodles": # fill_color(app, doc, view, 0, 0, w, h, QColor(130, 130, 130)) # else: # fill_color(app, doc, view, 0, 0, w, h, QColor(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))) # # random.seed(path.name) # randcolor2 = QColor(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) # black = QColor(35, 7, 33) # border = 15 # fill_color(app, doc, view, w-square_size-100-border, h-square_size-100-border, square_size+(border*2), square_size+(border*2), black) # fill_color(app, doc, view, w-square_size-100, h-square_size-100, square_size, square_size, randcolor2) # # app.action('merge_layer').trigger() # doc.waitForDone() # app.action('deselect').trigger() # doc.waitForDone() # newLayer2 = doc.createNode("PaintLayer", "paintlayer") # doc.rootNode().addChildNode(newLayer2, None) # doc.save() # win.activate() # win.showView(v) # v.setVisible() # currentPreset = v.currentBrushPreset() # v.showFloatingMessage( # generate_id(seed=now_str, separator='-', word_count=3), # QIcon(QPixmap.fromImage(currentPreset.image())), # 8000, # 99 # ) # # # def get_last_page(path: Path) -> None: # raise Exception("This function should never be called.") # app = Krita.instance() # win = app.activeWindow() # view = win.activeView() # paths = path.glob("*.kra") # next_page_candidate = None # i = 0 # l = sorted(paths, key=lambda w: w.as_posix()) # for p in l: # i += 1 # try: # dt = datetime.strptime(Path(p).name, f"{dt_fmt}.kra") # if next_page_candidate is None or dt > next_page_candidate: # next_page_candidate = dt # except Exception as e: # print(e) # if next_page_candidate is not None: # #Check if next page already open in krita # for v in app.activeWindow().views(): # if v.document().fileName() == next_page_candidate.strftime(dt_fmt) + ".kra": # print(v.document().annotation("sketchbook_page")) # b = Path(path).joinpath(next_page_candidate.strftime(dt_fmt) + ".kra").as_posix() # doc2 = app.openDocument(b) # app.activeWindow().addView(doc2) # currentPreset = v.currentBrushPreset() # o = f"{Path(path).stem.upper()} " # o += generate_id(seed=next_page_candidate.strftime(dt_fmt), separator='-', word_count=3) # o += f" {i}/{len(l)}" # v.showFloatingMessage( # o, # QIcon(QPixmap.fromImage(currentPreset.image())), # 5000, # 99 # ) # else: # print("Failure") # # create_new_page(path) # # TODO: automatically close next and previous pages +3 to save memory def animation_tools_toggle(sketchbookname): app = Krita.instance() win = app.activeWindow() doc = app.activeDocument() for w in win.dockers(): # print(w.objectName()) # if w.objectName() in ["TimelineDocker", "OnionSkinsDocker", "AnimationCurvesDocker"]: if w.objectName() in ["TimelineDocker"]: print('>a', sketchbookname in ['animations']) print('>b', bool(doc.animationLength() > 1)) print('>c', doc.animationLength()) w.setVisible(sketchbookname in ['animations'] or doc.animationLength() > 1) # print(w.isEnabled()) def get_next_prev_page(path: Path, current_page_dt: datetime, prev=False, exact=False) -> None: app = Krita.instance() doc = app.activeDocument() win = app.activeWindow() view = win.activeView() paths = path.glob("*.kra") next_page_candidate = None # print("Current page: "+current_page_dt.strftime(dt_fmt)) i = 0 l = list(reversed(sorted(paths)) if prev else sorted(paths)) for p in l: i += 1 if exact: if p == Path(path).joinpath(f"{current_page_dt.strftime(dt_fmt)}.kra"): dt = datetime.strptime(Path(p).name, f"{dt_fmt}.kra") next_page_candidate = dt break if p == Path(path).joinpath(f"{current_page_dt.strftime(dt_fmt)}.kra"): continue try: dt = datetime.strptime(Path(p).name, f"{dt_fmt}.kra") if prev: if current_page_dt > dt: next_page_candidate = dt break else: if current_page_dt < dt: next_page_candidate = dt break except Exception as e: pass # print('sketchbookmode:', str(e)) if next_page_candidate is not None: #Check if next page already open in krita # print('cand '+Path(path).joinpath(next_page_candidate.strftime(dt_fmt) + ".kra").as_posix()) for v in app.activeWindow().views(): # print('view '+v.document().fileName()) if v.document().fileName() == Path(path).joinpath(next_page_candidate.strftime(dt_fmt) + ".kra").as_posix(): doc.setBatchmode(True) win.activate() win.showView(v) v.setVisible() currentPreset = view.currentBrushPreset() o = f"({len(app.activeWindow().views())}) " o += f"{Path(path).stem.upper()} " o += generate_id(seed=next_page_candidate.strftime(dt_fmt), separator='-', word_count=3) o += f" {len(l) - i + 1 if prev else i}/{len(l)}" r = FOLDERS.index(Path(path).name) r2 = FOLDERS[r+1 if r+1 < len(FOLDERS) else 0].upper() r3 = FOLDERS[r-1 if r-1 >= 0 else -1].upper() v.showFloatingMessage( f"{r2}\n{o}\n{r3}", # str(Path(path).joinpath(next_page_candidate.strftime(dt_fmt) + ".kra")), QIcon(QPixmap.fromImage(currentPreset.image())), 3000, 0 ) doc.setBatchmode(False) # print("OPEN ALREADY") animation_tools_toggle(path.stem) history[Path(path).stem.lower()] = next_page_candidate return doc.setBatchmode(True) doc2 = app.openDocument(Path(path).joinpath(f"{next_page_candidate.strftime(dt_fmt)}.kra").as_posix()) doc.setBatchmode(False) animation_tools_toggle(path.stem) history[Path(path).stem.lower()] = next_page_candidate app.activeWindow().addView(doc2) else: history[Path(path).stem.lower()] = None doc.setBatchmode(True) create_new_page2(path) doc.setBatchmode(False) animation_tools_toggle(path.stem) # TODO: automatically close next and previous pages +3 to save memory class SketchbookMode(Extension): def __init__(self, parent): self.books = FOLDERS self.head_book = "sketches" self.head_page = None super(SketchbookMode, self).__init__(parent) for d in self.books: history[d] = None def setup(self): pass def initialize(self): pass def createActions(self, window): def next_page(): app = Krita.instance() win = app.activeWindow() current_doc = win.activeView().document() if current_doc: try: dt = datetime.strptime(Path(current_doc.fileName()).name, f"{dt_fmt}.kra") get_next_prev_page(Path(current_doc.fileName()).parent, dt) except Exception as e: pass #print(e) else: get_next_prev_page(Path(current_doc.fileName()).parent, datetime.now()+timedelta(days=9999999), prev=True) def prev_page(): app = Krita.instance() win = app.activeWindow() current_doc = win.activeView().document() if current_doc: try: dt = datetime.strptime(Path(current_doc.fileName()).name, f"{dt_fmt}.kra") get_next_prev_page(Path(current_doc.fileName()).parent, dt, prev=True) except Exception as e: pass #print(e) else: get_next_prev_page(Path(current_doc.fileName()).parent, datetime.now()+timedelta(days=9999999), prev=True) def next_sketchbook(): print("next_sketchbook") app = Krita.instance() win = app.activeWindow() current_doc = win.activeView().document() if current_doc: dirname = Path(current_doc.fileName()).parent.stem print('dirname', dirname) if dirname in self.books: i = self.books.index(dirname) + 1 next_book = self.books[i if i < len(self.books) else i % len(self.books)] p = Path(current_doc.fileName()).parent.parent.joinpath(next_book) print(p.name.lower()) if history[p.name.lower()] is None: get_next_prev_page(p, datetime.now(), True) else: get_next_prev_page(p, history[p.name.lower()], True, True) # get_last_page(p) else: p = Path(current_doc.fileName()).parent.parent.joinpath(self.head_book) get_next_prev_page(p, datetime.now(), True) # get_last_page(p) print("next_sketchbook", dirname, p.as_posix()) def prev_sketchbook(): print("prev_sketchbook") app = Krita.instance() win = app.activeWindow() current_doc = win.activeView().document() if current_doc: dirname = Path(current_doc.fileName()).parent.stem print('dirname', dirname) if dirname in self.books: i = self.books.index(dirname) - 1 next_book = self.books[i if i < len(self.books) else i % len(self.books)] p = Path(current_doc.fileName()).parent.parent.joinpath(next_book) print(p.name.lower()) if history[p.name.lower()] is None: get_next_prev_page(p, datetime.now(), True) else: get_next_prev_page(p, history[p.name.lower()], True, True) # get_last_page(p) else: p = Path(current_doc.fileName()).parent.parent.joinpath(self.head_book) get_next_prev_page(p, datetime.now(), True) # get_last_page(p) print("prev_sketchbook", dirname, p.as_posix()) def toggle_tab_bar(): from PyQt5.QtWidgets import QStackedWidget, QTabBar, QMdiArea qwin = Krita.instance().activeWindow().qwindow() for a in qwin.findChildren(QMdiArea): e = a.findChild(QTabBar) if e: e.hide() if e.isVisible() else e.show() # print(dir(a.findChild(QTabBar))) break def fn1(): view = Krita.instance().activeWindow().activeView() canvas = view.canvas() canvas.setRotation(canvas.rotation()+90) def fn2(): view = Krita.instance().activeWindow().activeView() canvas = view.canvas() canvas.mirror() canvas.setRotation(180 if canvas.rotation() == 0 else 0) action = window.createAction("sketchbook_next_page", str(f"Get next sketchbook page"), "") action.triggered.connect(next_page) action = window.createAction("sketchbook_prev_page", str(f"Get prev sketchbook page"), "") action.triggered.connect(prev_page) action = window.createAction("sketchbook_next_sketchbook", str(f"Get next sketchbook type"), "") action.triggered.connect(next_sketchbook) action = window.createAction("sketchbook_prev_sketchbook", str(f"Get prev sketchbook type"), "") action.triggered.connect(prev_sketchbook) action = window.createAction("sketchbook_toggle_tab_bar", str(f"Toggle hide tab bar"), "") action.triggered.connect(toggle_tab_bar) action = window.createAction("rotate_90", str(f"Rotate 90"), "") action.triggered.connect(fn1) action = window.createAction("flip_vertical", str(f"Flip vert"), "") action.triggered.connect(fn2) # action = window.createAction("sketchbook_last_page", str(f"Toggle hide tab bar"), "") # action.triggered.connect(toggle_tab_bar)