#-*- coding: utf-8 -*-

# Copyright 2012-2016 Mir Calculate. http://www.calculate-linux.org
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

from __future__ import print_function
from __future__ import absolute_import
import os
import time
import urllib.request as urllib2
import pwd
import sys

from calculate.consolegui import qt
# from calculate.core.client.function import create_obj
# from .utils import create_obj
from . import utils
from calculate.lib.utils.files import readLinesFile, listDirectory, readFile, \
    getProgPath, process, STDOUT
from calculate.lib.utils.colortext.palette import (
    GuiPalette as WorkPalette)
from calculate.lib.utils.tools import Locker

ParameterWindow = qt.QPalette.Window

def get_system_rgb(obj, pallete_type):
    color = obj.palette().color(pallete_type).getRgb()
    return "rgb%s"%str(color[0:3])

def dpivalue(size):
    try:
        return size * qt.QApplication.screens()[0].logicalDotsPerInch() / 96.0;
    except BaseException as e:
        print(str(e))
        if isinstance(e, KeyboardInterrupt):
            raise
        return size

def alphed(rgbstr, value):
    # return rgbstr.replace(")", ",%d)"%value)
    return f"rgba({rgbstr[4:-1]}, {value})"

def get_icon(*images):
    fimage = images[0]
    if fimage.startswith("/") or fimage.endswith(".svg") or fimage.endswith(".png"):
        icon = qt.QIcon(fimage)
        images = images[1:]
        if not icon.isNull():
            return icon
    else:
        icon = qt.QIcon()
    themeName = qt.QIcon.themeName()
    for image in images:
        for theme in (themeName, "Calculate", "Tango", "Adwaita"):
            icon.setThemeName(theme)
            icon = icon.fromTheme(image)
            if not icon.isNull():
                return icon
    return qt.QIcon()

def get_pixmap(*images, **kw):
    pixmap = None
    fallback_icon = kw.get('fallback_icon', None)
    _size = kw.get('size', 32)
    qsize = kw.get('size', qt.QSize(_size,_size))
    for image in images:
        icon = get_icon(image)
        if not icon.isNull():
            return icon.pixmap(_size)
        elif os.path.isfile(image):
            ir = qt.QImageReader(image)
            ir.setScaledSize(qsize)
            img = ir.read()
            return qt.QPixmap().fromImage(img)
    else:
        if fallback_icon:
            return get_icon('applications-system').pixmap(_size)
    return None


# _('The user must not be root')
class TopMenu(qt.QPushButton):
    def __init__(self, label, images, parent = None):
        super().__init__(parent)
        self.setStyleSheet("QPushButton{border: none; margin: 0px;}"
                           "QPushButton:hover{border: 1px solid #73D1FF;"
                           "border-radius: 3px; margin: 0px;}")
#     self.setStyleSheet("QPushButton{border: none; margin: 0px 0px 0px 0px;}"
#                           ":hover {border: 1px solid #73D1FF;"
#                           "border-radius: 3px; margin: 0px 0px 0px 0px;}"
#                           ":pressed {border: 1px solid #63C1EF;"
#                           "border-radius: 3px; margin: 20px 0px 0px 0px;}")
        self.layout = qt.QVBoxLayout(self)

        self.image_lbl = qt.QLabel(self)

        icon = get_icon(*images)

#        icon.actualSize(qt.QSize(48,48))
        pm1 = icon.pixmap(24)

#        img = p.toImage()
#        p.fromImage(img)
        pm2 = pm1.scaled(qt.QSize(24, 24), qt.Qt.KeepAspectRatio,
                        qt.Qt.SmoothTransformation)
#        pm2.scaled(24,24)

        self.image_lbl.setPixmap(pm2)
#        self.image_lbl.adjustSize()
        #self.image_lbl.setFixedHeight(dpivalue(24))
        self.image_lbl.setAlignment(qt.Qt.AlignCenter)

        # add transparency
        self.image_lbl.setAttribute(qt.Qt.WA_NoSystemBackground)


        self.layout.addWidget(self.image_lbl)
        self.setFlat(True)


        self.lbl = qt.QLabel(label, self)
        self.lbl.setAlignment(qt.Qt.AlignCenter)

        # add transparency
        self.lbl.setAttribute(qt.Qt.WA_NoSystemBackground)

        self.layout.addWidget(self.lbl)
        self.layout.setContentsMargins(2,4,2,4)
        self.layout.setSpacing(0)

#        self.setFixedSize(48,40)
        self.setFixedHeight(52)
        if self.lbl.sizeHint().width() > 32:
            self.setFixedWidth(self.lbl.sizeHint().width()+16)
        else:
            self.setFixedWidth(48)
        self.updateGeometry()
        self.setFocusPolicy(qt.Qt.NoFocus)

        self.setAttribute(qt.Qt.WA_DeleteOnClose)

    def mousePressEvent(self, event):
        self.layout.setContentsMargins(2,5,2,4)
        event.accept()
        qt.QPushButton.mousePressEvent(self, event)

    def mouseReleaseEvent(self, event):
        self.layout.setContentsMargins(2,4,2,4)
        event.accept()
        qt.QPushButton.mouseReleaseEvent(self, event)

    def text(self):
        return self.lbl.text()

    def setText(self, text):
        self.lbl.setText(text)
        self.setFixedHeight(52)
        if self.lbl.sizeHint().width() > 48:
            self.setFixedWidth(self.lbl.sizeHint().width()+16)
        else:
            self.setFixedWidth(48)

class HelpMenu(TopMenu):
    def __init__(self, label, images, actions, parent):
        TopMenu.__init__(self, label, images, parent)
        self._parent = parent
        self.actions = actions

    def mousePressEvent(self, event):
        if event.button() != qt.Qt.LeftButton:
            event.ignore()
            return 0
        TopMenu.mousePressEvent(self, event)
        menu = qt.QMenu(self)

        About_icon = get_icon(
            '/usr/share/pixmaps/calculate-console-online.svg',
            'help-about', 'help-browser')

        about  = qt.QAction(About_icon, _("About"), self,
                            triggered=self.actions.help)
        menu.addAction(about)

        menu.addSeparator()
        handbook_icon = get_icon('help-contents','system-help','help-browser')

        handbook  = qt.QAction(handbook_icon,_("Info"),\
                                      self, triggered=self.actions.hand_book)
        menu.addAction(handbook)

        menu.addSeparator()
        bug_icon = get_icon('tools-report-bug','system-help','help-browser')

        bug  = qt.QAction(bug_icon, _("Report a Bug"), \
                                      self, triggered=self.actions.bug_report)
        menu.addAction(bug)
#        menu.addSeparator()
        x = self._parent.pos().x() + self.pos().x()
        y = self._parent.pos().y() + self.pos().y() + 2*self.size().height()
        menu.exec_(qt.QPoint(x, y))
        TopMenu.mouseReleaseEvent(self, event)

class ButtonMenu(qt.QPushButton):
    def __init__(self, name, label, images, parent):
        super().__init__(parent)
        self.layout = qt.QVBoxLayout(self)
        self.layout.setAlignment(qt.Qt.AlignHCenter | qt.Qt.AlignTop)

        self.image_lbl = qt.QLabel(self)
        if not images:
            images = ''

        pm2 = get_pixmap(*images.split(','),
                         fallback_icon='applications-system',
                         size=32)

        if pm2:
            pm2 = pm2.scaled(qt.QSize(32,32), qt.Qt.IgnoreAspectRatio,
                            qt.Qt.SmoothTransformation)

        self.image_lbl.setPixmap(pm2)
        self.image_lbl.setMinimumHeight(32)
        self.image_lbl.setAlignment(qt.Qt.AlignHCenter)

        # add transparency
        self.image_lbl.setAttribute(qt.Qt.WA_NoSystemBackground)

        self.layout.addWidget(self.image_lbl)
        self.setFlat(True)

        if not label:
            label = name
        self.lbl = LabelWordWrap(label, self)
        self.lbl.setFixedHeight(dpivalue(52) - 22)
        self.lbl.setAlignment(qt.Qt.AlignHCenter | qt.Qt.AlignTop)
        self.lbl.resize(self.lbl.sizeHint())
        self.lbl.setStyleSheet("QLabel {border: None;}")
        # add transparency
        self.lbl.setAttribute(qt.Qt.WA_NoSystemBackground)

        self.layout.addWidget(self.lbl)
        self.layout.setContentsMargins(0,8,0,0)
#        self.layout.setSpacing(28)

        self.setFixedSize(20 + dpivalue(90),54 + dpivalue(30))
        self.setObjectName(name)

        # rgb(218,218,218)
        # rgb(230,230,230)
        self.updateColors()
        self.updateGeometry()

    def updateColors(self):
        self.setStyleSheet(
            "QPushButton:flat {border: None;}"
            "QPushButton:hover:pressed {border: none;"
            "background-color: %s;"
            "border-radius: 7px;}"
            "QPushButton:hover:!pressed {background-color: "
            "%s; border-radius: 7px;}" %
            (alphed(get_system_rgb(self, qt.QPalette.Highlight),255),
             alphed(get_system_rgb(self, qt.QPalette.Highlight),100)))

    #def mousePressEvent(self, *args, **kwargs):
    #    self.lbl.setStyleSheet("QLabel {border: None; color: %s;}"%
    #                           get_system_rgb(self, qt.QPalette.Base))
    #    return super(ButtonMenu, self).mousePressEvent(*args, **kwargs)

    #def enterEvent(self, *args, **kwargs):
    #    self.lbl.setStyleSheet("QLabel {border: None; color: %s;}"%
    #                           get_system_rgb(self, qt.QPalette.Text))
    #    return super(ButtonMenu, self).enterEvent(*args, **kwargs)

    #def leaveEvent(self, *args, **kwargs):
    #    self.lbl.setStyleSheet("QLabel {border: None; color: %s;}"%
    #                           get_system_rgb(self, qt.QPalette.Text))
    #    return super(ButtonMenu, self).leaveEvent(*args, **kwargs)

    def text(self):
        return self.lbl.text()

class ErrorLabel (qt.QWidget):
    def __init__(self, parent, text = None):
        super().__init__(parent)
        self._parent = parent
        layout = qt.QHBoxLayout(self)

        self.image_lbl = qt.QLabel(self)

        pm1 = get_pixmap("dialog-warning", size=16)
        if pm1:
            pm2 = pm1.scaled(qt.QSize(16, 16),
                             qt.Qt.KeepAspectRatio,
                             qt.Qt.SmoothTransformation)
            self.image_lbl.setPixmap(pm2)
        self.image_lbl.setAlignment(qt.Qt.AlignCenter)

        # add transparency
        self.image_lbl.setAttribute(qt.Qt.WA_NoSystemBackground)
        self.image_lbl.setAlignment(qt.Qt.AlignVCenter)

        layout.addWidget(self.image_lbl)

        self.text_lbl = qt.QLabel()
        self.text_lbl.setWordWrap(True)
        self.text_lbl.setAlignment(qt.Qt.AlignVCenter)
        self.text_lbl.setTextInteractionFlags (self.text_lbl.\
                    textInteractionFlags() | qt.Qt.TextSelectableByMouse)

        maximum = qt.QSizePolicy.Maximum
        exp = qt.QSizePolicy.Expanding
        self.text_lbl.setSizePolicy(exp, maximum)

        layout.addWidget(self.text_lbl)
        layout.setAlignment(qt.Qt.AlignLeft)
        layout.setContentsMargins (0,0,0,0)

        if text:
            self.setText(text)
        self.hide()

        # for clear memory after closed this window
        self.setAttribute(qt.Qt.WA_DeleteOnClose)

    def mousePressEvent(self, event):
        if event.button() == qt.Qt.RightButton:
            if hasattr(self, 'menu'):
                self.menu.move(qt.QCursor.pos())
                self.menu.show()
        event.accept()

    def setText(self, txt):
        txt.replace('\n',' ')
        self.text_lbl.setText(txt)

        if not hasattr(self, 'menu'):
            self.menu = qt.QMenu(self)

            bug_icon = get_icon('tools-report-bug','system-help','help-browser')
            bug  = qt.QAction(bug_icon, _("Report a Bug"), self, \
                                 triggered=self.bug_report)
            self.menu.addAction(bug)

    def bug_report(self):
        self._parent.ClientObj.MainWidget.bug_report()
        self._parent.ClientObj.MainWidget.bugWidget.set_message_text\
                                        (self.text_lbl.text())


ERROR_ICON_SIZE = 16

class ErrorWgt(qt.QWidget):
    def __init__(self, text='', parent=None):
        super().__init__()
        self._parent = parent
        layout = qt.QHBoxLayout(self)


        self.text = LabelWordWrap(text, self)
        self.text.setTextInteractionFlags (self.text.textInteractionFlags() \
                                         | qt.Qt.TextSelectableByMouse)
        layout.addWidget(self.text)

        layout.setContentsMargins(0,0,0,0)
        layout.setSpacing(4)
        layout.setAlignment(qt.Qt.AlignTop)
        self.set_status = False
        self.add_menu()
        self.resize(self.sizeHint())


    def set_warning(self):
        self.text.setStyleSheet("color:blue;")

    def set_error(self):
        self.text.setStyleSheet("font-weight:bold;color:red;")

    def add_menu(self):
        if not hasattr(self, 'menu'):
            self.menu = qt.QMenu(self)
            
            bug_icon = get_icon('tools-report-bug','system-help','help-browser')
            bug  = qt.QAction(bug_icon, _("Report a Bug"), self, \
                                 triggered=self.bug_report)
    #        bug.setDisabled(True)
            self.menu.addAction(bug)

    def bug_report(self):
        self._parent._parent.bug_report()
        self._parent._parent.bugWidget.set_message_text\
                                        (self.text.text())

    def mousePressEvent(self, event):
        if event.button() == qt.Qt.RightButton:
            if hasattr(self, 'menu'):
                self.menu.move(qt.QCursor.pos())
                self.menu.show()
        event.accept()

    def resizeEvent(self, resize_var):
        self.setFixedHeight(self.text.height())
#        self.setFixedHeight(self.text.height() + 24)

class LabelWordWrap(qt.QLabel):
    def __init__(self, name, parent = None, mono=False, margin_top=0):
        if not name:
            name = ''
        try:
            # name = name.decode('utf-8')
            name = name
            if not mono:
                name = name.replace("&nbsp;"," ")
            else:
                name = name.replace("&#9;", "&nbsp;"*8)
            leftMargin = len(name)-len(name.lstrip(' '))
            name = name[leftMargin:]
        except (UnicodeDecodeError, UnicodeEncodeError):
            pass
        super().__init__(name, parent)
        WorkPalette.defaultBackground = get_system_rgb(
            self, qt.QPalette.Window)
        WorkPalette.defaultColor[0] = get_system_rgb(
            self, qt.QPalette.Text)
        if mono:
            self.setStyleSheet(
                'font-family: Liberation Mono;color:{color};'
                'background-color:{background};'.format(
                    color=WorkPalette.defaultColor[0],
                    background=WorkPalette.defaultBackground
                ))
        else:
            self.setStyleSheet('margin-left:%dpx;margin-top:%d;'%(
                leftMargin*5, margin_top))

        minimum = qt.QSizePolicy.Minimum
        exp = qt.QSizePolicy.Expanding
        self.setSizePolicy(exp, minimum)

        self.setWordWrap(True)

        # for clear memory after closed this window
        self.setAttribute(qt.Qt.WA_DeleteOnClose)

class ClearLineEdit(qt.QLineEdit):
    def __init__(self, text = None, parent=None):
        super().__init__(text, parent)
        self.def_text = text
        self.button=qt.QToolButton(self)
        self.button.setCursor(qt.Qt.ArrowCursor)
        self.button.hide()
        self.button.setFocusPolicy(qt.Qt.NoFocus)
        icon = get_icon("edit-clear")
        if not icon.isNull():
            self.button.setIcon(icon)
        else:
            self.button.setText('clear')
        self.button.setStyleSheet("border: none;")
        self.textChanged.connect(self.changed)
        self.button.clicked.connect(self.clear)

        # for clear memory after closed this window
        self.setAttribute(qt.Qt.WA_DeleteOnClose)

        layout=qt.QVBoxLayout(self)
        layout.addWidget(self.button,0,qt.Qt.AlignRight)
        layout.setSpacing(0)

    def changed(self,text):
        if len(text)==0: self.button.hide()
        else: self.button.show()

    def focusInEvent(self, FocusEvent):
        if self.text() == self.def_text:
            self.clear()

    def focusOutEvent(self, FocusEvent):
        if self.text() == '':
            self.setText(self.def_text)

class FileOpenWgt(qt.QWidget):
    textChanged = qt.Signal()
    def __init__(self, parent, type, caption=None, directory=None):
        super().__init__(parent)
        self.type = type
        self.caption = caption
        self.dir = directory

        self.data = None

        self.hlayout = qt.QHBoxLayout(self)

        self.lineEdit = qt.QLineEdit(self)
        self.lineEdit.textChanged.connect(self.textChanged)

        self.button=qt.QToolButton(self)
        self.button.setCursor(qt.Qt.ArrowCursor)
        self.button.setFocusPolicy(qt.Qt.NoFocus)
        icon = get_icon("document-open")
        if not icon.isNull():
            self.button.setIcon(icon)
        else:
            self.button.setText(_('Open'))
        self.button.setStyleSheet("border: none;")
        self.button.clicked.connect(self.file_dialog)

        # for clear memory after closed this window
        self.setAttribute(qt.Qt.WA_DeleteOnClose)

        self.hlayout.addWidget(self.lineEdit)
        self.hlayout.addWidget(self.button)
        self.hlayout.setSpacing(0)

        if self.type == 'files':
            self.lineEdit.setReadOnly(True)

    def file_dialog(self):
        self.fd = qt.QFileDialog(self, self.caption, self.dir)

        self.fd.setWindowModality(qt.Qt.WindowModal)
        if self.type == 'dir':
            data = self.fd.getExistingDirectory()
        if self.type == 'file':
            data = self.fd.getOpenFileName()
            data = data[0]
        if self.type == 'files':
            data = self.fd.getOpenFileNames()
            data = data[0]
        if data:
            self.data = data
            self.set_label()

    def set_label(self):
        if type(self.data) in [str]:
            self.lineEdit.setText(self.data)
        elif type(self.data) == list:
            lbl = ', '.join(self.data)
            self.lineEdit.setText(lbl)

    def text(self):
        return self.lineEdit.text()

    def setText(self, text):
        return self.lineEdit.setText(text)

class ComboFileWgt(qt.QLabel):
#    textChanged = qt.Signal()
    def __init__(self, parent, type, choice = None, caption=None, \
                 value=None, comments = None):
        super().__init__(parent)
        self.type = type
        self.caption = caption
        self.value = value

        if hasattr (comments, 'string'):
            self.comments = comments.string
        else:
            self.comments = None

        self.data = None

        if not choice:
            choice = []
        if not value in choice and value:
            choice.append(value)
            if self.comments:
                self.comments.append(value)

        self.layout = qt.QHBoxLayout(self)
        self.layout.setContentsMargins(0,0,0,0)
        self.ComboBox = qt.QComboBox()
        self.setContentsMargins(0,0,0,0)
        self.ComboBox.currentIndexChanged.connect(self.setCursorPos)
        self.ComboBox.setEditable(True)
        self.lineEdit = self.ComboBox.lineEdit()
        self.setFixedHeight(self.ComboBox.sizeHint().height()+2)
        self.layout.addWidget(self.ComboBox)

        self.view_value = []
        if choice:
            if not self.comments:
                for item in choice:
                    self.ComboBox.addItem(item)
                    if value == item:
                        self.ComboBox.setCurrentIndex(self.ComboBox.count()-1)
            else:
                for item in range (len(self.comments)):
                    try:
                        self.ComboBox.addItem(self.comments[item])
                        self.view_value.append(self.comments[item])
                    except IndexError:
                        self.ComboBox.addItem(choice[item])
                        self.view_value.append(choice[item])
                    self.ComboBox.setItemData(item,choice[item])

                    if value == choice[item]:
                        self.ComboBox.setCurrentIndex(self.ComboBox.count()-1)
        self.ComboBox.setSizeAdjustPolicy(
            qt.QComboBox.AdjustToMinimumContentsLengthWithIcon)

        self.button = qt.QToolButton(self)
        self.button.setCursor(qt.Qt.ArrowCursor)
        self.button.setFocusPolicy(qt.Qt.NoFocus)

        icon = get_icon("document-open")
        if not icon.isNull():
            self.button.setIcon(icon)
        else:
            self.button.setText(_('Open'))
        self.button.clicked.connect(self.file_dialog)

        self.layout.addWidget(self.button)
        self.unsetErrorBorder()

    def setCursorPos(self, num = None):
        self.lineEdit.setCursorPosition(0)

    def file_dialog(self):
        self.fd = qt.QFileDialog(self, self.caption)

        self.fd.setWindowModality(qt.Qt.WindowModal)
        if self.type == 'dir':
            data = self.fd.getExistingDirectory()
        if self.type == 'file':
            data = self.fd.getOpenFileName()
            data = data[0]
        if self.type == 'files':
            data = self.fd.getOpenFileNames()
            data = data[0]
        if data:
            self.data = data
            self.set_label()

    def set_label(self):
        if type(self.data) in [str]:
            lbl = self.data
            self.ComboBox.addItem(lbl)

        elif type(self.data) == list:
            lbl = ', '.join(self.data)
            self.ComboBox.addItem(lbl)

        if self.comments:
            self.ComboBox.setItemData(self.ComboBox.count()-1, lbl)
        self.ComboBox.setCurrentIndex(self.ComboBox.count()-1)

    def text(self):
        if self.comments:
            if self.ComboBox.currentText() in self.view_value:
                return self.ComboBox.itemData(self.ComboBox.currentIndex())
        return self.ComboBox.currentText()

    def setText(self, text):
        self.ComboBox.addItem(text)
        if self.comments:
            self.ComboBox.setItemData(self.ComboBox.count()-1, text)
        self.ComboBox.setCurrentIndex(self.ComboBox.count()-1)

    def setErrorBorder(self):
        style = ".ComboFileWgt {border: 1px solid red; margin: 0px;}"
        self.setStyleSheet(style)

    def unsetErrorBorder(self):
        style = ".ComboFileWgt {border: 1px solid transparent; margin: 0px;}"
        self.setStyleSheet(style)

class ReadonlyCheckBox(qt.QCheckBox):
    def __init__(self, parent):
        super().__init__(parent)
        self.setFocusPolicy(qt.Qt.NoFocus)
        self.disabled = False

    def mousePressEvent(self, event):
        cur_state = self.checkState()
        event.accept()
        qt.QCheckBox.click(self)
        if self.disabled:
            self.setCheckState(cur_state)

class CentralCheckBox (qt.QWidget):
    def __init__(self, parent, tristate, text = None, ind_col = False):
        super().__init__(parent)
        self.lay = qt.QHBoxLayout(self)
        self.pCheckB = ReadonlyCheckBox(self)
        self.lay.addWidget(self.pCheckB)
        self.lay.setAlignment(qt.Qt.AlignHCenter)
        self.lay.setContentsMargins(3,3,3,3)
        self.setLayout(self.lay)
        if tristate:
            self.pCheckB.setTristate(True)
            self.pCheckB.setCheckState(qt.Qt.PartiallyChecked)
        if not ind_col:
            self.pCheckB.clicked.connect(self.change_label)
            self.change_label()
        self.setStyleSheet('padding: 0px; margin-left: 2px;')
        self.setFocusPolicy(qt.Qt.NoFocus)
        self.setAttribute(qt.Qt.WA_DeleteOnClose)

    def setChecked(self, check = True):
        self.pCheckB.setChecked(check)
        self.change_label()

    def isChecked(self):
        return self.pCheckB.isChecked()

    def set_label(self, text):
        self.pCheckB.setText(text)

    def change_label(self):
        if self.pCheckB.disabled:
            return
        elif self.pCheckB.checkState() == \
                                    qt.Qt.PartiallyChecked:
            self.set_label(_('Auto'))
        elif self.pCheckB.checkState() == qt.Qt.Checked:
            self.set_label(_('Yes'))
        else:
            self.set_label(_('No'))

    def setCheckState(self, CheckState):
        self.pCheckB.setCheckState(CheckState)
        self.change_label()

    def getState(self):
        if self.pCheckB.isTristate():
            if self.pCheckB.checkState() == \
                                        qt.Qt.PartiallyChecked:
                return ''
            elif self.pCheckB.checkState() == qt.Qt.Checked:
                return 'on'
            else:
                return 'off'
        else:
            if self.pCheckB.isChecked():
                return 'on'
            else:
                return 'off'

    def setState(self, text):
        if text.lower() in ['yes', 'on']:
            self.pCheckB.setCheckState(qt.Qt.Checked)
        elif text.lower() in ['no', 'off']:
            self.pCheckB.setCheckState(qt.Qt.Unchecked)
        else:
            self.pCheckB.setCheckState(qt.Qt.PartiallyChecked)
        self.change_label()

    def setCheckable(self, set_bool):
        self.pCheckB.setCheckable(set_bool)

    def _setDisabled(self):
        self.pCheckB.disabled = True

class QComboWgt(qt.QLabel):
    currentIndexChanged = qt.Signal(int)
    def __init__(self, parent = None):
        super().__init__(parent)
        self.layout = qt.QVBoxLayout(self)
        self.layout.setContentsMargins(0,0,0,0)
        self.ComboBox = qt.QComboBox()
        self.setContentsMargins(0,0,0,0)
        self.ComboBox.currentIndexChanged.connect(self.currentIndexChanged)
        self.setFixedHeight(self.ComboBox.sizeHint().height()+2)
        self.layout.addWidget(self.ComboBox)
        self.unsetErrorBorder()

    def insertSeparator(self, separator):
        self.ComboBox.insertSeparator(separator)
    def addItem(self, item):
        self.ComboBox.addItem(item)
    def insertItem(self, pos, item):
        self.ComboBox.insertItem(pos, item)
    def setItemData(self, pos, item):
        self.ComboBox.setItemData(pos, item)
    def setCurrentIndex(self, ind):
        self.ComboBox.setCurrentIndex(ind)
    def currentIndex(self):
        return self.ComboBox.currentIndex()
    def currentText(self):
        return self.ComboBox.currentText()
    def itemData(self, ind):
        return self.ComboBox.itemData(ind)
    def unsetErrorBorder(self):
        style = ".QComboWgt {border: 1px solid transparent; margin: 0px;}"
        self.setStyleSheet(style)
    def setErrorBorder(self):
        style = ".QComboWgt {border: 1px solid red; margin: 0px;}"
        self.setStyleSheet(style)
    def setDuplicatesEnabled(self, boolean = True):
        self.ComboBox.setDuplicatesEnabled(boolean)
    def setEditable(self, boolean = True):
        self.ComboBox.setEditable(boolean)
    def setLineEdit(self, lineEdit):
        self.ComboBox.setLineEdit(lineEdit)
    def lineEdit(self):
        return self.ComboBox.lineEdit()

class ListWidget (qt.QListWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setDropIndicatorShown(True)

    def dropEvent(self, event):
        temp_item = event.source().takeItem(event.source().currentRow())
        self.addItem(temp_item)
        event.accept()

class MultipleChoiceDialog (qt.QWidget):
    """ Widget opens a dialog multiple select """
    def __init__(self, parent, Available_dict, Available_list, Selected_list, \
                 add_ability):
        super().__init__()
        self._parent = parent
        self.layout = qt.QGridLayout(self)
        self.layout.setColumnStretch(0,5)
        self.layout.setColumnStretch(1,5)
        self.layout.setColumnStretch(2,0)
        self.layout.setColumnStretch(3,5)
        self.layout.setColumnStretch(4,5)

        self.Available_dict = Available_dict

        minimum = qt.QSizePolicy.Maximum
        exp = qt.QSizePolicy.Expanding
        # if there is a possibility of adding
        if add_ability:
            add_line_wgt = qt.QWidget(self)
            add_line_layout = qt.QHBoxLayout(add_line_wgt)
            # add "input new items" LineEdit
            self.add_LineEdit = qt.QLineEdit(self)
            self.add_LineEdit.setSizePolicy(exp, minimum)
            add_line_layout.addWidget(self.add_LineEdit)

            # add "add new items" PushButton
            self.add_Button = qt.QPushButton(self)
            self.add_Button.setFixedWidth(32)
            icon = get_icon("list-add")
            if not icon.isNull():
                self.add_Button.setIcon(icon)
            else:
                self.add_Button.setText('Add Item')
            self.add_Button.setShortcut \
                                    (qt.QKeySequence(qt.Qt.Key_Return))
            self.add_Button.clicked.connect(self.add_new_item)
            self.add_Button.setSizePolicy(exp, minimum)
            add_line_layout.addWidget(self.add_Button)

            self.layout.addWidget(add_line_wgt, 0,0,1,5)

        # add 2 labels
        self.available_label = qt.QLabel('Available values', self)
        self.available_label.setSizePolicy(exp, minimum)
        self.layout.addWidget(self.available_label, 1,0,1,2)

        self.selected_label = qt.QLabel('Selected values', self)
        self.selected_label.setSizePolicy(exp, minimum)
        self.layout.addWidget(self.selected_label, 1,3,1,2)

        #add left list
        self.left_ListWidget = ListWidget(self)
        self.left_ListWidget.itemDoubleClicked.connect(self.plus_item)
        self.layout.addWidget(self.left_ListWidget, 2,0,2,2)

        p_m_wgt = qt.QWidget(self)
        p_m_layout = qt.QVBoxLayout(p_m_wgt)

         # add '++' button
        self.plus_all_Button = qt.QPushButton(self)
        icon_next = get_icon('go-last-view', 'go-last')
        if not icon_next.isNull():
            self.plus_all_Button.setIcon(icon_next)
        else:
            self.plus_all_Button.setText('->\n->')
        self.plus_all_Button.clicked.connect(self.plus_all_items)
        p_m_layout.addWidget(self.plus_all_Button)

         # add '+' button
        self.plus_Button = qt.QPushButton(self)
        icon_plus = get_icon('go-next-view', 'go-next')
        if not icon_plus.isNull():
            self.plus_Button.setIcon(icon_plus)
        else:
            self.plus_Button.setText('->')
        self.plus_Button.clicked.connect(self.plus_item)
        p_m_layout.addWidget(self.plus_Button)

        # add '-' button
        self.minus_Button = qt.QPushButton(self)
        icon_minus = get_icon('go-previous-view', 'go-previous')
        if not icon_minus.isNull():
            self.minus_Button.setIcon(icon_minus)
        else:
            self.minus_Button.setText('<-')
        self.minus_Button.clicked.connect(self.minus_item)
        p_m_layout.addWidget(self.minus_Button)

        self.layout.addWidget(p_m_wgt, 2, 2, 2, 1)

        # add '--' button
        self.minus_all_Button = qt.QPushButton(self)
        icon_all_minus = get_icon('go-first-view', 'go-first')
        if not icon_all_minus.isNull():
            self.minus_all_Button.setIcon(icon_all_minus)
        else:
            self.minus_all_Button.setText('<-\n<-')
        self.minus_all_Button.clicked.connect(self.minus_all_items)
        p_m_layout.addWidget(self.minus_all_Button)

        #add right list
        self.right_ListWidget = ListWidget(self)
        self.right_ListWidget.itemDoubleClicked.connect(self.minus_item)
        self.layout.addWidget(self.right_ListWidget, 2,3,2,2)

        buttons_wgt = qt.QWidget(self)
        buttons_layout = qt.QHBoxLayout(buttons_wgt)
        # add OK button
        self.Ok_Button = qt.QPushButton('Ok', self)
        self.Ok_Button.clicked.connect(self.ok_pressed)
        self.Ok_Button.setFixedWidth(100)
        buttons_layout.addWidget(self.Ok_Button)

        # add Cancel button
        self.Cancel_Button = qt.QPushButton(_('Cancel'), self)
        self.Cancel_Button.clicked.connect(self.close)
        self.Cancel_Button.setFixedWidth(100)
        buttons_layout.addWidget(self.Cancel_Button)

        self.layout.addWidget(buttons_wgt, 4,3,1,2, qt.Qt.AlignRight)

        #add Items in list
        self.left_ListWidget.addItems(map(lambda x: Available_dict[x],
                                   filter (lambda x: x not in Selected_list,
                                           Available_list)))
        self.right_ListWidget.addItems(map(lambda x: Available_dict[x],
                                 filter (lambda x: x in Available_dict.keys(),
                                 Selected_list)))

        self.layout.setRowStretch(0,0)
        self.layout.setRowStretch(1,0)
        self.layout.setRowStretch(2,1)
        self.layout.setRowStretch(3,1)
        self.layout.setRowStretch(4,0)
        self.setLayout(self.layout)

    def add_new_item(self):
        # Slot click event add_Button
        if self.add_LineEdit.text() not in [None, '']:
            self.right_ListWidget.addItem(self.add_LineEdit.text())
            self.add_LineEdit.setText('')
        self.add_LineEdit.setFocus()

    def plus_all_items(self):
        # get item in left_ListWidget and set this item in right_ListWidget
        while True:
            temp_item = self.left_ListWidget.takeItem(0)
            if not temp_item:
                return
            self.right_ListWidget.addItem(temp_item)

    def plus_item(self):
        # get item in left_ListWidget and set this item in right_ListWidget
        temp_item = self.left_ListWidget.takeItem \
                                        (self.left_ListWidget.currentRow())
        self.right_ListWidget.addItem(temp_item)

    def minus_item(self):
        # get item in right_ListWidget and set this item in left_ListWidget
        temp_item = self.right_ListWidget.takeItem \
                                        (self.right_ListWidget.currentRow())
        self.left_ListWidget.addItem(temp_item)

    def minus_all_items(self):
        # get item in left_ListWidget and set this item in right_ListWidget
        while True:
            temp_item = self.right_ListWidget.takeItem(0)
            if not temp_item:
                return
            self.left_ListWidget.addItem(temp_item)

    def ok_pressed(self):
        # save all lists and close this widget
        self._parent.Selected = []
        revertDict = {y:x for x,y in self.Available_dict.items()}
        for i in range(self.right_ListWidget.count()):
            text = self.right_ListWidget.takeItem(0).text()
            if text in revertDict:
                self._parent.Selected.append(revertDict[text])
            else:
                self._parent.Selected.append(text)

        self._parent.avail = []
        for i in range(self.left_ListWidget.count()):
            text = self.left_ListWidget.takeItem(0).text()
            if text in revertDict:
                self._parent.avail.append(revertDict[text])
            else:
                self._parent.avail.append(text)

#        self._parent.Selected = ','.join(self._parent.select)
        self._parent.change_value()
        self.close()

    def keyPressEvent(self, key):
        if key.key() in [qt.Qt.Key_Enter, qt.Qt.Key_Return]:
            if hasattr (self, 'add_Button'):
                self.add_new_item()

class MultipleButton(qt.QPushButton):
    def __init__(self, text, parent):
        super().__init__(text, parent)
        self.setStyleSheet("text-align: left; padding: 3px;")
        self.setFocusPolicy(qt.Qt.NoFocus)

    def mousePressEvent(self, button = None):
        self.parent().mousePressEvent()

class MultipleChoice (qt.QWidget):
    Changed = qt.Signal()
    # multiple-choice widget displayed in the table
    def __init__(self, parent, Available_list, Selected, comments, \
                 add_ability = False, expert = False):
        super().__init__(parent)
        ''' Available_list is string list, Selected_list is string,
                                            add_ability is boolean'''
        self.avail = Available_list
        self.Selected = Selected if Selected else []
        if hasattr(comments, 'string'):
            self.Comments = comments.string
        else:
            self.Comments = []
#        self.select = Selected if Selected else []
        self.ability = add_ability

        self.value_dict = None
        self.value_dict = {}
        for i in range (len(self.avail)):
            if len(self.Comments) > i:
                self.value_dict[self.avail[i]] = self.Comments[i]
            else:
                self.value_dict[self.avail[i]] = self.avail[i]

        layout = qt.QHBoxLayout(self)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)

        self.label_text =  ','.join(map (lambda x: self.value_dict[x], \
                                filter (lambda x: x in self.value_dict.keys(),
                                self.Selected)))
        self.lbl = MultipleButton(self.label_text, self)

        self.lbl.setMaximumWidth(450)
        maximum = qt.QSizePolicy.Maximum
        exp = qt.QSizePolicy.Expanding
        self.lbl.setSizePolicy(exp, maximum)
        layout.addWidget(self.lbl)

        self.button=qt.QToolButton(self)
#        self.button.hide()
        self.button.setFocusPolicy(qt.Qt.NoFocus)
        icon = get_icon("list-add")
        if not icon.isNull():
            self.button.setIcon(icon)
        else:
            self.button.setText('+')
        self.button.setStyleSheet("border: none;")
        self.button.setFixedWidth(24)
        self.button.clicked.connect(self.mousePressEvent)
        layout.addWidget(self.button, qt.Qt.AlignRight)

        if expert:
            self.clear_button = qt.QPushButton(self)
            self.clear_button.setFocusPolicy(qt.Qt.NoFocus)
            icon = get_icon('edit-clear')
            if not icon.isNull():
                self.clear_button.setIcon(icon)
            else:
                self.clear_button.setText('C')
            self.clear_button.setToolTip(_('Clear the table'))
            self.clear_button.setStyleSheet("border: none;")
            self.clear_button.setFixedWidth(24)
            self.clear_button.clicked.connect(self.default_value)
            layout.addWidget(self.clear_button, qt.Qt.AlignRight)

        self.setAttribute(qt.Qt.WA_DeleteOnClose)

        self.setLayout(layout)

    def mousePressEvent(self, button = None):
        # call widget MultipleChoiceDialog in new window
        self.MCD = MultipleChoiceDialog(self, self.value_dict, self.avail, \
                                        self.Selected, self.ability)
        self.MCD.setWindowModality(qt.Qt.WindowModal)
        self.MCD.move(qt.QCursor.pos ())
        self.MCD.show()

    def change_value(self):
        # show values in label
#        self.select = self.Selected.split(',') if self.Selected else []
        self.label_text = ','.join(
            self.value_dict.get(x, x) for x in self.Selected)
        self.lbl.setText(self.label_text)
        self.Changed.emit()

    def text(self):
        return self.lbl.text()

    def values(self):
        res_dict = {}
        for key in self.value_dict:
            res_dict[self.value_dict[key]] = key

        res = map(lambda x: res_dict[x],
                  filter (lambda x: x in res_dict, self.Selected))
        res += filter (lambda x: not x in res_dict, self.Selected)
        return res

    def default_value(self):
        self.label_text = ''
        self.lbl.setText(self.label_text)

class AddLineWidget (qt.QWidget):
    def __init__(self, parent, text):
        super().__init__()
        layout = qt.QHBoxLayout(self)
        self.add_line = qt.QLineEdit(self)
        self.add_line.setFixedWidth(100)
        add_button = qt.QPushButton(text, self)
        close_button = qt.QPushButton(_("Cancel"), self)

        layout.addWidget(self.add_line)
        layout.addWidget(add_button)
        layout.addWidget(close_button)

        add_button.clicked.connect(parent.add_line)
        close_button.clicked.connect(self.close)
        self.setWindowTitle(text)
        self.move(qt.QCursor.pos())
        self.show()

class MultipleCheckBox(qt.QCheckBox):
    def __init__(self, parent):
        super().__init__(parent)

class SelectTable(qt.QWidget):
    Changed = qt.Signal()
    # multiple-choice table
    def __init__(self, parent, Available_list, Selected, comments, \
                 add_ability = False, expert = False, default = None):
        super().__init__(parent)
        self._parent = parent

        self.Available_list = Available_list
        self.Selected = Selected
        self.items_dict = {}
        self.comments = []
        self.expert = expert
        self.set_auto = expert if default else False
        self.default = default

        if hasattr(comments, 'string'):
            comments = comments.string
        else:
            comments = None

        self.grid = qt.QGridLayout(self)
        self.grid.setContentsMargins(0, 0, 0, 0)
        self.grid.setSpacing(0)
        self.grid.setAlignment(qt.Qt.AlignTop)

        unit_layout = qt.QHBoxLayout()
        unit_layout.setContentsMargins(0, 0, 0, 0)
        unit_layout.setSpacing(0)

        if add_ability:
            plus_but = qt.QPushButton(self)
            icon = get_icon('list-add')
            if not icon.isNull():
                plus_but.setIcon(icon)
            else:
                plus_but.setText('+')

            plus_but.setToolTip(_('Add a row'))
            plus_but.setFixedSize(30, 30)
            plus_but.clicked.connect(self.line_add)
            unit_layout.addWidget(plus_but)

        self.recover_but = qt.QPushButton(self)
        icon = get_icon('edit-clear')
        if not icon.isNull():
            self.recover_but.setIcon(icon)
        else:
            self.recover_but.setText('R')

        self.recover_but.setToolTip(_('Recover the table'))
        self.recover_but.setFixedSize(30, 30)

        self.recover_but.clicked.connect(self.recover_table)

        unit_layout.addWidget(self.recover_but)

        unit_layout.setAlignment(qt.Qt.AlignLeft)
        self.grid.addLayout(unit_layout, 0,0)

        self.table = qt.QTableWidget(self)

        self.row_count = len(Available_list)
        for num in range(self.row_count):
            try:
                if not comments:
                    comment = Available_list[num]
                else:
                    comment = comments[num]
                    if not comment:
                        comment = Available_list[num]
            except IndexError:
                comment = Available_list[num]
            self.items_dict[comment] = Available_list[num]
            self.comments.append(comment)

        self.create_table()

        self.table.itemClicked.connect(self.row_activate)

        self.grid.addWidget(self.table, 1, 0, 1, 2)
        self.resize(self.sizeHint())


    def create_table(self, hard_auto = False):
        self.table.setColumnCount(2)
        self.table.setRowCount(self.row_count + 1)

        for i in range (2):
            tablewidgetitem = qt.QTableWidgetItem('')
            tablewidgetitem.setBackground(qt.QBrush(qt.QColor \
                                                      ('#dddddd')))
            self.table.setItem(0, i, tablewidgetitem)

        all_check = qt.QCheckBox()
        all_check.setToolTip(_('Check all'))
        all_check.clicked.connect(self.select_all)
        self.table.setCellWidget(0, 0, all_check)

        self.add_select_check(hard_auto)
        for row in range(self.row_count):
            tablewidgetitem = qt.QTableWidgetItem(self.comments[row])
            self.table.setItem(row + 1, 1, tablewidgetitem)
            if not self.expert or not self.default:
                if self.items_dict[self.comments[row]] in self.Selected:
                    if not hard_auto:
                        self.table.cellWidget(row + 1 ,0).setChecked(True)

#        if not add_ability:
        self.table.setEditTriggers(qt.QAbstractItemView.NoEditTriggers)

        self.table.setSelectionMode(qt.QAbstractItemView.NoSelection)

        self.table.horizontalHeader().setStretchLastSection(True)

        self.table.horizontalScrollBar().hide()
        self.table.setColumnWidth(0, 24)

        self.table.verticalHeader().hide()
        self.table.horizontalHeader().hide()
        self.resize_table()

    def select_all(self):
        self.Changed.emit()
        if self.table.cellWidget(0,0).isChecked():
            check = qt.Qt.Checked
        else:
            check = qt.Qt.Unchecked
        for i in range(1, self.table.rowCount()):
            self.table.cellWidget(i,0).setTristate(False)
        for i in range(1, self.table.rowCount()):
            self.table.cellWidget(i,0).setCheckState(check)

    def row_activate(self, item):
        self.table.cellWidget(item.row(),0).click()

    def selected_row(self):
        self.Changed.emit()
        if self.set_auto:
            for i in range(1, self.table.rowCount()):
                if self.table.cellWidget(i,0).checkState() == \
                                qt.Qt.PartiallyChecked:
                    self.table.cellWidget(i,0).setChecked(False)

                self.table.cellWidget(i,0).setTristate(False)
            self.set_auto = False

    def add_select_check(self, hard_auto):
        # add row Selected
        for row in range (1, self.table.rowCount()):
            cb = MultipleCheckBox(self.table)
            if self.expert and self.default:
                cb.setCheckState(qt.Qt.PartiallyChecked)
            if hard_auto:
                cb.setCheckState(qt.Qt.PartiallyChecked)
#            cb.setToolTip(_('Delete the row'))
            cb.clicked.connect(self.selected_row)
            self.table.setCellWidget(row, 0, cb)

    def add_line(self):
        self.Changed.emit()
        if self.set_auto:
            for i in range(1, self.table.rowCount()):
                self.table.cellWidget(i,0).setTristate(False)
                self.table.cellWidget(i,0).setChecked(False)
            self.set_auto = False
        text = self.addLineWgt.add_line.text()
        self.addLineWgt.close()
        row_number = self.table.rowCount()
        self.table.insertRow(row_number)
        cb = MultipleCheckBox(self.table)
        cb.clicked.connect(self.selected_row)
        self.table.setCellWidget(row_number, 0, cb)
        twi = qt.QTableWidgetItem(text)
        self.table.setItem(row_number, 1, twi)
        self.resize_table()

    def line_add(self):
        self.addLineWgt = AddLineWidget(self, _('Add a row'))

    def resize_table(self):
        # Resize table
        h = 2 * self.table.frameWidth()
        for row_in_table in range (self.table.rowCount()):
            h += self.table.rowHeight(row_in_table)
        self.table.setFixedHeight(h)

    def recover_table(self):
        hard_auto = False
        if self.expert:
            self.set_auto = True
            hard_auto = True
        self.create_table(hard_auto = hard_auto)

    def values(self):
        result = []
        for row in range(1, self.table.rowCount()):
            if self.table.cellWidget(row, 0).checkState() == \
                                qt.Qt.PartiallyChecked:
                return []
            if self.table.cellWidget(row, 0).checkState() == \
                                         qt.Qt.Checked:
                value = self.table.item(row, 1).text()
                if value in self.items_dict.keys():
                    result.append(self.items_dict[value])
                else:
                    result.append(value)
        return result

class SelectList(qt.QGroupBox):
    Changed = qt.Signal()
    def __init__(self, parent, label, Available_list, Selected, comments, \
                        add_ability = False, expert = False, default = None):
        super().__init__(label, parent)
        self._parent = parent
        self.Available_list = Available_list
        self.Selected = Selected
        self.items_dict = {}
        self.comments = []
        self.expert = expert
        self.set_auto = expert if default else False
        self.default = default

        if hasattr(comments, 'string'):
            comments = comments.string
        else:
            comments = None

        self.grid = qt.QGridLayout(self)
        self.grid.setContentsMargins(0,0,0,0)
        self.grid.setSpacing(4)
        self.grid.setAlignment(qt.Qt.AlignTop | qt.Qt.AlignLeft)

        buttons_layout = qt.QHBoxLayout()
        buttons_layout.setAlignment(qt.Qt.AlignLeft)
        buttons_layout.setContentsMargins(0,0,0,0)
        if add_ability:
            self.plus_but = qt.QPushButton(self)
            self.plus_but.setFocusPolicy(qt.Qt.NoFocus)
            self.plus_but.setFixedSize(30, 30)
            icon = get_icon('list-add')
            if not icon.isNull():
                self.plus_but.setIcon(icon)
            else:
                self.plus_but.setText('+')
            self.plus_but.setToolTip(_('Add a row'))
            self.plus_but.clicked.connect(self.line_add)
            self.plus_but.setDisabled(True)
            buttons_layout.addWidget(self.plus_but)

        self.recover_but = qt.QPushButton(self)
        self.recover_but.setFocusPolicy(qt.Qt.NoFocus)
        self.recover_but.setFixedSize(30, 30)
        icon = get_icon('edit-undo')
        if not icon.isNull():
            self.recover_but.setIcon(icon)
        else:
            self.recover_but.setText('R')

        self.recover_but.setToolTip(_('Reset'))
        self.recover_but.clicked.connect(self.recover_list)
        if default:
            self.recover_but.setDisabled(True)

        buttons_layout.addWidget(self.recover_but)
        self.grid.addLayout(buttons_layout, 0, 0)

        self.row_count = len(Available_list)
        for num in range(self.row_count):
            try:
                if not comments:
                    comment = Available_list[num]
                else:
                    comment = comments[num]
                    if not comment:
                        comment = Available_list[num]
            except IndexError:
                comment = Available_list[num]
            self.items_dict[comment] = Available_list[num]
            self.comments.append(comment)

        self.CheckBoxList = []
        for row in range(self.row_count):
            item = qt.QCheckBox(self.comments[row])
            item.setFocusPolicy(qt.Qt.NoFocus)
            item.setStyleSheet("QCheckBox {margin: 2px;}"
            "QCheckBox:hover { margin: 2px;"
            "background-color: transparent;}")
            if self.expert:
                item.setTristate(True)
            if self.expert and self.default:
                item.setCheckState(qt.Qt.PartiallyChecked)

            item.clicked.connect(self.selected_row)
            self.grid.addWidget(item, row + 1, 0, 1, 3)
            if not self.expert or not self.default:
                if self.items_dict[self.comments[row]] in self.Selected:
                    item.setChecked(True)
            if not self.set_auto:
                item.setTristate(False)
            self.CheckBoxList.append(item)
        self.resize(self.sizeHint())
        self.setStyleSheet("QGroupBox {"
            'padding-top: 8px; padding-bottom: 0px;'
            'padding-left: 5px; padding-right: 5px;'
            'border: 1px solid gray;'
            'border-left-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1,'
            'stop: 0 gray, stop: 1 transparent);'
            'border-top-color: qlineargradient( x1: 0, y1: 0, x2: 1, y2: 0,'
            'stop: 0 gray, stop: 1 transparent);'
            'border-right: 0px; border-bottom: 0px;'
            'border-top-left-radius: 2px;'

            'background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,'
            'stop: 0 rgba(200, 200, 200, 75), stop: 0.5 transparent,'
            'stop: 1 transparent);}'

            'QGroupBox::title {'
            'background-color: transparent;'
            'subcontrol-position: top center;'
            'margin-top: 6px;}')

    def selected_row(self):
        self.Changed.emit()
        if hasattr (self, 'plus_but'):
            self.plus_but.setEnabled(True)
        self.recover_but.setEnabled(True)
        if self.set_auto:
            for i in range(self.row_count):
                if self.CheckBoxList[i].checkState() == \
                                qt.Qt.PartiallyChecked:
                    self.CheckBoxList[i].setChecked(False)
                self.CheckBoxList[i].setTristate(False)
            self.set_auto = False

    def add_line(self):
        self.Changed.emit()
        if hasattr (self, 'plus_but'):
            self.plus_but.setEnabled(True)
        self.recover_but.setEnabled(True)
        if self.set_auto:
            for i in range(self.row_count):
                self.CheckBoxList[i].setTristate(False)
                self.CheckBoxList[i].setChecked(False)
            self.set_auto = False
        text = self.addLineWgt.add_line.text()
        self.addLineWgt.close()

        item = qt.QCheckBox(text)
        item.setFocusPolicy(qt.Qt.NoFocus)
        item.setStyleSheet("QCheckBox {margin: 2px;}"
            "QCheckBox:hover { margin: 2px;"
            "background-color: transparent;}")
        self.CheckBoxList.append(item)
        self.grid.addWidget(item, self.row_count + 1, 0, 1, 3)
        self.row_count += 1
        item.clicked.connect(self.selected_row)

    def line_add(self):
        self.addLineWgt = AddLineWidget(self, _('Add a row'))

    def recover_list(self):
        if hasattr (self, 'plus_but'):
            self.plus_but.setDisabled(True)
        self.recover_but.setDisabled(True)
        for i in range(len(self.CheckBoxList)):
            item = self.CheckBoxList.pop()
            item.hide()
            self.grid.removeWidget(item)
            del item

        hard_auto = False
        if self.expert:
            self.set_auto = True
            hard_auto = True

        self.CheckBoxList = []
        self.row_count = len(self.Available_list)
        for row in range(self.row_count):
            item = qt.QCheckBox(self.comments[row])
            item.setStyleSheet("QCheckBox {margin: 2px;}"
                         "QCheckBox:hover {margin: 2px;"
                         "background-color: transparent;}")
            if self.expert:
                item.setTristate(True)
            if self.expert and self.default:
                item.setCheckState(qt.Qt.PartiallyChecked)
            if hard_auto:
                item.setCheckState(qt.Qt.PartiallyChecked)

            item.clicked.connect(self.selected_row)
            self.grid.addWidget(item, row + 1, 0, 1, 3)
            if not self.expert or not self.default:
                if self.items_dict[self.comments[row]] in self.Selected:
                    if not hard_auto:
                        item.setChecked(True)
            self.CheckBoxList.append(item)
        self.resize(self.sizeHint())

    def values(self):
        result = []
        for row in range(self.row_count):
            if self.CheckBoxList[row].checkState() == \
                                        qt.Qt.PartiallyChecked:
                return []
            if self.CheckBoxList[row].checkState() == \
                                        qt.Qt.Checked:
                value = self.CheckBoxList[row].text()
                if value in self.items_dict.keys():
                    result.append(self.items_dict[value])
                else:
                    result.append(value)
        return result

class ExpertWidget (qt.QPushButton):
    # multiple-choice widget displayed in the table
    def __init__(self, label, parent):
        super().__init__()
        self.setStyleSheet('''QPushButton:pressed {border: none;}
                                        QPushButton::hover {border: none;}''')
        layout = qt.QHBoxLayout(self)

        layout.setContentsMargins(0,8,0,0)
        layout.setSpacing(5)

        self.image_lbl = qt.QLabel(self)
        self.images = ['draw-triangle2', 'media-playback-start']
        layout.addWidget(self.image_lbl)

        self.text_lbl = qt.QLabel(label, self)
        self.setFocusPolicy(qt.Qt.NoFocus)
        layout.addWidget(self.text_lbl)
        layout.setAlignment(qt.Qt.AlignLeft | qt.Qt.AlignVCenter)

    def set_close(self):
        self.icon = get_icon(*self.images)

        pm = self.icon.pixmap(16)
        pm = pm.scaled(qt.QSize(16, 16), qt.Qt.KeepAspectRatio, \
                        qt.Qt.SmoothTransformation)

        self.image_lbl.setPixmap(pm)
        self.image_lbl.setAlignment(qt.Qt.AlignLeft)

        # add transparency
        self.image_lbl.setAttribute(qt.Qt.WA_NoSystemBackground)

    def set_open(self):
        self.icon = get_icon(*self.images)

        pm = self.icon.pixmap(16)

        pm = pm.scaled(qt.QSize(16, 16), qt.Qt.KeepAspectRatio, \
                        qt.Qt.SmoothTransformation)

        pm = pm.transformed(qt.QTransform().rotate(90))
        self.image_lbl.setPixmap(pm)
        self.image_lbl.setAlignment(qt.Qt.AlignCenter)

        # add transparency
        self.image_lbl.setAttribute(qt.Qt.WA_NoSystemBackground)

class FlowLayout(qt.QLayout):
    def __init__(self, parent=None, margin=0, spacing=-1):
        super().__init__(parent)
        self.setSpacing(spacing)
        self.itemList = []

    def __del__(self):
        item = self.takeAt(0)
        while item:
            item = self.takeAt(0)

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

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

    def itemAt(self, index):
        if index >= 0 and index < len(self.itemList):
            return self.itemList[index]
        return None

    def takeAt(self, index):
        if index >= 0 and index < len(self.itemList):
            return self.itemList.pop(index)
        return None

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

    def hasHeightForWidth(self):
        return True

    def heightForWidth(self, width):
        height = self.doLayout(qt.QRect(0, 0, width, 0), True)
        return height

    def setGeometry(self, rect):
        super(FlowLayout, self).setGeometry(rect)
        self.doLayout(rect, False)

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

    def minimumSize(self):
        size = qt.QSize()
        for item in self.itemList:
            size = size.expandedTo(item.minimumSize())
        return size

    def doLayout(self, rect, testOnly):
        x = rect.x()
        y = rect.y()
        lineHeight = 0

        for item in self.itemList:
            wid = item.widget()
            spaceX = self.spacing() + wid.style().layoutSpacing \
                            (qt.QSizePolicy.PushButton, \
                            qt.QSizePolicy.PushButton, qt.Qt.Horizontal)
            spaceY = self.spacing() + wid.style().layoutSpacing \
                            (qt.QSizePolicy.PushButton, \
                            qt.QSizePolicy.PushButton, qt.Qt.Vertical)
            nextX = x + item.sizeHint().width() + spaceX
            if nextX - spaceX > rect.right() and lineHeight > 0:
                x = rect.x()
                y = y + lineHeight + spaceY
                nextX = x + item.sizeHint().width() + spaceX
                lineHeight = 0

            if not testOnly:
                item.setGeometry(qt.QRect(qt.QPoint(x, y), \
                                                    item.sizeHint()))

            x = nextX
            lineHeight = max(lineHeight, item.sizeHint().height())
        return y + lineHeight - rect.y()

class PlusRow (qt.QWidget):
    """ Widget opens a dialog multiple select """
    def __init__(self, parent, table, field, changed = False, num_row = None):
        super().__init__()
        self.grid = qt.QGridLayout(self)
        self.grid.setContentsMargins(24,8,24,8)
        self.grid.setSpacing(6)
        self.field = field
        self.table = table
        self._parent = parent
        self.changed = changed
        self.num_row = num_row
        x = 0
        y = 0
        self.widget_dict = {}
        if hasattr(field,"label"):
            self.setWindowTitle(field.label or field.name)

        for i in range (len(field.tablevalue.values.ChoiceValue)):
            col = i+1
            element = field.tablevalue.values.ChoiceValue[i].typefield
            name = field.tablevalue.head.string[i]
            # add element in frame
            if element == 'input':
                #add label
                lbl = qt.QLabel(name, self)
                lbl.setAlignment(qt.Qt.AlignRight| qt.Qt.AlignVCenter)
                self.grid.addWidget(lbl, x, y)

                self.widget_dict[str(i)] = qt.QLineEdit(self)
                if field.value:
                    self.widget_dict[str(i)].setText(field.value)
                if field.type == 'int':
                    self.rx = qt.QRegExp ("^[\d]{1,50}$")
                    self.validator = qt.QRegExpValidator(self.rx, self)
                    self.widget_dict[str(i)].setValidator(self.validator)
                elif field.type == 'float':
                    self.rx = qt.QRegExp ("^[\d]{1,50}[.][\d]{1,50}$")
                    self.validator = qt.QRegExpValidator(self.rx, self)
                    self.widget_dict[str(i)].setValidator(self.validator)
                if changed:
                    text = self.table.item(num_row, col).text()
                    self.widget_dict[str(i)].setText(text)
                self.grid.addWidget(self.widget_dict[str(i)], x, y+1)
                x += 1

            elif element in ['check', 'check_tristate']:
                lbl = qt.QLabel(name, self)
                lbl.setAlignment(qt.Qt.AlignRight| qt.Qt.AlignVCenter)
                self.grid.addWidget(lbl, x, y)
                if element == 'check_tristate':
                    self.widget_dict[str(i)] = CentralCheckBox(self, True)
                else:
                    self.widget_dict[str(i)] = CentralCheckBox(self, False)
                if changed:
                    text = self.table.item(num_row, col).data(1)
                    self.widget_dict[str(i)].setState(text)

                self.grid.addWidget(self.widget_dict[str(i)], x, y+1, \
                                    qt.Qt.AlignLeft)
                x += 1

            elif element == 'combo':
                ChoiceValue = field.tablevalue.values.ChoiceValue[i]
                if ChoiceValue.comments and \
                                    hasattr (ChoiceValue.comments, 'string'):
                    choice = ChoiceValue.comments.string
                    values = ChoiceValue.values.string

                else:
                    if ChoiceValue.values and \
                                       hasattr (ChoiceValue.values, 'string'):
                        choice = ChoiceValue.values.string
                    else:
                        choice = []
                    values = choice

                #add label
                lbl = qt.QLabel(name, self)
                lbl.setAlignment(qt.Qt.AlignRight| qt.Qt.AlignVCenter)
                self.grid.addWidget(lbl, x, y)
                self.ComboBox = qt.QComboBox(self)
                text = ''
                if changed:
                    text = self.table.item(num_row, col).text()
                    if text in choice:
                        ind = choice.index(text)
                        text = values[ind]
                for ch in range(len(values)):
                    if len(choice) > ch:
                        if choice[ch]:
                            self.ComboBox.addItem(choice[ch])
                        else:
                            self.ComboBox.addItem(values[ch])
                    else:
                        self.ComboBox.addItem(values[ch])
                    self.ComboBox.setItemData(ch, values[ch])
                    if text and text == values[ch]:
                        self.ComboBox.setCurrentIndex(self.ComboBox.count()-1)

                self.widget_dict[str(i)] = self.ComboBox
                self.grid.addWidget(self.widget_dict[str(i)], x, y+1)
                x += 1

            elif element == 'comboEdit':
                ChoiceValue = field.tablevalue.values.ChoiceValue[i]
                if ChoiceValue.comments and \
                                    hasattr (ChoiceValue.comments, 'string'):
                    choice = ChoiceValue.comments.string
                    values = ChoiceValue.values.string

                else:
                    if ChoiceValue.values and \
                                        hasattr (ChoiceValue.values, 'string'):
                        choice = ChoiceValue.values.string
                    else:
                        choice = []
                    values = choice

                #add label
                lbl = qt.QLabel(name, self)
                lbl.setAlignment(qt.Qt.AlignRight| qt.Qt.AlignVCenter)
                self.grid.addWidget(lbl, x, y)
                self.ComboBox = qt.QComboBox(self)
                self.ComboBox.setDuplicatesEnabled(False)
                self.ComboBox.setEditable(True)
                le = qt.QLineEdit(self)
                # le.setStyleSheet('QLineEdit {background:white;margin: 1px;}')
                self.ComboBox.setLineEdit(le)
                text = None
                if changed:
                    text = self.table.item(num_row, col).text()
                for ch in range(len(values)):
                    if len(choice) > ch:
                        if choice[ch]:
                            self.ComboBox.addItem(choice[ch])
                        else:
                            self.ComboBox.addItem(values[ch])
                    else:
                        self.ComboBox.addItem(values[ch])
                    self.ComboBox.setItemData(ch, values[ch])
                    if text and text == values[ch]:
                        self.ComboBox.setCurrentIndex(self.ComboBox.count()-1)

                if not text in values and text != None:
                    self.ComboBox.addItem(text)
                    self.ComboBox.setItemData(self.ComboBox.count(), text)
                    self.ComboBox.setCurrentIndex(self.ComboBox.count()-1)

                self.widget_dict[str(i)] = self.ComboBox

                self.grid.addWidget(self.widget_dict[str(i)], x, y+1)
                x += 1

            elif element in ['multichoice', 'multichoice_add']:
                if field.element == 'multichoice_add':
                    add_ability = True
                else:
                    add_ability = False
                choice = field.tablevalue.values.ChoiceValue[i].values.string
                comments = field.tablevalue.values.ChoiceValue[i].comments
                default = []
                if changed:
                    text = self.table.item(num_row, col).text()
                    default = text.split(',')
                def_res = []

                if comments and hasattr (comments, 'string'):
                    comm = comments.string
                else: comm = []
                for item in default:
                    if item in comm:
                        ind = comm.index(item)
                        def_res.append(choice[ind])
                    else: def_res.append(item)

                self.widget_dict[str(i)] = \
                MultipleChoice(self, choice, def_res, comments, add_ability)
                #add label
                lbl = qt.QLabel(name, self)
                lbl.setAlignment(qt.Qt.AlignRight| qt.Qt.AlignVCenter)
                self.grid.addWidget(lbl, x, y)
                self.grid.addWidget(self.widget_dict[str(i)], x, y+1)
                x += 1

            elif element == 'password':
                if not name or name.lower() == 'password':
                    name = _('Password')
                lbl1 = LabelWordWrap(name, self)
                lbl1.setAlignment(qt.Qt.AlignRight| qt.Qt.AlignVCenter)
                lbl2 = LabelWordWrap(_('Repeat'), self)
                lbl2.setAlignment(qt.Qt.AlignRight| qt.Qt.AlignVCenter)

                layout = qt.QVBoxLayout()
                layout.setContentsMargins(0,0,0,0)
                layout.setSpacing(0)

                layout.addWidget(lbl1)
                layout.addWidget(lbl2)

                self.grid.addLayout(layout, x, y, 2, 1)

                self.widget_dict[str(i)] = SimplePasswordWidget \
                                                         (self, lbl1, lbl2)
                self.grid.addWidget(self.widget_dict[str(i)], x, y+1, 2, 1)
                x += 2

            elif element == 'readonly' and field.type == 'writable':
                self.widget_dict[str(i)] = ''
                if '0' not in self.widget_dict:
                    continue
                index_widget = self.widget_dict['0']

                ChoiceValue = field.tablevalue.values.ChoiceValue[i]
                values = ChoiceValue.values.string
                comments = ChoiceValue.comments.string
                index_comment = []
                index_values = []
                if hasattr (field.tablevalue.values.ChoiceValue[0].comments, \
                                  'string') and hasattr (field.tablevalue. \
                                  values.ChoiceValue[0].values, 'string'):
                    index_comment = field.tablevalue.values.ChoiceValue[0].\
                                comments.string
                    index_values = field.tablevalue.values.ChoiceValue[0].\
                                values.string

                find_flag = False
                text = self.widget_dict['0'].currentText()
                if text in index_comment:
                    com_ind = index_comment.index(text)
                    val = index_values[com_ind]
                    if val in values:
                        find_flag = True
                        val_ind = values.index(val)
                        self.widget_dict[str(i)] = str(comments[val_ind])
                if text in values:
                    find_flag = True
                    ind = values.index(text)
                    self.widget_dict[str(i)] = str(comments[ind])

                if not find_flag:
                    self.widget_dict[str(i)] = ''

                if type(index_widget) in [qt.QComboBox]:
                    index_widget.editTextChanged.connect(self.change_readonly \
                            (i, values, comments, index_comment, index_values))
                if type(index_widget) in [qt.QLineEdit]:
                    index_widget.textChanged.connect(self.change_readonly \
                            (i, values, comments, index_comment, index_values))

        # add OK button
        self.button_layout = qt.QHBoxLayout()
        self.Ok_Button = qt.QPushButton('Ok', self)
        self.Ok_Button.setFixedWidth(128)
        self.Ok_Button.setShortcut(qt.QKeySequence(qt.Qt.Key_Return))
        self.Ok_Button.clicked.connect(self.ok_pressed)
        self.button_layout.addWidget(self.Ok_Button)

        # add Cancel button
        self.Cancel_Button = qt.QPushButton('Cancel', self)
        self.Cancel_Button.setFixedWidth(128)
        self.Ok_Button.setShortcut(qt.QKeySequence(qt.Qt.Key_Escape))
        self.Cancel_Button.clicked.connect(self.close)
        self.button_layout.addWidget(self.Cancel_Button)
        self.button_layout.setAlignment(qt.Qt.AlignRight)
        self.grid.addLayout(self.button_layout,x,y,1,2,qt.Qt.AlignRight)

        self.grid.setColumnStretch(0,0)
        self.grid.setColumnStretch(1,5)

        self.resize(self.sizeHint().width(), self.sizeHint().height())
        self.setFixedHeight(self.sizeHint().height())

        move_x = parent.window().x() + parent.window().width() - \
                 parent.width() + parent.width()/2 - self.size().width()/2

        self.move(move_x, parent.window().y() + parent.window().height()/2 - \
                  self.size().height()/2)

    def change_readonly(self, i, values, comments, index_comment,index_values):
        def wrapper(index):
            find_flag = False
            text = self.widget_dict['0'].currentText()
            if text in index_comment:
                com_ind = index_comment.index(text)
                val = index_values[com_ind]
                if val in values:
                    find_flag = True
                    val_ind = values.index(val)
                    self.widget_dict[str(i)] = str(comments[val_ind])
            if text in values:
                find_flag = True
                ind = values.index(text)
                self.widget_dict[str(i)] = str(comments[ind])
            if not find_flag:
                self.widget_dict[str(i)] = ''
        return wrapper

    def ok_pressed(self):
        items = filter(lambda x: type(self.widget_dict[str(x)]) == \
                       SimplePasswordWidget, self.widget_dict.keys())
        if filter(lambda x: not self.widget_dict[str(x)].status(), items):
            return 1

        if self.changed:
            row = self.num_row
        else:
            row = self.table.rowCount()
            self.table.setRowCount(row + 1)
        # add widgets in table
        for i in range (len(self.field.tablevalue.values.ChoiceValue)):
            col = i + 1
            val = ''
            if str(i) not in self.widget_dict:
                continue
            if type(self.widget_dict[str(i)]) == CentralCheckBox:
                state = self.widget_dict[str(i)].getState()
                if state == 'on':
                    val = _('Yes')
                elif state == 'off':
                    val = _('No')
                elif not state:
                    val = _('Auto')

            elif type(self.widget_dict[str(i)]) == qt.QComboBox:
                val = self.widget_dict[str(i)].currentText()

            elif type(self.widget_dict[str(i)]) == str:
                if self.widget_dict[str(i)]:
                    val = self.widget_dict[str(i)]

            elif type(self.widget_dict[str(i)]) in [MultipleChoice,
                                                    qt.QLineEdit]:
                val = self.widget_dict[str(i)].text()

            elif type(self.widget_dict[str(i)]) == SimplePasswordWidget:
                if self.widget_dict[str(i)].status():
                    passwd = self.widget_dict[str(i)].get_password()
                    val = '***' if passwd else ''
                else:
                    return 1

            tablewidgetitem = qt.QTableWidgetItem(val)
            if type(self.widget_dict[str(i)]) == CentralCheckBox:
                tablewidgetitem.setData(1, self.widget_dict[str(i)].getState())
            if type(self.widget_dict[str(i)]) == SimplePasswordWidget:
                tablewidgetitem.setData(1, passwd)
            self.table.setItem(row, col, tablewidgetitem)

            self.table.item(row, col).setFlags(qt.Qt.ItemIsEditable)
            brush = qt.QBrush(
                self.palette().color(qt.QPalette.Text))
            self.table.item(row, col).setForeground(brush)

        # adding in table 'readonly' values
        diff = self.table.columnCount() - \
                             len(self.field.tablevalue.values.ChoiceValue) - 1
        for j in range (diff):
            column = len(self.field.tablevalue.values.ChoiceValue) + j + 1
            tablewidgetitem = qt.QTableWidgetItem()
            self.table.setItem(row, column, tablewidgetitem)

            self.table.item(row, column).setFlags(qt.Qt.ItemIsEditable)
            font = self.table.item(row, column).font()
            font.setWeight(qt.QFont.Black)
            self.table.item(row, column).setFont(font)

        if self.field.type == 'writable':
            self._parent.add_select_check(self.table)

        # Resize table
        if self.table.bFixedHeight:
            h = self.table.horizontalHeader().height() + \
                2 * self.table.frameWidth()
            h += self.table.horizontalScrollBar().height()
            for row_in_table in range (self.table.rowCount()):
                h += self.table.rowHeight(row_in_table)
            self.table.setFixedHeight(h)

        if self.table.rowCount() == 1:
            self.table.horizontalHeader().resizeSections(
                qt.QHeaderView.ResizeToContents)
        self.table.setColor()
        self.close()

class PasswordWgt(qt.QWidget):
    # answer to the server question
    def __init__(self, parent, text):
        super().__init__()
        self._parent = parent
        self.text = text
        if parent.label:
            self.setWindowTitle(parent.label)

        self.layout = qt.QGridLayout(self)

        self.pass_edit = qt.QLineEdit(self)
        self.pass_edit.setEchoMode(self.pass_edit.Password)

        self.layout.addWidget(LabelWordWrap(_('Password')),0,0)
        self.layout.addWidget(self.pass_edit,0,1)

        self.pass_edit2 = qt.QLineEdit(self)
        self.pass_edit2.setEchoMode(self.pass_edit2.Password)

        if self.text:
            self.pass_edit.setText('***')
            self.pass_edit2.setText('***')

        self.layout.addWidget(LabelWordWrap(_('Repeat'), self), 1, 0)
        self.layout.addWidget(self.pass_edit2, 1, 1)
        self.pass_edit.textChanged.connect(self.check_passwd)
        self.pass_edit2.textChanged.connect(self.check_passwd)

        self.ok_button = qt.QPushButton(_('Ok'), self)
        self.ok_button.setShortcut(qt.QKeySequence(qt.Qt.Key_Return))
        self.ok_button.clicked.connect(self.send_password)
        self.ok_button.setDisabled(True)
        self.layout.addWidget(self.ok_button,2,0)

        self.cancel_button = qt.QPushButton(_('Cancel'), self)
        self.cancel_button.setShortcut(qt.QKeySequence \
                                                    (qt.Qt.Key_Escape))
        self.cancel_button.clicked.connect(self.close)
        self.layout.addWidget(self.cancel_button,2,1)
        self.resize(self.sizeHint() + qt.QSize(40,0))
        self.setFixedHeight(self.sizeHint().height())
        self.move(qt.QCursor.pos())

    def send_password(self):
        password = self.pass_edit.text()
        if password == self.pass_edit2.text() and password != '***':
            self.text = password
            self._parent.set_text(password)
            self.close()
        else:
            self.ok_button.setDisabled(True)

    def check_passwd(self):
        if self.pass_edit.text() != self.pass_edit2.text():
            self.ok_button.setDisabled(True)
        else:
            self.ok_button.setEnabled(True)

class PasswordWidget(qt.QLineEdit):
    def __init__(self, parent, text = '', label = ''):
        super().__init__()
        self.text = text
        self.label = label
        self.setEchoMode(self.Password)

        self.set_text(text)
        self.setReadOnly(True)

    def mousePressEvent(self, button = None):
        self.passwgt = PasswordWgt(self, self.text)
        self.passwgt.setWindowModality(qt.Qt.WindowModal)
        self.passwgt.show()

    def set_text(self, text):
        self.text = text
        if text:
            self.setText('***')
        else:
            self.setText('')

    def get_text(self):
        if not self.text:
            self.text = ''
        return self.text

class SimplePasswordWidget(qt.QWidget):
    def __init__(self, parent, lbl1, lbl2):
        super().__init__()
        self.layout = qt.QVBoxLayout(self)
        self.layout.setContentsMargins(0,0,0,0)
        self.layout.setSpacing(4)

        self.lbl1 = lbl1
        self.lbl2 = lbl2
        self._status = True

        self.pass_edit = qt.QLineEdit(self)
        self.pass_edit.setEchoMode(self.pass_edit.Password)

        self.layout.addWidget(self.pass_edit)

        self.pass_edit2 = qt.QLineEdit(self)
        self.pass_edit2.setEchoMode(self.pass_edit2.Password)

        self.layout.addWidget(self.pass_edit2)
        self.pass_edit.textChanged.connect(self.check_passwd)
        self.pass_edit2.textChanged.connect(self.check_passwd)

    def check_passwd(self):
        if self.pass_edit.text() != self.pass_edit2.text():
            self._status = False
            self.set_error()
        else:
            self._status = True
            self.set_normal()

    def status(self):
        return self._status

    def set_error(self):
        self.lbl1.setStyleSheet("QLabel { color : red; }")
        self.lbl2.setStyleSheet("QLabel { color : red; }")

    def set_normal(self):
        self.lbl1.setStyleSheet("QLabel { color : black; }")
        self.lbl2.setStyleSheet("QLabel { color : black; }")

    def get_password(self):
        if self.status():
            return self.pass_edit.text()
        else:
            raise Exception


class ResultLayout(qt.QVBoxLayout):
    """
    Слой с результатами работы задачи
    """
    def __init__(self, parent):
        super().__init__(parent)
        self.setAlignment(qt.Qt.AlignTop)
        self.setContentsMargins(28, 28, 28, 10)
        self.setSpacing(2)
        self.content = qt.QVBoxLayout()
        self.content.setAlignment(qt.Qt.AlignTop)
        self.addLayout(self.content)

        self.kill_process_button = self._create_button(_('Break the process'))
        self.kill_process_button.setFixedHeight(dpivalue(32))
        parent._parent.control_button.set_break_button(self.kill_process_button)

    def _addWidget(self, widget):
        self.content.addWidget(widget)

    def _create_button(self, label, width=144):
        button = qt.QPushButton(label)
        button.setFixedWidth(dpivalue(width))
        button.setContentsMargins(0, 10, 0, 0)
        button.setFixedHeight(dpivalue(32))
        #button.setMinimumHeight(
        #    button.minimumSizeHint().height())
        #button.setMaximumHeight(
        #    button.minimumSizeHint().height())
        return button

    def hide_kill_button(self):
        #self.removeWidget(self.kill_process_button)
        self.kill_process_button.close()


class LabelTaskWgt(qt.QLabel):
    def __init__(self, name, parent=None):
        super().__init__(name, parent)
        self.setStyleSheet("color: #B3ABA7;")

    def sizeHint(self):
        self.br_ = qt.QFontMetrics(self.font()).boundingRect('')
        return self.br_.size()

    def paintEvent(self, e):
        p = qt.QPainter(self)
        fm = p.fontMetrics()
        y = (self.sizeHint().height() - self.br_.height()) / 2 + fm.ascent()

        dot_w = fm.width('. ')
        for x in range (0, self.width(), dot_w):
            p.drawText(x, y, '. ')

class TaskWidget(qt.QWidget):
    console_ok = '/usr/share/icons/Calculate/16x16/client-gui/console_ok'
    console_cancel = ('/usr/share/icons/Calculate/16x16/client-gui/'
                      'console_cancel')
    console_skip = "object-select-symbolic"

    def __init__(self, text='', parent=None, clean_text=None):
        super().__init__(parent)
        self._layout = qt.QHBoxLayout(self)

        if clean_text is None:
            clean_text = text
        self.text = qt.QLabel(text, self)
        fm = qt.QFontMetrics(self.text.font())
        d_w = fm.width(clean_text)
        pref = qt.QSizePolicy.Preferred
        exp = qt.QSizePolicy.Expanding
        self.text.setSizePolicy(exp, pref)
        self.text.setMinimumHeight(self.text.sizeHint().height())
        self.text.setMinimumWidth(d_w)
        self._layout.addWidget(self.text)
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(8)
        self.status = False

    def set_status(self, message=None, color=None):
        if not self.status:
            point_lbl = LabelTaskWgt('', self)
            self._layout.addWidget(point_lbl)

            self.image_lbl = qt.QLabel(self)
            self.image_lbl.setFixedHeight(16)
            self._layout.addWidget(self.image_lbl)
            self._layout.setStretch(1, 5)

            #self.image_lbl.setPixmap(icon.pixmap(16))
            self.image_lbl.setStyleSheet('color:%s;'%color)
            self.image_lbl.setText("%s"%message.upper())
            self.status = True

    def set_ok(self):
        self.set_status("ok",color="green")

    def set_error(self):
        self.set_status("failed", color="red")

    def set_skip(self):
        self.set_status("skip", color="gold")


class ButtonsWidget(qt.QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)
        self.layout = qt.QHBoxLayout(self)

        self.layout.setContentsMargins(0,0,0,0)
        self.layout.setSpacing(0)
        self.layout.setAlignment(qt.Qt.AlignRight)

    def add_button(self, button):
        self.layout.addWidget(button)

def _print (*args):
    # print(" ".join(map(lambda x:unicode(x).encode('utf-8'),args)))
    print(" ".join(map(lambda x:str(x),args)))

def show_msg(text, title = None, parent = None):
    msgBox = qt.QMessageBox(parent)
    #DEBUG: want traceback? force error there.
    # raise Exception
    if title:
        msgBox.setWindowTitle(title)
    else:
        msgBox.setWindowTitle("Calculate Console")
    if not text:
        return 1
    if not type(text) in [str]:
        
        if hasattr(text, '__iter__'):
            #print(f'{text} is iterable')
            temp = ''
            for i in text:
                try:
                    # temp += str(i).decode('utf-8')+' '
                    temp += str(i) + ' '
                except (UnicodeEncodeError, UnicodeDecodeError):
                    temp += str(i) + ' '
            text = temp
        else:
            text = str(text)
    msgBox.setText(text)
    msgBox.setStandardButtons(qt.QMessageBox.Ok)
    #TODO this is broken
    msgBox.setWindowIcon(get_icon('calculate-install.svg'))
    msgBox.exec_()

def show_question(parent, text, informative_text = None, cursor_pos = False,
                  not_move = False, title = None):
    msgBox = qt.QMessageBox()
    msgBox.setText(text)
    msgBox.setInformativeText(informative_text)
    msgBox.setStandardButtons(qt.QMessageBox.Yes | qt.QMessageBox.No)
    msgBox.setDefaultButton(qt.QMessageBox.No)
    if title:
        msgBox.setWindowTitle(title)
    # translate
    msgBox.button(msgBox.Yes).setText(_('Yes'))
    msgBox.button(msgBox.No).setText(_('No'))

    if not_move:
        reply = msgBox.exec_()
        return reply
    if cursor_pos:
        msgBox.move(qt.QCursor.pos())
    else:
        msgBox.move(parent.frameGeometry().x()+parent.size().width()/2 - 150,\
                parent.frameGeometry().y() + parent.size().height()/2 - 100)

    reply = msgBox.exec_()
    return reply

#def uniq(seq):
#    seen = set()
#    seen_add = seen.add
#    return [ x for x in seq if x not in seen and not seen_add(x)]

def uniq(seq):
    seen = set()
    return [ x for x in seq if x not in seen and not seen.add(x)]

class VerifyError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

def client_post_auth(client):
    """ authorization client or post request """
    try:
        if not os.path.exists(client.CERT_FILE):
            show_msg (_('You do not have a certificate. Please generate a '
                    'new request and get the new certificate from the server.'))
            return 1
    except VerifyError as e:
        show_msg (e.value)
        return 1
    return 0

class ClientSignal(qt.QThread):
    sid_sig = qt.Signal(int, int)
    connect_count = qt.Signal(str, int, int)
    def __init__(self, ClientObj):
        super().__init__()
        self.ClientObj = ClientObj
        self.connect_count.connect(ClientObj._parent.connect_count_changed)

    def run(self):
        self.exit_flag = False
        self.ClientObj.has_connect = None
        try:
            client_active = self.ClientObj.VarsApi.Get \
                            ('core.cl_core_client_active_period')
        except:
            show_msg('Write cl_core_client_active_period Error!')
            client_active = 15
        sid = get_sid(self.ClientObj.client)
        client = self.ClientObj.client
        while not self.exit_flag:
            reply = 2
            try:
                reply = client.service.active_client(sid)
            except urllib2.URLError:
                reply = 2
            except Exception as e:
                show_msg (e.message, 'no connection to server!')
            if reply == 0:
                #if not self.ClientObj.has_connect:
                self.connect_count.emit(self.ClientObj.host_name,
                                             self.ClientObj.port, 1)
                #self.ClientObj.has_connect = 1
            else:
                #if self.ClientObj.has_connect:
                self.connect_count.emit(self.ClientObj.host_name,
                                             self.ClientObj.port, 0)
                #self.ClientObj.has_connect = 0
            self.sid_sig.emit(sid, reply)
            for i in range (5):
                time.sleep(float(client_active)/15.0)
                if self.exit_flag:
                    self.connect_count.emit(self.ClientObj.host_name,
                                            self.ClientObj.port, 0)
                    return
        self.connect_count.emit(self.ClientObj.host_name,self.ClientObj.port,0)

    def close(self):
        self.exit_flag = True

def post_connect_action(client, ClientObj):
    if client_post_auth(client):
        # Exit with closing session
        client_del_sid(ClientObj.client)
        ClientObj.client = None

        ClientObj.MainWidget.process_dict = {}
        from .ConnectionTabs import SelectedMethodWgt
        if type (ClientObj._parent) == SelectedMethodWgt:
            sys.exit(1)
        return 1

    ClientObj.signaling = ClientSignal(ClientObj)

    ClientObj.signaling.sid_sig.connect(ClientObj.MainWidget.signaling_slot)
    ClientObj.signaling.start()

    ClientObj.sid = get_sid(ClientObj.client)
    # Add Icons in MainMenu
    icon_visible(ClientObj.MainWidget, 'Disconnect', True)
    icon_visible(ClientObj.MainWidget, 'Processes', True)
    icon_visible(ClientObj.MainWidget, 'Session', True)
    icon_visible(ClientObj.MainWidget, 'Connect', False)
    icon_visible(ClientObj.MainWidget, 'Certificates', False)

    ClientObj.methods_list = client_list_methods(ClientObj.sid, client)
    if ClientObj.methods_list  == 1:
        show_msg (_('No methods available!'), parent = ClientObj.MainWidget)
        ClientObj.MainWidget.disconnect(True)
        return 1
    ClientObj.MainWidget.display_methods()

def icon_visible (mainwgt, name, action):
    # show/hide Icon in MainMenu
    if hasattr (mainwgt.topmenu, name):
        getattr (mainwgt.topmenu, name).setVisible(action)

from calculate.lib.utils import ip as ip_mod

def get_ip_mac():
    for Interfaces in ip_mod.getInterfaces():
        try:
            ip, mac, client_type = utils.get_ip_mac_type('gui')
            return (ip, mac)
        except:
            pass
    return ('no_ip','no_mac')

def client_del_sid(client):
    """ delete this session """
    sid = get_sid(client)
    try:
        s = client.service.del_sid(sid)
        fd = open(client.SID_FILE, 'w')
        fd.close()

        if s[0][0] == "-1":
            _print (_("No access to the file!"))
            return -1
        if s[0][0] == "1":
            _print (_("Failed to obtain certificate data!"))
            return -2
        if s[0][0] == "Permission denied":
            _print (_("%s: Permission denied") % s[1][1])
            return -3
        if s[0][0] == '0':
            pass
#            _print (_("SID deleted!"))
    except urllib2.URLError as e:
        if e.__str__() == '<urlopen error The read operation timed out>':
            _print ('Closing process...')
#        _print (_("SID deleted!"))
        return 0
    except Exception as e:
        _print (_("Error removing the session from the server"), e)
        return 1
    return 0

def client_list_methods(sid, client):
    """ get & show all available methods for this certificate """
    DAT = 0 # Access to data soap structure
    RES = 0 # Access to result
    COM = 0 # Getting command group

    try:
        results = client.service.get_methods(sid, 'gui')
    except urllib2.URLError as e:
        _print ('client.service.get_methods in client_list_methods Exception')
        return 1
    if not results:
        return 1
    try:
        if results[DAT][RES][RES][COM] == '0':
            return 1
    except:
        pass
    return results[DAT]

# get session id
def get_sid (client):
    SID_FILE = client.SID_FILE
    with Locker(fn=client.SID_LOCK):
        server_host_name = client.server_host_name
        if not os.path.exists(SID_FILE):
            fs = open(SID_FILE, 'w')
            fs.write('%s 0\n' %server_host_name)
            fs.close()
        else:
            fs = open(SID_FILE, 'r')
            lines = fs.readlines()
            fs.close()
            for line in lines:
                word = line.split()
                if word:
                    if word[0] == server_host_name:
                        sid = int (word[1])
                        return sid
        return 0

class ClientServiceThread(qt.QThread):
    signal = qt.Signal(object)
    signal_extended = qt.Signal(object, object)
    def __init__(self, ClientObj, method_name, *args, **kwargs):
        super().__init__()
        self.ClientObj = ClientObj
        self.method_name = method_name
        self.args = args
        # установка kwargs с провркой на лишние
        self.return_except, self.sleeptime, self.through_object = \
            (lambda return_except=False,sleeptime=None,
                   through_object=None:
                   (return_except,sleeptime,through_object))(**kwargs)
        self.close_flag = False

    def run(self):
        client = self.ClientObj.client
        if self.sleeptime:
            try:
                for i in range(10):
                    time.sleep(self.sleeptime / 10.0)
                    if self.close_flag:
                        return
            except TypeError:
                _print ('TypeError Exception in class ClientServiceThread')

        try:
            print(f"method name : {self.method_name}")
            # print(client.service[0])
            result = client.service[0][self.method_name](*self.args)
        except Exception as e:
            if self.return_except:
                _print ("EMIT EXCEPTION!")
                if self.close_flag:
                    return
                if self.through_object:
                    self.signal_extended.emit(Exception(e), \
                                              self.through_object)
                else:
                    self.signal.emit(Exception(e))
                return
            else:
                _print ("EXCEPTION!", e)
                return
        if self.close_flag:
            return
        if self.through_object:
            self.signal_extended.emit(result, self.through_object)
        else:
            self.signal.emit(result)

    def close(self):
        self.close_flag = True

class ImageLabel(qt.QLabel):
    def __init__(self, image, height_image, parent):
        super().__init__()
#        self._parent = parent
        save_path = os.path.join('/tmp', 'calculate-' + \
                                 pwd.getpwuid(os.getuid()).pw_name)
        if not os.path.isdir(save_path):
            os.mkdir(save_path)
        repeat = None

        image_path, filename = image.rsplit('/',1)
        image_conf = os.path.join(image_path, 'conf')

        repeat_dict = {'no' : 'no-repeat', 'x' : 'repeat-x'}
        for line in readLinesFile(image_conf):
            list_data = line.split()
            if len (list_data) < 2:
                return False
            if list_data[0] == filename:
                if not list_data[1] in repeat_dict.keys():
                    return False
                repeat = list_data[1]
                break

        style = ''

        def resize_image(source_path, height, output_path):
            convert_cmd = getProgPath('/usr/bin/convert')
            identify_cmd = getProgPath('/usr/bin/identify')

            def convert_image(source, res, target):
                command = [convert_cmd, "-quality", "100",
                           source, "-resize", "%s" % res,
                           "-strip",
                           target]
                           #"-strip", "-gravity", "center",
                           #"-crop", "%s+0+0" % res, target]

                convert = process(*command, stderr=STDOUT)
                if convert.success():
                    return True
                return False

            def get_image_resolution(source):
                identify = process(identify_cmd, "-format", "%w %h", source)
                if identify.success():
                    swidth, _sep, sheight = identify.read().strip().partition(" ")
                    if swidth.isdigit() and sheight.isdigit():
                        return int(swidth), int(sheight)
                    return None, None
                return None, None

            cx, cy = get_image_resolution(source_path)
            
            if cx and cy:
                if convert_image(source_path, "{}x{}".format(cx, height),
                    output_path):

                    return get_image_resolution(output_path)
            
            return None

        if len(list_data) == 3:
            fix_image_path = os.path.join(image_path, list_data[2])
            if os.path.isfile(fix_image_path):
                layout = qt.QHBoxLayout(self)
                fix_image = qt.QLabel(self)
                temp_file = os.path.join(save_path, '%s_fix' %filename)
                sizes = resize_image(fix_image_path, height_image, temp_file)
                if sizes:
                    os.chmod(temp_file, 0o666)
                    fix_image.setFixedWidth(sizes[0])
                    fix_image.setStyleSheet("background-image: url(%s); " \
                                            %temp_file)
                    layout.addWidget(fix_image)
                    layout.setContentsMargins(0,0,0,0)
                    layout.setAlignment(qt.Qt.AlignLeft)

        elif len(list_data) > 3:
            color1, color2 = list_data[-2:]
            style = "background-color: qlineargradient(x1: 0, y1: 0, " + \
                "x2: 0, y2: 1, stop: 0 %s, stop: 1 %s);" %(color1, color2)

        temp_file = os.path.join(save_path, '%s_temp' %filename)
        sizes = resize_image(image, height_image, temp_file)
        if sizes:
            os.chmod(temp_file, 0o666)
            style += "background-image: url(%s); " %temp_file
            style += "background-attachment: fixed; "
            style += "background-repeat: %s; " %repeat_dict[repeat.lower()]
            style += "border-bottom: 1px solid #B8B3B0;"
            self.setStyleSheet(style)
            self.setFixedHeight(sizes[1])

def get_view_params(client, method, step = None, expert = None, brief = None):
    view_params = utils.create_obj(client, method)
    view_params.step = step
    view_params.expert = expert
    view_params.brief = brief
    if hasattr(view_params,"clienttype"):
        view_params.clienttype = "gui"
    return view_params

def owner(pid):
    UID = 1
    for ln in open('/proc/%s/status' %pid):
        if ln.startswith('Uid:'):
            uid = int(ln.split()[UID])
            return pwd.getpwuid(uid).pw_name

def getRunProc():
    """List run program"""
    def getCmd(procNum):
        cmdLineFile = '/proc/%s/cmdline'%procNum
        try:
            if os.path.exists(cmdLineFile):
                return [readFile(cmdLineFile).strip(), procNum]
        except:
            pass
        return ["", procNum]
    if not os.access('/proc',os.R_OK):
        return []
    return map(getCmd,
           filter(lambda x:x.isdigit(),
           listDirectory('/proc')))
