Beispiel #1
0
def _get_monospace_font_impl(small=False) -> QFont:
    begun = time.monotonic()
    multiplier = 0.8 if small else 1.0
    min_font_size = min(7, QFont().pointSize())
    preferred = [
        "Consolas",
        "DejaVu Sans Mono",
        "Monospace",
        "Lucida Console",
        "Monaco",
    ]
    for name in preferred:
        font = QFont(name)
        if QFontInfo(font).fixedPitch():
            font.setPointSize(
                round(max(min_font_size,
                          QFont().pointSize() * multiplier)))
            _logger.info(
                "Selected monospace font (%.6f seconds): %r",
                time.monotonic() - begun,
                font.toString(),
            )
            return font

    font = QFont()
    font.setStyleHint(QFont().Monospace)
    font.setFamily("monospace")
    _logger.info(
        "Using fallback monospace font (%.6f seconds): %r",
        time.monotonic() - begun,
        font.toString(),
    )
    return font
Beispiel #2
0
def get_monospace_font():
    preferred = ['Consolas', 'DejaVu Sans Mono', 'Monospace', 'Lucida Console', 'Monaco']
    for name in preferred:
        font = QFont(name)
        if QFontInfo(font).fixedPitch():
            logger.debug('Preferred monospace font: %r', font.toString())
            return font

    font = QFont()
    font.setStyleHint(QFont().Monospace)
    font.setFamily('monospace')
    logger.debug('Using fallback monospace font: %r', font.toString())
    return font
Beispiel #3
0
def get_monospace_font():
    preferred = ['Consolas', 'DejaVu Sans Mono', 'Monospace', 'Lucida Console', 'Monaco']
    for name in preferred:
        font = QFont(name)
        if QFontInfo(font).fixedPitch():
            logger.debug('Preferred monospace font: %r', font.toString())
            return font

    font = QFont()
    font.setStyleHint(QFont().Monospace)
    font.setFamily('monospace')
    logger.debug('Using fallback monospace font: %r', font.toString())
    return font
Beispiel #4
0
    def __init__(self, text='', font_string=None, margins: Margins = None):
        super().__init__(margins)
        self.text = text

        if font_string is None:
            font = QFont()
            font.setStyleHint(QFont.Helvetica)
            font.setFamily('Helvetica Neue')

            # font.Helvetica
            print('Default font:', font.family(), font.families(),
                  font.toString())
            font.setPixelSize(USABLE_HEIGHT)
            self.font_string = font.toString()
        else:
            self.font_string = font_string
Beispiel #5
0
 def load(self):
     """Load the value from config to GUI
     """
     font = QFont(self.config.get(self.familyOptionName),
                  self.config.get(self.sizeOptionName))
     self.editControl.setFont(font)
     self.editControl.setToolTip(font.toString())
Beispiel #6
0
    def setFont(self, font=None):
        if font is None:
            if "Font" in self.config['Paper']:
                font = QFont()
                font.fromString(self.config['Paper']['Font'])

        if font is not None:
            self.config['Paper']['Font'] = font.toString()
            for i in range(self.tab_bar.count()):
                editor = self.tab_bar.widget(i)
                editor.setFont(font)
Beispiel #7
0
 def render__label_qfont(self, qfont: QFont):
     self.cfg.render.label_font = attr.evolve(
         self.cfg.render.label_font,
         # Font file selection
         family=qfont.family(),
         bold=qfont.bold(),
         italic=qfont.italic(),
         # Font size
         size=qfont.pointSizeF(),
         # QFont implementation details
         toString=qfont.toString(),
     )
	def parseFont(self, info):
		font = QFont(self.font())
		for s in info.split(' '):
			s = s.strip().lower()
			if (s.endswith("pt")):
				font.setPointSizeF(float(s[:-2]))

			elif s == "bold" or s == "b": font.setBold(True)
			elif s == "italic" or s == "i": font.setItalic(True)
			elif s == "underline" or s == "u": font.setUnderline(True)
			elif s == "strike": font.setStrikeOut(True)
		print(font.toString())
		return font
Beispiel #9
0
 def render(self):
     d = self.data
     font = QFont()
     font.fromString(d.font_string)
     width = QFontMetrics(font).width(d.text)
     print(width, font.toString(), d.text)
     img = QImage(width, USABLE_HEIGHT, QImage.Format_ARGB32)
     img.fill(0xffffffff)
     p = QPainter(img)
     p.setFont(font)
     rect = img.rect().marginsRemoved(d.margins.getQMargins())
     p.drawText(rect, Qt.AlignLeft | Qt.AlignHCenter, d.text)
     p.end()
     del p
     return img
Beispiel #10
0
    def open_font_dialog(self):
        """
        Opens a QFontDialog and updates current font and config with the choice (if any).
        :return:
        """
        font = QFont()
        font.fromString(read_config(self.cfg_section, self.cfg_option, literal_eval=False))
        font, ok = QFontDialog.getFont()

        # If user selected a font.
        if ok:
            # Update current font ref.
            self.current_font = font

            # Save selected font to config.
            set_config(self.cfg_section, self.cfg_option, font.toString())

            # Make button text reflect changes.
            self.update_info()
Beispiel #11
0
    def wheelEvent(self, event):
        """
        We catch wheelEvent if key modifier is CTRL to change font size.
        Note: this should be in a class specific for main textEditView (#TODO).
        """
        if event.modifiers() & Qt.ControlModifier:
            # Get the wheel angle.
            d = event.angleDelta().y() / 120

            # Update settings
            f = QFont()
            f.fromString(settings.textEditor["font"])
            f.setPointSizeF(f.pointSizeF() + d)
            settings.textEditor["font"] = f.toString()

            # Update font to all textEditView. Drastically.
            for w in F.mainWindow().findChildren(textEditView, QRegExp(".*")):
                w.loadFontSettings()

            # We tell the world that we accepted this event
            event.accept()
            return

        QTextEdit.wheelEvent(self, event)
Beispiel #12
0
    def wheelEvent(self, event):
        """
        We catch wheelEvent if key modifier is CTRL to change font size.
        Note: this should be in a class specific for main textEditView (#TODO).
        """
        if event.modifiers() & Qt.ControlModifier:
            # Get the wheel angle.
            d = event.angleDelta().y() / 120

            # Update settings
            f = QFont()
            f.fromString(settings.textEditor["font"])
            f.setPointSizeF(f.pointSizeF() + d)
            settings.textEditor["font"] = f.toString()

            # Update font to all textEditView. Drastically.
            for w in F.mainWindow().findChildren(textEditView, QRegExp(".*")):
                w.loadFontSettings()

            # We tell the world that we accepted this event
            event.accept()
            return

        QTextEdit.wheelEvent(self, event)
Beispiel #13
0
class Command(QtCore.QObject):

    videoTask = QtCore.pyqtSignal(str, str, QFont, int, int, int, int, tuple,
                                  tuple, str, str)

    def __init__(self):
        QtCore.QObject.__init__(self)

        import argparse
        self.parser = argparse.ArgumentParser(
            description='Create a visualization for an audio file')
        self.parser.add_argument('-i',
                                 '--input',
                                 dest='input',
                                 help='input audio file',
                                 required=True)
        self.parser.add_argument('-o',
                                 '--output',
                                 dest='output',
                                 help='output video file',
                                 required=True)
        self.parser.add_argument('-b',
                                 '--background',
                                 dest='bgimage',
                                 help='background image file',
                                 required=True)
        self.parser.add_argument('-t',
                                 '--text',
                                 dest='text',
                                 help='title text',
                                 required=True)
        self.parser.add_argument('-f',
                                 '--font',
                                 dest='font',
                                 help='title font',
                                 required=False)
        self.parser.add_argument('-s',
                                 '--fontsize',
                                 dest='fontsize',
                                 help='title font size',
                                 required=False)
        self.parser.add_argument('-c',
                                 '--textcolor',
                                 dest='textcolor',
                                 help='title text color in r,g,b format',
                                 required=False)
        self.parser.add_argument('-C',
                                 '--viscolor',
                                 dest='viscolor',
                                 help='visualization color in r,g,b format',
                                 required=False)
        self.parser.add_argument('-x',
                                 '--xposition',
                                 dest='xposition',
                                 help='x position',
                                 required=False)
        self.parser.add_argument('-y',
                                 '--yposition',
                                 dest='yposition',
                                 help='y position',
                                 required=False)
        self.parser.add_argument('-a',
                                 '--alignment',
                                 dest='alignment',
                                 help='title alignment',
                                 required=False,
                                 type=int,
                                 choices=[0, 1, 2])
        self.args = self.parser.parse_args()

        self.settings = QSettings('settings.ini', QSettings.IniFormat)

        # load colours as tuples from comma-separated strings
        self.textColor = core.Core.RGBFromString(
            self.settings.value("textColor", '255, 255, 255'))
        self.visColor = core.Core.RGBFromString(
            self.settings.value("visColor", '255, 255, 255'))
        if self.args.textcolor:
            self.textColor = core.Core.RGBFromString(self.args.textcolor)
        if self.args.viscolor:
            self.visColor = core.Core.RGBFromString(self.args.viscolor)

        # font settings
        if self.args.font:
            self.font = QFont(self.args.font)
        else:
            self.font = QFont(self.settings.value("titleFont", QFont()))

        if self.args.fontsize:
            self.fontsize = int(self.args.fontsize)
        else:
            self.fontsize = int(self.settings.value("fontSize", 35))
        if self.args.alignment:
            self.alignment = int(self.args.alignment)
        else:
            self.alignment = int(self.settings.value("alignment", 0))

        if self.args.xposition:
            self.textX = int(self.args.xposition)
        else:
            self.textX = int(self.settings.value("xPosition", 70))

        if self.args.yposition:
            self.textY = int(self.args.yposition)
        else:
            self.textY = int(self.settings.value("yPosition", 375))

        ffmpeg_cmd = self.settings.value("ffmpeg_cmd", expanduser("~"))

        self.videoThread = QtCore.QThread(self)
        self.videoWorker = video_thread.Worker(self)

        self.videoWorker.moveToThread(self.videoThread)
        self.videoWorker.videoCreated.connect(self.videoCreated)

        self.videoThread.start()
        self.videoTask.emit(self.args.bgimage, self.args.text, self.font,
                            self.fontsize, self.alignment, self.textX,
                            self.textY, self.textColor, self.visColor,
                            self.args.input, self.args.output)

    def videoCreated(self):
        self.videoThread.quit()
        self.videoThread.wait()
        self.cleanUp()

    def cleanUp(self):
        self.settings.setValue("titleFont", self.font.toString())
        self.settings.setValue("alignment", str(self.alignment))
        self.settings.setValue("fontSize", str(self.fontsize))
        self.settings.setValue("xPosition", str(self.textX))
        self.settings.setValue("yPosition", str(self.textY))
        self.settings.setValue("visColor", '%s,%s,%s' % self.visColor)
        self.settings.setValue("textColor", '%s,%s,%s' % self.textColor)
        sys.exit(0)
class Command(QObject):

    videoTask = pyqtSignal(str, str, QFont, float, int, int, int, int, int,
                           tuple, tuple, str, str)

    def __init__(self):
        QObject.__init__(self)

        import argparse

        self.parser = argparse.ArgumentParser(
            description="Create a visualization for an audio file")
        self.parser.add_argument("-i",
                                 "--input",
                                 dest="input",
                                 help="input audio file",
                                 required=True)
        self.parser.add_argument("-o",
                                 "--output",
                                 dest="output",
                                 help="output video file",
                                 required=True)
        self.parser.add_argument(
            "-b",
            "--background",
            dest="bgimage",
            help="background image file",
            required=True,
        )
        self.parser.add_argument("-t",
                                 "--text",
                                 dest="text",
                                 help="title text",
                                 required=True)
        self.parser.add_argument("-f",
                                 "--font",
                                 dest="font",
                                 help="title font",
                                 required=False)
        self.parser.add_argument(
            "-r",
            "--resolution",
            dest="resolution",
            help="video resolution (WxH, e.g. 1280x720)",
            required=False,
        )
        self.parser.add_argument("--fps",
                                 dest="fps",
                                 help="frames per second",
                                 required=False)
        self.parser.add_argument("-s",
                                 "--fontsize",
                                 dest="fontsize",
                                 help="title font size",
                                 required=False)
        self.parser.add_argument(
            "-c",
            "--textcolor",
            dest="textcolor",
            help="title text color in r,g,b format",
            required=False,
        )
        self.parser.add_argument(
            "-C",
            "--viscolor",
            dest="viscolor",
            help="visualization color in r,g,b format",
            required=False,
        )
        self.parser.add_argument(
            "-x",
            "--xposition",
            dest="xposition",
            help="text x position",
            required=False,
        )
        self.parser.add_argument(
            "-y",
            "--yposition",
            dest="yposition",
            help="text y position",
            required=False,
        )
        self.parser.add_argument(
            "-a",
            "--alignment",
            dest="alignment",
            help="title alignment",
            required=False,
            type=int,
            choices=[0, 1, 2],
        )
        self.args = self.parser.parse_args()

        self.settings = QSettings("settings.ini", QSettings.IniFormat)

        # load colours as tuples from comma-separated strings
        self.textColor = core.Core.RGBFromString(
            self.settings.value("textColor", "255, 255, 255"))
        self.visColor = core.Core.RGBFromString(
            self.settings.value("visColor", "255, 255, 255"))
        if self.args.textcolor:
            self.textColor = core.Core.RGBFromString(self.args.textcolor)
        if self.args.viscolor:
            self.visColor = core.Core.RGBFromString(self.args.viscolor)

        # font settings
        if self.args.font:
            self.font = QFont(self.args.font, self.fontsize)
        else:
            self.font = QFont()
            self.font.fromString(self.settings.value("titleFont"))
        if self.args.fontsize:
            self.font.setPointSize(self.fontsize)

        if self.args.alignment:
            self.alignment = int(self.args.alignment)
        else:
            self.alignment = int(self.settings.value("alignment", 0))

        if self.args.fps:
            self.fps = float(self.args.fps)
        else:
            self.fps = float(self.settings.value("fps", 30))

        if self.args.resolution:
            x, y = self.args.resolution.split("x")
            self.resX = int(x)
            self.resY = int(y)
        else:
            self.resX = int(self.settings.value("xResolution", 1280))
            self.resY = int(self.settings.value("yResolution", 720))

        if self.args.xposition:
            self.textX = int(self.args.xposition)
        else:
            self.textX = int(self.settings.value("xPosition", 0))

        if self.args.yposition:
            self.textY = int(self.args.yposition)
        else:
            self.textY = int(self.settings.value("yPosition", 0))

        self.videoThread = QThread(self)
        self.videoWorker = video_thread.Worker(self)

        self.videoWorker.moveToThread(self.videoThread)
        self.videoWorker.videoCreated.connect(self.videoCreated)

        self.videoThread.start()
        self.videoTask.emit(
            self.args.bgimage,
            self.args.text,
            self.font,
            self.fps,
            self.alignment,
            self.textX,
            self.textY,
            self.resX,
            self.resY,
            self.textColor,
            self.visColor,
            self.args.input,
            self.args.output,
        )

    def videoCreated(self):
        self.videoThread.quit()
        self.videoThread.wait()
        self.cleanUp()

    def cleanUp(self):
        self.settings.setValue("titleFont", self.font.toString())
        self.settings.setValue("fps", str(self.fps))
        self.settings.setValue("alignment", str(self.alignment))
        self.settings.setValue("xPosition", str(self.textX))
        self.settings.setValue("yPosition", str(self.textY))
        self.settings.setValue("xResolution", str(self.resX))
        self.settings.setValue("yResolution", str(self.resY))
        self.settings.setValue("visColor", "%s,%s,%s" % self.visColor)
        self.settings.setValue("textColor", "%s,%s,%s" % self.textColor)
        sys.exit(0)
Beispiel #15
0
class App(QMainWindow):
    def __init__(self, *arg, **kwargs):
        '''
        Initialize the Application.
        '''

        super().__init__()
        self.setWindowTitle('TopWatch')
        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
                            | Qt.Dialog)
        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAttribute(Qt.WA_TranslucentBackground, True)

        # Hidden opacity used as a temporary slot when opacity is changed for blinking
        self._opacity = 1

        # set app icon
        self.scriptDir = opath.dirname(opath.realpath(__file__))
        self.setWindowIcon(QIcon(opath.join(self.scriptDir, 'icon.png')))

        # Setup initial color, font and window position
        configuration, ok = setup.init(self.scriptDir)
        self.color = configuration['color']
        self.font = QFont()
        self.font.fromString(configuration['font'])

        self.xpos = configuration['x']
        self.ypos = configuration['y']
        self.setGeometry(self.xpos, self.ypos,
                         self.geometry().width(),
                         self.geometry().height())

        self.opacity = configuration['opacity']

        self.blinkActive = False
        self.blinkPeriod = configuration['blinkPeriod']
        self.blinkNb = configuration['blinkNb']
        self.blinkFreq = configuration['blinkFreq']

        # Add label
        self.label = QLabel('', self)
        self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setStyleSheet('QLabel { color: %s}' % self.color)
        self.label.setFont(self.font)
        self.showTime()

        self.setCentralWidget(self.label)

        # Set menu
        menubar = self.menuBar()
        colorAction = QAction('&Text color', self)
        colorAction.setShortcut('Ctrl+C')
        colorAction.setStatusTip('Change text color')
        colorAction.triggered.connect(self.changeColor)

        fontAction = QAction('&Change font', self)
        fontAction.setShortcut('Ctrl+F')
        fontAction.setStatusTip('Change text font')
        fontAction.triggered.connect(self.changeFont)

        resetAction = QAction('&Reset', self)
        resetAction.setShortcut('Ctrl+Alt+R')
        resetAction.setStatusTip('Reset configuration')
        resetAction.triggered.connect(self.reset)

        saveAction = QAction('&Save', self)
        saveAction.setShortcut('Ctrl+S')
        saveAction.setStatusTip('Save current configuration')
        saveAction.triggered.connect(self.save)

        blinkAction = QAction('&Blink', self)
        blinkAction.setShortcut('Ctrl+b')
        blinkAction.setStatusTip('Blink configuration')
        blinkAction.triggered.connect(self.blinkWindow)

        self.filemenu = menubar.addMenu('&File')
        self.filemenu.addAction(saveAction)

        self.editmenu = menubar.addMenu('&Edit')
        self.editmenu.addAction(blinkAction)

        self.settingmenu = menubar.addMenu('&Settings')
        self.settingmenu.addAction(colorAction)
        self.settingmenu.addAction(fontAction)
        self.settingmenu.addAction(resetAction)

        # Start timer
        self.timer = QTimer()
        self.timer.timeout.connect(self.showTime)
        self.timer.start(1000)

        # Blink timer
        self.blinktimer = QTimer()
        self.blinktimer.timeout.connect(self.run_blink)

        # Small timer used to make the text flicker rapidly
        self.smalltimer = QTimer()
        self.smalltimer.timeout.connect(self.blink_text)

        self.op = QGraphicsOpacityEffect(self)
        self.op.setOpacity(self.opacity)
        self.label.setGraphicsEffect(self.op)
        self.setAutoFillBackground(True)

        self.show()

        # Set dimensions relative to label dimensions
        width = self.label.fontMetrics().width(self.label.text()) + 5
        height = self.label.fontMetrics().height() + 5
        self.setFixedSize(width, height)

    #####################################
    #        Blink windows setup        #
    #####################################

    def blinkWindow(self, *args, **kwargs):
        '''
        Creates a window to setup blinking.
        If blinking is activated, calling this function deactivates it.
        '''

        if self.blinkActive:
            # Reset to default values and show back the clock
            self.blinkActive = False

            # Stop timers
            self.smalltimer.stop()
            self.blinktimer.stop()

            # Resume previous opacity
            self.opacity = self._opacity
            self.setLabelOpacity(self.opacity)
        else:
            blinkDialog = BlinkWindow(self)
            blinkDialog.show()

        return

    def blink_text(self, *args, **kwargs):
        '''Function used to make the text blink a given number of times.'''

        self.cnt += 1
        self.setLabelOpacity(1 - self.opacity)

        # Blink 9 times for now and then stop small timer
        if self.cnt == self.blinkNb:
            self.setLabelOpacity(0)
            self.smalltimer.stop()

        return

    def run_blink(self, *args, **kwargs):
        '''Function called ever time the text must be blinked.'''

        # Counter used to know when to stop the flickering
        self.cnt = 0
        self.smalltimer.start(100)
        return

    def start_blink(self, blinkfreq, period, nb, *args, **kwargs):
        '''
        Starts blinking of the clock.

        :param float blinkfreq: number of ms between blinks
        :param QTimeEdit period: time between two blink phases
        :param int nb: number of blinks per blink phase
        '''

        if not isinstance(blinkfreq, (int, float)):
            raise TypeError(
                'Blinking frequency must be an int but is given as a %s' %
                type(blinkfreq))
        else:
            blinkfreq = int(blinkfreq)

        if blinkfreq <= 0:
            raise ValueError(
                'Blinking frequency must be positive only (current value is %f)'
                % blinkfreq)

        if not isinstance(nb, (int, float)):
            raise TypeError(
                'Number of blinks must be int but is given as a %s' % type(nb))
        else:
            nb = int(nb)

        if nb <= 0:
            raise ValueError(
                'Number of blinks must be positive only (current value is %d)'
                % nb)

        # Store values if the user save the current configuration later on
        self.blinkActive = True
        self.blinkNb = nb
        self.blinkFreq = blinkfreq  # in ms
        self.blinkPeriod = period

        # Period between blinking phases in ms
        period_ms = sum([
            int(i) * 60**pos for pos, i in enumerate(
                self.blinkPeriod.toString().split(':')[::-1])
        ]) * 1000

        # Save opacity for when we go back to normal
        self._opacity = self.opacity
        self.setLabelOpacity(0)

        self.blinktimer.start(period_ms)
        return

    #############################################
    #               Miscellaneous               #
    #############################################

    def setLabelOpacity(self, value, *args, **kwargs):
        '''Set the opacity of the label.'''

        if value > 1:
            value = 1
        elif value < 0:
            value = 0

        self.opacity = value
        self.op.setOpacity(self.opacity)
        return

    def changeColor(self, *args, **kwargs):
        '''Ask for a text color and change it.'''

        color = QColorDialog.getColor()
        if color.isValid():
            self.color = color
            self.label.setStyleSheet('QLabel { color: %s }' %
                                     self.color.name())
        return

    def changeFont(self, *args, **kwargs):
        '''Ask for a text style and change it.'''

        font, ok = QFontDialog.getFont()
        if ok:
            self.font = font
            self.updateFont()
        return

    def keyPressEvent(self, e, *args, **kwargs):
        ''''Actions taken when a key is pressed.'''

        # Deal with shift key being pressed first
        if e.modifiers() & Qt.ShiftModifier:
            if e.key() == Qt.Key_Up:
                self.setLabelOpacity(self.opacity + 0.05)
            elif e.key() == Qt.Key_Down:
                self.setLabelOpacity(self.opacity - 0.05)
        else:
            if e.key() == Qt.Key_Down:
                newSize = self.font.pointSize() - 1
                if newSize < 1:
                    newSize = 1

                self.font.setPointSize(newSize)

            elif e.key() == Qt.Key_Up:
                self.font.setPointSize(self.font.pointSize() + 1)

            else:
                return

            self.updateFont()
        return

    def reset(self, *args, **kwargs):
        '''Reset the configuration.'''

        # Reset interface
        self.color = '#ffdd1c'
        self.font.fromString('fixed,30,-1,5,75,0,0,0,0,0')
        self.label.setStyleSheet('QLabel { color: %s }' % self.color)
        self.updateFont()

        # Reset configuration file
        setup.default('settings.yaml')
        return

    def updateFont(self, *args, **kwargs):
        '''Update the label font with the value given in self.font and update the window size accordingly.'''

        self.label.setFont(self.font)
        width = self.label.fontMetrics().width(self.label.text()) + 2
        height = self.label.fontMetrics().height() + 2
        self.setFixedSize(width, height)
        return

    def save(self, *args, **kwargs):
        '''Save the current configuration.'''

        # Try to save color with its name if it exists, otherwise use color code
        try:
            color = self.color.name()
        except AttributeError:
            color = self.color

        # Convert blinking period from Qt Qtimer to string
        period_str = self.blinkPeriod.toString()

        configuration = {
            'font': self.font.toString(),
            'color': color,
            'x': self.x(),
            'y': self.y(),
            'opacity': round(self.opacity, 2),
            'blinkPeriod': period_str,
            'blinkFreq': int(self.blinkFreq),
            'blinkNb': int(self.blinkNb)
        }
        setup.writeConfiguration(opath.join(self.scriptDir, 'settings.yaml'),
                                 configuration)
        return

    def showTime(self, *args, **kwargs):
        '''Update the time label when value has changed.'''

        time = QDateTime.currentDateTime()
        timeStr = time.toString('hh:mm')

        if timeStr != self.label.text():
            self.label.setText(timeStr)
        return

    ############################################
    #               Mouse events               #
    ############################################

    def mousePressEvent(self, event):

        button = event.button()

        if button == 1:
            self.oldPos = event.globalPos()
        elif button == 2:
            self.close()
        return

    def mouseMoveEvent(self, event):
        delta = QPoint(event.globalPos() - self.oldPos)
        self.move(self.x() + delta.x(), self.y() + delta.y())
        self.oldPos = event.globalPos()
        return
    def setFontStyle(self, style: str):
        font = QFont()
        font.fromString(self.settings[NotebookSettings.font_info])
        font.setFamily(style)

        self.settings[NotebookSettings.font_info] = font.toString()
Beispiel #17
0
class Component(Component):
    name = 'Title Text'
    version = '1.0.1'

    def widget(self, *args):
        super().widget(*args)
        self.title = 'Text'
        self.alignment = 1
        self.titleFont = QFont()
        self.fontSize = self.height / 13.5

        self.page.comboBox_textAlign.addItem("Left")
        self.page.comboBox_textAlign.addItem("Middle")
        self.page.comboBox_textAlign.addItem("Right")
        self.page.comboBox_textAlign.setCurrentIndex(int(self.alignment))

        self.page.spinBox_fontSize.setValue(int(self.fontSize))
        self.page.lineEdit_title.setText(self.title)

        self.page.pushButton_center.clicked.connect(self.centerXY)
        self.page.fontComboBox_titleFont.currentFontChanged.connect(
            self.update)

        self.trackWidgets(
            {
                'textColor': self.page.lineEdit_textColor,
                'title': self.page.lineEdit_title,
                'alignment': self.page.comboBox_textAlign,
                'fontSize': self.page.spinBox_fontSize,
                'xPosition': self.page.spinBox_xTextAlign,
                'yPosition': self.page.spinBox_yTextAlign,
                'fontStyle': self.page.comboBox_fontStyle,
                'stroke': self.page.spinBox_stroke,
                'strokeColor': self.page.lineEdit_strokeColor,
                'shadow': self.page.checkBox_shadow,
                'shadX': self.page.spinBox_shadX,
                'shadY': self.page.spinBox_shadY,
                'shadBlur': self.page.spinBox_shadBlur,
            },
            colorWidgets={
                'textColor': self.page.pushButton_textColor,
                'strokeColor': self.page.pushButton_strokeColor,
            },
            relativeWidgets=[
                'xPosition', 'yPosition', 'fontSize', 'stroke', 'shadX',
                'shadY', 'shadBlur'
            ])
        self.centerXY()

    def update(self):
        self.titleFont = self.page.fontComboBox_titleFont.currentFont()
        if self.page.checkBox_shadow.isChecked():
            self.page.label_shadX.setHidden(False)
            self.page.spinBox_shadX.setHidden(False)
            self.page.spinBox_shadY.setHidden(False)
            self.page.label_shadBlur.setHidden(False)
            self.page.spinBox_shadBlur.setHidden(False)
        else:
            self.page.label_shadX.setHidden(True)
            self.page.spinBox_shadX.setHidden(True)
            self.page.spinBox_shadY.setHidden(True)
            self.page.label_shadBlur.setHidden(True)
            self.page.spinBox_shadBlur.setHidden(True)

    def centerXY(self):
        self.setRelativeWidget('xPosition', 0.5)
        self.setRelativeWidget('yPosition', 0.521)

    def getXY(self):
        '''Returns true x, y after considering alignment settings'''
        fm = QtGui.QFontMetrics(self.titleFont)
        x = self.pixelValForAttr('xPosition')

        if self.alignment == 1:  # Middle
            offset = int(fm.width(self.title) / 2)
            x -= offset
        if self.alignment == 2:  # Right
            offset = fm.width(self.title)
            x -= offset

        return x, self.yPosition

    def loadPreset(self, pr, *args):
        super().loadPreset(pr, *args)

        font = QFont()
        font.fromString(pr['titleFont'])
        self.page.fontComboBox_titleFont.setCurrentFont(font)

    def savePreset(self):
        saveValueStore = super().savePreset()
        saveValueStore['titleFont'] = self.titleFont.toString()
        return saveValueStore

    def previewRender(self):
        return self.addText(self.width, self.height)

    def properties(self):
        props = ['static']
        if not self.title:
            props.append('error')
        return props

    def error(self):
        return "No text provided."

    def frameRender(self, frameNo):
        return self.addText(self.width, self.height)

    def addText(self, width, height):
        font = self.titleFont
        font.setPixelSize(self.fontSize)
        font.setStyle(QFont.StyleNormal)
        font.setWeight(QFont.Normal)
        font.setCapitalization(QFont.MixedCase)
        if self.fontStyle == 1:
            font.setWeight(QFont.DemiBold)
        if self.fontStyle == 2:
            font.setWeight(QFont.Bold)
        elif self.fontStyle == 3:
            font.setStyle(QFont.StyleItalic)
        elif self.fontStyle == 4:
            font.setWeight(QFont.Bold)
            font.setStyle(QFont.StyleItalic)
        elif self.fontStyle == 5:
            font.setStyle(QFont.StyleOblique)
        elif self.fontStyle == 6:
            font.setCapitalization(QFont.SmallCaps)

        image = FramePainter(width, height)
        x, y = self.getXY()
        log.debug('Text position translates to %s, %s', x, y)
        if self.stroke > 0:
            outliner = QtGui.QPainterPathStroker()
            outliner.setWidth(self.stroke)
            path = QtGui.QPainterPath()
            if self.fontStyle == 6:
                # PathStroker ignores smallcaps so we need this weird hack
                path.addText(x, y, font, self.title[0])
                fm = QtGui.QFontMetrics(font)
                newX = x + fm.width(self.title[0])
                strokeFont = self.page.fontComboBox_titleFont.currentFont()
                strokeFont.setCapitalization(QFont.SmallCaps)
                strokeFont.setPixelSize(int((self.fontSize / 7) * 5))
                strokeFont.setLetterSpacing(QFont.PercentageSpacing, 139)
                path.addText(newX, y, strokeFont, self.title[1:])
            else:
                path.addText(x, y, font, self.title)
            path = outliner.createStroke(path)
            image.setPen(QtCore.Qt.NoPen)
            image.setBrush(PaintColor(*self.strokeColor))
            image.drawPath(path)

        image.setFont(font)
        image.setPen(self.textColor)
        image.drawText(x, y, self.title)

        # turn QImage into Pillow frame
        frame = image.finalize()
        if self.shadow:
            shadImg = ImageEnhance.Contrast(frame).enhance(0.0)
            shadImg = shadImg.filter(ImageFilter.GaussianBlur(self.shadBlur))
            shadImg = ImageChops.offset(shadImg, self.shadX, self.shadY)
            shadImg.paste(frame, box=(0, 0), mask=frame)
            frame = shadImg

        return frame

    def commandHelp(self):
        print('Enter a string to use as centred white text:')
        print('    "title=User Error"')
        print('Specify a text color:\n    color=255,255,255')
        print('Set custom x, y position:\n    x=500 y=500')

    def command(self, arg):
        if '=' in arg:
            key, arg = arg.split('=', 1)
            if key == 'color':
                self.page.lineEdit_textColor.setText(arg)
                return
            elif key == 'size':
                self.page.spinBox_fontSize.setValue(int(arg))
                return
            elif key == 'x':
                self.page.spinBox_xTextAlign.setValue(int(arg))
                return
            elif key == 'y':
                self.page.spinBox_yTextAlign.setValue(int(arg))
                return
            elif key == 'title':
                self.page.lineEdit_title.setText(arg)
                return
        super().command(arg)
    def setFontSize(self, size: str):
        font = QFont()
        font.fromString(self.settings[NotebookSettings.font_info])
        font.setPointSize(int(size))

        self.settings[NotebookSettings.font_info] = font.toString()
Beispiel #19
0
 def load(self):
     """Load the value from config to GUI
     """
     font = QFont(self.config.get(self.familyOptionName), self.config.get(self.sizeOptionName))
     self.editControl.setFont(font)
     self.editControl.setToolTip(font.toString())
Beispiel #20
0
    def __init__(self, parent, path=""):
        #super().__init__()
        super(TextEdit, self).__init__(parent)

        self.parent = parent
        self.path = path

        font = QFont("Monospace", 8)  #QFont()
        #font.setFamily("Monospace")
        font.setStyleHint(QFont.Monospace)
        font.setStyle(QFont.StyleNormal)
        font.setStyleStrategy(QFont.PreferDefault)
        font.setWeight(QFont.ExtraLight)
        font.setCapitalization(QFont.MixedCase)
        font.setHintingPreference(QFont.PreferDefaultHinting)
        font.setLetterSpacing(QFont.PercentageSpacing, 100.0)
        font.setStretch(QFont.AnyStretch)

        font.setBold(False)
        font.setFixedPitch(True)
        font.setItalic(False)
        font.setKerning(True)
        font.setOverline(False)  # sobrelinea
        #font.setPixelSize(8) #font.setPointSize(8) font.setPointSizeF(8)
        font.setStrikeOut(False)  # tachado
        #font.setStyleName()
        font.setUnderline(False)
        #font.setWordSpacing(1)
        print(font.toString())

        charFormat = QTextCharFormat()
        charFormat.setFont(font)

        #self.setTabStopWidth(4)
        self.setCursorWidth(5)
        self.setCurrentCharFormat(charFormat)
        #print(self.document().defaultTextOption())

        #FIXME: Usaremos qss
        pal = QPalette()
        bgc = QColor(39, 40, 34)
        pal.setColor(QPalette.Base, bgc)
        textc = QColor(255, 255, 255)
        pal.setColor(QPalette.Text, textc)
        self.setPalette(pal)

        self.setLineWrapMode(QPlainTextEdit.NoWrap)

        #self.setTextBackgroundColor(QColor(0, 255, 255))
        #self.setTextColor(QColor(0, 255, 255))
        #self.setFontWeight(QFont.Normal)

        #cursor = self.textCursor()
        #cursor.movePosition(QTextCursor.End)
        #self.setDocumentTitle("Coso")

        #self.syntaxHighlighter = PythonHighlighter(self.document())

        # Señales
        #self.blockCountChanged.connect(self.__newBlock)
        #self.cursorPositionChanged.connect()
        #self.selectionChanged.connect(self.__changedSelection)
        #self.textChanged.connect(self.__changedText)
        #self.updateRequest.connect((const QRect &rect, int dy)
        #self.modificationChanged.connect(self.__chanedModification)

        #self.copyAvailable.connect(self.__copyAvailable)
        #self.undoAvailable.connect(self.__undoAvailable)
        #self.redoAvailable.connect(self.__redoAvailable)

        if os.path.exists(self.path):
            file = open(self.path, 'r')
            data = file.read()
            texto = self.__limpiar_codigo(data)
            self.setPlainText(texto)
            self.document().setModified(data != texto)
            if data != texto:
                print("El texto fue corregido al abrir el archivo.")
        else:
            self.setPlainText(
                "#!/usr/bin/python3\n# -*- coding: utf-8 -*-\n\n")
            self.document().setModified(True)

        self.setFocus()
Beispiel #21
0
class FontPickerButton(QPushButton):
    def __init__(self, parent, cfg_section, cfg_option, tooltip=None, actions=None, actions_kwargs=None):
        """
        A custom QPushButton that launches a QFontDialog.
        :param parent:          Parent ptr.
        :param cfg_section:     Config section.
        :param cfg_option:      Config Option.
        :param tooltip:         String to show on tooltip.
        :param actions:         Function to call when font is selected.
        :param actions_kwargs:  Keyword arguments (dict) to send in checked action calls.
        """
        super(QPushButton, self).__init__(parent=parent)
        self.parent = parent
        self.logger = create_logger(__name__)
        self.tooltip = tooltip
        self.cfg_section = cfg_section
        self.cfg_option = cfg_option
        self.current_font = QFont()
        self.current_font.fromString(read_config(self.cfg_section, self.cfg_option, literal_eval=False))
        self.update_info()

        self.clicked.connect(self.open_font_dialog)

    def weight_map_lookup(self, weight):
        """
        Checks if a weight exists in the font weight map,
        if not then it reports it and returns a fallback string.
        :param weight:
        :return:
        """
        if str(weight) in FONT_WEIGHT_MAP:
            return FONT_WEIGHT_MAP[str(weight)]
        else:
            self.logger.error("Umatched font weight: {}!".format(weight))
            return "UNDEFINED({})".format(weight)

    def map_font_str(self, font_str):
        """
        Maps a comma separated QFont.toString to a much more sensible dict, which it then returns.

        QFont.toString composition (comma separated, always in the following order):
            Family:      Font family name.
            Point size:  Point size of the font.
                -1 if the font size was specified in pixels.
            Pixel size:  Pixel size of the font if it was set with pixel size.
                -1 if the size was set with point size.
            Style hint:  Affects the {QFont}{font matching} algorithm. See QFont.StyleHint and QFont constants.
                 Style hints are used by the {QFont}{font matching} algorithm to find an appropriate default family
                 if a selected font family is not available.

                AnyStyle leaves the font matching algorithm to choose the family. This is the default.

                0 seems to be equivalent to Helvetica and 5 is AnyStyle.
            Weight:      Weight of the font (0-99), usually it's a predefined enum.
                Qt uses a weighting scale from 0 to 99 similar to, but not the same as, the scales used in Windows or
                CSS. A weight of 0 is ultralight, whilst 99 will be an extremely black.
            Style:       Style of the font (enum of the different styles of glyphs that are used to display text).
                Only covers the following types: Normal = 0, Italic = 1, Oblique = 2
            Underline:   Self-explanatory.
                0 if False, 1 if True.
            Strikeout:   Self-explanatory.
                0 if False, 1 if True.
            Fixed pitch: Fixed pitch value of the matched window system font.
                0 if False, 1 if True.

        Useful url:
            shorthand:              https://bit.ly/2XIjI5B
            raw (with linebreaks):  https://cep.xray.aps.anl.gov/software/qt4-x11-4.2.2-browser/
                                    d7/da1/class_q_font.html#5ab046d742a8538c2e2e50c2e03733ea

        :param font_str: A string in the form of QFont.toString().
        :return:
        """
        font_info = font_str.split(',')
        font_info_map = {'family':      str(font_info[0]),                      'point_size': int(font_info[1]),
                         'pixel_size':  float(font_info[2]),                    'style_hint': int(font_info[3]),
                         'weight':      self.weight_map_lookup(font_info[4]),   'style':      int(font_info[5]),
                         'underline':   bool(int(font_info[6])),                'strikeout':  bool(int(font_info[7])),
                         'fixed_pitch': bool(int(font_info[8])),                'raw_mode':   bool(int(font_info[9])),
                         'font_style': str(font_info[10])}

        return font_info_map

    def format_qfont_str(self, font_str):
        """
        Formats a QFont.toString to a more human readable string.
        :param font_str:
        :return:
        """
        # Map the string to a font info map/dict.
        f: dict = self.map_font_str(font_str)

        # Make a list of enabled setting keys.
        enabled_bools = []
        for key, value in f.items():
            if value is True:
                enabled_bools.append(HUMAN_READABLE_KEYS[key])

        # It is guaranteed to be either pt or px, so ternary works fine for this.
        pt_or_px = "{}pt.".format(f['point_size']) if f['point_size'] != -1 else "{}px.".format(f['pixel_size'])

        # Determine the enabled (boolean) settings:
        bools = []
        for boolean in enabled_bools:
            bools.append(boolean)
            bools.append(", ")

        if len(bools) > 0:
            # Strip trailing runaway comma-space delimiter
            bools = bools[:-1]

            # Wrap in parenthesis
            bools.insert(0, '(')
            bools.append(')')

        # Retval for weight (optional): " (" + f['weight'] + ")" if f['weight'] != f['font_style'] else "",

        return "{} ({}) {} {}".format(f['family'], f['font_style'], pt_or_px,
                                      "".join(bools) if not len(bools) == 0 else "")

    def update_info(self):
        """
        Update info (various text/labels etc).
        :return:
        """
        self.setText(self.format_qfont_str(self.current_font.toString()))
        if self.tooltip:
            self.setToolTip(self.tooltip)

    def open_font_dialog(self):
        """
        Opens a QFontDialog and updates current font and config with the choice (if any).
        :return:
        """
        font = QFont()
        font.fromString(read_config(self.cfg_section, self.cfg_option, literal_eval=False))
        font, ok = QFontDialog.getFont()

        # If user selected a font.
        if ok:
            # Update current font ref.
            self.current_font = font

            # Save selected font to config.
            set_config(self.cfg_section, self.cfg_option, font.toString())

            # Make button text reflect changes.
            self.update_info()
Beispiel #22
0
class PFSActivity(PFSActive):
	def __init__(self, id: str, x: int, y: int, text: str="Atividade"):
		PFSActive.__init__(self, id, x, y)
		self._subPage = None
		self._textFont = QFont("Helvetica", 15)
		self._fontMetrics = QFontMetrics(self._textFont)
		self._minWidth = 0
		self._minHeight = 0
		self.setText(text)
		self._width = self._minWidth
		self._height = self._minHeight
		self._inputNum = 1
		self._outputNum = 1
		self._space = 5
		
	def inputNum(self):
		return self._inputNum
	
	def outputNum(self):
		return self._outputNum
		
	def copy(self, x, y):
		ans = PFSActivityContent()
		ans._id = self._id
		ans._x = self.x() - x
		ans._y = self.y() - y
		ans._text = self._text
		ans._width = self._width
		ans._height = self._height
		ans._textFont = self._textFont
		ans._fontMetrics = self._fontMetrics
		ans._pen = self._pen
		ans._brush = self._brush
		ans._tags = self._tags
		ans._inputNum = self._inputNum
		ans._outputNum = self._outputNum
		return ans
	
	def paste(content, id, dx, dy):
		ans = PFSActivity(id, content._x + dx, content._y + dy, content._text)
		ans._width = content._width
		ans._height = content._height
		ans._textFont = content._textFont
		ans._fontMetrics = content._fontMetrics
		ans._pen = content._pen
		ans._brush = content._brush
		ans._inputNum = content._inputNum
		ans._outputNum = content._outputNum
		for tag in content._tags:
			ans.addTag(tag._name, tag._use, False)
		return ans
	
	def tree(self, parent):
		tree = PFSTreeItem(parent, [self._id], 0, QIcon(PFSActivityIcon()))
		tree.clicked.connect(self.selectSingle)
		if self._subPage is not None:
			child = self._subPage.tree(tree)		
		return tree
	
	def simpleTree(self, parent):
		tree = PFSTreeItem(parent, [self._id], 0, QIcon(PFSActivityIcon()))
		tree.clicked.connect(self.selectSingle)
		return tree
	
	def hasSubPage(self):
		return self._subPage is not None
	
	def setSubPage(self, page):
		if self._subPage is not None:
			return False
		self._subPage = page
		return True
	
	def removeSubPage(self):
		self._subPage = None
	
	def subPage(self):
		return self._subPage
	
	def generateXml(self, xml: QXmlStreamWriter):
		PFSXmlBase.open(xml)
		xml.writeStartElement("activity")
		xml.writeAttribute("id", self._id)
		xml.writeAttribute("inputnum", str(self._inputNum))
		xml.writeAttribute("outputnum", str(self._outputNum))
		PFSXmlBase.graphicsNode(xml, QRectF(self.x(), self.y(), self._width, self._height), self._pen, self._brush)
		PFSXmlBase.text(xml, self._text, 0, 0, font=self._textFont, tag="text", align="center")
		PFSBasicElement.generateXml(self, xml)
		xml.writeEndElement() #fecha activity
		PFSXmlBase.close(xml)
	
	def createFromXml(node: QDomNode):
		if node.nodeName() != "activity":
			return None
		if not (node.hasAttributes() and node.attributes().contains("id")):
			return None
		id = node.attributes().namedItem("id").nodeValue()
		childs = node.childNodes()
		graphics = None
		text = None
		if node.attributes().contains("inputnum"):
			inputNum =  int(node.attributes().namedItem("inputnum").nodeValue())
		else:
			inputNum = 1
		if node.attributes().contains("outputnum"):
			outputNum =  int(node.attributes().namedItem("outputnum").nodeValue())
		else:
			outputNum = 1
		tags = []
		for i in range(childs.count()):
			child = childs.at(i)
			if child.nodeName() == "graphics":
				graphics = PFSXmlBase.getNode(child)
			if child.nodeName() == "text":
				text = PFSXmlBase.getText(child)
			if child.nodeName() == "tags":
				tags = PFSBasicElement.createFromXml(child)
		if graphics is not None and text is not None:
			ac = PFSActivityContent()
			ac._id = id
			ac._x = graphics.rect.x()
			ac._y = graphics.rect.y()
			ac._text = text.annotation
			ac._width = graphics.rect.width()
			ac._height = graphics.rect.height()		
			if text.font is not None:
				ac._textFont = text.font
				ac._fontMetrics = QFontMetrics(text.font)
			if graphics.line is not None:
				ac._pen = graphics.line
			if graphics.brush is not None:
				ac._brush = graphics.brush
			ac._tags = tags
			ac._inputNum = inputNum
			ac._outputNum = outputNum
			return ac
		return None
		
	def paint(self, p: QPainter, o: QStyleOptionGraphicsItem, w: QWidget):
		p.setPen(Qt.NoPen)
		p.setBrush(self._brush)
		rect = self.boundingRect()
		p.drawRect(rect)
		p.setPen(self._pen)
		p.setFont(self._textFont)
		p.drawText(rect, Qt.AlignCenter, self._text)
		p.save()
		if self.isSelected():
			if self._pen.color() == PFSElement.SELECTED_PEN:
				p.setPen(PFSElement.SELECTED_PEN_ALT)
			else:
				p.setPen(PFSElement.SELECTED_PEN)
		h = (self._height -self._space*(self._inputNum-1))/self._inputNum
		p.save()
		p.translate(self.x(), self.y())
		for i in range(self._inputNum):
			p.drawLine(0, 0, 6, 0)
			p.drawLine(0, h, 6, h)
			p.drawLine(0, 0, 0, h)
			p.translate(0, h + self._space)
		p.restore()
		h = (self._height -self._space*(self._outputNum-1))/self._outputNum
		p.translate(self.x() + self._width, self.y())
		for i in range(self._outputNum):
			p.drawLine(0, 0, -6, 0)
			p.drawLine(0, h, -6, h)
			p.drawLine(0, 0, 0, h)
			p.translate(0, h + self._space)	
		p.restore()
		
	def setText(self, text: str):
		self._text = text
		s = self.minimunSize()
		if self._width < s.width():
			self._width = s.width()
		if self._height < s.height():
			self._height = s.height()
		if self.scene() is not None:
			self.scene().update()
			self.changed.emit()
			
	def setInputNum(self, text: str):
		self._inputNum = int(text)
		if self.scene() is not None:
			self.scene().update()
			self.changed.emit()
	
	def setOutputNum(self, text: str):
		self._outputNum = int(text)
		if self.scene() is not None:
			self.scene().update()
			self.changed.emit()	
			
	def setFont(self, font: QFont):
		self._textFont = font
		self._fontMetrics = QFontMetrics(font)
		self.scene().update()
	
	def getText(self):
		return self._text
		
	def minimunSize(self):
		s = self._fontMetrics.size(Qt.TextExpandTabs, self._text)
		self._minWidth = s.width() + 15
		self._minHeight = s.height() + 4
		return QSizeF(self._minWidth, self._minHeight)
	
	def boundingRect(self):
		s = self.minimunSize()
		width = max(self._width,s.width()) 
		height = max(self._height,s.height())
		return QRectF(self.x(), self.y(), width, height)
	
	def getBestRelationPoint(self, p: QPointF) -> QPointF:
		r = self.sceneBoundingRect()
		if p.x() > r.center().x():
			x = r.right()
		else:
			x = r.x()
		y = p.y()
		if p.y() < r.y():
			y = r.y()
		elif p.y() > r.bottom():
			y = r.bottom()
		return QPointF(x, y)
		
	def getBestRelationPointInput(self, p: QPointF, i: int) -> QPointF:
		r = self.sceneBoundingRect()
		x = r.x()
		h = (self._height - (self._inputNum - 1)*self._space)/self._inputNum
		y0 = r.y() + (self._space + h)*i
		y = p.y()
		if y < y0:
			y = y0
		elif y > y0 + h:
			y = y0 + h
		return QPointF(x, y)
		
	def getBestRelationPointOutput(self, p: QPointF, i: int) -> QPointF:
		r = self.sceneBoundingRect()
		x = r.right()
		h = (self._height - (self._outputNum - 1)*self._space)/self._outputNum
		y0 = r.y() + (self._space + h)*i
		y = p.y()
		if y < y0:
			y = y0
		elif y > y0 + h:
			y = y0 + h
		return QPointF(x, y)
	
	def getBestRelationPointSecondary(self, p: QPointF, posX: float) -> QPointF:
		r = self.sceneBoundingRect()
		x = r.x() + 6 + posX/100*(self._width - 12)
		y = r.y()
		if p.y() > r.center().y():
			y = r.bottom()
		return QPointF(x, y)
	
	def propertiesTable(self):
		ans = []
		lblType = PFSTableLabel("Elemento")
		lblValue = PFSTableNormal("Atividade")
		lblValue.setFlags(Qt.NoItemFlags)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("ID")
		lblValue = PFSTableNormal(self._id)
		lblValue.setFlags(Qt.NoItemFlags)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Posição X")
		lblValue = PFSTableValueText(str(self.x()))
		lblValue.edited.connect(self.changeElementPosX)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Posição Y")
		lblValue = PFSTableValueText(str(self.y()))
		lblValue.edited.connect(self.changeElementPosY)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Largura")
		lblValue = PFSTableValueText(str(self._width))
		lblValue.edited.connect(self.changeElementWidth)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Altura")
		lblValue = PFSTableValueText(str(self._height))
		lblValue.edited.connect(self.changeElementHeight)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Texto")
		lblValue = PFSTableValueText(self._text)
		lblValue.edited.connect(self.changeText)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Fonte")
		lblValue = PFSTableValueButton(self._textFont.toString())
		lblValue.clicked.connect(self.changeFont)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Cor do contorno")
		lblValue = PFSTableValueButton(self._pen.color().name())
		lblValue.clicked.connect(self.changeLineColor)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Linha do contorno")
		lblValue = PFSTableValueCombo(self.PEN_LIST, self._pen.style())
		self.penEdited.connect(lblValue.updateText)
		lblValue.currentTextChanged.connect(self.changeLineStyle)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Espessura do contorno")
		lblValue = PFSTableValueText(str(self._pen.width()))
		lblValue.edited.connect(self.changeLineWidth)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Cor do preenchimento")
		lblValue = PFSTableValueButton(self._brush.color().name())
		lblValue.clicked.connect(self.changeFillColor)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Entradas")
		lblValue = PFSTableValueText(str(self._inputNum))
		lblValue.edited.connect(self.changeInputNum)
		ans.append([lblType, lblValue])
		lblType = PFSTableLabel("Saídas")
		lblValue = PFSTableValueText(str(self._outputNum))
		lblValue.edited.connect(self.changeOutputNum)
		ans.append([lblType, lblValue])		
		lblType = PFSTableLabelTags("Tags")
		lblValue = PFSTableValueBox(self._tags, self.createTag)
		ans.append([lblType, lblValue])
		return ans
	
	def changeText(self, prop):
		x = PFSUndoPropertyText(prop, self.setText)
		x.setText("Alterar texto")
		self.scene()._page._net.undoStack.push(x)
	
	def changeInputNum(self, prop):
		x = PFSUndoPropertyText(prop, self.setInputNum)
		x.setText("Alterar entradas")
		self.scene()._page._net.undoStack.push(x)
		
	def changeOutputNum(self, prop):
		x = PFSUndoPropertyText(prop, self.setOutputNum)
		x.setText("Alterar saídas")
		self.scene()._page._net.undoStack.push(x)	
	
	def changeFont(self):
		font, ans = QFontDialog.getFont(self._textFont, self.scene()._page._net, "Escolha a fonte do texto")
		if ans:
			x = PFSUndoPropertyButton(font, self._textFont, self.setFont)
			x.setText("Alterar fonte")
			self.scene()._page._net.undoStack.push(x)
	
	def changeElementWidth(self, prop):
		if float(prop.text()) > self._minWidth:
			x = PFSUndoPropertyText(prop, self.resizeWidth)
			x.setText("Alterar largura")
			self.scene()._page._net.undoStack.push(x)

	def changeElementHeight(self, prop):
		if float(prop.text()) > self._minHeight:
			x = PFSUndoPropertyText(prop, self.resizeHeight)
			x.setText("Alterar altura")
			self.scene()._page._net.undoStack.push(x)	
    def __init__(self, parent=None):
        super().__init__(parent)

        self.settings = QSettings()
        self.settings.beginGroup("plugins/layertreeicons")

        self.setWindowTitle(self.tr("Default layer tree properties"))
        self.setMinimumSize(QSize(250, 0))
        layout = QVBoxLayout(self)

        form_layout = QFormLayout()

        hlayout = QHBoxLayout()
        self.group_font_label = QLabel("")
        group_font_button = QToolButton(self)
        group_font_button.setText("...")
        hlayout.addWidget(self.group_font_label)
        hlayout.addWidget(group_font_button)
        form_layout.addRow(self.tr("Group node font"), hlayout)
        group_font_button.setToolTip("Select font")
        group_font_button.clicked.connect(self.select_group_font)

        hlayout = QHBoxLayout()
        self.layer_font_label = QLabel("")
        layer_font_button = QToolButton(self)
        layer_font_button.setText("...")
        hlayout.addWidget(self.layer_font_label)
        hlayout.addWidget(layer_font_button)
        form_layout.addRow(self.tr("Layer node font"), hlayout)
        layer_font_button.setToolTip("Select font")
        layer_font_button.clicked.connect(self.select_layer_font)

        self.icon_size_combo = QComboBox(self)
        self.icon_size_combo.addItem(self.tr("default"), -1)
        for val in (16, 24, 32, 48, 64):
            self.icon_size_combo.addItem(f"{val} px", val)

        idx = self.icon_size_combo.findData(self.settings.value("iconsize", -1, int))
        self.icon_size_combo.setCurrentIndex(idx)
        self.icon_size_combo.currentIndexChanged.connect(self.on_icon_size_changed)

        form_layout.addRow(self.tr("Icon Size"), self.icon_size_combo)

        layout.addLayout(form_layout)
        group_box = QGroupBox(self)
        group_box.setTitle("Default Icons")
        self.form_layout = QFormLayout(group_box)
        layout.addWidget(group_box)
        self.reset_button = QPushButton(self.tr("Reset default properties"))
        layout.addWidget(self.reset_button)

        self.reset_button.clicked.connect(self.reset_all)

        self.resource_browser = ResourceBrowser(parent)

        self.source_data = {
            "group": (self.tr("Group"), ":/images/themes/default/mActionFolder.svg",),
            "raster": (self.tr("Raster"), ":/images/themes/default/mIconRaster.svg",),
            "point": (self.tr("Point"), ":/images/themes/default/mIconPointLayer.svg",),
            "line": (self.tr("Line"), ":/images/themes/default/mIconLineLayer.svg",),
            "polygon": (
                self.tr("Polygon"),
                ":/images/themes/default/mIconPolygonLayer.svg",
            ),
            "nogeometry": (
                self.tr("No Geometry"),
                ":/images/themes/default/mIconTableLayer.svg",
            ),
        }

        if Qgis.QGIS_VERSION_INT > 30200:

            self.source_data["mesh"] = (
                self.tr("Mesh Layer"),
                ":/images/themes/default/mIconMeshLayer.svg",
            )

        for settings_key, (text, default_icon) in self.source_data.items():

            button = QToolButton(self)
            button.setObjectName(settings_key)
            button.setPopupMode(QToolButton.MenuButtonPopup)
            button.setIconSize(QSize(24, 24))
            button.setIcon(QIcon(default_icon))
            label = QLabel(text, self)
            label.setMinimumSize(QSize(label.minimumSize().width(), 38))
            self.form_layout.addRow(label, button)

            action_from_qgis = QAction("Set from QGIS ressources", button)
            action_from_qgis.triggered.connect(
                partial(self.set_icon_from_ressources, settings_key)
            )
            button.addAction(action_from_qgis)
            button.clicked.connect(action_from_qgis.trigger)

            action_from_file = QAction("Set from file", button)
            action_from_file.triggered.connect(
                partial(self.set_icon_from_file, settings_key)
            )
            button.addAction(action_from_file)

            action_reset = QAction("Reset", button)
            action_reset.triggered.connect(partial(self.reset, settings_key))
            button.addAction(action_reset)

        f = QFont()
        if f.fromString(self.settings.value("group_font")) and f.family():
            iface.layerTreeView().layerTreeModel().setLayerTreeNodeFont(
                QgsLayerTree.NodeGroup, f
            )
        else:
            iface.layerTreeView().layerTreeModel().setLayerTreeNodeFont(
                QgsLayerTree.NodeGroup, iface.layerTreeView().font()
            )
            self.settings.setValue(
                "group_font", iface.layerTreeView().font().toString()
            )

        f = QFont()
        if f.fromString(self.settings.value("layer_font")) and f.family():
            iface.layerTreeView().layerTreeModel().setLayerTreeNodeFont(
                QgsLayerTree.NodeLayer, f
            )
        else:
            f = iface.layerTreeView().font()
            f.setBold(True)
            iface.layerTreeView().layerTreeModel().setLayerTreeNodeFont(
                QgsLayerTree.NodeLayer, f
            )
            self.settings.setValue("layer_font", f.toString())
        self.update_font_labels()