#-*- 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. import os import time import urllib.request as urllib2 import pwd import sys DEBUG_LEVEL = 99999 def debug(level, *args): if level <= DEBUG_LEVEL: for s in args: print(s, end=' ') print() from .. 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 int(size * qt.QApplication.screens()[0].logicalDotsPerInch() / 96.0); except BaseException as e: print(str(e)) if isinstance(e, KeyboardInterrupt): raise return int(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(" "," ") else: name = name.replace(" ", " "*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__() debug(11, "Creating multiple choice dialog") 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([Available_dict[x] for x in Available_list if x not in Selected_list]) self.right_ListWidget.addItems([Available_dict[x] for x in Selected_list if x in Available_dict.keys()]) 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) # debug(11, "ADDED mouse press event") 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 ()) debug(11, "MultipleChoice mouse event") 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 = [res_dict[x] for x in self.Selected if x in res_dict] res += [x for x in self.Selected if not x in res_dict] 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()) debug(11, "AddLineWidget init") 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().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 = (x for x in self.widget_dict.keys() if type(self.widget_dict[str(x)]) == SimplePasswordWidget) if [x for x in items if not self.widget_dict[str(x)].status()]: 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((str(x) for x in 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, '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__() == '': _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(): tmp = identify.read() if isinstance(tmp, bytes): swidth, _sep, sheight = identify.read().decode(encoding="UTF-8").strip().partition(" ") else: 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 [getCmd(x) for x in listDirectory('/proc') if x.isdigit()]