248 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# -*- coding: utf-8 -*-
 | 
						|
#
 | 
						|
# buffer.py - management of WeeChat buffers/nicklist
 | 
						|
#
 | 
						|
# Copyright (C) 2011-2021 Sébastien Helleu <flashcode@flashtux.org>
 | 
						|
#
 | 
						|
# This file is part of QWeeChat, a Qt remote GUI for WeeChat.
 | 
						|
#
 | 
						|
# QWeeChat is free software; you can redistribute it and/or modify
 | 
						|
# it under the terms of the GNU General Public License as published by
 | 
						|
# the Free Software Foundation; either version 3 of the License, or
 | 
						|
# (at your option) any later version.
 | 
						|
#
 | 
						|
# QWeeChat is distributed in the hope that it will be useful,
 | 
						|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
# GNU General Public License for more details.
 | 
						|
#
 | 
						|
# You should have received a copy of the GNU General Public License
 | 
						|
# along with QWeeChat.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
#
 | 
						|
 | 
						|
"""Management of WeeChat buffers/nicklist."""
 | 
						|
 | 
						|
from pkg_resources import resource_filename
 | 
						|
 | 
						|
from PySide6 import QtCore, QtGui, QtWidgets
 | 
						|
 | 
						|
from qweechat.chat import ChatTextEdit
 | 
						|
from qweechat.input import InputLineEdit
 | 
						|
from qweechat.weechat import color
 | 
						|
 | 
						|
 | 
						|
class GenericListWidget(QtWidgets.QListWidget):
 | 
						|
    """Generic QListWidget with dynamic size."""
 | 
						|
 | 
						|
    def __init__(self, *args):
 | 
						|
        super().__init__(*args)
 | 
						|
        self.setMaximumWidth(100)
 | 
						|
        self.setTextElideMode(QtCore.Qt.ElideNone)
 | 
						|
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
 | 
						|
        self.setFocusPolicy(QtCore.Qt.NoFocus)
 | 
						|
        pal = self.palette()
 | 
						|
        pal.setColor(QtGui.QPalette.Highlight, QtGui.QColor('#ddddff'))
 | 
						|
        pal.setColor(QtGui.QPalette.HighlightedText, QtGui.QColor('black'))
 | 
						|
        self.setPalette(pal)
 | 
						|
 | 
						|
    def auto_resize(self):
 | 
						|
        size = self.sizeHintForColumn(0)
 | 
						|
        if size > 0:
 | 
						|
            size += 4
 | 
						|
        self.setMaximumWidth(size)
 | 
						|
 | 
						|
    def clear(self, *args):
 | 
						|
        """Re-implement clear to set dynamic size after clear."""
 | 
						|
        QtWidgets.QListWidget.clear(*(self,) + args)
 | 
						|
        self.auto_resize()
 | 
						|
 | 
						|
    def addItem(self, *args):
 | 
						|
        """Re-implement addItem to set dynamic size after add."""
 | 
						|
        QtWidgets.QListWidget.addItem(*(self,) + args)
 | 
						|
        self.auto_resize()
 | 
						|
 | 
						|
    def insertItem(self, *args):
 | 
						|
        """Re-implement insertItem to set dynamic size after insert."""
 | 
						|
        QtWidgets.QListWidget.insertItem(*(self,) + args)
 | 
						|
        self.auto_resize()
 | 
						|
 | 
						|
 | 
						|
class BufferListWidget(GenericListWidget):
 | 
						|
    """Widget with list of buffers."""
 | 
						|
 | 
						|
    def switch_prev_buffer(self):
 | 
						|
        if self.currentRow() > 0:
 | 
						|
            self.setCurrentRow(self.currentRow() - 1)
 | 
						|
        else:
 | 
						|
            self.setCurrentRow(self.count() - 1)
 | 
						|
 | 
						|
    def switch_next_buffer(self):
 | 
						|
        if self.currentRow() < self.count() - 1:
 | 
						|
            self.setCurrentRow(self.currentRow() + 1)
 | 
						|
        else:
 | 
						|
            self.setCurrentRow(0)
 | 
						|
 | 
						|
 | 
						|
class BufferWidget(QtWidgets.QWidget):
 | 
						|
    """
 | 
						|
    Widget with (from top to bottom):
 | 
						|
    title, chat + nicklist (optional) + prompt/input.
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self, display_nicklist=False):
 | 
						|
        super().__init__()
 | 
						|
 | 
						|
        # title
 | 
						|
        self.title = QtWidgets.QLineEdit()
 | 
						|
        self.title.setFocusPolicy(QtCore.Qt.NoFocus)
 | 
						|
 | 
						|
        # splitter with chat + nicklist
 | 
						|
        self.chat_nicklist = QtWidgets.QSplitter()
 | 
						|
        self.chat_nicklist.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
 | 
						|
                                         QtWidgets.QSizePolicy.Expanding)
 | 
						|
        self.chat = ChatTextEdit(debug=False)
 | 
						|
        self.chat_nicklist.addWidget(self.chat)
 | 
						|
        self.nicklist = GenericListWidget()
 | 
						|
        if not display_nicklist:
 | 
						|
            self.nicklist.setVisible(False)
 | 
						|
        self.chat_nicklist.addWidget(self.nicklist)
 | 
						|
 | 
						|
        # prompt + input
 | 
						|
        self.hbox_edit = QtWidgets.QHBoxLayout()
 | 
						|
        self.hbox_edit.setContentsMargins(0, 0, 0, 0)
 | 
						|
        self.hbox_edit.setSpacing(0)
 | 
						|
        self.input = InputLineEdit(self.chat)
 | 
						|
        self.hbox_edit.addWidget(self.input)
 | 
						|
        prompt_input = QtWidgets.QWidget()
 | 
						|
        prompt_input.setLayout(self.hbox_edit)
 | 
						|
 | 
						|
        # vbox with title + chat/nicklist + prompt/input
 | 
						|
        vbox = QtWidgets.QVBoxLayout()
 | 
						|
        vbox.setContentsMargins(0, 0, 0, 0)
 | 
						|
        vbox.setSpacing(0)
 | 
						|
        vbox.addWidget(self.title)
 | 
						|
        vbox.addWidget(self.chat_nicklist)
 | 
						|
        vbox.addWidget(prompt_input)
 | 
						|
 | 
						|
        self.setLayout(vbox)
 | 
						|
 | 
						|
    def set_title(self, title):
 | 
						|
        """Set buffer title."""
 | 
						|
        self.title.clear()
 | 
						|
        if title is not None:
 | 
						|
            self.title.setText(title)
 | 
						|
 | 
						|
    def set_prompt(self, prompt):
 | 
						|
        """Set prompt."""
 | 
						|
        if self.hbox_edit.count() > 1:
 | 
						|
            self.hbox_edit.takeAt(0)
 | 
						|
        if prompt is not None:
 | 
						|
            label = QtWidgets.QLabel(prompt)
 | 
						|
            label.setContentsMargins(0, 0, 5, 0)
 | 
						|
            self.hbox_edit.insertWidget(0, label)
 | 
						|
 | 
						|
 | 
						|
class Buffer(QtCore.QObject):
 | 
						|
    """A WeeChat buffer."""
 | 
						|
 | 
						|
    bufferInput = QtCore.Signal(str, str)
 | 
						|
 | 
						|
    def __init__(self, data=None):
 | 
						|
        QtCore.QObject.__init__(self)
 | 
						|
        self.data = data or {}
 | 
						|
        self.nicklist = {}
 | 
						|
        self.widget = BufferWidget(display_nicklist=self.data.get('nicklist',
 | 
						|
                                                                  0))
 | 
						|
        self.update_title()
 | 
						|
        self.update_prompt()
 | 
						|
        self.widget.input.textSent.connect(self.input_text_sent)
 | 
						|
 | 
						|
    def pointer(self):
 | 
						|
        """Return pointer on buffer."""
 | 
						|
        return self.data.get('__path', [''])[0]
 | 
						|
 | 
						|
    def update_title(self):
 | 
						|
        """Update title."""
 | 
						|
        try:
 | 
						|
            self.widget.set_title(
 | 
						|
                color.remove(self.data['title']))
 | 
						|
        except Exception:  # noqa: E722
 | 
						|
            # TODO: Debug print the exception to be fixed.
 | 
						|
            # traceback.print_exc()
 | 
						|
            self.widget.set_title(None)
 | 
						|
 | 
						|
    def update_prompt(self):
 | 
						|
        """Update prompt."""
 | 
						|
        try:
 | 
						|
            self.widget.set_prompt(self.data['local_variables']['nick'])
 | 
						|
        except Exception:  # noqa: E722
 | 
						|
            self.widget.set_prompt(None)
 | 
						|
 | 
						|
    def input_text_sent(self, text):
 | 
						|
        """Called when text has to be sent to buffer."""
 | 
						|
        if self.data:
 | 
						|
            self.bufferInput.emit(self.data['full_name'], text)
 | 
						|
 | 
						|
    def nicklist_add_item(self, parent, group, prefix, name, visible):
 | 
						|
        """Add a group/nick in nicklist."""
 | 
						|
        if group:
 | 
						|
            self.nicklist[name] = {
 | 
						|
                'visible': visible,
 | 
						|
                'nicks': []
 | 
						|
            }
 | 
						|
        else:
 | 
						|
            self.nicklist[parent]['nicks'].append({
 | 
						|
                'prefix': prefix,
 | 
						|
                'name': name,
 | 
						|
                'visible': visible,
 | 
						|
            })
 | 
						|
 | 
						|
    def nicklist_remove_item(self, parent, group, name):
 | 
						|
        """Remove a group/nick from nicklist."""
 | 
						|
        if group:
 | 
						|
            if name in self.nicklist:
 | 
						|
                del self.nicklist[name]
 | 
						|
        else:
 | 
						|
            if parent in self.nicklist:
 | 
						|
                self.nicklist[parent]['nicks'] = [
 | 
						|
                    nick for nick in self.nicklist[parent]['nicks']
 | 
						|
                    if nick['name'] != name
 | 
						|
                ]
 | 
						|
 | 
						|
    def nicklist_update_item(self, parent, group, prefix, name, visible):
 | 
						|
        """Update a group/nick in nicklist."""
 | 
						|
        if group:
 | 
						|
            if name in self.nicklist:
 | 
						|
                self.nicklist[name]['visible'] = visible
 | 
						|
        else:
 | 
						|
            if parent in self.nicklist:
 | 
						|
                for nick in self.nicklist[parent]['nicks']:
 | 
						|
                    if nick['name'] == name:
 | 
						|
                        nick['prefix'] = prefix
 | 
						|
                        nick['visible'] = visible
 | 
						|
                        break
 | 
						|
 | 
						|
    def nicklist_refresh(self):
 | 
						|
        """Refresh nicklist."""
 | 
						|
        self.widget.nicklist.clear()
 | 
						|
        for group in sorted(self.nicklist):
 | 
						|
            for nick in sorted(self.nicklist[group]['nicks'],
 | 
						|
                               key=lambda n: n['name']):
 | 
						|
                prefix_color = {
 | 
						|
                    '': '',
 | 
						|
                    ' ': '',
 | 
						|
                    '+': 'yellow',
 | 
						|
                }
 | 
						|
                col = prefix_color.get(nick['prefix'], 'green')
 | 
						|
                if col:
 | 
						|
                    icon = QtGui.QIcon(
 | 
						|
                        resource_filename(__name__,
 | 
						|
                                          'data/icons/bullet_%s_8x8.png' %
 | 
						|
                                          col))
 | 
						|
                else:
 | 
						|
                    pixmap = QtGui.QPixmap(8, 8)
 | 
						|
                    pixmap.fill()
 | 
						|
                    icon = QtGui.QIcon(pixmap)
 | 
						|
                item = QtWidgets.QListWidgetItem(icon, nick['name'])
 | 
						|
                self.widget.nicklist.addItem(item)
 | 
						|
                self.widget.nicklist.setVisible(True)
 |