Commit ecf39bd7 authored by dmMaze's avatar dmMaze
Browse files

support hide text style panel

parent bd09cfaf
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -937,7 +937,6 @@ TextAreaStyleButton {
    border-radius: 10px;
    padding: 5px;
    background-color: @widgetBackgroundColor;
    
}

TextAreaStyleButton#NewTextStyleButton {
@@ -956,6 +955,19 @@ TextAreaStyleButton::hover {
    background-color: #cad7ed;
}

HidePanelButton {
    width: 12px;
    height: 12px;
    padding: 3px;
    border: none;
    background-color: @widgetBackgroundColor;
    image: url(icons/titlebar_close.svg);
}

HidePanelButton::hover {
    background-color: #FF605C;
}

Widget#TextStyleAreaContent {
    background-color : @emptyContentBackgroundColor;
    border-radius: 7px;

ui/flow_layout.py

0 → 100644
+206 −0
Original line number Diff line number Diff line
from qtpy.QtWidgets import QLayout, QWidgetItem, QLayoutItem, QWidgetItem, QWidget
from qtpy.QtCore import QParallelAnimationGroup, Qt, QPropertyAnimation, QEasingCurve, QSize, QRect, QPoint
from typing import List

class WidgetItem(QWidgetItem):

    def sizeHint(self) -> QSize:
        return self.widget().sizeHint()


class FlowLayout(QLayout):
    """ Flow layout """

    def __init__(self, parent=None, needAni=False, isTight=False):
        """
        Parameters
        ----------
        parent:
            parent window or layout

        needAni: bool
            whether to add moving animation

        isTight: bool
            whether to use the tight layout when widgets are hidden
        """
        super().__init__(parent)
        self._items = []    # type: List[QLayoutItem]
        self._anis = []
        self._aniGroup = QParallelAnimationGroup(self)
        self._verticalSpacing = 10
        self._horizontalSpacing = 10
        self.duration = 300
        self.ease = QEasingCurve.Linear
        self.needAni = needAni
        self.isTight = isTight

        self.height = 0

    def insertWidget(self, idx: int, w: QWidget):
        self.addChildWidget(w)
        self.insertItem(idx, WidgetItem(w))

    def insertItem(self, idx:int, item):
        self._items.insert(idx, item)

    def addItem(self, item):
        self._items.append(item)

    def addWidget(self, w):
        super().addWidget(w)
        if not self.needAni:
            return

        ani = QPropertyAnimation(w, b'geometry')
        ani.setEndValue(QRect(QPoint(0, 0), w.size()))
        ani.setDuration(self.duration)
        ani.setEasingCurve(self.ease)
        w.setProperty('flowAni', ani)
        self._anis.append(ani)
        self._aniGroup.addAnimation(ani)

    def setAnimation(self, duration, ease=QEasingCurve.Linear):
        """ set the moving animation

        Parameters
        ----------
        duration: int
            the duration of animation in milliseconds

        ease: QEasingCurve
            the easing curve of animation
        """
        if not self.needAni:
            return

        self.duration = duration
        self.ease = ease

        for ani in self._anis:
            ani.setDuration(duration)
            ani.setEasingCurve(ease)

    def count(self):
        return len(self._items)

    def itemAt(self, index: int):
        if 0 <= index < len(self._items):
            return self._items[index]

        return None

    def takeAt(self, index: int):
        if 0 <= index < len(self._items):
            item = self._items[index]   # type: QWidgetItem
            ani = item.widget().property('flowAni')
            if ani:
                self._anis.remove(ani)
                self._aniGroup.removeAnimation(ani)
                ani.deleteLater()

            return self._items.pop(index).widget()

        return None

    def removeWidget(self, widget):
        for i, item in enumerate(self._items):
            if item.widget() is widget:
                return self.takeAt(i)

    def removeAllWidgets(self):
        """ remove all widgets from layout """
        while self._items:
            self.takeAt(0)

    def takeAllWidgets(self):
        """ remove all widgets from layout and delete them """
        while self._items:
            w = self.takeAt(0)
            if w:
                w.deleteLater()

    def expandingDirections(self):
        return Qt.Orientation(0)

    def hasHeightForWidth(self):
        return True

    def heightForWidth(self, width: int):
        """ get the minimal height according to width """
        return self._doLayout(QRect(0, 0, width, 0), False)

    def setGeometry(self, rect: QRect):
        super().setGeometry(rect)
        self._doLayout(rect, True)

    def sizeHint(self):
        return self.minimumSize()

    def minimumSize(self):
        size = QSize()

        for item in self._items:
            size = size.expandedTo(item.minimumSize())

        m = self.contentsMargins()
        size += QSize(m.left()+m.right(), m.top()+m.bottom())

        return size

    def setVerticalSpacing(self, spacing: int):
        """ set vertical spacing between widgets """
        self._verticalSpacing = spacing

    def verticalSpacing(self):
        """ get vertical spacing between widgets """
        return self._verticalSpacing

    def setHorizontalSpacing(self, spacing: int):
        """ set horizontal spacing between widgets """
        self._horizontalSpacing = spacing

    def horizontalSpacing(self):
        """ get horizontal spacing between widgets """
        return self._horizontalSpacing

    def _doLayout(self, rect: QRect, move: bool):
        """ adjust widgets position according to the window size """
        aniRestart = False
        margin = self.contentsMargins()
        x = rect.x() + margin.left()
        y = rect.y() + margin.top()
        rowHeight = 0
        spaceX = self.horizontalSpacing()
        spaceY = self.verticalSpacing()

        for i, item in enumerate(self._items):
            if item.widget() and not item.widget().isVisible() and self.isTight:
                continue

            nextX = x + item.sizeHint().width() + spaceX

            if nextX - spaceX > rect.right() and rowHeight > 0:
                x = rect.x() + margin.left()
                y = y + rowHeight + spaceY
                nextX = x + item.sizeHint().width() + spaceX
                rowHeight = 0

            if move:
                target = QRect(QPoint(x, y), item.sizeHint())
                if not self.needAni:
                    item.setGeometry(target)
                elif target != self._anis[i].endValue():
                    self._anis[i].stop()
                    self._anis[i].setEndValue(target)
                    aniRestart = True

            x = nextX
            rowHeight = max(rowHeight, item.sizeHint().height())

        if self.needAni and aniRestart:
            self._aniGroup.stop()
            self._aniGroup.start()

        self.height = y + rowHeight + margin.bottom() - rect.y()
        return self.height
 No newline at end of file
+14 −94
Original line number Diff line number Diff line
@@ -4,14 +4,15 @@ from typing import List

from qtpy.QtWidgets import QComboBox, QMenu, QMessageBox, QStackedLayout, QGraphicsDropShadowEffect, QLineEdit, QScrollArea, QSizePolicy, QHBoxLayout, QVBoxLayout, QFrame, QFontComboBox, QApplication, QPushButton, QCheckBox, QLabel
from qtpy.QtCore import Signal, Qt, QRectF
from qtpy.QtGui import QDoubleValidator, QFocusEvent, QMouseEvent, QTextCursor, QFontMetrics, QIcon, QColor, QPixmap, QPainter, QContextMenuEvent, QKeyEvent
from qtpy.QtGui import QDoubleValidator, QFocusEvent, QMouseEvent, QTextCursor, QFontMetrics, QColor, QPixmap, QPainter, QContextMenuEvent, QKeyEvent


from utils.fontformat import FontFormat
from utils import shared
from utils.config import pcfg, save_text_styles, text_styles
from utils import config as C
from .stylewidgets import Widget, ColorPicker, ClickableLabel, CheckableLabel, TextChecker, FlowLayout, ScrollBar
from .stylewidgets import Widget, ColorPicker, ClickableLabel, CheckableLabel, TextChecker, ScrollBar, ViewWidget
from .flow_layout import FlowLayout
from .textitem import TextBlkItem
from .text_graphical_effect import TextEffectPanel
from . import funcmaps as FM
@@ -352,14 +353,6 @@ class FontFamilyComboBox(QFontComboBox):
            self.apply_fontfamily()


CHEVRON_SIZE = 20
def chevron_down():
    return QIcon(r'icons/chevron-down.svg').pixmap(CHEVRON_SIZE, CHEVRON_SIZE, mode=QIcon.Mode.Normal)

def chevron_right():
    return QIcon(r'icons/chevron-right.svg').pixmap(CHEVRON_SIZE, CHEVRON_SIZE, mode=QIcon.Mode.Normal)


class StyleLabel(QLineEdit):

    edit_finished = Signal()
@@ -820,92 +813,19 @@ class TextStyleArea(QScrollArea):
        return super().contextMenuEvent(e)


class ExpandLabel(Widget):

    clicked = Signal()

    def __init__(self, text=None, parent=None, expanded=False, *args, **kwargs):
        super().__init__(parent=parent, *args, **kwargs)
        self.textlabel = QLabel(self)
        self.textlabel.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)
        font = self.textlabel.font()
        if shared.ON_MACOS:
            font.setPointSize(13)
        else:
            font.setPointSizeF(10)
        self.textlabel.setFont(font)
        self.arrowlabel = QLabel(self)
        self.arrowlabel.setFixedSize(CHEVRON_SIZE, CHEVRON_SIZE)
        self.arrowlabel.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)

        if text is not None:
            self.textlabel.setText(text)
        layout = QHBoxLayout(self)
        layout.addWidget(self.arrowlabel)
        layout.addWidget(self.textlabel)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(1)
        layout.addStretch(-1)
    
        self.expanded = False
        self.setExpand(expanded)
        self.setFixedHeight(26)

    def setExpand(self, expand: bool):
        self.expanded = expand
        if expand:
            self.arrowlabel.setPixmap(chevron_down())
        else:
            self.arrowlabel.setPixmap(chevron_right())

    def mousePressEvent(self, e: QMouseEvent) -> None:
        if e.button() == Qt.MouseButton.LeftButton:
            self.setExpand(not self.expanded)
            pcfg.expand_tstyle_panel = self.expanded
            self.clicked.emit()
        return super().mousePressEvent(e)


class TextStylePanel(Widget):

    def __init__(self, text=None, parent=None, expanded=True, *args, **kwargs):
        super().__init__(parent=parent, *args, **kwargs)
        
        self.title_label = ExpandLabel(text, self, expanded=expanded)
        self.style_area = TextStyleArea(self)

        layout = QVBoxLayout(self)
        layout.addWidget(self.title_label)
        layout.addWidget(self.style_area)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        if not expanded:
            self.style_area.hide()
        
        self.title_label.clicked.connect(self.on_title_label_clicked)
        self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum)

    def expand(self):
        if not self.title_label.expanded:
            self.title_label.setExpand(True)
        if self.style_area.isHidden():
            self.style_area.show()

    def on_title_label_clicked(self):
        if self.title_label.expanded:
            self.style_area.show()
        else:
            self.style_area.hide()
class TextStylePanel(ViewWidget):

    def setTitle(self, text: str):
        self.title_label.textlabel.setText(text)
    def __init__(self, text=None, parent=None, *args, **kwargs):

    def elidedText(self, text: str):
        fm = QFontMetrics(self.title_label.font())
        return fm.elidedText(text, Qt.TextElideMode.ElideRight, self.style_area.width() - 40)
        style_area = TextStyleArea()
        super().__init__(style_area, text=text, parent=parent, *args, **kwargs)
        self.style_area = style_area

    def title(self) -> str:
        return self.title_label.textlabel.text()
        self.register_view_widget(
            'show_text_style_preset',
            'expand_tstyle_panel',
            self.tr('Show Text Style Panel')
        )


class FontFormatPanel(Widget):
@@ -1003,7 +923,7 @@ class FontFormatPanel(Widget):
        lettersp_hlayout.setSpacing(shared.WIDGET_SPACING_CLOSE)
        
        self.global_fontfmt_str = self.tr("Global Font Format")
        self.textstyle_panel = TextStylePanel(self.global_fontfmt_str, parent=self, expanded=pcfg.expand_tstyle_panel)
        self.textstyle_panel = TextStylePanel(self.global_fontfmt_str, parent=self)
        self.textstyle_panel.style_area.active_text_style_label_changed.connect(self.on_active_textstyle_label_changed)
        self.textstyle_panel.style_area.active_stylename_edited.connect(self.on_active_stylename_edited)

+2 −1
Original line number Diff line number Diff line
@@ -10,7 +10,8 @@ from utils.logger import logger as LOGGER
from .page_search_widget import SearchEditor, HighlightMatched, SEARCHRST_HIGHLIGHT_COLOR
from .misc import doc_replace
from utils.config import pcfg
from .stylewidgets import Widget, NoBorderPushBtn, ProgressMessageBox
from .stylewidgets import Widget, NoBorderPushBtn
from .message import ProgressMessageBox
from .textitem import TextBlkItem, TextBlock
from .textedit_area import TransPairWidget, SourceTextEdit, TransTextEdit
from .config_proj import ProjImgTrans
+1 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ from utils.logger import logger as LOGGER
from utils.io_utils import imread, imwrite
from utils import create_error_dialog
from .config_proj import ProjImgTrans
from .stylewidgets import ProgressMessageBox
from .message import ProgressMessageBox


class ThreadBase(QThread):
Loading