Example #1
0
def stamp_image(image, expression_str, position, feature):
    painter = QPainter(image)
    data = roam.api.utils.replace_expression_placeholders(expression_str, feature)
    if not data:
        return image

    data = data.replace(r"\n", "<br>")
    style = """
    body {
        color: yellow;
    }
    """
    doc = QTextDocument()
    doc.setDefaultStyleSheet(style)
    data = "<body>{}</body>".format(data)
    doc.setHtml(data)
    point = QPointF(20, 20)

    # Wrap the text so we don't go crazy
    if doc.size().width() > 300:
        doc.setTextWidth(300)
    if position == "top-left":
        point = QPointF(20, 20)
    elif position == "top-right":
        x = image.width() - 20 - doc.size().width()
        point = QPointF(x, 20)
    elif position == "bottom-left":
        point = QPointF(20, image.height() - 20 - doc.size().height())
    elif position == "bottom-right":
        x = image.width() - 20 - doc.size().width()
        y = image.height() - 20 - doc.size().height()
        point = QPointF(x, y)
    painter.translate(point)
    doc.drawContents(painter)
    return image
Example #2
0
	def textDocument(self, title, htmltext):
		td = QTextDocument()
		td.setMetaInformation(QTextDocument.DocumentTitle, title)
		if self.ss:
			td.setDefaultStyleSheet(self.ss)
		td.setHtml(htmltext)
		td.setDefaultFont(globalSettings.font)
		return td
Example #3
0
	def textDocument(self, title, htmltext):
		td = QTextDocument()
		td.setMetaInformation(QTextDocument.DocumentTitle, title)
		if self.ss:
			td.setDefaultStyleSheet(self.ss)
		td.setHtml(htmltext)
		td.setDefaultFont(globalSettings.font)
		return td
Example #4
0
def color_json(obj):
    doc = QTextDocument()
    doc.setDefaultStyleSheet(open('stylesheet/json_style.css').read())
    if isinstance(obj, str):
        doc.setHtml(string_to_html(obj))
    else:
        doc.setHtml(json_to_html(obj))
    return doc
Example #5
0
	def textDocument(self):
		td = QTextDocument()
		td.setMetaInformation(QTextDocument.DocumentTitle, self.getDocumentTitle())
		if self.ss:
			td.setDefaultStyleSheet(self.ss)
		td.setHtml(self.getHtml())
		td.setDefaultFont(globalSettings.font)
		return td
Example #6
0
	def textDocument(self):
		td = QTextDocument()
		td.setMetaInformation(QTextDocument.DocumentTitle, self.getDocumentTitle())
		if self.ss:
			td.setDefaultStyleSheet(self.ss)
		td.setHtml(self.getHtml())
		if self.font:
			td.setDefaultFont(self.font)
		return td
Example #7
0
def collect_block_and_char_format():
    q = QTextDocument()
    q.setDefaultStyleSheet(CSS)
    css = dict(_CSS_BASE)
    css.pop("body")
    q.setHtml("")
    old = q.allFormats()

    html = "".join((f"<{k}>a</{k}>" for k in css.keys()))
    q.setHtml(html)
    charFormat = []
    blockFormat = []
    for f in q.allFormats():
        if f in old:
            continue
        elif f.isCharFormat():
            charFormat.append(f.toCharFormat())
        elif f.isBlockFormat():  # pragma: no branch
            blockFormat.append(f.toBlockFormat())

    return BlockFormat_(charFormat), BlockFormat_(blockFormat)
Example #8
0
class CompletionItemDelegate(QStyledItemDelegate):
    """Delegate used by CompletionView to draw individual items.

    Mainly a cleaned up port of Qt's way to draw a TreeView item, except it
    uses a QTextDocument to draw the text and add marking.

    Original implementation:
        qt/src/gui/styles/qcommonstyle.cpp:drawControl:2153

    Attributes:
        _opt: The QStyleOptionViewItem which is used.
        _style: The style to be used.
        _painter: The QPainter to be used.
        _doc: The QTextDocument to be used.
    """

    # FIXME this is horribly slow when resizing.
    # We should probably cache something in _get_textdoc or so, but as soon as
    # we implement eliding that cache probably isn't worth much anymore...
    # https://github.com/qutebrowser/qutebrowser/issues/121

    def __init__(self, parent=None):
        self._painter = None
        self._opt = None
        self._doc = None
        self._style = None
        super().__init__(parent)

    def _draw_background(self):
        """Draw the background of an ItemViewItem."""
        self._style.drawPrimitive(self._style.PE_PanelItemViewItem, self._opt,
                                  self._painter, self._opt.widget)

    def _draw_icon(self):
        """Draw the icon of an ItemViewItem."""
        icon_rect = self._style.subElementRect(
            self._style.SE_ItemViewItemDecoration, self._opt, self._opt.widget)
        if not icon_rect.isValid():
            # The rect seems to be wrong in all kind of ways if no icon should
            # be displayed.
            return

        mode = QIcon.Normal
        if not self._opt.state & QStyle.State_Enabled:
            mode = QIcon.Disabled
        elif self._opt.state & QStyle.State_Selected:
            mode = QIcon.Selected
        state = QIcon.On if self._opt.state & QStyle.State_Open else QIcon.Off
        self._opt.icon.paint(self._painter, icon_rect,
                             self._opt.decorationAlignment, mode, state)

    def _draw_text(self, index):
        """Draw the text of an ItemViewItem.

        This is the main part where we differ from the original implementation
        in Qt: We use a QTextDocument to draw text.

        Args:
            index: The QModelIndex of the item to draw.
        """
        if not self._opt.text:
            return

        text_rect_ = self._style.subElementRect(
            self._style.SE_ItemViewItemText, self._opt, self._opt.widget)
        qtutils.ensure_valid(text_rect_)
        margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin,
                                         self._opt, self._opt.widget) + 1
        # remove width padding
        text_rect = text_rect_.adjusted(margin, 0, -margin, 0)
        qtutils.ensure_valid(text_rect)
        # move text upwards a bit
        if index.parent().isValid():
            text_rect.adjust(0, -1, 0, -1)
        else:
            text_rect.adjust(0, -2, 0, -2)
        self._painter.save()
        state = self._opt.state
        if state & QStyle.State_Enabled and state & QStyle.State_Active:
            cg = QPalette.Normal
        elif state & QStyle.State_Enabled:
            cg = QPalette.Inactive
        else:
            cg = QPalette.Disabled

        if state & QStyle.State_Selected:
            self._painter.setPen(
                self._opt.palette.color(cg, QPalette.HighlightedText))
            # This is a dirty fix for the text jumping by one pixel for
            # whatever reason.
            text_rect.adjust(0, -1, 0, 0)
        else:
            self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))

        if state & QStyle.State_Editing:
            self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))
            self._painter.drawRect(text_rect_.adjusted(0, 0, -1, -1))

        self._painter.translate(text_rect.left(), text_rect.top())
        self._get_textdoc(index)
        self._draw_textdoc(text_rect, index.column())
        self._painter.restore()

    def _draw_textdoc(self, rect, col):
        """Draw the QTextDocument of an item.

        Args:
            rect: The QRect to clip the drawing to.
        """
        # We can't use drawContents because then the color would be ignored.
        clip = QRectF(0, 0, rect.width(), rect.height())
        self._painter.save()

        if self._opt.state & QStyle.State_Selected:
            color = config.val.colors.completion.item.selected.fg
        elif not self._opt.state & QStyle.State_Enabled:
            color = config.val.colors.completion.category.fg
        else:
            colors = config.val.colors.completion.fg
            # if multiple colors are set, use different colors per column
            color = colors[col % len(colors)]
        self._painter.setPen(color)

        ctx = QAbstractTextDocumentLayout.PaintContext()
        ctx.palette.setColor(QPalette.Text, self._painter.pen().color())
        if clip.isValid():
            self._painter.setClipRect(clip)
            ctx.clip = clip
        self._doc.documentLayout().draw(self._painter, ctx)
        self._painter.restore()

    def _get_textdoc(self, index):
        """Create the QTextDocument of an item.

        Args:
            index: The QModelIndex of the item to draw.
        """
        # FIXME we probably should do eliding here. See
        # qcommonstyle.cpp:viewItemDrawText
        # https://github.com/qutebrowser/qutebrowser/issues/118
        text_option = QTextOption()
        if self._opt.features & QStyleOptionViewItem.WrapText:
            text_option.setWrapMode(QTextOption.WordWrap)
        else:
            text_option.setWrapMode(QTextOption.ManualWrap)
        text_option.setTextDirection(self._opt.direction)
        text_option.setAlignment(
            QStyle.visualAlignment(self._opt.direction,
                                   self._opt.displayAlignment))

        if self._doc is not None:
            self._doc.deleteLater()
        self._doc = QTextDocument(self)
        self._doc.setDefaultFont(self._opt.font)
        self._doc.setDefaultTextOption(text_option)
        self._doc.setDocumentMargin(2)

        assert _cached_stylesheet is not None
        self._doc.setDefaultStyleSheet(_cached_stylesheet)

        if index.parent().isValid():
            view = self.parent()
            pattern = view.pattern
            columns_to_filter = index.model().columns_to_filter(index)
            if index.column() in columns_to_filter and pattern:
                repl = r'<span class="highlight">\g<0></span>'
                pat = html.escape(re.escape(pattern)).replace(r'\ ', r'|')
                txt = html.escape(self._opt.text)
                text = re.sub(pat, repl, txt, flags=re.IGNORECASE)
                self._doc.setHtml(text)
            else:
                self._doc.setPlainText(self._opt.text)
        else:
            self._doc.setHtml('<span style="font: {};">{}</span>'.format(
                html.escape(config.val.fonts.completion.category),
                html.escape(self._opt.text)))

    def _draw_focus_rect(self):
        """Draw the focus rectangle of an ItemViewItem."""
        state = self._opt.state
        if not state & QStyle.State_HasFocus:
            return
        o = self._opt
        o.rect = self._style.subElementRect(
            self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget)
        o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item
        qtutils.ensure_valid(o.rect)
        if state & QStyle.State_Enabled:
            cg = QPalette.Normal
        else:
            cg = QPalette.Disabled
        if state & QStyle.State_Selected:
            role = QPalette.Highlight
        else:
            role = QPalette.Window
        o.backgroundColor = self._opt.palette.color(cg, role)
        self._style.drawPrimitive(QStyle.PE_FrameFocusRect, o, self._painter,
                                  self._opt.widget)

    def sizeHint(self, option, index):
        """Override sizeHint of QStyledItemDelegate.

        Return the cell size based on the QTextDocument size, but might not
        work correctly yet.

        Args:
            option: const QStyleOptionViewItem & option
            index: const QModelIndex & index

        Return:
            A QSize with the recommended size.
        """
        value = index.data(Qt.SizeHintRole)
        if value is not None:
            return value
        self._opt = QStyleOptionViewItem(option)
        self.initStyleOption(self._opt, index)
        self._style = self._opt.widget.style()
        self._get_textdoc(index)
        docsize = self._doc.size().toSize()
        size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt,
                                            docsize, self._opt.widget)
        qtutils.ensure_valid(size)
        return size + QSize(10, 3)

    def paint(self, painter, option, index):
        """Override the QStyledItemDelegate paint function.

        Args:
            painter: QPainter * painter
            option: const QStyleOptionViewItem & option
            index: const QModelIndex & index
        """
        self._painter = painter
        self._painter.save()
        self._opt = QStyleOptionViewItem(option)
        self.initStyleOption(self._opt, index)
        self._style = self._opt.widget.style()

        self._draw_background()
        self._draw_icon()
        self._draw_text(index)
        self._draw_focus_rect()

        self._painter.restore()
class CompletionItemDelegate(QStyledItemDelegate):

    """Delegate used by CompletionView to draw individual items.

    Mainly a cleaned up port of Qt's way to draw a TreeView item, except it
    uses a QTextDocument to draw the text and add marking.

    Original implementation:
        qt/src/gui/styles/qcommonstyle.cpp:drawControl:2153

    Attributes:
        _opt: The QStyleOptionViewItem which is used.
        _style: The style to be used.
        _painter: The QPainter to be used.
        _doc: The QTextDocument to be used.
    """

    # FIXME this is horribly slow when resizing.
    # We should probably cache something in _get_textdoc or so, but as soon as
    # we implement eliding that cache probably isn't worth much anymore...
    # https://github.com/qutebrowser/qutebrowser/issues/121

    def __init__(self, parent=None):
        self._painter = None
        self._opt = None
        self._doc = None
        self._style = None
        super().__init__(parent)

    def _draw_background(self):
        """Draw the background of an ItemViewItem."""
        self._style.drawPrimitive(self._style.PE_PanelItemViewItem, self._opt,
                                  self._painter, self._opt.widget)

    def _draw_icon(self):
        """Draw the icon of an ItemViewItem."""
        icon_rect = self._style.subElementRect(
            self._style.SE_ItemViewItemDecoration, self._opt, self._opt.widget)
        if not icon_rect.isValid():
            # The rect seems to be wrong in all kind of ways if no icon should
            # be displayed.
            return

        mode = QIcon.Normal
        if not self._opt.state & QStyle.State_Enabled:
            mode = QIcon.Disabled
        elif self._opt.state & QStyle.State_Selected:
            mode = QIcon.Selected
        state = QIcon.On if self._opt.state & QStyle.State_Open else QIcon.Off
        self._opt.icon.paint(self._painter, icon_rect,
                             self._opt.decorationAlignment, mode, state)

    def _draw_text(self, index):
        """Draw the text of an ItemViewItem.

        This is the main part where we differ from the original implementation
        in Qt: We use a QTextDocument to draw text.

        Args:
            index: The QModelIndex of the item to draw.
        """
        if not self._opt.text:
            return

        text_rect_ = self._style.subElementRect(
            self._style.SE_ItemViewItemText, self._opt, self._opt.widget)
        qtutils.ensure_valid(text_rect_)
        margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin,
                                         self._opt, self._opt.widget) + 1
        # remove width padding
        text_rect = text_rect_.adjusted(margin, 0, -margin, 0)
        qtutils.ensure_valid(text_rect)
        # move text upwards a bit
        if index.parent().isValid():
            text_rect.adjust(0, -1, 0, -1)
        else:
            text_rect.adjust(0, -2, 0, -2)
        self._painter.save()
        state = self._opt.state
        if state & QStyle.State_Enabled and state & QStyle.State_Active:
            cg = QPalette.Normal
        elif state & QStyle.State_Enabled:
            cg = QPalette.Inactive
        else:
            cg = QPalette.Disabled

        if state & QStyle.State_Selected:
            self._painter.setPen(self._opt.palette.color(
                cg, QPalette.HighlightedText))
            # This is a dirty fix for the text jumping by one pixel for
            # whatever reason.
            text_rect.adjust(0, -1, 0, 0)
        else:
            self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))

        if state & QStyle.State_Editing:
            self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))
            self._painter.drawRect(text_rect_.adjusted(0, 0, -1, -1))

        self._painter.translate(text_rect.left(), text_rect.top())
        self._get_textdoc(index)
        self._draw_textdoc(text_rect, index.column())
        self._painter.restore()

    def _draw_textdoc(self, rect, col):
        """Draw the QTextDocument of an item.

        Args:
            rect: The QRect to clip the drawing to.
        """
        # We can't use drawContents because then the color would be ignored.
        clip = QRectF(0, 0, rect.width(), rect.height())
        self._painter.save()

        if self._opt.state & QStyle.State_Selected:
            color = config.val.colors.completion.item.selected.fg
        elif not self._opt.state & QStyle.State_Enabled:
            color = config.val.colors.completion.category.fg
        else:
            colors = config.val.colors.completion.fg
            # if multiple colors are set, use different colors per column
            color = colors[col % len(colors)]
        self._painter.setPen(color)

        ctx = QAbstractTextDocumentLayout.PaintContext()
        ctx.palette.setColor(QPalette.Text, self._painter.pen().color())
        if clip.isValid():
            self._painter.setClipRect(clip)
            ctx.clip = clip
        self._doc.documentLayout().draw(self._painter, ctx)
        self._painter.restore()

    def _get_textdoc(self, index):
        """Create the QTextDocument of an item.

        Args:
            index: The QModelIndex of the item to draw.
        """
        # FIXME we probably should do eliding here. See
        # qcommonstyle.cpp:viewItemDrawText
        # https://github.com/qutebrowser/qutebrowser/issues/118
        text_option = QTextOption()
        if self._opt.features & QStyleOptionViewItem.WrapText:
            text_option.setWrapMode(QTextOption.WordWrap)
        else:
            text_option.setWrapMode(QTextOption.ManualWrap)
        text_option.setTextDirection(self._opt.direction)
        text_option.setAlignment(QStyle.visualAlignment(
            self._opt.direction, self._opt.displayAlignment))

        if self._doc is not None:
            self._doc.deleteLater()
        self._doc = QTextDocument(self)
        self._doc.setDefaultFont(self._opt.font)
        self._doc.setDefaultTextOption(text_option)
        self._doc.setDocumentMargin(2)

        assert _cached_stylesheet is not None
        self._doc.setDefaultStyleSheet(_cached_stylesheet)

        if index.parent().isValid():
            view = self.parent()
            pattern = view.pattern
            columns_to_filter = index.model().columns_to_filter(index)
            if index.column() in columns_to_filter and pattern:
                repl = r'<span class="highlight">\g<0></span>'
                pat = html.escape(re.escape(pattern)).replace(r'\ ', r'|')
                txt = html.escape(self._opt.text)
                text = re.sub(pat, repl, txt, flags=re.IGNORECASE)
                self._doc.setHtml(text)
            else:
                self._doc.setPlainText(self._opt.text)
        else:
            self._doc.setHtml(
                '<span style="font: {};">{}</span>'.format(
                    html.escape(config.val.fonts.completion.category),
                    html.escape(self._opt.text)))

    def _draw_focus_rect(self):
        """Draw the focus rectangle of an ItemViewItem."""
        state = self._opt.state
        if not state & QStyle.State_HasFocus:
            return
        o = self._opt
        o.rect = self._style.subElementRect(
            self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget)
        o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item
        qtutils.ensure_valid(o.rect)
        if state & QStyle.State_Enabled:
            cg = QPalette.Normal
        else:
            cg = QPalette.Disabled
        if state & QStyle.State_Selected:
            role = QPalette.Highlight
        else:
            role = QPalette.Window
        o.backgroundColor = self._opt.palette.color(cg, role)
        self._style.drawPrimitive(QStyle.PE_FrameFocusRect, o, self._painter,
                                  self._opt.widget)

    def sizeHint(self, option, index):
        """Override sizeHint of QStyledItemDelegate.

        Return the cell size based on the QTextDocument size, but might not
        work correctly yet.

        Args:
            option: const QStyleOptionViewItem & option
            index: const QModelIndex & index

        Return:
            A QSize with the recommended size.
        """
        value = index.data(Qt.SizeHintRole)
        if value is not None:
            return value
        self._opt = QStyleOptionViewItem(option)
        self.initStyleOption(self._opt, index)
        self._style = self._opt.widget.style()
        self._get_textdoc(index)
        docsize = self._doc.size().toSize()
        size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt,
                                            docsize, self._opt.widget)
        qtutils.ensure_valid(size)
        return size + QSize(10, 3)

    def paint(self, painter, option, index):
        """Override the QStyledItemDelegate paint function.

        Args:
            painter: QPainter * painter
            option: const QStyleOptionViewItem & option
            index: const QModelIndex & index
        """
        self._painter = painter
        self._painter.save()
        self._opt = QStyleOptionViewItem(option)
        self.initStyleOption(self._opt, index)
        self._style = self._opt.widget.style()

        self._draw_background()
        self._draw_icon()
        self._draw_text(index)
        self._draw_focus_rect()

        self._painter.restore()
Example #10
0
def test_TextSectoinFormatter(data, res):
    a = QTextDocument()
    a.setDefaultStyleSheet(CSS)
    a.setHtml(data)
    builded = TextSectionFormatter(a.toHtml()).build_body()
    assert builded == res
Example #11
0
class MainWindow(QMainWindow, Ui_MainWindow):
    page_changed = pyqtSignal(int)
    sql_chosen = pyqtSignal(Path)
    data_chosen = pyqtSignal(Path)
    table_chosen = pyqtSignal(Path)
    sql_finished = pyqtSignal()

    def __init__(self,
                 connection: Connection,
                 base: Path,
                 *args,
                 obj=None,
                 **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)
        self.connection = connection
        self.base_path = base
        self.base_path.mkdir(parents=True, exist_ok=True)
        self.last_start = None
        self.status = None
        self.cost = None
        self.using_db = None
        self.current_page = -1
        self.results = []
        self.tasks = []
        self.tables: Dict[str, Set[str]] = {}

        self.tree_file.setModel(QStandardItemModel())
        self.update_tree_file()

        self.timer = QTimer(self)
        self.timer.setInterval(100)
        self.timer.timeout.connect(self.update_cost)

        self.mutex = QMutex()
        self.wait_condition = QWaitCondition()
        self.queue = Queue(1)
        self.worker = Worker(connection, self.mutex, self.wait_condition,
                             self.queue)
        self.worker.executed.connect(self.worker_execute)
        self.worker.finished.connect(self.worker_finish)
        self.worker.start()

        self.document = QTextDocument(self)
        self.processing_highlight = False
        self.document.setDefaultStyleSheet(SQLHighlighter.style())
        self.text_code.setDocument(self.document)
        self.text_code.setFocus()

        self.set_status(Status.Waiting)
        self.set_result_report()
        self.change_page()
        self.update_buttons()
        self.change_db(None)

        self.page_changed.connect(self.change_page)
        self.page_changed.connect(self.show_result)
        self.page_changed.connect(self.update_buttons)
        self.sql_finished.connect(self.update_tree_file)

    @pyqtSlot()
    def worker_execute(self):
        self.set_status(Status.Building)

    @pyqtSlot(tuple)
    def worker_finish(self, args: Tuple[Tuple[Union[QAbstractItemModel, str],
                                              timedelta]]):
        self.set_status(Status.Rendering)
        error = None
        for model, cost in args:
            if not model:
                continue
            elif isinstance(model, QAbstractItemModel):
                self.results.append((model, cost))
            elif model.startswith('#'):
                self.change_db(model[1:])
            else:
                error = model
        if self.results:
            self.page_changed.emit(-1)
        self.timer.stop()
        if error:
            self.error_report('执行错误', error)
        self.set_status(Status.Waiting)
        self.sql_finished.emit()

    def set_status(self, status: Status, cost=None):
        self.status = status
        msg = '状态:' + status.value
        if cost:
            msg += ',已进行%.1fs' % cost.total_seconds()
        self.statusbar.showMessage(msg)

    def show_result(self, page: int):
        result, cost = self.results[page]
        self.table_result.setModel(result)
        self.table_result.resizeColumnsToContents()
        self.set_result_report(result.rowCount(), cost)

    def change_page(self, page: int = -1):
        pages = len(self.results)
        if page < 0:
            page += pages
        self.current_page = page
        self.label_page.setText(f'{self.current_page + 1}/{pages}')

    def update_buttons(self, page: int = -1):
        if page < 0:
            page += len(self.results)
        self.button_next.setEnabled(page < len(self.results) - 1)
        self.button_last.setEnabled(bool(page and self.results))
        self.button_clear.setEnabled(bool(self.results))

        self.action_next.setEnabled(self.button_next.isEnabled())
        self.action_last.setEnabled(self.button_last.isEnabled())
        self.action_clear.setEnabled(self.button_clear.isEnabled())

    def change_db(self, database):
        self.using_db = database
        self.label_db.setText('当前数据库: %s' % database)

    def set_result_report(self, size: int = 0, cost: timedelta = timedelta(0)):
        self.label_result.setText(f'用时{cost.total_seconds():.2f}秒,共{size}个结果')

    def update_tree_file(self):
        model: QStandardItemModel = self.tree_file.model()
        root = model.invisibleRootItem()
        old_databases = set(self.tables)  # remember current databases in GUI
        for database in self.base_path.iterdir():
            if database.is_file():
                continue
            db_name = database.name
            db = None
            for row in range(root.rowCount()):
                if root.child(row, 0).text() == db_name:
                    db = root.child(row, 0)
                    break
            if db is None:
                db = ReadOnlyItem(db_name)
                db.appendRow(ReadOnlyItem('table'))
                db.appendRow(ReadOnlyItem('schema'))
                self.tables[db_name] = set()
                root.appendRow(db)
                old_tables = set()
            else:
                old_databases.remove(
                    db_name)  # ensured this database still exists
                old_tables = set(
                    self.tables[db_name])  # remember current tables in GUI
            table = db.child(0, 0)
            schema = db.child(1, 0)
            for file in database.glob('*.table'):
                table_name = file.stem
                if table_name in self.tables[db_name]:
                    old_tables.remove(
                        table_name)  # ensured this table still exists
                    continue
                self.tables[db_name].add(table_name)
                table.appendRow(ReadOnlyItem(table_name))
                schema.appendRow(ReadOnlyItem(table_name))
            for row in reversed(range(table.rowCount())):
                if table.child(row, 0).text(
                ) in old_tables:  # Remove redundant tables in GUI
                    self.tables[db_name].remove(table.child(row, 0).text())
                    table.removeRow(row)
                    schema.removeRow(row)
        for row in reversed(range(
                root.rowCount())):  # remove redundant databases in GUI
            if root.child(row, 0).text() in old_databases:
                self.tables.pop(root.child(row, 0).text())
                root.removeRow(row)

    def run_sql(self, sql):
        if self.status != Status.Waiting:
            self.error_report('系统忙碌', '请等待当前SQL运行、渲染完成后再执行新的SQL')
            return
        self.mutex.lock()
        self.queue.put(sql)
        self.wait_condition.wakeAll()
        self.mutex.unlock()

        self.timer.start()
        self.last_start = datetime.now()
        self.set_status(Status.Running)

    def update_cost(self):
        cost = datetime.now() - self.last_start
        self.set_status(self.status, cost)

    def load_sql(self, path):
        try:
            self.document.setPlainText(open(path, encoding='utf-8').read())
        except Exception as e:
            self.error_report(type(e).__name__, str(e))

    def load_data(self, path):
        table = path.stem.upper()
        window = TableChooseWindow(self.using_db,
                                   self.tables,
                                   table,
                                   parent=self)
        # window.setWindowFlag(Qt.FramelessWindowHint)
        if window.exec():
            database = window.combo_db.currentText()
            table = window.combo_table.currentText()
            self.run_sql((path, database, table))
            self.change_db(database)

    def error_report(self, title, content):
        QMessageBox.critical(self, title, content)

    @pyqtSlot(QModelIndex)
    def on_tree_file_doubleClicked(self, index: QModelIndex):
        if index.parent().data() == 'table':
            sql = f'USE {index.parent().parent().data()};SELECT * FROM {index.data()};'
            self.run_sql(sql)
        elif index.parent().data() == 'schema':
            sql = f'USE {index.parent().parent().data()};DESC {index.data()};'
            self.run_sql(sql)

    @pyqtSlot()
    def on_text_code_textChanged(self):
        if self.processing_highlight:
            self.processing_highlight = False
        else:
            self.processing_highlight = True
            sql = self.text_code.toPlainText()
            highlighted = SQLHighlighter.highlight(sql)
            cursor = self.text_code.textCursor()
            cursor_position = cursor.position()
            self.document.setHtml(highlighted)
            cursor.setPosition(cursor_position)
            self.text_code.setTextCursor(cursor)

    def keyPressEvent(self, event: QKeyEvent) -> None:
        if event.key() == Qt.Key_Return:  # enter
            if event.modifiers() in (
                    Qt.ControlModifier,
                    Qt.AltModifier):  # alt + enter or ctrl + enter
                self.run_sql(self.text_code.toPlainText())
                return
        return super(QMainWindow, self).keyPressEvent(event)

    @pyqtSlot()
    def on_button_clear_clicked(self):
        if self.table_result.model():
            self.table_result.setModel(None)
        self.results.clear()
        self.change_page()
        self.update_buttons()
        self.set_result_report()

    @pyqtSlot()
    def on_button_next_clicked(self):
        if self.button_next.isEnabled():
            self.page_changed.emit(self.current_page + 1)

    @pyqtSlot()
    def on_button_last_clicked(self):
        if self.button_last.isEnabled():
            self.page_changed.emit(self.current_page - 1)

    @pyqtSlot()
    def open_action(self):
        file, _ = QFileDialog.getOpenFileName(self, '选择sql文件', '.',
                                              'SQL (*.sql);;All files (*)')
        if file:
            self.load_sql(Path(file))

    @pyqtSlot()
    def insert_action(self):
        file, _ = QFileDialog.getOpenFileName(self, '选择tbl文件', '.',
                                              'TBL (*.tbl);;All files (*)')
        if file:
            self.load_data(Path(file))

    @pyqtSlot()
    def exit_action(self):
        self.close()

    @pyqtSlot()
    def next_action(self):
        self.button_next.clicked.emit()

    @pyqtSlot()
    def last_action(self):
        self.button_last.clicked.emit()

    @pyqtSlot()
    def clear_action(self):
        self.button_clear.clicked.emit()

    def dragEnterEvent(self, e: QDragEnterEvent) -> None:
        if e.mimeData().hasUrls():
            urls = e.mimeData().urls()
            if urls and len(urls) == 1 and urls[0].path().endswith(
                ('.sql', '.tbl')):
                e.accept()

    def dropEvent(self, e: QDropEvent) -> None:
        path = Path(e.mimeData().urls()[0].path())
        if path.suffix == '.sql':
            self.load_sql(path)
        elif path.suffix == '.tbl':
            self.load_data(path)
Example #12
0
    def __init__(self, html, allow_cancel=False, msg="Wiersze błędne:"):
        super(ReportDialog, self).__init__()

        OKButton = QtGui.QPushButton("OK")
        OKButton.setDefault(True)

        buttonBox = QtGui.QDialogButtonBox()
        buttonBox.addButton(OKButton, QtGui.QDialogButtonBox.AcceptRole)
        if allow_cancel:
            buttonBox.addButton(QtGui.QPushButton("Przerwij"),
                                QtGui.QDialogButtonBox.RejectRole)

        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.cancel)

        content = QtGui.QTextEdit()

        grid = QtGui.QGridLayout()

        grid.addWidget(QtGui.QLabel(msg), 0, 0)
        grid.addWidget(content, 1, 0)

        layout = QtGui.QVBoxLayout()
        layout.addLayout(grid)
        layout.addWidget(buttonBox)

        self.setLayout(layout)
        self.setWindowTitle("Weryfikacja")
        self.resize(1000, 800)

        doc = QTextDocument()
        css = """
			table.invoices tr td {
				padding-left: 4px;
				padding-right: 4px;
			}
			table.invoices tr {
				padding-bottom: 5px;
				border: 1px solid #000 !important;
			}
			table.invoices {
				with: 100%;
				border-collapse: collapse;
			}
			table.invoices, table.invoices th, table.invoices td {
				border: 1px solid black;
			}
			table.invoices td.currency {
				text-align: right;
				font-family: monospace;
			}
			ul.errors li {
				color: #E44;
			}
		"""
        doc.setDefaultStyleSheet(css)

        content.setDocument(doc)
        content.setReadOnly(True)
        content.setHtml(html)

        self.status = None