class TabBarPlus(QtGui.QTabBar): """Tab bar that has a plus button floating to the right of the tabs.""" plusClicked = QtCore.Signal() def __init__(self): super(self.__class__, self).__init__() # Plus Button self.plusButton = QtGui.QPushButton("+") self.plusButton.setParent(self) # self.plusButton.setFixedSize(20, 20) # Small Fixed size self.plusButton.setMaximumWidth(20) self.plusButton.clicked.connect(self.plusClicked.emit) self.movePlusButton() # Move to the correct location # end Constructor def sizeHint(self): """Return the size of the TabBar with increased width for the plus button.""" sizeHint = QtGui.QTabBar.sizeHint(self) width = sizeHint.width() height = sizeHint.height() return QtCore.QSize(width + 25, height) # end tabSizeHint def resizeEvent(self, event): """Resize the widget and make sure the plus button is in the correct location.""" super(self.__class__, self).resizeEvent(event) self.movePlusButton() # end resizeEvent def tabLayoutChange(self): """This virtual handler is called whenever the tab layout changes. If anything changes make sure the plus button is in the correct location. """ super(self.__class__, self).tabLayoutChange() self.movePlusButton() # end tabLayoutChange def movePlusButton(self): """Move the plus button to the correct location.""" # Find the width of all of the tabs size = sum([self.tabRect(i).width() for i in range(self.count())]) # size = 0 # for i in range(self.count()): # size += self.tabRect(i).width() # Set the plus button location in a visible area h = self.geometry().top() w = self.width() if size > w: # Show just to the left of the scroll buttons self.plusButton.move(w - 54, h) else: self.plusButton.move(size, h)
class mayaBatchClass(QtCore.QObject): progress_out = QtCore.Signal(object) def __init__(self, parent=None): super(self.__class__, self).__init__(parent=parent) self.batch_process = QtCore.QProcess(self) self.actions() def start_batch(self): self.batch_process.setProcessChannelMode( QtCore.QProcess.MergedChannels) self.batch_process.readyRead.connect(self.progress_output) self.batch_process.waitForReadyRead(True) self.batch_process.start( u'{0}/python3/App/Python/python.exe'.format(TACTIC_DIR), ['{0}/bin/startup_standalone.py'.format(TACTIC_DIR)]) def progress_output(self): log_output = str(self.batch_process.readAllStandardOutput()) self.progress_out.emit(log_output) self.write_log(log_output) def write_log(self, log_text): log_path = u'{0}/log_out.log'.format(TACTIC_DIR) if os.path.exists(gf.extract_dirname(log_path)): with codecs.open(log_path, 'a+', 'utf-8') as log_file: log_file.write(log_text) else: os.makedirs(gf.extract_dirname(log_path)) with codecs.open(log_path, 'w+', 'utf-8') as log_file: log_file.write(log_text) log_file.close() def actions(self): self.batch_process.error.connect(self.error_handle) #self.batch_process.stateChanged.connect(self.state_changed_handle) #self.batch_process.readyRead.connect(self.progress_output) def error_handle(self, message=None): if message: print('Some errors', message)
class SquareLabel(QtGui.QLabel): clicked = QtCore.Signal() def __init__(self, menu, action, parent=None): super(self.__class__, self).__init__(parent=parent) self.menu = menu self.action = action def mousePressEvent(self, event): self.clicked.emit() event.accept() def enterEvent(self, event): self.setAutoFillBackground(False) self.menu.setActiveAction(self.action) def leaveEvent(self, event): self.setAutoFillBackground(True)
class Output(QtCore.QObject): written = QtCore.Signal(unicode) flushed = QtCore.Signal() def __init__(self, std, parent_stream=None, parent=None): """ Initialize default settings. """ self.__parent_stream = parent_stream super(Output, self).__init__(parent) self.__std = std self.softspace = 0 def readline(self, *args, **kwargs): """ Read line method. """ return self.__std.readline(*args, **kwargs) def stream(self): """ Get parent stream. """ return self.__parent_stream def write(self, text): """ Write text message. """ result = self.__std.write(text) # try: # # text = unicode(text).encode('utf-8', errors='ignore') # text = str(text) # # except UnicodeEncodeError or UnicodeDecodeError: # text = u"Failed to encode error message..." self.written.emit(text) return result def writelines(self, line_list): """ Write lines. """ result = self.__std.writelines(line_list) for line in line_list: # try: # line = unicode(line) # # except UnicodeEncodeError or UnicodeDecodeError: # line = u"Failed to encode error message..." self.written.emit(line) return result def flush(self, *args, **kwargs): """ Flush """ result = self.__std.flush(*args, **kwargs) self.flushed.emit() return result
class EditorWindow(QtGui.QPlainTextEdit): returnPressed = QtCore.Signal() closeRequested = QtCore.Signal() restoreLastClosedRequested = QtCore.Signal() reloadRequested = QtCore.Signal() openRequested = QtCore.Signal() saveRequested = QtCore.Signal() saveAsRequested = QtCore.Signal() saveAllRequested = QtCore.Signal() searchRequested = QtCore.Signal() newFileRequested = QtCore.Signal() SAVE_HISTORY = False DRAW_LINE_NUMBER = True INDENT_DRAW = True INDENT_SPACE_COUNT = 4 INDENT_DRAW_WIDTH = 0.5 INDENT_REPLACE_SPACE = True HIGHLIGHT_SELECTED_LINE = True COLOR_MAP = { "background": Qt4Gui.QColor("#A88627"), "line_number": QtCore.Qt.black, "line_number_background": Qt4Gui.QColor("#5C5C5C"), "indent": QtCore.Qt.white, "highlight_selected_line": Qt4Gui.QColor("#4D4225"), "highlight_selected": Qt4Gui.QColor("#665526"), "highlight_find_word": Qt4Gui.QColor(QtCore.Qt.gray).lighter(130), "highlight_similiar_word": Qt4Gui.QColor(QtCore.Qt.gray).lighter(130), } @staticmethod def GetColor(key): """ Get color by given key. """ if key in EditorWindow.COLOR_MAP: return EditorWindow.COLOR_MAP[key] else: return Qt4Gui.QColor("#black") @staticmethod def LineIndent(line): """ Get line indent. """ indent = 0 sub_count = 0 indent_end = 0 for ch in line: if ch == "\t": indent += 1 sub_count = 0 indent_end += 1 elif ch == " ": sub_count += 1 indent_end += 1 if sub_count == EditorWindow.INDENT_SPACE_COUNT: sub_count = 0 indent += 1 else: sub_count = 0 break return indent @staticmethod def LineIndentInfo(line): """ Get line indent info. """ space_count = 0 tab_count = 0 for ch in line: if ch == "\t": tab_count += 1 elif ch == " ": space_count += 1 else: break indent_end = tab_count + space_count indent = tab_count + (space_count / EditorWindow.INDENT_SPACE_COUNT) real_indent_end = tab_count + ( (space_count / EditorWindow.INDENT_SPACE_COUNT) * EditorWindow.INDENT_SPACE_COUNT) need_to_indent = indent_end - real_indent_end return indent, indent_end, real_indent_end, need_to_indent @staticmethod def GetIndentSymbol(): """ Get indent character. """ indent_symbol = "\t" if EditorWindow.INDENT_REPLACE_SPACE: indent_symbol = " " * EditorWindow.INDENT_SPACE_COUNT return indent_symbol @staticmethod def LineWithoutIndent(line): """ Get line without indnt. """ result = "" breaked = False for ch in line: if ch != "\t": if ch != " ": breaked = True if breaked: result += ch return result def __init__(self, parent=None): """ Initialize default settings. """ QtGui.QPlainTextEdit.__init__(self, parent) self._line_area = line_number_area.LineNumberArea(self) self.blockCountChanged.connect(self.updateLineNumberAreaWidth) self.updateRequest.connect(self.updateLineNumberArea) self.cursorPositionChanged.connect(self.highlightCurrentLine) self.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) self.setTabStopWidth(self.fontMetrics().width( " " * EditorWindow.INDENT_SPACE_COUNT)) self.updateLineNumberAreaWidth(0) self.highlightCurrentLine() self._highlight_handle = syntax_highlighter.SyntaxHighlighter( self.document()) def selectedText(self): """ Get selected text. """ cursor = self.textCursor() text = cursor.selectedText() text = text.replace(u"\u2029", "\n") text = text.replace(u"\u2028", "\n") # text = unicode(text) while text.startswith("\n"): text = text[1:] while text.endswith("\n"): text = text[:-1] return text def lineNumberAreaPaintEvent(self, event): """ Line number area paint event. """ if EditorWindow.DRAW_LINE_NUMBER: painter = Qt4Gui.QPainter(self._line_area) painter.setRenderHint(Qt4Gui.QPainter.Antialiasing) painter.fillRect(event.rect(), EditorWindow.GetColor("line_number_background")) painter.setPen(EditorWindow.GetColor("line_number")) block = self.firstVisibleBlock() block_number = block.blockNumber() top = self.blockBoundingGeometry(block).translated( self.contentOffset()).top() bottom = top + self.blockBoundingRect(block).height() while block.isValid() and top <= event.rect().bottom(): if block.isVisible() and bottom >= event.rect().top(): number = str(block_number + 1) painter.drawText(0, top, self._line_area.width(), self.fontMetrics().height(), QtCore.Qt.AlignRight, number) block = block.next() top = bottom bottom = top + self.blockBoundingRect(block).height() block_number += 1 def lineNumberAreaWidth(self): """ Get line number area size. """ digits = 1 last = max(1, self.blockCount()) while last >= 10: last /= 10 digits += 1 space = 3 + self.fontMetrics().width("9") * digits return space def resizeEvent(self, event): """ Resize event. """ QtGui.QPlainTextEdit.resizeEvent(self, event) content_rect = self.contentsRect() self._line_area.setGeometry( QtCore.QRect(content_rect.left(), content_rect.top(), self.lineNumberAreaWidth(), content_rect.height())) def updateLineNumberAreaWidth(self, block_count): """ Update line number area size. """ self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0) def highlightCurrentLine(self): """ Highlight current line. """ if EditorWindow.HIGHLIGHT_SELECTED_LINE: selection_list = [] selection = QtGui.QTextEdit.ExtraSelection() line_color = EditorWindow.GetColor("highlight_selected_line") selection.format.setBackground(line_color) selection.format.setProperty(Qt4Gui.QTextFormat.FullWidthSelection, True) selection.cursor = self.textCursor() selection.cursor.clearSelection() selection_list.append(selection) self.setExtraSelections(selection_list) def updateLineNumberArea(self, rect, number): """ Update line number area. """ if number: self._line_area.scroll(0, number) else: self._line_area.update(0, rect.y(), self._line_area.width(), rect.height()) if rect.contains(self.viewport().rect()): self.updateLineNumberAreaWidth(0) def search(self, text, matchCase=False, completeWord=False, regEnabled=False, up=False, wrap=False): """ Search text. """ flags = None if up: if not flags: flags = QtGui.QTextDocument.FindBackward else: flags |= QtGui.QTextDocument.FindBackward if matchCase: if not flags: flags = QtGui.QTextDocument.FindCaseSensitively else: flags |= QtGui.QTextDocument.FindCaseSensitively if completeWord: if not flags: flags = QtGui.QTextDocument.FindWholeWords else: flags |= QtGui.QTextDocument.FindWholeWords color = self.GetColor("highlight_find_word") cursor = self.textCursor() extraSelections = [] if flags: _search = lambda _text: self.find(_text, flags) else: _search = lambda _text: self.find(_text) if wrap: self.moveCursor(Qt4Gui.QTextCursor.Start) count = 0 first_occur = None while _search(text): extra = QtGui.QTextEdit.ExtraSelection() extra.format.setBackground(color) if first_occur is None: first_occur = self.textCursor() extra.cursor = self.textCursor() extraSelections.append(extra) count += 1 self.setExtraSelections(extraSelections) if first_occur is not None: self.setTextCursor(first_occur) def enter(self): """ Enter event. """ indent_symbol = self.GetIndentSymbol() cursor = self.textCursor() position = cursor.position() if cursor.hasSelection(): cursor.removeSelectedText() previous_pos = cursor.position() cursor.movePosition(Qt4Gui.QTextCursor.StartOfLine) cursor.movePosition(Qt4Gui.QTextCursor.EndOfLine, Qt4Gui.QTextCursor.KeepAnchor) offset_pos = cursor.position() line = cursor.selectedText() cursor.setPosition(previous_pos) offset = offset_pos - previous_pos if offset > 0: line = line[:-offset] if line: indent = self.LineIndent(line) if line[-1] == ":": cursor.insertText("\n" + (indent_symbol * (indent + 1))) else: cursor.insertText("\n" + (indent_symbol * (indent))) else: cursor.insertText("\n") self.setTextCursor(cursor) def updateIndent(self, value): """ Update indent. """ indent_symbol = self.GetIndentSymbol() cursor = self.textCursor() position = cursor.position() start = cursor.selectionStart() end = cursor.selectionEnd() cursor.setPosition(start) cursor.movePosition(Qt4Gui.QTextCursor.StartOfLine) cursor.setPosition(end, Qt4Gui.QTextCursor.KeepAnchor) cursor.movePosition(Qt4Gui.QTextCursor.EndOfLine, Qt4Gui.QTextCursor.KeepAnchor) abs_start = cursor.selectionStart() abs_end = cursor.selectionEnd() text = cursor.selectedText() text = text.replace(u"\u2029", "\n") text = text.replace(u"\u2028", "\n") text = str(text) if text.count("\n") == 0 and (abs_start != start or abs_end != end or start == end): # Single selection add indent. indent, indent_end, real_indent_end, need_to_indent = self.LineIndentInfo( text) relative_position = start - abs_start indent_offset = self.INDENT_SPACE_COUNT - ( (len(text[real_indent_end:relative_position]) % self.INDENT_SPACE_COUNT)) if relative_position > indent_end: less_offset = self.INDENT_SPACE_COUNT - indent_offset if less_offset == 0: less_offset += self.INDENT_SPACE_COUNT less_position = position - less_offset if less_position < 0: less_position = 0 cursor.setPosition(less_position) else: if need_to_indent > 0 and value < 0: indent += 1 cursor.setPosition(abs_start) cursor.setPosition(abs_start + indent_end, Qt4Gui.QTextCursor.KeepAnchor) cursor.insertText(indent_symbol * (indent + value)) else: # Muliline add indent. replace_text = [] line_number = 0 for line in text.splitlines(): indent = self.LineIndent(line) line = self.LineWithoutIndent(line) replace_text.append(indent_symbol * (indent + value) + line) line_number += 1 replace_text = "\n".join(replace_text) cursor.insertText(replace_text) cursor.setPosition(abs_start) cursor.movePosition(Qt4Gui.QTextCursor.StartOfLine, Qt4Gui.QTextCursor.MoveAnchor) for l in range(line_number - 1): cursor.movePosition(Qt4Gui.QTextCursor.Down, Qt4Gui.QTextCursor.KeepAnchor) cursor.movePosition(Qt4Gui.QTextCursor.EndOfLine, Qt4Gui.QTextCursor.KeepAnchor) self.setTextCursor(cursor) def updateLinePosition(self, value): """ Update line position. """ cursor = self.textCursor() position = cursor.position() if cursor.hasSelection(): start = cursor.selectionStart() end = cursor.selectionEnd() else: start = cursor.position() end = start # Get full line. cursor.setPosition(start) cursor.movePosition(Qt4Gui.QTextCursor.StartOfLine) cursor.setPosition(end, Qt4Gui.QTextCursor.KeepAnchor) cursor.movePosition(Qt4Gui.QTextCursor.EndOfLine, Qt4Gui.QTextCursor.KeepAnchor) # Get information about selection. source_start = cursor.selectionStart() source_end = cursor.selectionEnd() source_text = cursor.selectedText() previous_position = cursor.position() if value > 0: cursor.setPosition(end) cursor.movePosition(Qt4Gui.QTextCursor.Down) else: cursor.setPosition(start) cursor.movePosition(Qt4Gui.QTextCursor.Up) cursor.movePosition(Qt4Gui.QTextCursor.StartOfLine) cursor.movePosition(Qt4Gui.QTextCursor.EndOfLine, Qt4Gui.QTextCursor.KeepAnchor) target_position = cursor.position() if target_position == previous_position: if position < end: cursor.setPosition(end) cursor.setPosition(start, Qt4Gui.QTextCursor.KeepAnchor) else: cursor.setPosition(start) cursor.setPosition(end, Qt4Gui.QTextCursor.KeepAnchor) else: cursor.movePosition(Qt4Gui.QTextCursor.StartOfLine) cursor.movePosition(Qt4Gui.QTextCursor.EndOfLine, Qt4Gui.QTextCursor.KeepAnchor) target_start = cursor.selectionStart() target_end = cursor.selectionEnd() target_text = cursor.selectedText() cursor.beginEditBlock() # Replace selected lines to next line. cursor.setPosition(source_start) cursor.setPosition(source_end, Qt4Gui.QTextCursor.KeepAnchor) cursor.insertText(target_text) cursor.movePosition(Qt4Gui.QTextCursor.StartOfLine) cursor.movePosition(Qt4Gui.QTextCursor.EndOfLine, Qt4Gui.QTextCursor.KeepAnchor) current_start = cursor.selectionStart() current_end = cursor.selectionEnd() if value > 0: cursor.setPosition(current_end) cursor.movePosition(Qt4Gui.QTextCursor.Down) else: cursor.setPosition(current_start) cursor.movePosition(Qt4Gui.QTextCursor.Up) cursor.movePosition(Qt4Gui.QTextCursor.StartOfLine) cursor.movePosition(Qt4Gui.QTextCursor.EndOfLine, Qt4Gui.QTextCursor.KeepAnchor) selection_start_position = cursor.selectionStart() cursor.insertText(source_text) selection_end_position = selection_start_position + (source_end - source_start) cursor.setPosition(selection_start_position) cursor.movePosition(Qt4Gui.QTextCursor.StartOfLine) cursor.setPosition(selection_end_position, Qt4Gui.QTextCursor.KeepAnchor) cursor.movePosition(Qt4Gui.QTextCursor.EndOfLine, Qt4Gui.QTextCursor.KeepAnchor) cursor.endEditBlock() self.setTextCursor(cursor) def moveLineUp(self): """ Move line up. """ self.updateLinePosition(-1) def moveLineDowm(self): """ Move line down. """ self.updateLinePosition(1) def addIndent(self): """ Add line indent. """ self.updateIndent(1) def removeIndent(self): """ Remove indent. """ self.updateIndent(-1) def keyPressEvent(self, event): """ Key press event. """ if event.key( ) == QtCore.Qt.Key_Return and QtGui.QApplication.keyboardModifiers( ) == QtCore.Qt.ControlModifier: self.returnPressed.emit() event.accept() else: if event.key() == QtCore.Qt.Key_Return: self.enter() elif event.key() == QtCore.Qt.Key_Tab: self.addIndent() elif event.key() == QtCore.Qt.Key_Backtab: self.removeIndent() elif event.key( ) == QtCore.Qt.Key_Up and QtGui.QApplication.keyboardModifiers( ) == (QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier): self.moveLineUp() elif event.key( ) == QtCore.Qt.Key_Down and QtGui.QApplication.keyboardModifiers( ) == (QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier): self.moveLineDowm() elif event.key( ) == QtCore.Qt.Key_W and QtGui.QApplication.keyboardModifiers( ) == QtCore.Qt.ControlModifier: self.closeRequested.emit() elif event.key( ) == QtCore.Qt.Key_T and QtGui.QApplication.keyboardModifiers( ) == (QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier): self.restoreLastClosedRequested.emit() elif event.key( ) == QtCore.Qt.Key_R and QtGui.QApplication.keyboardModifiers( ) == (QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier): self.reloadRequested.emit() elif event.key( ) == QtCore.Qt.Key_O and QtGui.QApplication.keyboardModifiers( ) == QtCore.Qt.ControlModifier: self.openRequested.emit() elif event.key( ) == QtCore.Qt.Key_S and QtGui.QApplication.keyboardModifiers( ) == QtCore.Qt.ControlModifier: self.saveRequested.emit() elif event.key( ) == QtCore.Qt.Key_S and QtGui.QApplication.keyboardModifiers( ) == QtCore.Qt.AltModifier: self.saveAsRequested.emit() elif event.key( ) == QtCore.Qt.Key_S and QtGui.QApplication.keyboardModifiers( ) == (QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier): self.saveAllRequested.emit() elif event.key( ) == QtCore.Qt.Key_F and QtGui.QApplication.keyboardModifiers( ) == QtCore.Qt.ControlModifier: self.searchRequested.emit() elif event.key( ) == QtCore.Qt.Key_N and QtGui.QApplication.keyboardModifiers( ) == QtCore.Qt.ControlModifier: self.newFileRequested.emit() else: super(EditorWindow, self).keyPressEvent(event)
class Ui_repositoryEditorWidget(QtGui.QDialog): saved_signal = QtCore.Signal(object, object) edited_signal = QtCore.Signal(object, object) def __init__(self, sobject_item, mode='create', parent=None): super(self.__class__, self).__init__(parent=parent) self.sobject_item = sobject_item self.mode = mode self.saved = False self.exclude_repo_list = self.get_exclude_repo_list() self.create_ui() def create_ui(self): if self.mode == 'create': self.setWindowTitle('Choose Repositories to Watch') else: self.setWindowTitle('Editing Watch Folders') self.resize(600, 420) self.setSizeGripEnabled(True) self.creat_layout() self.create_repo_path_line_edit() self.create_repo_combo_box() self.create_repos_tree_widget() self.create_buttons() if self.mode == 'edit': self.fill_repo_combo_box(self.exclude_repo_list) self.fill_repo_tree_widget(self.exclude_repo_list) else: self.fill_repo_combo_box() self.fill_repo_tree_widget() self.check_save_ability() self.controls_actions() def controls_actions(self): self.add_new_button.clicked.connect(self.add_new_repo) self.remove_button.clicked.connect(self.delete_selected_repo) self.save_button.clicked.connect(self.save_and_close) self.close_button.clicked.connect(self.close) def creat_layout(self): self.main_layout = QtGui.QGridLayout() self.main_layout.setContentsMargins(9, 9, 9, 9) self.main_layout.setColumnStretch(0, 1) self.setLayout(self.main_layout) def create_repos_tree_widget(self): self.repos_tree_widget = QtGui.QTreeWidget() self.repos_tree_widget.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection) self.repos_tree_widget.setEditTriggers( QtGui.QAbstractItemView.NoEditTriggers) self.repos_tree_widget.setRootIsDecorated(False) self.repos_tree_widget.setHeaderHidden(True) self.repos_tree_widget.setObjectName('repos_tree_widget') self.main_layout.addWidget(self.repos_tree_widget, 2, 0, 2, 1) def create_repo_path_line_edit(self): self.repo_path_line_edit_layout = QtGui.QHBoxLayout() self.repo_path_line_edit_layout.addWidget( QtGui.QLabel('Relative Watch Path:')) self.repo_path_line_edit = QtGui.QLineEdit() self.repo_path_line_edit_layout.addWidget(self.repo_path_line_edit) if self.mode == 'create': paths = tc.get_dirs_with_naming(self.sobject_item.get_search_key(), process_list=['watch_folder']) self.repo_path_line_edit.setText(paths['versionless'][0]) elif self.mode == 'edit': self.repo_path_line_edit.setText( self.sobject_item.get_watch_folder_path()) self.main_layout.addLayout(self.repo_path_line_edit_layout, 0, 0, 1, 2) def create_repo_combo_box(self): self.repo_combo_box = QtGui.QComboBox() self.main_layout.addWidget(self.repo_combo_box, 1, 0, 1, 1) def check_save_ability(self): if self.repos_tree_widget.topLevelItemCount() < 1: self.save_button.setEnabled(False) else: self.save_button.setEnabled(True) def get_exclude_repo_list(self): watch_folder_ui = env_inst.watch_folders.get( self.sobject_item.project.get_code()) watch_dict = watch_folder_ui.get_watch_dict_by_skey( self.sobject_item.get_search_key()) if watch_dict: return watch_dict['rep'] else: return [] def fill_repo_combo_box(self, exlude_list=None): self.repo_combo_box.clear() if not exlude_list: exlude_list = [] base_dirs = env_tactic.get_all_base_dirs() # Default repo states for key, val in base_dirs: if val['value'][4] and val['value'][3] not in exlude_list: self.repo_combo_box.addItem(val['value'][1]) self.repo_combo_box.setItemData( self.repo_combo_box.count() - 1, val) self.repo_combo_box.addItem('All Repos') current_repo = gf.get_value_from_config(cfg_controls.get_checkin(), 'repositoryComboBox') if current_repo: self.repo_combo_box.setCurrentIndex(current_repo) def fill_repo_tree_widget(self, exlude_list=None): self.repos_tree_widget.clear() if not exlude_list: exlude_list = [] base_dirs = env_tactic.get_all_base_dirs() # Default repo states for key, val in base_dirs: if val['value'][4] and val['value'][3] in exlude_list: root_item = QtGui.QTreeWidgetItem() root_item.setText(0, val['value'][1]) root_item.setData(0, QtCore.Qt.UserRole, val) self.repos_tree_widget.addTopLevelItem(root_item) def create_buttons(self): self.add_new_button = QtGui.QPushButton('Add') self.add_new_button.setMinimumWidth(90) self.remove_button = QtGui.QPushButton('Remove') self.remove_button.setMinimumWidth(90) self.save_button = QtGui.QPushButton('Save and Close') self.save_button.setMinimumWidth(90) self.close_button = QtGui.QPushButton('Cancel') self.close_button.setMinimumWidth(90) self.main_layout.addWidget(self.add_new_button, 1, 1, 1, 1) self.main_layout.addWidget(self.remove_button, 2, 1, 1, 1) self.main_layout.addWidget(self.save_button, 4, 0, 1, 1) self.main_layout.addWidget(self.close_button, 4, 1, 1, 1) spacer = QtGui.QSpacerItem(0, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.main_layout.addItem(spacer, 3, 1, 1, 1) def add_new_repo(self): current_repo_index = self.repo_combo_box.currentIndex() current_repo = self.repo_combo_box.itemData(current_repo_index) if current_repo: self.repo_combo_box.removeItem(current_repo_index) root_item = QtGui.QTreeWidgetItem() root_item.setText(0, current_repo['value'][1]) root_item.setData(0, QtCore.Qt.UserRole, current_repo) self.exclude_repo_list.append(current_repo['value'][3]) self.repos_tree_widget.addTopLevelItem(root_item) else: for i in range(self.repo_combo_box.count() - 1): current_repo = self.repo_combo_box.itemData(i) root_item = QtGui.QTreeWidgetItem() root_item.setText(0, current_repo['value'][1]) root_item.setData(0, QtCore.Qt.UserRole, current_repo) self.exclude_repo_list.append(current_repo['value'][3]) self.repos_tree_widget.addTopLevelItem(root_item) self.fill_repo_combo_box(self.exclude_repo_list) self.check_save_ability() def delete_selected_repo(self): current_repo_item = self.repos_tree_widget.currentItem() if current_repo_item: current_repo = current_repo_item.data(0, QtCore.Qt.UserRole) self.exclude_repo_list.remove(current_repo['value'][3]) self.repos_tree_widget.takeTopLevelItem( self.repos_tree_widget.currentIndex().row()) self.fill_repo_combo_box(self.exclude_repo_list) self.check_save_ability() def set_saved(self): self.saved = True def save_and_close(self): self.set_saved() params = (self.get_repos_list(), self.sobject_item) self.sobject_item.set_watch_folder_path( str(self.repo_path_line_edit.text())) if self.mode == 'create': self.saved_signal.emit(*params) if self.mode == 'edit': self.edited_signal.emit(*params) self.close() def get_repos_list(self): repos_list = [] for i in range(self.repos_tree_widget.topLevelItemCount()): top_item = self.repos_tree_widget.topLevelItem(i) repo_dict = top_item.data(0, QtCore.Qt.UserRole) repos_list.append(repo_dict['value'][3]) return repos_list
class Ui_tacticSidebarWidget(QtGui.QWidget): clicked = QtCore.Signal(object) def __init__(self, project, parent=None): super(self.__class__, self).__init__(parent=parent) self.project = project self.checkin_out_config_projects = cfg_controls.get_checkin_out_projects( ) self.checkin_out_config = cfg_controls.get_checkin_out() self.create_ui() def create_ui(self): self.main_layout = QtGui.QVBoxLayout() self.main_layout.setContentsMargins(0, 0, 0, 0) self.main_layout.setSpacing(0) self.setLayout(self.main_layout) self.tree_widget = Ui_extendedTreeWidget(self) self.tree_widget.setMaximumSize(QtCore.QSize(0, 16777215)) self.tree_widget.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self.tree_widget.setEditTriggers( QtGui.QAbstractItemView.NoEditTriggers) self.tree_widget.setIndentation(0) self.tree_widget.setSelectionBehavior( QtGui.QAbstractItemView.SelectRows) self.tree_widget.setTabKeyNavigation(True) self.tree_widget.setVerticalScrollMode( QtGui.QAbstractItemView.ScrollPerPixel) self.tree_widget.setAllColumnsShowFocus(True) self.tree_widget.setRootIsDecorated(False) self.tree_widget.setHeaderHidden(True) self.tree_widget.setExpandsOnDoubleClick(False) self.tree_widget.setObjectName('sidebar_widget') self.tree_widget.setMinimumHeight(400) self.tree_widget.setMinimumWidth(250) self.tree_widget.setFocusPolicy(QtCore.Qt.NoFocus) self.tree_widget.setStyleSheet(gf.get_qtreeview_style(True)) self.main_layout.addWidget(self.tree_widget) self.controls_actions() def controls_actions(self): self.tree_widget.itemClicked.connect(self.tree_widget_item_click) def tree_widget_item_click(self, item): item_widget = self.tree_widget.itemWidget(item, 0) self.clicked.emit(item_widget) def get_ignore_stypes_list(self): ignore_tabs_list = [] if self.checkin_out_config and self.checkin_out_config_projects and self.checkin_out_config_projects.get( self.project.get_code()): if not gf.get_value_from_config(self.checkin_out_config, 'processTabsFilterGroupBox'): ignore_tabs_list = [] else: ignore_tabs_list = self.checkin_out_config_projects[ self.project.get_code()]['stypes_list'] if not ignore_tabs_list: ignore_tabs_list = [] return ignore_tabs_list def initial_fill(self): self.tree_widget.clear() sidebar = self.project.get_config_views() current_login = env_inst.get_current_login_object() project_code = self.project.get_code() if sidebar.has_definition(): project_definition = sidebar.get_view('SideBarWdg') # making sure if there is *special TH* definition tactic_handler_definition = sidebar.get_view( 'SideBarWdg', 'tactic_handler') if not tactic_handler_definition: tactic_handler_definition = sidebar.get_view( 'SideBarWdg', 'project_view') tactic_handler_sidebar = [] for th_def in tactic_handler_definition: th_def_name = th_def['name'] for prj_def in project_definition: if prj_def['name'] == th_def_name: tactic_handler_sidebar.append(prj_def) for sidebar_item in tactic_handler_sidebar: access = current_login.check_security( group='link', path='element:{0}'.format(sidebar_item.get('name')), project=project_code) if access == 'allow': stype_code = None view_definition = None sub_definitions = [] layout = 'default' if sidebar_item.search_type: stype_code = sidebar_item.search_type.string if sidebar_item.layout: layout = sidebar_item.layout.string if sidebar_item.view: view_definition = sidebar.get_view( 'SideBarWdg', sidebar_item.view.string) for sub_def in view_definition: sub_def_name = sub_def['name'] for sub_prj_def in project_definition: if sub_prj_def['name'] == sub_def_name: sub_definitions.append(sub_prj_def) if stype_code and stype_code.startswith('sthpw'): stype = env_inst.get_stype_by_code(stype_code) else: stype = self.project.stypes.get(stype_code) item_info = { 'title': sidebar_item.get('title'), 'name': sidebar_item.get('name'), 'display_class': sidebar_item.display.get('class'), 'search_type': stype_code, 'layout': layout, 'view_definition': view_definition, 'sub_definitions': sub_definitions, 'item': sidebar_item, } gf.add_sidebar_item( tree_widget=self.tree_widget, stype=stype, project=self.project, item_info=item_info, ) self.tree_widget.resizeColumnToContents(0)
class Stream(QtCore.QObject): __stdout = None __stderr = None __excepthook = None __stream = None __original__stdout = sys.stdout __original__stdin = sys.stdin __original__stderr = sys.stderr __original__excepthook = sys.excepthook exceptedWritten = QtCore.Signal(unicode) outputWritten = QtCore.Signal(unicode) errorWritten = QtCore.Signal(unicode) inputWritten = QtCore.Signal(unicode) @staticmethod def get_stream(): """ Get current stream. """ return Stream.__stream def __new__(cls, *args): """ Get python stream instance. """ if Stream.__stream is None: result = super(Stream, cls).__new__(cls, *args) else: result = Stream.__stream return result def __init__(self, *args): """ Initialize default settings. """ super(Stream, self).__init__(*args) if Stream.__stream is None: Stream.__stream = self from . import OutputCls, ExceptionHook self.out = OutputCls(Stream.__original__stdout, self) Stream.__stdout = self.out self.out.written.connect(self.writeOutput) self.inp = OutputCls(Stream.__original__stdin, self) Stream.__stdin = self.inp self.inp.written.connect(self.writeInput) self.err = OutputCls(Stream.__original__stderr, self) Stream.__stderr = self.err self.err.written.connect(self.writeError) self.excepthandler = ExceptionHook(Stream.__original__excepthook) Stream.__excepthook = self.excepthandler.excepthook sys.stdin = Stream.__stdin sys.stdout = Stream.__stdout sys.stderr = Stream.__stderr sys.excepthook = self.excepthandler.excepthook self.excepthandler.excepted.connect(self.writeExcepted) self.excepthandler.excepted.connect(self.writeErrorToStream) self.err_count = 0 self.out_count = 0 self.in_count = 0 def writeErrorToStream(self, text): """ Write string to error output. """ # try: # text = unicode(text) # # except UnicodeDecodeError or UnicodeEncodeError: # text = u"Failed to encode error message..." Stream.__stderr.write(text) self.exceptedWritten.emit(text) def writeOutputToStream(self, text): """ Write string to output. """ # try: # text = unicode(text) # # except UnicodeDecodeError or UnicodeEncodeError: # text = u"Failed to encode error message..." Stream.__stdout.write(text) def writeInputToStream(self, text): """ Write string to input output. """ # try: # text = unicode(text) # # except UnicodeDecodeError or UnicodeEncodeError: # text = u"Failed to encode error message..." Stream.__stdin.write(text) def input(self, text): """ Write input text. """ # try: # text = unicode(text) # # except UnicodeDecodeError or UnicodeEncodeError: # text = u"Failed to encode error message..." self.writeInput(text) self.writeInput("\n") def writeInput(self, text): """ Handle input text. """ # try: # text = unicode(text) # # except UnicodeDecodeError or UnicodeEncodeError: # text = u"Failed to encode error message..." self.inputWritten.emit(text) if self.in_count < sys.maxint: self.in_count += 1 def writeError(self, text): """ Write error text. """ # try: # text = unicode(text) # # except UnicodeDecodeError or UnicodeEncodeError: # text = u"Failed to encode error message..." self.errorWritten.emit(text) if self.err_count < sys.maxint: self.err_count += 1 def writeOutput(self, text): """ Write output text. """ # try: # text = unicode(text) # # except UnicodeDecodeError or UnicodeEncodeError: # text = u"Failed to encode error message..." self.outputWritten.emit(text) if self.out_count < sys.maxint: self.out_count += 1 def writeExcepted(self, text): """ Write excepted. """ # try: # text = unicode(text) # # except UnicodeDecodeError or UnicodeEncodeError: # text = u"Failed to encode error message..." self.exceptedWritten.emit(text) if self.err_count < sys.maxint: self.err_count += 1
class AppClient(QtCore.QObject): connected = QtCore.Signal() disconnected = QtCore.Signal() received = QtCore.Signal(QtCore.QByteArray) def __init__(self, port, host="127.0.0.1", parent=None): super(AppClient, self).__init__(parent) self.__port = port self.__host = host self.__key = None # temp = os.path.abspath(os.environ.get("TEMP", os.path.expanduser("~/temp"))).replace("\\", "/").rstrip("/") + "/AppConnection" # if not os.path.exists(temp): # os.makedirs(temp) # # logging.basicConfig(filename=temp + "/AppClient_{0}.{1}.log".format(host, port), level=logging.INFO, format="%(asctime)s - %(message)s") # self.__logger = logging.getLogger("AppClient_{0}.{1}.log".format(host, port)) self.__blocksize = 0 self.__blockdata = None self.__blockstream = None self.__keep_connection = 0 self.__connection = 0 self.__connection_timer = QtCore.QTimer(self) self.__connection_attempt = 0 self.__client = None def reset(self): self.__blocksize = 0 self.__blockdata = None self.__blockstream = None def isConnected(self): if self.__client: state = self.__client.state() if state == QtNetwork.QAbstractSocket.UnconnectedState or state == QtNetwork.QAbstractSocket.ClosingState: return False return True return False def waitForReadyRead(self): return self.__client.waitForReadyRead() def waitForConnected(self): return self.__client.waitForConnected() def run(self): # self.__logger.info("connect to server [{0}]".format(self.__key)) self.__connection = 1 if self.__client is None: self.__client = QtNetwork.QTcpSocket(self) self.__client.connected.connect(self.__connected) self.__client.disconnected.connect(self.__disconnected) self.__client.readyRead.connect(self.__received) self.__client.error.connect(self.__error) self.__client.blockSignals(False) self.__run() self.__connection_timer.timeout.connect(self.__run) self.__connection_timer.start(3000) def __run(self): # self.__logger.info("connect to server [{0}]".format(self.__key)) if self.__connection: state = self.__client.state() if state == QtNetwork.QAbstractSocket.UnconnectedState or state == QtNetwork.QAbstractSocket.ClosingState: self.__connection_attempt += 1 if state == QtNetwork.QAbstractSocket.ConnectedState: self.__connection_timer.stop() self.__connection_attempt = 0 elif self.__connection_attempt > 10 and not self.__keep_connection: self.__client.abort() self.__connection_timer.stop() self.__connection_attempt = 0 elif state == QtNetwork.QAbstractSocket.UnconnectedState or state == QtNetwork.QAbstractSocket.HostLookupState: self.__client.connectToHost( QtNetwork.QHostAddress(self.__host), self.__port) elif self.__connection_timer.isActive(): self.__connection_timer.stop() def stop(self): # self.__logger.info("disconnect from server [{0}]".format(self.__key)) self.__connection = 0 if self.__connection_timer.isActive(): self.__connection_timer.stop() if self.__client: self.__client.blockSignals(True) self.__client.close() self.__client.deleteLater() del self.__client self.__client = None self.reset() self.blockSignals(True) self.deleteLater() def __connected(self): # self.__logger.info("connected to server [{0}]".format(self.__key)) if self.__connection_timer.isActive(): self.__connection_timer.stop() self.connected.emit() def __disconnected(self): # self.__logger.info("disconnected from server [{0}]".format(self.__key)) if self.__client: self.__client.blockSignals(True) self.__client.close() self.__client.deleteLater() del self.__client self.__client = None self.reset() self.disconnected.emit() if self.__connection_timer.isActive(): self.__connection_timer.stop() if self.__keep_connection and self.__connection: self.run() def __received(self): # self.__logger.info("receive message from server [{0}]".format(self.__key)) if self.__client: stream = QtCore.QDataStream(self.__client) stream.setVersion(QtCore.QDataStream.Qt_4_7) while True: if not self.__client: break if not self.__blocksize: if self.__client.bytesAvailable() < ctypes.sizeof( ctypes.c_long): break self.__blocksize = stream.readUInt64() if self.__client.bytesAvailable() < self.__blocksize: break if self.__blocksize and self.__blockdata is None: self.__blockdata = QtCore.QByteArray() self.__blockstream = QtCore.QDataStream( self.__blockdata, QtCore.QIODevice.ReadWrite) self.__blockstream.setVersion(QtCore.QDataStream.Qt_4_7) self.__blockstream.writeUInt64(self.__blocksize) data = QtCore.QByteArray() stream >> data if self.__blocksize: self.__blockstream << data if self.__blockdata.size() - ctypes.sizeof( ctypes.c_long) == self.__blocksize: self.__blockstream.device().seek(0) size = self.__blockstream.readUInt64() message = QtCore.QByteArray() self.__blockstream >> message self.__blockdata = None self.__blocksize = 0 self.__blockstream = 0 # system = 0 if message[:7] == "system:": # system = 1 if message[:11] == "system:key:" and message.size( ) == 47: self.__key = None try: self.__key = uuid.UUID(str(message[11:])) except: self.stop() elif self.__key is None: self.stop() elif message == "system:stop": self.stop() # if system: # self.__logger.info("received system message from server with size " + repr(size) + " [{0}]".format(self.__key)) else: # self.__logger.info("received message from server with size " + repr(size) + " [{0}]".format(self.__key)) self.received.emit(message) # else: # self.__logger.warning("can`t receive message from server [{0}]".format(self.__key)) def send(self, data): if self.isConnected(): # self.__logger.info("send message to server [{0}]".format(self.__key)) block = QtCore.QByteArray() stream = QtCore.QDataStream(block, QtCore.QIODevice.WriteOnly) stream.setVersion(QtCore.QDataStream.Qt_4_7) stream.writeUInt64(0) stream << QtCore.QByteArray(data) stream.device().seek(0) stream.writeUInt64(block.size() - ctypes.sizeof(ctypes.c_long)) stream.device().seek(block.size()) stream.writeUInt64(0) s = 0 while s < block.size(): if self.__client.state( ) != QtNetwork.QAbstractSocket.ConnectedState: # self.__logger.warning("is not connected to server [{0}]".format(self.__key)) break w = self.__client.write(block) s += w # else: # self.__logger.warning("is not connected to server [{0}]".format(self.__key)) def __error(self): # self.__logger.warning("error [{0}]".format(self.__key)) if self.__client.state() == QtNetwork.QAbstractSocket.UnconnectedState: restore = True else: self.__client.abort() restore = True if restore and self.__keep_connection and self.__connection: self.reset() # self.__connection_timer.timeout.connect(self.__run) self.__connection_timer.start(3000) elif self.__connection_timer.isActive(): self.__connection_timer.stop() def setKeepConnection(self, value): if value: self.__keep_connection = 1 else: self.__keep_connection = 0 def keepConnection(self): if self.__keep_connection: return True return False
class ThreadsPool(QtCore.QThread): # TODO add wake-up timer finished = QtCore.Signal() started = QtCore.Signal() def __init__(self, max_threads=1, parent=None): super(ThreadsPool, self).__init__(parent=parent) self.max_threads = max_threads self.poll_time = 10 self._op_queue = [] self._threads = [] self._thread_free = 0 self._started = False def reset_poll_timer(self): self.poll_time = self.idle_poll_time @property def is_started(self): return self._started @property def is_stopped(self): return not self._started def add_task(self, func, *args, **kwargs): if self._started: op = OperationWorker(func, *args, **kwargs) self._op_queue.append(op) return op def start(self): self._started = True self._threads = [] for i in range(self.max_threads): self._threads.append(OperationThread(self)) self._threads[i].start() self._thread_free += 1 super(ThreadsPool, self).start() def exit(self): # frees ops queue and waits while queued threads running # stops polling self._started = False self._op_queue = [] self._thread_free = 0 for op_thread in self._threads: op_thread.stop_tasks() op_thread.exit() op_thread.wait() self._threads = [] super(ThreadsPool, self).exit() def run(self): self.started.emit() while self._started: self.msleep(self.poll_time) for op_thread in self._threads: if op_thread.is_free: if self._op_queue: op = self._op_queue.pop(0) op_thread.add(op) self._thread_free -= 1 else: self._thread_free += 1 else: self.finished.emit()
class Ui_topBarWidget(QtGui.QWidget): hamburger_clicked = QtCore.Signal() def __init__(self, parent=None): super(self.__class__, self).__init__(parent=parent) self.current_project = None self.shown = False self.hamburger_connected_method = None self.create_ui() def create_ui(self): self.create_layout() self.create_hamburger_button() self.create_project_icon_widget() self.create_projects_combo() self.create_spacer() self.create_info_label() self.create_user_icon_widget() self.create_config_button() self.fill_config_menu() # self.fill_projects_menu() def create_layout(self): self.main_layout = QtGui.QHBoxLayout() self.setLayout(self.main_layout) self.main_layout.setSpacing(0) self.main_layout.setContentsMargins(0, 0, 0, 0) def create_info_label(self): self.info_label = QtGui.QLabel() self.info_label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) self.info_label.setText('') self.loading_tool_button = QtGui.QToolButton() self.loading_tool_button.setStyleSheet('QToolButton {border: 0px;background: transparent;}') self.loading_tool_button.setIcon(gf.get_icon('loading', icons_set='mdi', scale_factor=1, spin=[self.loading_tool_button, 30, 45])) self.main_layout.addWidget(self.info_label) self.main_layout.addWidget(self.loading_tool_button) def set_current_project(self, project=None): self.current_project = project if self.current_project: self.hamburger_tab_button.setHidden(False) self.projects_chooser_button.setText(self.current_project.info.get('title')) self.fill_project_icon() self.fill_user_icon() else: self.hamburger_tab_button.setHidden(True) self.projects_chooser_button.setText('Projects') self.fill_project_icon() self.fill_user_icon() def set_info_status_text(self, status_text=''): self.info_label.setText(status_text) if status_text == '': self.loading_tool_button.setHidden(True) else: self.loading_tool_button.setHidden(False) def create_hamburger_button(self): self.hamburger_tab_button = StyledToolButton(shadow_enabled=True, size='small', square_type=True) self.hamburger_tab_button.setIcon(gf.get_icon('menu', icons_set='mdi', scale_factor=1.2)) self.hamburger_tab_button.clicked.connect(self.hamburger_tab_button_click) self.hamburger_tab_button.setHidden(True) self.left_buttons_layout = QtGui.QHBoxLayout() self.left_buttons_layout.setContentsMargins(0, 0, 0, 0) self.left_buttons_layout.setSpacing(0) self.left_buttons_widget = QtGui.QWidget(self) self.left_buttons_widget.setLayout(self.left_buttons_layout) self.left_buttons_widget.setMinimumSize(60, 36) self.left_buttons_layout.addWidget(self.hamburger_tab_button) self.main_layout.addWidget(self.left_buttons_widget) def hamburger_tab_button_click(self): self.hamburger_clicked.emit() def connect_hamburger(self, method): if self.hamburger_connected_method: self.hamburger_clicked.disconnect(self.hamburger_connected_method) self.hamburger_connected_method = method self.hamburger_clicked.connect(self.hamburger_connected_method) def create_project_icon_widget(self): self.project_icon_widget = Ui_projectIconWidget() effect = QtGui.QGraphicsOpacityEffect(self) effect.setOpacity(0.7) self.project_icon_widget.setGraphicsEffect(effect) self.main_layout.addWidget(self.project_icon_widget) def fill_project_icon(self): self.project_icon_widget.set_project(self.current_project) self.project_icon_widget.fill_info() def fill_user_icon(self): self.user_icon_widget.set_login(env_inst.get_current_login_object()) def create_spacer(self): spacer_item = QtGui.QSpacerItem(0, 0, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Ignored) self.main_layout.addItem(spacer_item) def create_config_button(self): self.config_button = StyledToolButton() self.config_button.setPopupMode(QtGui.QToolButton.InstantPopup) self.config_button.setArrowType(QtCore.Qt.NoArrow) self.config_button.setIcon(gf.get_icon('settings', icons_set='mdi')) self.main_layout.addWidget(self.config_button) def create_user_icon_widget(self): self.user_icon_widget = Ui_userIconWidget() self.main_layout.addWidget(self.user_icon_widget) def create_projects_combo(self): self.projects_chooser_button = StyledChooserToolButton() self.projects_chooser_button.setText('Projects') self.main_layout.addWidget(self.projects_chooser_button) def fill_projects_menu(self): pass # self.menuProject = self.projects_chooser_button.get_menu() # self.menuProject.setObjectName("menuProject") # self.menuProject.setTitle(u"Projects") # self.projects_chooser_button.setMenu(self.menuProject) def fill_config_menu(self): self.menuConfig = QtGui.QMenu(self.config_button) self.menuConfig.setObjectName("menuConfig") self.menuConfig.setTitle(u"Menu") self.actionConfiguration = QtGui.QAction(self) self.actionConfiguration.setObjectName("actionConfiguration") self.actionUpdate = QtGui.QAction(self) self.actionUpdate.setObjectName("actionUpdate") self.actionExit = QtGui.QAction(self) self.actionExit.setObjectName("actionExit") self.actionApply_to_all_Tabs = QtGui.QAction(self) self.actionApply_to_all_Tabs.setObjectName("actionApply_to_all_Tabs") self.actionScriptEditor = QtGui.QAction(self) self.actionScriptEditor.setObjectName("actionScriptEditor") self.actionDock_undock = QtGui.QAction(self) self.actionDock_undock.setObjectName("actionDock_undock") self.actionDebug_Log = QtGui.QAction(self) self.actionDebug_Log.setObjectName("actionDebug_Log") self.actionSave_Preferences = QtGui.QAction(self) self.actionSave_Preferences.setObjectName("actionSave_Preferences") self.actionReloadCache = QtGui.QAction(self) self.actionReloadCache.setObjectName("actionReloadCache") self.menuConfig.addAction(self.actionConfiguration) self.menuConfig.addAction(self.actionSave_Preferences) self.menuConfig.addAction(self.actionReloadCache) self.menuConfig.addAction(self.actionApply_to_all_Tabs) self.menuConfig.addAction(self.actionDock_undock) self.menuConfig.addSeparator() self.menuConfig.addAction(self.actionScriptEditor) self.menuConfig.addAction(self.actionDebug_Log) self.menuConfig.addSeparator() self.menuConfig.addAction(self.actionUpdate) self.menuConfig.addSeparator() self.menuConfig.addSeparator() self.menuConfig.addAction(self.actionExit) self.actionConfiguration.setText(u"Configuration") self.actionUpdate.setText(u"Update") self.actionExit.setText(u"Exit") self.actionApply_to_all_Tabs.setText(u"Current view to All Tabs") self.actionScriptEditor.setText(u"Script Editor") self.actionDock_undock.setText(u"Dock/undock") self.actionDebug_Log.setText(u"Debug Log") self.actionSave_Preferences.setText(u"Save Preferences") self.actionReloadCache.setText(u"Reload Cache") self.actionExit.setIcon(gf.get_icon('window-close', icons_set='mdi')) self.actionConfiguration.setIcon(gf.get_icon('settings', icons_set='mdi')) self.actionSave_Preferences.setIcon(gf.get_icon('content-save', icons_set='mdi')) self.actionReloadCache.setIcon(gf.get_icon('reload', icons_set='mdi')) self.actionApply_to_all_Tabs.setIcon(gf.get_icon('hexagon-multiple', icons_set='mdi')) self.actionScriptEditor.setIcon(gf.get_icon('script', icons_set='mdi')) self.actionDebug_Log.setIcon(gf.get_icon('bug', icons_set='mdi')) self.actionUpdate.setIcon(gf.get_icon('update', icons_set='mdi')) if env_mode.get_mode() == 'standalone': self.actionDock_undock.setVisible(False) self.config_button.setMenu(self.menuConfig) self.config_button.setPopupMode(QtGui.QToolButton.InstantPopup) def paintEvent(self, event): # Don't know why on maya there goes different events if event.type() == QtCore.QEvent.Paint: super(Ui_topBarWidget, self).paintEvent(event) painter = Qt4Gui.QPainter() painter.begin(self) rect = self.rect() painter.fillRect(rect.x(), rect.y(), rect.width(), rect.height(), Qt4Gui.QColor(48, 48, 48))
class Ui_repoSyncDialog(QtGui.QDialog): downloads_finished = QtCore.Signal() file_download_done = QtCore.Signal(object) def __init__(self, stype, sobject, parent=None): super(self.__class__, self).__init__(parent=parent) self.stype = stype self.sobject = sobject self.togglers = [False, False, False, False] self.repo_sync_items = [] self.sync_tasks = 0 self.sync_in_progress = False self.interrupted = False self.auto_close = False self.get_all_presets_from_server() self.create_ui() def create_ui(self): if self.sobject: self.setWindowTitle('Sync Repo for: {0}'.format(self.sobject.get_title())) else: self.setWindowTitle('Sync Repo for: {0}'.format(self.stype.get_pretty_name())) self.setSizeGripEnabled(True) self.setFocusPolicy(QtCore.Qt.StrongFocus) self.create_tree_widget() self.fill_presets_combo_box() self.fill_tree_widget() self.fit_to_content_tree_widget() self.create_controls() self.controls_actions() self.create_download_queue() self.resize(650, 550) self.readSettings() def controls_actions(self): self.none_button.clicked.connect(lambda: self.switch_items('none')) self.all_process_button.clicked.connect(lambda: self.switch_items('process')) self.all_with_builtins_button.clicked.connect(lambda: self.switch_items('builtins')) self.all_children_button.clicked.connect(lambda: self.switch_items('children')) self.tree_widget.itemChanged.connect(self.check_tree_items) self.presets_combo_box.currentIndexChanged.connect(self.apply_repo_sync_preset) self.start_sync_button.clicked.connect(self.start_sync_ui) def create_download_queue(self): self.download_queue = Ui_repoSyncQueueWidget(embedded=True) self.download_queue.downloads_finished.connect(self.files_downloads_finished) self.download_queue.file_download_done.connect(self.file_download_finished) self.grid.addWidget(self.download_queue, 0, 2, 4, 2) def files_downloads_finished(self): self.sync_in_progress = False if not self.interrupted: self.downloads_finished.emit() if self.auto_close: self.close() self.downloads_progress_bar.setVisible(False) self.toggle_ui(True) def file_download_finished(self, fl): if not self.interrupted: self.file_download_done.emit(fl) progress = self.downloads_progress_bar.value() self.downloads_progress_bar.setValue(progress + 1) self.downloads_progress_bar.setFormat(u'%v / %m {}'.format(fl.get_filename_with_ext())) def check_tree_items(self, changed_item): if len(self.tree_widget.selectedItems()) > 1: for item in self.tree_widget.selectedItems(): item.setCheckState(0, changed_item.checkState(0)) def switch_items(self, item_type='none'): preset_dict = self.get_current_preset_dict() if preset_dict: if item_type == 'process': gf.set_tree_widget_checked_state( self.tree_widget, preset_dict, only_types_tuple=(':{pr}'), state=self.togglers[0] ) self.togglers[0] = not self.togglers[0] elif item_type == 'builtins': gf.set_tree_widget_checked_state( self.tree_widget, preset_dict, only_types_tuple=(':{b}'), state=self.togglers[1] ) self.togglers[1] = not self.togglers[1] elif item_type == 'children': gf.set_tree_widget_checked_state( self.tree_widget, preset_dict, only_types_tuple=(':{s}'), state=self.togglers[2] ) self.togglers[2] = not self.togglers[2] elif item_type == 'none': gf.set_tree_widget_checked_state( self.tree_widget, preset_dict, only_types_tuple=(':{s}', ':{pr}', ':{b}'), state=self.togglers[3] ) self.togglers[3] = not self.togglers[3] def create_controls(self): self.versionChooserHorizontalLayout = QtGui.QHBoxLayout() self.versionChooserHorizontalLayout.setContentsMargins(0, 0, 0, 0) self.versionChooserHorizontalLayout.setObjectName("versionChooserHorizontalLayout") self.versionlessSyncRadioButton = QtGui.QRadioButton() self.versionlessSyncRadioButton.setChecked(True) self.versionlessSyncRadioButton.setObjectName("versionlessSyncRadioButton") self.versionlessSyncRadioButton.setText('Versionless Sync') self.fullSyncRadioButton = QtGui.QRadioButton() self.fullSyncRadioButton.setObjectName("fullSyncRadioButton") self.fullSyncRadioButton.setText('Full Sync') self.versionChooserHorizontalLayout.addWidget(self.versionlessSyncRadioButton) self.versionChooserHorizontalLayout.addWidget(self.fullSyncRadioButton) self.none_button = QtGui.QPushButton('Toggle All') self.none_button.setIcon(gf.get_icon('checkbox-multiple-marked-outline', icons_set='mdi', scale_factor=1)) self.none_button.setFlat(True) self.all_process_button = QtGui.QPushButton('Toggle Process') self.all_process_button.setIcon(gf.get_icon('checkbox-blank-circle', icons_set='mdi', scale_factor=0.6)) self.all_process_button.setFlat(True) self.all_with_builtins_button = QtGui.QPushButton('Toggle Builtin Processes') self.all_with_builtins_button.setIcon(gf.get_icon('checkbox-blank-circle', icons_set='mdi', scale_factor=0.6)) self.all_with_builtins_button.setFlat(True) self.all_children_button = QtGui.QPushButton('Toggle Children') self.all_children_button.setIcon(gf.get_icon('view-sequential', icons_set='mdi', scale_factor=1)) self.all_children_button.setFlat(True) self.togglers_widget = QtGui.QWidget() self.togglers_layout = QtGui.QGridLayout() self.togglers_layout.setContentsMargins(0, 0, 0, 0) self.togglers_layout.setSpacing(6) self.togglers_widget.setLayout(self.togglers_layout) self.togglers_layout.addWidget(self.none_button, 0, 0, 1, 1) self.togglers_layout.addWidget(self.all_process_button, 0, 1, 1, 1) self.togglers_layout.addWidget(self.all_with_builtins_button, 1, 0, 1, 1) self.togglers_layout.addWidget(self.all_children_button, 1, 1, 1, 1) self.togglers_layout.addLayout(self.versionChooserHorizontalLayout, 2, 0, 1, 2) # Creating collapsable self.controls_collapsable = Ui_collapsableWidget(state=True) layout_colapsable = QtGui.QVBoxLayout() self.controls_collapsable.setLayout(layout_colapsable) self.controls_collapsable.setText('Hide Togglers') self.controls_collapsable.setCollapsedText('Show Togglers') layout_colapsable.addWidget(self.togglers_widget) self.controls_collapsable.collapsed.connect(self.toggle_presets_edit_buttons) self.start_sync_button = QtGui.QPushButton('Begin Repo Sync') self.start_sync_button.setFlat(True) start_sync_color = Qt4Gui.QColor(16, 160, 16) start_sync_color_active = Qt4Gui.QColor(16, 220, 16) self.start_sync_button.setIcon(gf.get_icon('sync', color=start_sync_color, color_active=start_sync_color_active, icons_set='mdi', scale_factor=1)) self.progress_bar = QtGui.QProgressBar() self.progress_bar.setMaximum(100) self.progress_bar.setTextVisible(True) self.progress_bar.setHidden(True) self.downloads_progress_bar = QtGui.QProgressBar() self.downloads_progress_bar.setMaximum(100) self.downloads_progress_bar.setTextVisible(True) self.downloads_progress_bar.setHidden(True) self.grid.addWidget(self.controls_collapsable, 2, 0, 1, 2) self.grid.addWidget(self.start_sync_button, 3, 0, 1, 2) self.grid.addWidget(self.progress_bar, 4, 0, 1, 4) self.grid.addWidget(self.downloads_progress_bar, 5, 0, 1, 4) def toggle_presets_edit_buttons(self, state): if state: self.add_new_preset_button.setHidden(True) self.save_new_preset_button.setHidden(True) self.remove_preset_button.setHidden(True) else: self.add_new_preset_button.setHidden(False) self.save_new_preset_button.setHidden(False) self.remove_preset_button.setHidden(False) def set_auto_close(self, auto_close): self.auto_close = auto_close def create_tree_widget(self): self.grid = QtGui.QGridLayout() self.grid.setContentsMargins(9, 9, 9, 9) self.grid.setSpacing(6) self.setLayout(self.grid) self.create_presets_combo_box() self.tree_widget = QtGui.QTreeWidget(self) self.tree_widget.setTabKeyNavigation(True) self.tree_widget.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel) self.tree_widget.setAllColumnsShowFocus(True) self.tree_widget.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.tree_widget.setHeaderHidden(True) self.tree_widget.setObjectName('tree_widget') self.tree_widget.setAlternatingRowColors(True) self.tree_widget.setStyleSheet(gf.get_qtreeview_style()) self.tree_widget.setRootIsDecorated(True) self.grid.addWidget(self.tree_widget, 1, 0, 1, 2) self.grid.setRowStretch(1, 1) def create_presets_combo_box(self): self.grid_presets = QtGui.QGridLayout() self.presets_combo_box = QtGui.QComboBox() self.add_new_preset_button = QtGui.QToolButton() self.add_new_preset_button.setAutoRaise(True) self.add_new_preset_button.setIcon(gf.get_icon('plus-box', icons_set='mdi', scale_factor=1.2)) self.add_new_preset_button.clicked.connect(self.add_new_preset) self.add_new_preset_button.setToolTip('Create new Preset and Save (from current state)') self.add_new_preset_button.setHidden(True) self.save_new_preset_button = QtGui.QToolButton() self.save_new_preset_button.setAutoRaise(True) self.save_new_preset_button.setIcon(gf.get_icon('content-save', icons_set='mdi', scale_factor=1)) self.save_new_preset_button.clicked.connect(self.save_preset_to_server) self.save_new_preset_button.setToolTip('Save Current Preset Changes') self.save_new_preset_button.setHidden(True) self.remove_preset_button = QtGui.QToolButton() self.remove_preset_button.setAutoRaise(True) self.remove_preset_button.setIcon(gf.get_icon('delete', icons_set='mdi', scale_factor=1)) self.remove_preset_button.clicked.connect(self.delete_preset_from_server) self.remove_preset_button.setToolTip('Remove Current Preset') self.remove_preset_button.setHidden(True) self.grid_presets.addWidget(self.remove_preset_button, 0, 0, 1, 1) self.grid_presets.addWidget(self.presets_combo_box, 0, 1, 1, 1) self.grid_presets.addWidget(self.save_new_preset_button, 0, 2, 1, 1) self.grid_presets.addWidget(self.add_new_preset_button, 0, 3, 1, 1) self.grid_presets.setColumnStretch(1, 0) self.grid.addLayout(self.grid_presets, 0, 0, 1, 2) def fill_presets_combo_box(self, current_preset=None): self.presets_combo_box.clear() current_idx = 0 for i, preset in enumerate(self.presets_list): self.presets_combo_box.addItem(preset['pretty_preset_name']) self.presets_combo_box.setItemData(i, preset['preset_name']) if preset['preset_name'] == current_preset: current_idx = i self.presets_combo_box.setCurrentIndex(current_idx) def fill_tree_widget(self): self.fill_builtin_processes() self.fill_stype_pipeline(self.stype) self.fill_children_pipelines_and_processes(self.stype) def fill_builtin_processes(self, parent_tree_item=None): if not parent_tree_item: parent_tree_item_add = self.tree_widget.addTopLevelItem else: parent_tree_item_add = parent_tree_item.addChild # Builtin processes for key in ['publish', 'attachment', 'icon']: top_item = QtGui.QTreeWidgetItem() top_item.setText(0, key.capitalize() + ' (builtin)') top_item.setCheckState(0, QtCore.Qt.Checked) top_item.setData(1, 0, '{0}:{1}'.format(key, '{b}')) parent_tree_item_add(top_item) def fill_stype_pipeline(self, stype=None, parent_tree_item=None): if not parent_tree_item: parent_tree_item_add = self.tree_widget.addTopLevelItem else: parent_tree_item_add = parent_tree_item.addChild if stype.pipeline: for stype_pipeline in stype.pipeline.values(): top_item = QtGui.QTreeWidgetItem() title = stype_pipeline.info.get('name') if not title: title = stype_pipeline.info.get('code') top_item.setText(0, title) top_item.setData(1, 0, '{0}:{1}'.format(stype_pipeline.info.get('code'), '{pp}')) parent_tree_item_add(top_item) for key, val in stype_pipeline.pipeline.items(): child_item = QtGui.QTreeWidgetItem() child_item.setText(0, key.capitalize()) child_item.setCheckState(0, QtCore.Qt.Unchecked) child_item.setData(1, 0, '{0}:{1}'.format(key, '{pr}')) item_color = Qt4Gui.QColor(200, 200, 200) process = stype_pipeline.get_pipeline_process(key) if process: hex_color = process.get('color') color = None if hex_color: color = gf.hex_to_rgb(hex_color, tuple=True) if color: item_color = Qt4Gui.QColor(*color) child_item.setIcon(0, gf.get_icon('circle', color=item_color, scale_factor=0.55)) top_item.addChild(child_item) top_item.setExpanded(True) def fill_children_pipelines_and_processes(self, stype=None, parent_tree_item=None): if not parent_tree_item: parent_tree_item_add = self.tree_widget.addTopLevelItem else: parent_tree_item_add = parent_tree_item.addChild project = self.stype.get_project() # Children process if stype.schema: for child in stype.schema.children: child_stype = project.stypes.get(child['from']) relationship_type = child.get('type') if child_stype: ignored = False if child_stype and relationship_type not in ['many_to_many']: # Breaking recursion # Similar logic in items: check_for_child_recursion() if parent_tree_item: parent = parent_tree_item.parent() # we storing ignore dicts in parent stypes, and checking it, so we break recursion # and also getting as deep as needed when syncing assets if parent: ignore_dict = parent.data(2, QtCore.Qt.UserRole) parent_stype = parent.data(3, QtCore.Qt.UserRole) ignore_dict.setdefault('children', []).append(parent_stype.info['code']) else: ignore_dict = {} else: ignore_dict = {} # Already added stypes per child tree if ignore_dict: if ignore_dict.get('children'): if child_stype.info['code'] in ignore_dict['children']: ignored = True if not ignored: top_item = QtGui.QTreeWidgetItem() top_item.setText(0, child_stype.get_pretty_name() + ' (child)') # Making items unchecked by default, because someone can sync all repo in chain top_item.setCheckState(0, QtCore.Qt.Unchecked) top_item.setData(1, 0, '{0}:{1}'.format(child_stype.get_code(), '{s}')) # setting ignore dicts and stype for top item top_item.setData(2, QtCore.Qt.UserRole, ignore_dict) top_item.setData(3, QtCore.Qt.UserRole, child_stype) clr = child_stype.get_stype_color(tuple=True) stype_color = None if clr: stype_color = Qt4Gui.QColor(clr[0], clr[1], clr[2], 255) top_item.setIcon(0, gf.get_icon('view-sequential', color=stype_color, icons_set='mdi', scale_factor=1.1)) self.fill_builtin_processes(top_item) self.fill_stype_pipeline(child_stype, top_item) parent_tree_item_add(top_item) self.fill_children_pipelines_and_processes(child_stype, top_item) def fit_to_content_tree_widget(self): items_count = 0 for item in QtGui.QTreeWidgetItemIterator(self.tree_widget): if item.value().isExpanded(): items_count += 1 row_height = items_count * self.tree_widget.sizeHintForRow(0) + 500 mouse_pos = Qt4Gui.QCursor.pos() self.setGeometry(mouse_pos.x(), mouse_pos.y(), 450, row_height) def add_new_preset(self): add_preset_dialog = QtGui.QDialog(self) add_preset_dialog.setWindowTitle('Save as new Preset {}'.format(self.stype.get_pretty_name())) add_preset_dialog.setMinimumSize(320, 80) add_preset_dialog.setMaximumSize(450, 80) add_preset_dialog_layout = QtGui.QVBoxLayout() add_preset_dialog.setLayout(add_preset_dialog_layout) add_preset_dialog_line_edit = QtGui.QLineEdit('New Preset') add_preset_dialog_button = QtGui.QPushButton('Create and Save') add_preset_dialog_layout.addWidget(add_preset_dialog_line_edit) add_preset_dialog_layout.addWidget(add_preset_dialog_button) add_preset_dialog_button.clicked.connect(lambda: self.save_preset_to_server( preset_name=add_preset_dialog_line_edit.text().lower().replace(' ', '_'), pretty_preset_name=add_preset_dialog_line_edit.text() )) add_preset_dialog_button.clicked.connect(add_preset_dialog.close) add_preset_dialog.exec_() # self.fill_presets_combo_box() def get_current_preset_name(self): current_index = self.presets_combo_box.currentIndex() return self.presets_combo_box.itemData(current_index) def get_current_preset_dict(self): preset_dict = self.get_preset_config(self.get_current_preset_name(), json=False) return preset_dict['data'] def get_preset_dict_by_type(self, type='pipeline', preset_dict=None, only_enabled=False): result_preset_dict = {} if type == 'pipeline': for name, preset in preset_dict.items(): if name.endswith(':{pp}'): result_preset_dict[name.replace(':{pp}', '')] = preset if type == 'builtin': for name, preset in preset_dict.items(): if name.endswith(':{b}'): if only_enabled: if preset['state']: result_preset_dict[name.replace(':{b}', '')] = preset else: result_preset_dict[name.replace(':{b}', '')] = preset if type == 'process': for name, preset in preset_dict.items(): if name.endswith(':{pr}'): if only_enabled: if preset['state']: result_preset_dict[name.replace(':{pr}', '')] = preset else: result_preset_dict[name.replace(':{pr}', '')] = preset if type == 'child': for name, preset in preset_dict.items(): if name.endswith(':{s}'): if only_enabled: if preset['state']: result_preset_dict[name.replace(':{s}', '')] = preset else: result_preset_dict[name.replace(':{s}', '')] = preset return result_preset_dict def apply_repo_sync_preset(self, current_index=None, preset_name=None): if not preset_name: preset_name = self.presets_combo_box.itemData(current_index) preset_dict = self.get_preset_by_name(preset_name) if preset_dict: # Pipeline items should not have check state, filter it with {pp} tag gf.set_tree_widget_checked_state(self.tree_widget, preset_dict, ignore_types_tuple=(':{pp}')) if preset_dict.get('get_versions'): if preset_dict['get_versions']: self.fullSyncRadioButton.setChecked(True) else: self.versionlessSyncRadioButton.setChecked(True) else: self.versionlessSyncRadioButton.setChecked(True) def get_preset_by_name(self, preset_name): # Only used on initial items filling if self.presets_list: for preset in self.presets_list: if preset['preset_name'] == preset_name: return preset def get_all_presets_from_server(self): server = tc.server_start() key = 'search_type:{0}'.format(self.stype.get_code()) search_type = 'sthpw/wdg_settings' project_code = self.stype.get_project().get_code() filters = [('key', 'like', '{0}%'.format(key)), ('project_code', project_code)] columns = ['data'] presets = server.query(search_type, filters, columns) if not presets: self.presets_list = [ { 'pretty_preset_name': 'Default', 'preset_name': 'default', } ] else: new_presets_list = [] for preset in presets: new_presets_list.append(gf.from_json(preset['data'])) self.presets_list = new_presets_list def get_preset_config(self, preset_name=None, pretty_preset_name=None, json=True): if not preset_name: preset_name = 'default' if not pretty_preset_name: pretty_preset_name = preset_name.capitalize().replace('_', ' ') # Preparing preset data preset_dict = { 'preset_name': preset_name, 'pretty_preset_name': pretty_preset_name, 'get_versions': self.fullSyncRadioButton.isChecked() } gf.get_tree_widget_checked_state(self.tree_widget, preset_dict) key = 'search_type:{0}:preset_name:{1}'.format(self.stype.get_code(), preset_name) if json: data_dict = gf.to_json(preset_dict) else: data_dict = preset_dict data = { 'data': data_dict, 'key': key, 'login': '******', 'project_code': self.stype.get_project().get_code(), } return data def add_file_objects_to_queue(self, files_objects_list): for file_object in files_objects_list: self.repo_sync_items.append(self.download_queue.schedule_file_object(file_object)) self.download_queue.files_num_label.setText( str(self.download_queue.files_queue_tree_widget.topLevelItemCount()) ) def get_presets_list(self): return self.presets_list def download_files(self): self.downloads_progress_bar.setVisible(True) if not self.interrupted: for repo_sync_item in self.repo_sync_items: repo_sync_item.download() self.download_queue.files_num_label.setText( str(self.download_queue.files_queue_tree_widget.topLevelItemCount()) ) self.downloads_progress_bar.setMaximum(len(self.repo_sync_items)) if not self.repo_sync_items: self.files_downloads_finished() def clear_queue(self): self.download_queue.clear_queue() self.repo_sync_items = [] def start_sync(self, preset_dict=None): self.sync_in_progress = True # it is recommended to use finished signal if not preset_dict: preset_dict = self.get_current_preset_dict() self.clear_queue() self.sobject.update_snapshots() self.sync_by_pipeline(self.sobject, preset_dict) self.sync_children(self.sobject, preset_dict) # self.download_files() def start_sync_ui(self, preset_dict=None): self.show() self.sync_in_progress = True self.progress_bar.setHidden(False) self.toggle_ui(False) self.clear_queue() if not preset_dict: preset_dict = self.get_current_preset_dict() if self.sobject: self.progress_bar.setValue(0) self.progress_bar.setFormat(u'Getting: {0}'.format(self.sobject.get_title())) self.update_sobject_snapshots_threaded(self.sobject, preset_dict) self.sync_children(self.sobject, preset_dict) self.save_last_sync_date() else: self.progress_bar.setValue(0) self.progress_bar.setFormat(u'Getting all: {0}'.format(self.stype.get_pretty_name())) self.update_sobjects_threaded(preset_dict) # self.download_files() # self.progress_bar.setHidden(True) # self.toggle_ui(True) def check_sync_tasks(self): if self.sync_tasks == 0: self.progress_bar.setHidden(True) self.download_files() def do_sync_all_sobjects(self, result): sobjects, query_info, preset_dict = result for sobject in sobjects.values(): total = query_info['total_sobjects_query_count'] self.progress_bar.setMaximum(total) progress = self.progress_bar.value() self.progress_bar.setValue(progress + 1) self.progress_bar.setFormat(u'%v / %m {}'.format(sobject.get_title())) self.update_sobject_snapshots_threaded(sobject, preset_dict) self.sync_children(sobject, preset_dict) self.save_last_sync_date(sobject) self.sync_tasks -= 1 self.check_sync_tasks() def update_sobjects_threaded(self, preset_dict): worker = env_inst.server_pool.add_task( tc.get_sobjects, self.stype.get_code(), [], project_code=self.stype.project.get_code(), get_all_snapshots=True ) worker.add_result_data(preset_dict) worker.result.connect(self.do_sync_all_sobjects) worker.error.connect(gf.error_handle) worker.start() self.sync_tasks += 1 def update_sobject_snapshots_threaded(self, sobject, preset_dict): if preset_dict.get('only_updates'): worker = env_inst.server_pool.add_task(sobject.update_snapshots, filters=[('timestamp', 'is after', self.get_last_sync_date())]) else: worker = env_inst.server_pool.add_task(sobject.update_snapshots) worker.finished.connect(partial(self.sync_by_pipeline, sobject, preset_dict)) worker.error.connect(gf.error_handle) worker.start() self.sync_tasks += 1 def interrupt_sync_process(self): self.interrupted = True def toggle_ui(self, enable=False): self.start_sync_button.setEnabled(enable) self.remove_preset_button.setEnabled(enable) self.add_new_preset_button.setEnabled(enable) self.save_new_preset_button.setEnabled(enable) self.controls_collapsable.setEnabled(enable) self.presets_combo_box.setEnabled(enable) self.download_queue.clear_queue_push_button.setEnabled(enable) def sync_by_pipeline(self, sobject=None, preset_dict=None): if not sobject: sobject = self.sobject if not preset_dict: preset_dict = self.get_current_preset_dict() current_pipeline_preset_dict = self.get_preset_dict_by_type('pipeline', preset_dict) current_builtin_preset_dict = self.get_preset_dict_by_type('builtin', preset_dict, True) if current_pipeline_preset_dict: for pipeline_name, preset in current_pipeline_preset_dict.items(): self.sync_by_sobject(sobject, preset.get('sub'), current_builtin_preset_dict) elif current_builtin_preset_dict: self.sync_by_sobject(sobject, {}, current_builtin_preset_dict) self.sync_tasks -= 1 self.check_sync_tasks() def sync_children(self, sobject=None, preset_dict=None): if not preset_dict: preset_dict = self.get_current_preset_dict() children_preset_dict = self.get_preset_dict_by_type('child', preset_dict, True) for child_code, children_preset in children_preset_dict.items(): self.get_related_sobjects_threaded(sobject, child_code, children_preset) def get_related_sobjects_threaded(self, sobject, child_code, children_preset): stype = sobject.get_stype() project_obj = stype.get_project() worker = env_inst.server_pool.add_task( sobject.get_related_sobjects, child_stype=project_obj.stypes.get(child_code), parent_stype=stype, get_all_snapshots=True ) worker.add_result_data(children_preset) worker.result.connect(self.do_get_related_sobjects) worker.error.connect(gf.error_handle) worker.start() self.sync_tasks += 1 def do_get_related_sobjects(self, result): related_sobjects, query_info, children_preset = result if related_sobjects: for related_sobject in related_sobjects.values(): self.update_sobject_snapshots_threaded(related_sobject, children_preset.get('sub')) self.sync_children(related_sobject, children_preset.get('sub')) total = query_info['total_sobjects_query_count'] self.progress_bar.setMaximum(total) progress = self.progress_bar.value() self.progress_bar.setValue(progress + 1) self.progress_bar.setFormat(u'%v / %m {}'.format(related_sobject.get_title())) self.sync_tasks -= 1 self.check_sync_tasks() def sync_by_sobject(self, sobject=None, sync_preset_dict=None, builtin_preset_dict=None): process_objects = sobject.get_all_processes() enabled_processes = self.get_preset_dict_by_type('process', sync_preset_dict, True) versionless_list = [] versions_list = [] versionless_only = self.versionlessSyncRadioButton.isChecked() if builtin_preset_dict: all_precesses = dict(tuple(enabled_processes.items()) + tuple(builtin_preset_dict.items())) else: all_precesses = enabled_processes self.progress_bar.setMaximum(len(process_objects.items())) for process_name, process_object in process_objects.items(): progress = self.progress_bar.value() self.progress_bar.setValue(progress + 1) self.progress_bar.setFormat(u'%v / %m {}'.format('{0}: {1}'.format(sobject.get_title(), process_name))) if not self.interrupted: if process_name in list(all_precesses.keys()): contexts = process_object.get_contexts() for context, context_obj in contexts.items(): versionless_snapshots = context_obj.get_versionless() for code, snapshot in versionless_snapshots.items(): versionless_list.extend(snapshot.get_files_objects()) if not versionless_only: versions_snapshots = context_obj.get_versions() for code, snapshot in versions_snapshots.items(): versions_list.extend(snapshot.get_files_objects()) if versionless_only: self.add_file_objects_to_queue(versionless_list) else: self.add_file_objects_to_queue(versionless_list) self.add_file_objects_to_queue(versions_list) def delete_preset_from_server(self, preset_name=None): if not preset_name: idx = self.presets_combo_box.currentIndex() preset_name = self.presets_combo_box.itemData(idx) # ask before delete buttons = (('Yes', QtGui.QMessageBox.YesRole), ('Cancel', QtGui.QMessageBox.NoRole)) reply = gf.show_message_predefined( 'Removing preset from server', u'Are You sure want to remove <b>" {0} "</b> preset from Server?'.format(preset_name), buttons=buttons, message_type='question', parent=self ) if reply == QtGui.QMessageBox.YesRole: server = tc.server_start() data = self.get_preset_config(preset_name) search_type = 'sthpw/wdg_settings' # Checking for existing key filters = [('key', data['key'])] columns = ['code', 'project'] widget_settings = server.query(search_type, filters, columns, single=True) search_key = widget_settings['__search_key__'] server.delete_sobject(search_key) self.get_all_presets_from_server() self.fill_presets_combo_box(preset_name) def save_preset_to_server(self, preset_name=None, pretty_preset_name=None): if not preset_name: idx = self.presets_combo_box.currentIndex() preset_name = self.presets_combo_box.itemData(idx) server = tc.server_start() data = self.get_preset_config(preset_name, pretty_preset_name) search_type = 'sthpw/wdg_settings' # Checking for existing key filters = [('key', data['key'])] columns = ['code', 'project'] widget_settings = server.query(search_type, filters, columns, single=True) if widget_settings: code = widget_settings['code'] project = widget_settings['project'] search_key = server.build_search_key(search_type, code, project) server.insert_update(search_key, data, triggers=False) else: server.insert(search_type, data, triggers=False) self.get_all_presets_from_server() self.fill_presets_combo_box(preset_name) def get_settings_dict(self): settings_dict = { 'presets_combo_box': self.presets_combo_box.currentIndex(), } return settings_dict def set_settings_from_dict(self, settings_dict=None): ref_settings_dict = { 'presets_combo_box': 0, } settings = gf.check_config(ref_settings_dict, settings_dict) initial_index = self.presets_combo_box.currentIndex() self.presets_combo_box.setCurrentIndex(int(settings['presets_combo_box'])) if initial_index == int(settings['presets_combo_box']): self.apply_repo_sync_preset(initial_index) def get_last_sync_date(self, sobject=None): if not sobject: sobject = self.sobject group_path = 'ui_search/{0}/{1}/{2}/sobjects_conf'.format( self.stype.project.info['type'], self.stype.project.info['code'], self.stype.get_code().split('/')[1] ) return env_read_config(filename=sobject.get_code(), unique_id=group_path, long_abs_path=True ) def save_last_sync_date(self, sobject=None): if not sobject: sobject = self.sobject group_path = 'ui_search/{0}/{1}/{2}/sobjects_conf'.format( self.stype.project.info['type'], self.stype.project.info['code'], self.stype.get_code().split('/')[1] ) current_datetime = QtCore.QDateTime.currentDateTime() env_write_config( current_datetime.toString('yyyy.MM.dd hh:mm:ss'), filename=sobject.get_code(), unique_id=group_path, long_abs_path=True ) def refresh_search_widget(self): checkin_out = env_inst.get_check_tree(self.stype.get_project().get_code(), 'checkin_out', self.stype.get_code()) if checkin_out: checkin_out.refresh_current_results() def readSettings(self): group_path = 'ui_search/{0}/{1}/{2}'.format( self.stype.project.info['type'], self.stype.project.info['code'], self.stype.get_code().split('/')[1] ) self.set_settings_from_dict( env_read_config( filename='repo_sync', unique_id=group_path, long_abs_path=True ) ) def writeSettings(self): group_path = 'ui_search/{0}/{1}/{2}'.format( self.stype.project.info['type'], self.stype.project.info['code'], self.stype.get_code().split('/')[1] ) env_write_config( self.get_settings_dict(), filename='repo_sync', unique_id=group_path, long_abs_path=True ) def closeEvent(self, event): if not self.sync_in_progress: self.writeSettings() self.deleteLater() self.refresh_search_widget() event.accept() else: buttons = (('Ok', QtGui.QMessageBox.NoRole), ('Interrupt', QtGui.QMessageBox.ActionRole)) reply = gf.show_message_predefined( title='Download in Progress', message='Some files are not yet Downloaded.\nInterrupt the Sync Process?.', buttons=buttons, parent=self, message_type='question', ) if reply == QtGui.QMessageBox.ActionRole: self.interrupt_sync_process() self.deleteLater() event.accept() else: event.ignore()
class Ui_repoSyncQueueWidget(QtGui.QMainWindow): downloads_finished = QtCore.Signal() file_download_done = QtCore.Signal(object) def __init__(self, embedded=False, parent=None): super(self.__class__, self).__init__(parent=parent) self.embedded = embedded self.queue_dict = {} self.total_downloading_count = 0 self.total_downloaded_count = 0 self.network_manager = QtNetwork.QNetworkAccessManager(self) self.network_manager.finished.connect(self.network_manager_finished) if self.embedded: self.create_embedded_ui() else: self.create_ui() def create_ui(self): self.setWindowTitle('Repository Sync Queue') self.statusbar = QtGui.QStatusBar(self) self.statusbar.setObjectName('statusbar') self.setStatusBar(self.statusbar) self.setWindowFlags(QtCore.Qt.Window) self.resize(350, 700) self.create_main_layout() self.create_controls_layout() self.create_controls() self.create_tree_widget() self.controls_actions() def controls_actions(self): self.clear_queue_push_button.clicked.connect(self.clear_queue) def create_embedded_ui(self): self.create_main_layout() self.main_layout.setContentsMargins(3, 0, 3, 0) self.create_controls_layout() self.create_controls() self.create_tree_widget() self.controls_actions() def create_main_layout(self): self.central_widget = QtGui.QWidget(self) self.central_widget.setObjectName('central_widget') self.main_layout = QtGui.QGridLayout(self.central_widget) self.main_layout.setContentsMargins(9, 9, 9, 9) self.main_layout.setSpacing(0) self.main_layout.setObjectName('main_layout') self.central_widget.setLayout(self.main_layout) self.setCentralWidget(self.central_widget) def create_controls_layout(self): self.controls_layout = QtGui.QGridLayout() self.controls_layout.setContentsMargins(0, 0, 0, 0) self.controls_layout.setSpacing(6) self.controls_layout.setObjectName('controls_layout') self.main_layout.addLayout(self.controls_layout, 0, 0, 1, 1) def create_controls(self): self.clear_queue_push_button = QtGui.QPushButton('Clear Queue') self.clear_queue_push_button.setMinimumSize(QtCore.QSize(120, 0)) self.clear_queue_push_button.setObjectName('clear_queue_push_button') self.clear_queue_push_button.setIcon(gf.get_icon('delete', icons_set='mdi')) self.clear_queue_push_button.setFlat(True) self.files_count_label = QtGui.QLabel('Downloads in Queue: ') self.files_count_label.setObjectName('files_count_label') self.files_num_label = QtGui.QLabel('') self.files_num_label.setObjectName("files_num_label") self.controls_layout.addWidget(self.files_count_label, 0, 0) self.controls_layout.addWidget(self.files_num_label, 0, 1) self.controls_layout.addWidget(self.clear_queue_push_button, 0, 2) def create_tree_widget(self): self.files_queue_tree_widget = QtGui.QTreeWidget() self.files_queue_tree_widget.setMinimumSize(QtCore.QSize(300, 0)) self.files_queue_tree_widget.setRootIsDecorated(False) self.files_queue_tree_widget.setHeaderHidden(True) self.files_queue_tree_widget.setObjectName('files_queue_tree_widget') self.files_queue_tree_widget.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.files_queue_tree_widget.setStyleSheet(gf.get_qtreeview_style()) self.main_layout.addWidget(self.files_queue_tree_widget) def create_progress_bar_widget(self): self.progress_bar_widget = QtGui.QProgressBar() self.progress_bar_widget.setTextVisible(True) self.progress_bar_widget.setVisible(True) self.progress_bar_widget.setHidden(True) self.statusbar.addPermanentWidget(self.progress_bar_widget) def set_progress_indicator_on(self): self.progress_bar_widget.setHidden(False) def set_progress_indicator_off(self): self.progress_bar_widget.setHidden(True) self.statusbar.showMessage('') def set_progress(self, progress, info_dict): self.progress_bar_widget.setMaximum(info_dict['total_count']) self.statusbar.showMessage(info_dict['status_text']) self.progress_bar_widget.setValue(progress + 1) if self.progress_bar_widget.maximum() == progress + 1: self.set_progress_indicator_off() def clear_queue(self): self.files_queue_tree_widget.clear() self.queue_dict = {} self.files_num_label.setText('') self.total_downloaded_count = 0 self.total_downloading_count = 0 def remove_item_from_queue(self, commit_item=None): self.queue_list.remove(commit_item) commit_item.close() commit_item.deleteLater() self.files_queue_tree_widget.takeTopLevelItem(self.files_queue_tree_widget.currentIndex().row()) self.check_queue() def network_manager_finished(self, reply): file_object = reply.request().attribute(QtNetwork.QNetworkRequest.User) if reply.error() == QtNetwork.QNetworkReply.NoError: self.do_download_file_object(file_object, reply) else: repo_sync_item = self.queue_dict.get(file_object.get_unique_id()) repo_sync_item.set_download_failed() def emit_if_all_downloads_done(self): if self.total_downloading_count == self.total_downloaded_count: self.downloads_finished.emit() def is_all_downloads_done(self): return self.total_downloading_count == self.total_downloaded_count def do_download_file_object(self, file_object, reply): # print(type(reply.readAll())) repo_sync_item = self.queue_dict.get(file_object.get_unique_id()) info_dict = { 'status_text': 'Downloading File', 'total_count': 4 } repo_sync_item.download_progress(3, info_dict) full_abs_path = file_object.prepare_repo() with open(full_abs_path, "wb") as downloaded_file: downloaded_file.write(bytearray(reply.readAll())) repo_sync_item.download_progress(4, info_dict) downloaded_file.close() repo_sync_item.set_download_finished() reply.deleteLater() def increment_downloaded(self, fl=None): self.total_downloaded_count += 1 self.emit_if_all_downloads_done() self.file_download_done.emit(fl) def schedule_file_object(self, file_object): # If we already downloaded particular file object, make a new instance of it if file_object.get_unique_id() in list(self.queue_dict.keys()): file_object = copy.copy(file_object) self.total_downloading_count += 1 repo_sync_item = gf.add_repo_sync_item(self.files_queue_tree_widget, file_object) self.queue_dict[file_object.get_unique_id()] = repo_sync_item repo_sync_item.set_network_manager(self.network_manager) self.files_queue_tree_widget.scrollToBottom() repo_sync_item.downloaded.connect(self.increment_downloaded) return repo_sync_item
class ExceptionHook(QtCore.QObject): excepted = QtCore.Signal(object) instance = None def __init__(self, excepthook, parent=None): super(ExceptionHook, self).__init__(parent) ExceptionHook.instance = self self.__excepthook = excepthook # Backup original excepthook object. @staticmethod def __get_excepthook(*args): exception_type, exception_value, exception_traceback = None, None, None for arg in args: if isinstance(arg, type): exception_type = arg elif isinstance(arg, BaseException): exception_value = arg elif isinstance(arg, types.TracebackType): exception_traceback = arg ZeroDivisionError exception_type_string = exception_type is not None and exception_type.__name__ or "UnknownError" exception_value_string = exception_value is not None and six.PY2 and (hasattr(exception_value, "message") and exception_value.message) or (hasattr(exception_value, "msg") and exception_value.msg) or "Unknown error handled" result = "" if exception_type is not None and exception_value is not None and exception_traceback is not None: python_traceback = Traceback.get_traceback(exception_traceback) result_temp = traceback.format_exception(exception_type, exception_value, python_traceback, limit=10) result = "" if result_temp: if isinstance(result_temp, (list, set, tuple)): result_temp = list(result_temp) else: result_temp = [result_temp] for result_temp_item in result_temp: if six.PY2 and isinstance(result_temp_item, (basestring, unicode)) or not six.PY2 and isinstance(result_temp_item, str): result += result_temp_item else: try: result += result_temp_item.__repr__() except UnicodeDecodeError or UnicodeEncodeError: try: result += str(result_temp_item) except UnicodeDecodeError or UnicodeEncodeError: result += "(Failed to decode Exception data)" result += "\n" if not result: result = "Error: " + exception_value_string + "\n" + exception_type_string + ": " + exception_value_string return result def excepthook(self, *args): result = ExceptionHook.__get_excepthook(*args) self.excepted.emit(result) @staticmethod def request(): exc_type, exc_value, exc_traceback = sys.exc_info() result = ExceptionHook.__get_excepthook(exc_type, exc_value, exc_traceback) if ExceptionHook.instance: ExceptionHook.instance.excepted.emit(result)
class OutputCls(QtCore.QObject): written = QtCore.Signal(unicode) flushed = QtCore.Signal() encoding = locale.getpreferredencoding() def __init__(self, std, parent_stream=None, parent=None): """ Initialize default settings. """ # self.__io = open('D:/APS/OneDrive/MEGAsync/TACTIC-handler/stuff.txt', 'w') self.__parent_stream = parent_stream super(OutputCls, self).__init__(parent) self.__std = std self.softspace = 0 def readline(self, *args, **kwargs): """ Read line method. """ return self.__std.readline(*args, **kwargs) def stream(self): """ Get parent stream. """ return self.__parent_stream def write(self, text): """ Write text message. """ # if text is not None: # if isinstance(text, (str, unicode)): # self.__std.write(text) # else: # self.__std.write(repr(text)) try: self.__std.write(text) self.written.emit(text) except: pass finally: return text # try: # # text = unicode(text).encode('utf-8', errors='ignore') # text = str(text) # # except UnicodeEncodeError or UnicodeDecodeError: # text = u"Failed to encode error message..." # self.written.emit(text) # return result def writelines(self, line_list): """ Write lines. """ result = self.__std.writelines(line_list) for line in line_list: # try: # line = unicode(line) # # except UnicodeEncodeError or UnicodeDecodeError: # line = u"Failed to encode error message..." self.written.emit(line) return result def flush(self, *args, **kwargs): """ Flush """ result = self.__std.flush(*args, **kwargs) self.flushed.emit() return result
class ExceptionHook(QtCore.QObject): excepted = QtCore.Signal(unicode) instance = None def __init__(self, excepthook, parent=None): super(ExceptionHook, self).__init__(parent) ExceptionHook.instance = self self.__excepthook = excepthook # Backup original excepthook object. @staticmethod def __get_excepthook(*args): return ExceptionHook.get_traceback() def excepthook(self, *args): result = ExceptionHook.__get_excepthook(*args) self.excepted.emit(result) @staticmethod def request(): exc_type, exc_value, exc_traceback = sys.exc_info() result = ExceptionHook.__get_excepthook(exc_type, exc_value, exc_traceback) if ExceptionHook.instance: ExceptionHook.instance.excepted.emit(result) @staticmethod def get_traceback(): result = u"" # Get information about latest traceback. exception_type, exception_value, exception_traceback = sys.exc_info() # Get exception as string. exception_type_string = exception_type is not None and exception_type.__name__ or u"UnknownError" exception_value_string = exception_value is not None and exception_value.message or u"Unknown error handled" # Get formatted traceback data. if hasattr(traceback, "format_exception"): format_traceback = traceback.format_exception(exception_type, exception_value, exception_traceback, limit=100) else: format_traceback = None if format_traceback: # Create traceback data list. if isinstance(format_traceback, (list, set, tuple)): format_traceback_list = list(format_traceback) else: format_traceback_list = [format_traceback] # Create traceback string. for format_traceback in format_traceback_list: try_unicode = True if isinstance(format_traceback, (basestring, unicode)): try: result += format_traceback except Exception as exception_data: try_unicode = True else: try: result += format_traceback.__repr__() except Exception as exception_data: try_unicode = True if try_unicode: try: result += unicode(format_traceback) except Exception as exception_data: result += u"(Can`t decode Exception data)" # Get default traceback string. if not result: result = u"Error: " + exception_value_string + u"\n" + exception_type_string + u": " + exception_value_string # Return traceback string. return result
class Ui_collapsableWidget(QtGui.QWidget, ui_collapsable.Ui_collapsableWidget): collapsed = QtCore.Signal(object) def __init__(self, text=None, state=False, parent=None): super(self.__class__, self).__init__(parent=parent) self.setupUi(self) self.collapse_state = False self.__collapsedTex = '' self.__text = '' self.setText(text) self.setCollapsed(state) self.create_ui() def create_ui(self): self.collapseToolButton.setMaximumHeight(26) self.controls_actions() self.custom_style_sheet() def custom_style_sheet(self): self.collapseToolButton.setStyleSheet( 'QToolButton {' 'background: rgba(96, 96, 96, 32);' 'border: 0px; border-radius: 3px; padding: 0px 0px;' 'border-left: 2px solid rgb(128, 128, 128); border-right: 2px solid rgb(128, 128, 128);}' 'QToolButton:pressed {' 'background: rgba(128, 128, 128, 32)}' ) def controls_actions(self): self.collapseToolButton.toggled.connect(self.__toggleCollapseState) def setText(self, text): self.__text = text self.collapseToolButton.setText(self.__text) def setCollapsedText(self, text): self.__collapsedTex = text self.collapseToolButton.setText(self.__collapsedTex) def setLayout(self, layout): layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) self.widget.setLayout(layout) def setCollapsed(self, state): if state: self.collapse_state = True self.collapseToolButton.setIcon(gf.get_icon('angle-right')) self.widget.setHidden(True) self.collapseToolButton.setChecked(False) if self.__collapsedTex: self.setCollapsedText(self.__collapsedTex) else: self.collapse_state = False self.collapseToolButton.setIcon(gf.get_icon('angle-down')) self.widget.setHidden(False) self.collapseToolButton.setChecked(True) self.setText(self.__text) def setCollapseState(self, state): if state: self.collapseToolButton.toggle() def __toggleCollapseState(self): if self.collapse_state: self.setCollapsed(False) self.collapsed.emit(False) else: self.setCollapsed(True) self.collapsed.emit(True) def isCollapsed(self): if self.collapse_state: return True else: return False
class OperationWorker(QtCore.QObject): started = QtCore.Signal() finished = QtCore.Signal() error = QtCore.Signal(object) result = QtCore.Signal(object) progress = QtCore.Signal(object) stop = QtCore.Signal(object) def __init__(self, func, *args, **kwargs): super(OperationWorker, self).__init__() self._func = func self._args = args self._kwargs = kwargs self.signals_enabled = True self._started = False self._result = None self._data = None @property def is_started(self): return self._started def add_result_data(self, data): # will add another data into result output # only for tuple output self._data = data def connect_progress(self, func): # attaching progress signal to kwargs # func should have "progress_signal" kwarg self.progress.connect(func) self._kwargs['progress_signal'] = self.progress def get_result_data(self): return self._data def start(self): self._started = True def retry(self): print('This is dummy func, not implemented yet') def do_task(self): self.started.emit() try: if self.signals_enabled: self._result = self._func(*self._args, **self._kwargs) if self._data: result = self._result + (self._data, ) self._result = result self.result.emit(self._result) self.finished.emit() except Exception as expected: if self.signals_enabled: traceback.print_exc(file=sys.stdout) stacktrace = traceback.format_exc() exception = { 'exception': expected, 'stacktrace': stacktrace, } self.error.emit((exception, self)) self.deleteLater()
class AppServer(QtCore.QObject): started = QtCore.Signal() finished = QtCore.Signal() accepted = QtCore.Signal(QtNetwork.QTcpSocket) connected = QtCore.Signal(QtNetwork.QTcpSocket) disconnected = QtCore.Signal(QtNetwork.QTcpSocket) received = QtCore.Signal(QtNetwork.QTcpSocket, QtCore.QByteArray) def __init__(self, port, host="127.0.0.1", parent=None): super(AppServer, self).__init__(parent) self.__port = port self.__host = host # temp = os.path.abspath(os.environ.get("TEMP", os.path.expanduser("~/temp"))).replace("\\", "/").rstrip("/") + "/AppConnection" # if not os.path.exists(temp): # os.makedirs(temp) # # logging.basicConfig(filename=temp + "/AppServer_{0}.{1}.log".format(host, port), level=logging.INFO, format="%(asctime)s - %(message)s") # self.__logger = logging.getLogger("AppServer_{0}.{1}.log".format(host, port)) self.__client_data = {} self.__server_timer = QtCore.QTimer(self) self.__server_timer.setSingleShot(True) self.__server_timer.timeout.connect(self.__run) self.__server_attempt = 0 self.__server = None def run(self): self.__server_attempt = 0 self.__run() def __run_request(self): self.__server_timer.start(1000) # def __del__(self): # # self.stop() def __run(self): # self.__logger.info("run server") if self.__server is None: self.__server = QtNetwork.QTcpServer(self) self.__server.newConnection.connect(self.__accepted) if not self.__server.isListening(): if self.__port != 0 and self.__host != "": port = self.__port host = QtNetwork.QHostAddress(self.__host) while True: listen = self.__server.listen(host, port) if not listen: listen = self.__server.isListening() if not listen: self.__server_attempt += 1 if self.__server_attempt == 3: s_client = AppClient(self.__port, self.__host) s_client.setKeepConnection(False) s_client.connected.connect( lambda c=s_client: c.send("system:stop")) s_client.run() break else: self.__server.close() else: break if self.__server.isListening(): # self.__logger.info("server is running") self.started.emit() elif self.__server_attempt < 3: self.__server_timer.start(1000) else: # self.__logger.info("server is running") self.started.emit() else: # self.__logger.info("server is running") self.started.emit() def stop(self): # self.__logger.info("stop server") key_list = self.__client_data.keys() while key_list: key = key_list.pop() m_client = self.__client_data[key][0] self.send(m_client, "system:stop") m_client.close() m_client.deleteLater() del self.__client_data[key] self.finished.emit() if self.__server: self.__server.close() self.__server.deleteLater() del self.__server self.__server = None def isListening(self): return self.__server and self.__server.isListening() or False def broadcast(self, data): # self.__logger.info("broadcast message '%s'" % data) for key in self.__client_data: self.send(self.__client_data[key][0], data) def __accepted(self): key = uuid.uuid4() # self.__logger.info("accepted connection from client [{0}]".format(key)) if self.__server: m_client = self.__server.nextPendingConnection() m_client.disconnected.connect(lambda c=m_client: self.__closed(c)) m_client.connected.connect(lambda c=m_client: self.__connected(c)) m_client.readyRead.connect(lambda c=m_client: self.__received(c)) m_client.setProperty("key", key) self.__client_data[key] = [m_client, 0, None, None] # self.send(m_client, "system:key:" + str(key)) self.accepted.emit(m_client) # else: # self.__logger.info("can`t accept connection from client [{0}]".format(key)) def __closed(self, m_client): # self.__logger.info("client closed") if isinstance(m_client, QtNetwork.QTcpSocket): self.disconnected.emit(m_client) key = m_client.property("key") del self.__client_data[key] m_client.deleteLater() # self.__logger.info("closed connection from client [{0}]".format(key)) def __connected(self, m_client): # self.__logger.info("client connected") if isinstance(m_client, QtNetwork.QTcpSocket): self.connected.emit(m_client) # key = m_client.property("key") # self.__logger.info("connection from client [{0}]".format(key)) def __received(self, m_client): key = m_client.property("key") # self.__logger.info("receive message from client [{0}]".format(key)) stream = QtCore.QDataStream(m_client) stream.setVersion(QtCore.QDataStream.Qt_4_7) if key in self.__client_data: while True: if not self.__client_data[key][1]: if m_client.bytesAvailable() < ctypes.sizeof( ctypes.c_long): break self.__client_data[key][1] = stream.readUInt64() if m_client.bytesAvailable() < self.__client_data[key][1]: break if self.__client_data[key][2] is None: self.__client_data[key][2] = QtCore.QByteArray() self.__client_data[key][3] = QtCore.QDataStream( self.__client_data[key][2], QtCore.QIODevice.ReadWrite) self.__client_data[key][3].setVersion( QtCore.QDataStream.Qt_4_7) self.__client_data[key][3].writeUInt64( self.__client_data[key][1]) data = QtCore.QByteArray() stream >> data if self.__client_data[key][1]: self.__client_data[key][3] << data if self.__client_data[key][2].size() - ctypes.sizeof( ctypes.c_long) == self.__client_data[key][1]: self.__client_data[key][3].device().seek(0) size = self.__client_data[key][3].readUInt64() message = QtCore.QByteArray() self.__client_data[key][3] >> message self.__client_data[key][2] = None self.__client_data[key][3] = None self.__client_data[key][1] = 0 # system = 0 if message[:7] == "system:": # system = 1 if message[:11] == "system:key:" and message.size( ) == 47: try: replace_key = uuid.UUID(str(message[11:])) except: replace_key = key if key != replace_key: # self.__logger.info("update client key from " + repr(key) + " to " + repr(replace_key)) self.__client_data[ replace_key] = self.__client_data[key] del self.__client_data[key] key = replace_key elif message == "system:stop": self.stop() # if system: # self.__logger.info("received system message from client with size " + repr(size) + " [{0}]".format(key)) else: # self.__logger.info("received message from client with size " + repr(size) + " [{0}]".format(key)) self.received.emit(m_client, message) def send(self, m_client, data): key = m_client.property("key") # self.__logger.info("send message to client [{0}]".format(key)) block = QtCore.QByteArray() stream = QtCore.QDataStream(block, QtCore.QIODevice.WriteOnly) stream.setVersion(QtCore.QDataStream.Qt_4_7) stream.writeUInt64(0) stream << QtCore.QByteArray(data) stream.device().seek(0) stream.writeUInt64(block.size() - ctypes.sizeof(ctypes.c_long)) stream.device().seek(block.size()) stream.writeUInt64(0) s = 0 while s < block.size(): if m_client.state() != QtNetwork.QAbstractSocket.ConnectedState: m_client.warning( "is not connected to server [{0}]".format(key)) break w = m_client.write(block) s += w