def __init__(self): super().__init__() self.setWindowTitle('Голосовая идентификация') self.setWindowIcon(QIcon('Voice-Search.ico')) self.vBox = QVBoxLayout() self.buttonsBox = QHBoxLayout() self.setLayout(self.vBox) # создание компонентов self.usersText = QLabel('В системе 28 пользователей') self.signUpButton = QPushButton('Зарегистрироваться') self.identifyButton = QPushButton('Идентифицировать') self.aboutButton = QPushButton('Как это работает?') # создание форм self.signUpWindow = SignUpWindow() self.identifyWindow = IdentifyWindow() self.aboutWindow = AboutWindow() # добавление компоненов на форму self.vBox.addWidget(self.usersText) self.vBox.addWidget(StaticImage('users.png')) self.vBox.addLayout(self.buttonsBox) self.buttonsBox.addWidget(self.signUpButton) self.buttonsBox.addWidget(self.identifyButton) self.buttonsBox.addWidget(self.aboutButton) # связка кнопок с формами self.signUpButton.clicked.connect(self.signUpWindow.show) self.identifyButton.clicked.connect(self.identifyWindow.show) self.aboutButton.clicked.connect(self.aboutWindow.show)
def __init__(self): QMainWindow.__init__(self) self.setupUi(self) self.reset_app() self.about_window = AboutWindow(self) self.deploy_window = DeployWindow(self) # Custom context Menu self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.treeWidget.customContextMenuRequested.connect(self.showContextMenu) # get any history of combo boxes and reset index self.comboServer.addItems(get_history('servers')) self.comboServer.setCurrentIndex(-1) self.comboFile.addItems(get_history('locals')) self.comboFile.setCurrentIndex(-1) # Set action for clicking About. self.actionAbout.triggered.connect(self.show_about_window) # Set action for closing the app. self.actionExit.triggered.connect(self.close) # Set action for reseting the app. self.actionReset.triggered.connect(self.reset_app) # Set action for clicking browse button self.buttonBrowse.clicked.connect(self.browse_file) # Set action for clicking the compare button self.buttonCompare.clicked.connect(self.compare) # On change of server value, check the connection. self.comboServer.currentIndexChanged.connect( self.check_server_value) self.comboServer.lineEdit().editingFinished.connect( self.check_server_value) # On change of folder value, check the connection. self.comboFile.currentIndexChanged.connect( self.check_folder_value) self.comboFile.lineEdit().editingFinished.connect( self.check_folder_value) self.setFocus()
def __init__(self): super(Ruler, self).__init__() self.old_position = None # is used for dragging of the window self.setMinimumWidth(50) self.setMinimumHeight(50) # load the options self.data = Data() # main widget self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.constructContextMenu) self.setWindowTitle('Screen Ruler') self.resize(self.data.get('ruler_width'), self.data.get('ruler_height')) self.setMouseTracking(True) self.setAttribute(Qt.WA_TranslucentBackground, True) self.setGeometry( QStyle.alignedRect( Qt.LeftToRight, Qt.AlignCenter, self.size(), QGuiApplication.primaryScreen().availableGeometry())) windowFlags = Qt.CustomizeWindowHint | Qt.FramelessWindowHint leftResize = SizeGrip(self, True) rightResize = SizeGrip(self, False) self.left_resize = leftResize self.right_resize = rightResize if self.data.get('always_above'): windowFlags = windowFlags | Qt.WindowStaysOnTopHint self.setWindowFlags( windowFlags) # Turns off the default window title hints # initialize the secondary windows self.about_window = AboutWindow() self.options_window = OptionsWindow(self) if self.data.get('options_opened'): self.openOptions()
class Ruler(QWidget): def __init__(self): super(Ruler, self).__init__() self.old_position = None # is used for dragging of the window self.setMinimumWidth(50) self.setMinimumHeight(50) # load the options self.data = Data() # main widget self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.constructContextMenu) self.setWindowTitle('Screen Ruler') self.resize(self.data.get('ruler_width'), self.data.get('ruler_height')) self.setMouseTracking(True) self.setAttribute(Qt.WA_TranslucentBackground, True) self.setGeometry( QStyle.alignedRect( Qt.LeftToRight, Qt.AlignCenter, self.size(), QGuiApplication.primaryScreen().availableGeometry())) windowFlags = Qt.CustomizeWindowHint | Qt.FramelessWindowHint leftResize = SizeGrip(self, True) rightResize = SizeGrip(self, False) self.left_resize = leftResize self.right_resize = rightResize if self.data.get('always_above'): windowFlags = windowFlags | Qt.WindowStaysOnTopHint self.setWindowFlags( windowFlags) # Turns off the default window title hints # initialize the secondary windows self.about_window = AboutWindow() self.options_window = OptionsWindow(self) if self.data.get('options_opened'): self.openOptions() def resizeEvent(self, event=None): size = self.size() width = size.width() height = size.height() leftResize = self.left_resize rightResize = self.right_resize length = leftResize.length if self.data.get('horizontal_orientation'): rightResize.move(width - length, 0) leftResize.resize(length, height) rightResize.resize(length, height) # vertical orientation else: rightResize.move(0, size.height() - rightResize.length) leftResize.resize(width, length) rightResize.resize(width, length) def paintEvent(self, event): paint = QPainter() paint.begin(self) paint.save() size = self.size() width = size.width() height = size.height() units = self.data.get('units') proportion = self.getProportion() horizontalOrientation = self.data.get('horizontal_orientation') if horizontalOrientation: rulerLength = width traceLengthLimit = height else: # vertical orientation rulerLength = height traceLengthLimit = width paint.translate(width, 0) paint.rotate(90) # the length of the traces (lines) small = traceLengthLimit / 6 medium = traceLengthLimit / 4 large = traceLengthLimit / 3 limit = rulerLength / proportion # draw less lines for centimeters if units == 'cm': step = 10 else: step = 5 # begin drawing fontSize = 10 font = QFont('Serif', fontSize) fontMetrics = QFontMetrics(font) # draw background background = self.data.get('background_color') paint.fillRect(0, 0, rulerLength, traceLengthLimit, background) # draw the lines paint.setPen(self.data.get('lines_color')) paint.setFont(font) # the builtin range() doesn't support floats def float_range(current, end, rangeStep): while current < end: yield current current += rangeStep # we skip 0 and start in the first step, since there's no point in drawing the first line/text (it would appear cut off, since we're at the limit) for a in float_range(step, limit, step): position = a * proportion if (a % 100) == 0: lineLength = large if units == 'px': text = '{}{}'.format(str(a), units) else: text = '{}{}'.format(str(int(a / 100)), units) textWidth = fontMetrics.boundingRect(text).width() paint.drawText(position - textWidth / 2, traceLengthLimit / 2 + fontSize / 2, text) elif (a % 50) == 0: lineLength = large # since 'cm' has a different step compared to the other units if units == 'cm': lineLength = medium elif (a % 25) == 0: lineLength = medium else: lineLength = small paint.drawLine(position, 0, position, lineLength) paint.drawLine(position, traceLengthLimit, position, traceLengthLimit - lineLength) # paint the division lines if self.data.get('division_lines'): paint.setPen(self.data.get('divisions_color')) halfPoint = rulerLength / 2 quarterPoint = rulerLength / 4 threeQuarterPoint = 3 / 4 * rulerLength paint.drawLine(quarterPoint, 0, quarterPoint, traceLengthLimit) paint.drawLine(halfPoint, 0, halfPoint, traceLengthLimit) paint.drawLine(threeQuarterPoint, 0, threeQuarterPoint, traceLengthLimit) paint.restore() paint.end() def mousePressEvent(self, event): self.old_position = event.globalPos() button = event.button() if button == Qt.MiddleButton: self.rotate(QCursor.pos()) def mouseMoveEvent(self, event, fromSizeGrip=False): buttons = event.buttons() # if we're on top of a SizeGrip, then clicking means we're resizing, and not moving the ruler if not fromSizeGrip and (buttons & Qt.LeftButton): position = event.globalPos() diff = position - self.old_position self.move(self.x() + diff.x(), self.y() + diff.y()) self.old_position = position if self.options_window: pos = self.pos() if self.data.get('horizontal_orientation'): distance = event.globalX() - pos.x() else: distance = event.globalY() - pos.y() unit = self.data.get('units') if unit != 'px': distance /= 100 value = distance / self.getProportion() string = '{:.2f} {}' else: value = distance # its already in pixels string = '{} {}' self.options_window.setCurrentLength(string.format(value, unit)) def keyPressEvent(self, event): key = event.key() modifiers = event.modifiers() if key == Qt.Key_O and modifiers == Qt.AltModifier: self.openOptions() elif key == Qt.Key_R and modifiers == Qt.AltModifier: self.rotate(QCursor.pos()) def constructContextMenu(self, position): globalPosition = self.mapToGlobal(position) menu = QMenu() optionsEntry = QAction('Options', menu) optionsEntry.setData(self.openOptions) def rotate(): mousePosition = QCursor.pos() self.rotate(mousePosition) rotateEntry = QAction('Rotate', menu) rotateEntry.setData(rotate) aboutEntry = QAction('About', menu) aboutEntry.setData(self.openAbout) quitEntry = QAction('Close', menu) quitEntry.setData(self.quit) menu.addAction(optionsEntry) menu.addAction(rotateEntry) menu.addAction(aboutEntry) menu.addAction(quitEntry) selectedItem = menu.exec_(globalPosition) """:type : QAction""" if selectedItem: selectedItem.data()() def openOptions(self): self.options_window.show() self.options_window.raise_() self.options_window.activateWindow() def rotate(self, mousePosition=None): self.data.update('horizontal_orientation', not self.data.get('horizontal_orientation')) size = self.size() # position the ruler so that the resulting rotation is based on where the mouse is if mousePosition: rulerX = self.x() rulerY = self.y() mouseX = mousePosition.x() mouseY = mousePosition.y() self.move(mouseX - (mouseY - rulerY), mouseY - (mouseX - rulerX)) # switch the width/height (to rotate 90 degrees) self.resize(size.height(), size.width()) self.resizeEvent() # if the options window is opened, update it if self.options_window: self.options_window.updateOrientation( self.data.get('horizontal_orientation')) def openAbout(self): self.about_window.show() self.about_window.raise_() self.about_window.activateWindow() def getProportion(self): units = self.data.get('units') if units == 'cm': # 1 mm -> something pixel # width mm -> width pixel pxToMm = 1 * self.width() / self.widthMM() proportion = pxToMm / 10 # from mm to cm elif units == 'inch': # we'll calculate from mm to inches pxToMm = 1 * self.width() / self.widthMM() # 1 inch 2.54 cm proportion = 0.254 * pxToMm else: # pixels proportion = 1 return proportion def quit(self): self.close() def closeEvent(self, event): self.data.save({ 'width': self.width(), 'height': self.height(), 'optionsOpened': self.options_window.isVisible() }) event.accept() QApplication.quit()
class MainWindow(QMainWindow): process_add_remove_semester = pyqtSignal(str) process_semester_update = pyqtSignal(str) process_subject_state_update = pyqtSignal(str) process_subject_convalidation = pyqtSignal(str) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.central_window = CentralWindow() self.central_window.send_semester_update.connect( self.receive_semester_update) self.central_window.send_subject_state_update.connect( self.receive_subject_state_update) self.init_GUI() def init_GUI(self): self.setMinimumWidth(450) self.setMinimumHeight(270) self.central_window.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setWindowTitle("Planificador de malla curricular") self.setWindowIcon(QIcon(path_logo)) self.setCentralWidget(self.central_window) about_section = QAction(QIcon(path_book), '&Sobre el programa', self) about_section.setShortcut('Ctrl+S') about_section.setStatusTip('Más información') about_section.triggered.connect(self.raise_about_window) exit_action = QAction(QIcon(path_exit), '&Exit', self) exit_action.setShortcut('Ctrl+E') exit_action.setStatusTip('Exit application') exit_action.triggered.connect(QApplication.quit) convalidate_action = QAction(QIcon(path_check_mark), '&Convalidar', self) convalidate_action.setStatusTip('Convalidar ramos') convalidate_action.triggered.connect(self.raise_convalidate_window) add_semester = QAction(QIcon(path_plus), '&Agregar Semestre', self) add_semester.setStatusTip('Se agregará un semestre al final') add_semester.triggered.connect(self.add_semester) remove_semester = QAction(QIcon(path_minus), '&Eliminar Semestre', self) message = 'Se eliminará el último semestre si está vacío' remove_semester.setStatusTip(message) remove_semester.triggered.connect(self.remove_semester) help_window = QAction(QIcon(path_question), '&Ayuda', self) message = 'Se mostrará una ventana de ayuda' help_window.setStatusTip(message) help_window.triggered.connect(self.raise_help_window) menubar = self.menuBar() archivo_menu = menubar.addMenu('&Opciones') archivo_menu.addAction(convalidate_action) archivo_menu.addAction(about_section) archivo_menu.addAction(exit_action) toolbar = self.addToolBar('Toolbar') toolbar.addAction(add_semester) toolbar.addAction(remove_semester) toolbar.addAction(help_window) toolbar.setIconSize(QSize(100, 16)) self.setGeometry(main_window_x_pos, main_window_y_pos, window_width, window_height) def resizeEvent(self, *args, **kwargs): self.process_semester_update.emit("") super().resizeEvent(*args, **kwargs) def update_status_bar(self, mensaje): self.statusBar().showMessage(mensaje) def raise_about_window(self): self.about_window = AboutWindow() self.about_window.show() def raise_convalidate_window(self): self.convalidate_window = ConvalidateWindow() self.convalidate_window.send_convalidation_to_main_window.connect( self.receive_subject_convalidation) def raise_help_window(self): self.help_window = HelpWindow() self.help_window.show() def receive_semester_update(self, string): self.process_semester_update.emit(string) def receive_subject_state_update(self, string): self.process_subject_state_update.emit(string) def receive_subject_convalidation(self, subject): self.process_subject_convalidation.emit(subject) def update_planner(self, string): self.central_window.update(string) def update_convalidate_window(self, message): self.convalidate_window.setMessage(message) def add_semester(self): self.process_add_remove_semester.emit('true') def remove_semester(self): self.process_add_remove_semester.emit('false')
def raise_about_window(self): self.about_window = AboutWindow() self.about_window.show()
def show_about_window(self): about = AboutWindow(self)
def init_calculator_gui(self): if self.master != None: self.master.title("Calculator") self.master.geometry('350x350') # Menubar ------------------------------------------------------------- # File Menu self.menubar = tk.Menu(self.master) self.filemenu = tk.Menu(self.menubar, tearoff=0) self.filemenu.add_command(label="Quit", command=self.quit) self.menubar.add_cascade(label="File", menu=self.filemenu) # About Menu self.about = AboutWindow("Calculator") self.helpmenu = tk.Menu(self.menubar, tearoff=0) self.helpmenu.add_command(label="About", command=self.about.run) self.menubar.add_cascade(label="Help", menu=self.helpmenu) if self.master != None: self.master.config(menu=self.menubar) # Status Bar self.status_text = tk.StringVar() self.status_text.set('') self.statusbar = tk.Label(self.master, textvariable=self.status_text, bd=1, relief=tk.SUNKEN, anchor=tk.W) self.statusbar.pack(side=tk.BOTTOM, fill=tk.X) # Calculator Display -------------------------------------------------- # Container for Calculator Display self.disp_container = tk.Frame(self.master, padx=5, pady=5, relief=tk.SUNKEN) self.disp_container.pack() # Variable for updating calculator display self.disp_text = tk.StringVar() self.disp_text.set('0') # Calculator display entry self.calc_display = tk.Label(self.disp_container, bg='white', textvariable=self.disp_text, height=2, width=48, anchor='e', padx=10, font='Helvetica 16 bold') self.calc_display.pack() # Calculator Keypad --------------------------------------------------- # Container for Calculator Keypad self.keypad_container = tk.Frame(self.master, padx=5, pady=5, relief=tk.RAISED) self.keypad_container.pack() # Calculator keys btn_percent = tk.Button(self.keypad_container, text="%", height=2, width=5, command=lambda: self.on_click_operator('%')) btn_percent.grid(row=0, column=0, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_divide = tk.Button(self.keypad_container, text="/", height=2, width=5, command=lambda: self.on_click_operator('/')) btn_divide.grid(row=0, column=1, sticky=tk.W + tk.E) btn_multi = tk.Button(self.keypad_container, text="*", height=2, width=5, command=lambda: self.on_click_operator('*')) btn_multi.grid(row=0, column=2, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_subtract = tk.Button(self.keypad_container, text="-", height=2, width=5, command=lambda: self.on_click_operator('-')) btn_subtract.grid(row=0, column=3, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_clear = tk.Button(self.keypad_container, text="C", height=2, width=5, bg="#d65a29", command=lambda: self.on_click_clear()) btn_clear.grid(row=0, column=4, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_seven = tk.Button(self.keypad_container, text="7", height=2, width=5, command=lambda: self.on_click_digit('7')) btn_seven.grid(row=1, column=0, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_eight = tk.Button(self.keypad_container, text="8", height=2, width=5, command=lambda: self.on_click_digit('8')) btn_eight.grid(row=1, column=1, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_nine = tk.Button(self.keypad_container, text="9", height=2, width=5, command=lambda: self.on_click_digit('9')) btn_nine.grid(row=1, column=2, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_add = tk.Button(self.keypad_container, text="+", height=5, width=5, command=lambda: self.on_click_operator('+')) btn_add.grid(row=1, column=3, padx=(3, 1), pady=(3, 1), rowspan=2, sticky=tk.W + tk.E + tk.S + tk.N) btn_ac = tk.Button(self.keypad_container, text="AC", height=2, width=5, command=lambda: self.on_click_ac()) btn_ac.grid(row=1, column=4, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_four = tk.Button(self.keypad_container, text="4", height=2, width=5, command=lambda: self.on_click_digit('4')) btn_four.grid(row=2, column=0, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_five = tk.Button(self.keypad_container, text="5", height=2, width=5, command=lambda: self.on_click_digit('5')) btn_five.grid(row=2, column=1, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_six = tk.Button(self.keypad_container, text="6", height=2, width=5, command=lambda: self.on_click_digit('6')) btn_six.grid(row=2, column=2, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_openbrace = tk.Button(self.keypad_container, text="(", height=2, width=5, command=lambda: self.on_click_symbol('(')) btn_openbrace.grid(row=2, column=4, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_one = tk.Button(self.keypad_container, text="1", height=2, width=5, command=lambda: self.on_click_digit('1')) btn_one.grid(row=3, column=0, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_two = tk.Button(self.keypad_container, text="2", height=2, width=5, command=lambda: self.on_click_digit('2')) btn_two.grid(row=3, column=1, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_three = tk.Button(self.keypad_container, text="3", height=2, width=5, command=lambda: self.on_click_digit('3')) btn_three.grid(row=3, column=2, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_equals = tk.Button(self.keypad_container, text="=", height=5, width=5, command=lambda: self.on_click_result()) btn_equals.grid(row=3, column=3, padx=(3, 1), pady=(3, 1), rowspan=2, sticky=tk.W + tk.E + tk.S + tk.N) btn_closebrace = tk.Button(self.keypad_container, text=")", height=2, width=5, command=lambda: self.on_click_symbol(')')) btn_closebrace.grid(row=3, column=4, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_zero = tk.Button(self.keypad_container, text="0", height=2, width=15, command=lambda: self.on_click_digit('0')) btn_zero.grid(row=4, column=0, padx=(3, 1), pady=(3, 1), columnspan=2, sticky=tk.W + tk.E + tk.S + tk.N) btn_dot = tk.Button(self.keypad_container, text=".", height=2, width=5, command=lambda: self.on_click_digit('.')) btn_dot.grid(row=4, column=2, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) btn_sign = tk.Button(self.keypad_container, text="+/-", height=2, width=5, command=lambda: self.on_click_sign()) btn_sign.grid(row=4, column=4, padx=(3, 1), pady=(3, 1), sticky=tk.W + tk.E + tk.S + tk.N) for i in range(4): self.keypad_container.grid_rowconfigure(i, weight=1) for i in range(4): self.keypad_container.grid_columnconfigure(i, weight=1)
class SSISDeployCheck(QMainWindow, SSISDeploymentChecker_ui.Ui_MainWindow): def __init__(self): QMainWindow.__init__(self) self.setupUi(self) self.reset_app() self.about_window = AboutWindow(self) self.deploy_window = DeployWindow(self) # Custom context Menu self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.treeWidget.customContextMenuRequested.connect(self.showContextMenu) # get any history of combo boxes and reset index self.comboServer.addItems(get_history('servers')) self.comboServer.setCurrentIndex(-1) self.comboFile.addItems(get_history('locals')) self.comboFile.setCurrentIndex(-1) # Set action for clicking About. self.actionAbout.triggered.connect(self.show_about_window) # Set action for closing the app. self.actionExit.triggered.connect(self.close) # Set action for reseting the app. self.actionReset.triggered.connect(self.reset_app) # Set action for clicking browse button self.buttonBrowse.clicked.connect(self.browse_file) # Set action for clicking the compare button self.buttonCompare.clicked.connect(self.compare) # On change of server value, check the connection. self.comboServer.currentIndexChanged.connect( self.check_server_value) self.comboServer.lineEdit().editingFinished.connect( self.check_server_value) # On change of folder value, check the connection. self.comboFile.currentIndexChanged.connect( self.check_folder_value) self.comboFile.lineEdit().editingFinished.connect( self.check_folder_value) self.setFocus() def show_about_window(self): self.about_window.show() def show_deploy_window(self, cmd, source, destination): self.deploy_window.server = self._compare_server sourcefolder = source.split('"')[-2] self.deploy_window.source_path = '\\'.join(sourcefolder.split('\\')[-5:-3]) self.deploy_window.deploy_path = destination.split('"')[-2] self.deploy_window.cmd = cmd self.deploy_window.update_deploy_label() self.deploy_window.show() def showContextMenu(self, position): """Creates a context menu for left click on tree.""" menu = QMenu(self) copy = QAction('Copy', self) deploy = QAction('Deploy', self) no_deploy = QAction('No local to deploy', self) menu.addAction(copy) # Add deploy option if left click is on valid Project node. current = self.treeWidget.currentItem() if not current.parent(): menu.addSeparator() if current.text(1) != 'No local copy found': menu.addAction(deploy) else: menu.addAction(no_deploy) copy.triggered.connect(self.copy_text) deploy.triggered.connect(self.deploy_project) menu.popup(self.treeWidget.mapToGlobal(position)) def deploy_project(self, project): """Starts window to deploy the project to the given server.""" deploy_wizard = find_deployment_exe() if not deploy_wizard: QMessageBox.critical(self, "Deploy Error", 'No Deploy Wizard installed. Check your SQL installation.') return project = self.treeWidget.currentItem() project_details = [x for x in self._projects if x.name == project.text(0)][0] # Source Path fmt = '/SourcePath:"{}" ' ispac_file = project_details.path.replace('\\obj\\','\\bin\\') ispac_file = ispac_file.replace('.dtproj','.ispac') if not os.path.isfile(ispac_file): QMessageBox.critical(self, "Deploy Error", 'No valid ispac file found to deploy.') return source_path = fmt.format(ispac_file) # Destination Server fmt = '/DestinationServer:"{}" ' dest_server = fmt.format(self._compare_server) # Destination Path fmt = '/DestinationPath:"/{a[0]}/{a[1]}/{a[2]}" ' dest_path = fmt.format(a = ['SSISDB', project_details.folder, project_details.name]) # Command Line cmd_line = ' '.join(['"{}"'.format(deploy_wizard), '/Silent ', source_path, dest_server, dest_path]) #QMessageBox.information(self, "Deploy", 'Can Deploy to:\n{}'.format( # cmd_line)) self.show_deploy_window(cmd_line, source_path, dest_path) def copy_text(self): """Copies the selected text from the tree.""" try: current_item = self.treeWidget.currentItem()#.text(0) except: return # Lowest level of tree if current_item.childCount() == 0: text = current_item.text(0) # Second level of tree. elif current_item.parent(): text = '{} - {}'.format(current_item.parent().text(0), current_item.text(0)) for n in range(current_item.childCount()): text += '\n\t{}'.format(current_item.child(n).text(0)) else: text = current_item.text(0) for n in range(current_item.childCount()): text += '\n{}'.format(current_item.child(n).text(0)) for n1 in range(current_item.child(n).childCount()): text += '\n\t{}'.format( current_item.child(n).child(n1).text(0)) pyperclip.copy(text) def compare(self): """Compares the local project against the deployed project.""" ## if license_check(): ## QMessageBox.critical(self, "Expired", 'No longer available.') ## return # Check the server is valid if self._current_server == '' or not self._projects: QMessageBox.warning(self, "Warning", 'Please select a valid server.') return # Check that the folder is valid. if not os.path.isdir(self._current_folder): QMessageBox.warning(self, "Warning", 'Please select a valid folder.') return # Get dtproj files local_projects = lp.find_obj_path(self._current_folder) if not local_projects: QMessageBox.warning(self, "Warning", 'No project files found. Check folder and try again.') return # Match up the local project to server project. local_project_files = {x:os.path.basename(x) for x in local_projects} project_matches = {p:[k for k,v in local_project_files.items() if p.name == v.split('.')[0]] for p in self._projects} duplicates = check_dupes(project_matches) if duplicates: message = 'The following projects have mulitple local versions - ' message += '{}/n'.format('\t\n'.join(duplicates)) message += 'Please check the folder you selected and try again.' QMessageBox.warning(self,message) return # Add path to server_projects self.append_project_path(project_matches) # Show message to confirm projects are being compared and set projects project_matches = self.projects_to_compare(project_matches) # Reset the tree view ahead of the reload. self.reset_tree() # Compare the packages between the server local for server_project, local_file in sorted( project_matches.items(), key=lambda x: x[0].name): if local_file: compares = deploy_check.main(self._connection, server_project.name, local_file[0]) self.add_to_tree(server_project, compares) else: self.add_to_tree(server_project, None, no_local=True) # Add the successful server and folder to the history to be used again. self.add_server_history() self.add_folder_history() self._compare_server = self._current_server self.treeWidget.show() def append_project_path(self, local_projects): """Appends the local path to the project if available.""" for project in self._projects: project.append_path({k.name:v[0] for k,v in local_projects.items() if v}) def add_to_tree(self, server_project, compares, no_local = False): """Adds a new trunk to the tree view for that particular project.""" project_item = QTreeWidgetItem(self.treeWidget) project_item.setText(0,server_project.name) project_item.setToolTip(0,server_project.last_deploy()) if no_local: project_item.setIcon(0,self.error_icon) project_item.setText(1,'No local copy found') return if not compares: project_item.setIcon(0,self.success_icon) project_item.setText(1,'Projects in Sync') return project_item.setIcon(0,self.project_icon) for comp_type, packages in [(k,v) for k,v in sorted(compares.items(), key=lambda x: x[0]) if v]: folder_item = QTreeWidgetItem(project_item) folder_item.setText(0,comp_type[2:]) folder_item.setIcon(0,self.folder_icon) folder_item.setToolTip(0, self.tool_tips[comp_type]) for package in packages: package_item = QTreeWidgetItem(folder_item) package_item.setText(0,package[0]) package_item.setIcon(0,self.package_icon) if comp_type == '2.No Local Version': package_item.setText(2,str(package[1])) elif comp_type == '1.No Server Version': package_item.setText(1,str(package[1])) else: package_item.setText(1,str(package[1])) package_item.setText(2,str(package[2])) package_item.setIcon(0,self.package_icon) def projects_to_compare(self, projects): """Show message to confirm projects are being compared and set projects.""" project = self.comboProject.currentText() if project in ['', 'All']: message = ('Comparing all projects on {} to local copy {}'.format( self._current_server, self._current_folder)) self.statusbar.showMessage(message) else: message = ("Comparing '{}' project on {} to local copy {}".format( project, self._current_server, self._current_folder)) self.statusbar.showMessage(message) projects = {k:v for k,v in projects.items() if k.name == project} return projects def check_server_value(self): """Checks the value of the server box and checks the connection.""" if not self.comboServer.currentText(): self.server_neutral() return new_value = self.comboServer.currentText() if self._current_server != new_value: self._current_server = new_value self._connection = check_server(self._current_server) self.statusbar.showMessage('finally here') if self._connection and type(self._connection) != str: self.successful_server() else: self.server_failure( self._connection if self._connection else 'Unable to connect to SSISDB') self._connection = None self.clear_projects() def successful_server(self): """Shows a successful connection to get projects.""" self.server_success() #self.add_server_history() self.set_projects() def set_projects(self): self._projects = server.get_projects(self._connection) if self._projects: message = 'Projects: %s' %(', '.join( [x.name for x in self._projects])) self.add_projects() self.statusbar.showMessage(message) else: self.statusbar.showMessage('No projects found on server.') def add_projects(self): """Adds projects to project drop down.""" items = ['All'] + [x.name for x in self._projects] self.comboProject.clear() self.comboProject.addItems(items) self.comboProject.show() def clear_projects(self): """Clears project drop down.""" self._projects = [] self.comboProject.clear() self.comboProject.hide() def add_server_history(self): """Adds to the existing history if server is successfully searched.""" current_text = self.comboServer.currentText() all_items = [self.comboServer.itemText(i) for i in range(self.comboServer.count())] if (current_text not in all_items): self.comboServer.addItem(current_text) add_history(current_text, all_items, 'servers') def check_folder_value(self): """Checks the value of the folder is a real directory.""" if not self.comboFile.currentText(): self.folder_neutral() return new_value = self.comboFile.currentText() if self._current_folder != new_value: self._current_folder = new_value if os.path.isdir(new_value): self.folder_success() #self.add_folder_history() else: self.folder_failure('The folder does not exist.') def check_folder(self): """Checks if the folder exists.""" if os.path.isdir(self._current_folder): self.folder_success() self.add_folder_history() else: self.folder_failure('The folder does not exist.') def add_folder_history(self): """Adds to the existing history if folder exists.""" current_text = self.comboFile.currentText() all_items = [self.comboFile.itemText(i) for i in range(self.comboFile.count())] if (current_text not in all_items): self.comboFile.addItem(current_text) add_history(current_text, all_items, 'locals') def reset_app(self): """Sets application back to start position.""" self.comboServer.setCurrentIndex(-1) self.comboFile.setCurrentIndex(-1) self.setFocus() self.reset_tree() self.comboProject.hide() self._current_server = '' self._current_folder = '' self._compare_server = '' self._connection = None self._projects = [] self.comboProject.hide() self.treeWidget.hide() def reset_tree(self): """Clears the tree view and hides from window.""" self.treeWidget.clear() self.treeWidget.hide() def browse_file(self): """Shows directory explorer to pick a folder.""" start_folder = (self._current_folder if self._current_folder != '' else 'C:\\') self._current_folder = str(QFileDialog.getExistingDirectory(self, "Select Directory", start_folder)) self.comboFile.lineEdit().setText( QDir.toNativeSeparators(self._current_folder)) self.check_folder()