def getPasswordsAlert(self): self.dialog = QDialog() self.dialog.setWindowIcon(QIcon('images/icon.ico')) self.dialog.setWindowTitle("Login Details") self.dialog.setStyleSheet("background-color: rgb(69,90,100);") self.dialog.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowContextHelpButtonHint) mainLayout = QVBoxLayout(self.dialog) loginHeadLayout = QVBoxLayout() loginHeadLayout.setContentsMargins(25, 25, 25, 25) loginHeadLayout.addStretch() loginHeadLayout.setSpacing(0) loginLabel = ImageLable("images/tick.png", " Login Credentials") loginLabel.setWhatsThis( "To use the application we need to access the FTP directories & the database you set up" ) loginLabel.setStyleSheet( "background-color: rgb(0,188,212);font-size:16px;") loginLabel.setContentsMargins(25, 25, 25, 25) loginHeadLayout.addWidget(loginLabel.getWidget()) detailsFrame = QFrame() detailsFrame.setContentsMargins(25, 25, 25, 25) detailsLayout = QVBoxLayout() detailsLayout.setSpacing(10) self.databasePasswordField = IconLineEdit('./images/key.png', "Database Password", True) detailsLayout.addWidget(self.databasePasswordField.getWidget()) self.ftpPasswordField = IconLineEdit('./images/key.png', "FTP Password", True) detailsLayout.addWidget(self.ftpPasswordField.getWidget()) loginButton = QPushButton("Login") loginButton.setObjectName("loginButton") loginButton.setStyleSheet( "background-color: rgb(0,188,212); font-size:16px;") loginButton.clicked.connect(self.closeWindow) detailsLayout.addWidget(loginButton) settingsButton = QPushButton("Edit Settings") settingsButton.setObjectName("loginButton") settingsButton.setStyleSheet( "background-color: rgb(192,192,192); font-size:16px;") settingsButton.clicked.connect(self.initialiseSettings) detailsLayout.addWidget(settingsButton) detailsFrame.setLayout(detailsLayout) detailsFrame.setStyleSheet( "border: 1px solid black; background-color: rgb(96,125,139);") loginHeadLayout.addWidget(detailsFrame) mainLayout.addLayout(loginHeadLayout) self.dialog.setAttribute(Qt.WA_DeleteOnClose) self.dialog.exec_()
def maintenanceUI(self, window): try: verticalContainer = QVBoxLayout() verticalContainer.setObjectName("verticalContainer") #layout for top bar topBarLayout = getTopBarLayout(self, window) verticalContainer.addLayout(topBarLayout) innerContainerFrame = QFrame() innerContainer = QHBoxLayout() #layout for login detail section commitDetailsLayout = QVBoxLayout() commitDetailsFrame = QFrame() self.openFileButton = QPushButton("Select File") self.openFileButton.setWhatsThis( "Select the file you're going to compare/push") self.openFileButton.setObjectName("openFile") self.openFileButton.setStyleSheet( "background-color: rgb(255,255,255); font-size:16px;") self.openFileButton.clicked.connect(self.openExplorer) commitDetailsLayout.addWidget(self.openFileButton) #spacing spacing = QLabel() spacing.setText("") spacing.setStyleSheet( "background-color: rgb(96,125,139); border: 1px solid rgb(96,125,139);" ) commitDetailsLayout.addWidget(spacing) self.commitTitle = IconLineEdit('./images/file.png', "Commit Title", False) self.commitTitle.setWhatsThis( "Choose a suitable title to give to the commit you're making") commitDetailsLayout.addWidget(self.commitTitle.getWidget()) self.commitDescription = QTextEdit() self.commitDescription.setWhatsThis( "Choose a suitable description to give to the commit you're making" ) self.commitDescription.setPlaceholderText("Commit Description...") self.commitDescription.setStyleSheet( "background-color: rgb(255,255,255); font-size:16px;") commitDetailsLayout.addWidget(self.commitDescription) addToRepoButton = QPushButton("Add to Repository") addToRepoButton.setObjectName("openFile") addToRepoButton.setWhatsThis( "Click this to push the file you selected to the chosen timeline" ) addToRepoButton.setStyleSheet( "background-color: rgb(0,188,212); font-size:16px;") addToRepoButton.clicked.connect(self.startPush) commitDetailsLayout.addWidget(addToRepoButton) commitDetailsFrame.setFixedWidth(200) commitDetailsFrame.setStyleSheet( "border: 1px solid rgb(96,125,139);") commitDetailsFrame.setLayout(commitDetailsLayout) innerContainer.addWidget(commitDetailsFrame) #bar to seperate 2 side lineLayout = QVBoxLayout() lineFrame = QFrame() lineFrame.setLayout(lineLayout) lineFrame.setStyleSheet( "background-color: rgb(0,188,212); border: 1px solid rgb(96,125,139);" ) lineFrame.setFixedWidth(10) innerContainer.addWidget(lineFrame) #Config comparison layout configLayout = QVBoxLayout() self.selectedConfig = QComboBox() self.selectedConfig.setWhatsThis( "This is a list of all the configs made to the devices you've deployed on this application" ) self.selectedConfig.setStyleSheet(getComboxboxStyle()) self.selectedConfig.activated.connect(self.getFileHistory) configLayout.addWidget(self.selectedConfig) self.startGrabber() #grab files from database self.whatsAdded = QTextEdit() self.whatsAdded.setWhatsThis( "This will show you what has been added to the file you've selected compared to what's on record" ) self.whatsAdded.setPlaceholderText("What's been added") self.whatsAdded.setReadOnly(True) self.whatsAdded.setStyleSheet( "QTextEdit {background-color: rgb(255,255,255); font-size:16px; color:green}" + getVerticalScrollStyle()) configLayout.addWidget(self.whatsAdded) self.whatsRemoved = QTextEdit() self.whatsRemoved.setWhatsThis( "This will show you what has been removed from the file that's on record" ) self.whatsRemoved.setPlaceholderText("What's been removed") self.whatsRemoved.setReadOnly(True) self.whatsRemoved.setStyleSheet( "QTextEdit {background-color: rgb(255,255,255); font-size:16px; color:red}" + getVerticalScrollStyle()) configLayout.addWidget(self.whatsRemoved) innerContainer.addLayout(configLayout) # Commit dot layout commitDotHeadingFrame = QFrame() commitDotHeadingFrame.setFixedWidth(250) commitDotHeadingFrame.setStyleSheet( "border: 1px solid rgb(96,125,139);") commitDotHeading = QVBoxLayout() commitDotHeading.setContentsMargins(0, 0, 0, 0) commitDotHeading.setSpacing(0) heading = QLabel() heading.setText("Commits") heading.setWhatsThis( "This will list out the timeline of commits made to files over time" ) heading.setStyleSheet( "background-color: rgb(0,188,212); font-size:12px;") commitDotHeading.addWidget(heading) self.commitDotLayout = QVBoxLayout() dot = QRadioButton() dot.setText("Commits Appear Here") dot.setStyleSheet("border: 1px solid rgb(96,125,139);") self.commitDotLayout.addWidget(dot) self.dots.append(dot) self.commitDotFrame = QFrame() self.commitDotFrame.setFixedWidth(230) self.commitDotFrame.setContentsMargins(0, 0, 0, 0) self.commitDotFrame.setStyleSheet( "border: 1px solid rgb(96,125,139);") self.commitDotFrame.setLayout(self.commitDotLayout) self.scrollArea = QScrollArea() self.scrollArea.setWidget(self.commitDotFrame) self.scrollArea.setStyleSheet(getHorizontalScrollStyle() + getVerticalScrollStyle()) commitDotHeading.addWidget(self.scrollArea) commitDotHeadingFrame.setLayout(commitDotHeading) innerContainer.addWidget(commitDotHeadingFrame) #entire inner window file config to layout innerContainerFrame.setLayout(innerContainer) innerContainerFrame.setStyleSheet( "background-color: rgb(96,125,139); border: 1px solid black; font-size:16px; " ) innerContainerEffect = QGraphicsDropShadowEffect() innerContainerEffect.setBlurRadius(15) innerContainerFrame.setGraphicsEffect(innerContainerEffect) verticalContainer.addWidget(innerContainerFrame) self.layout.setLayout(verticalContainer) self.canUseCombobox = True self.getFileHistory() except Exception as e: print(str(e))
class LoginManager(): def __init__(self, passwordManager): super(LoginManager, self).__init__() self.passwordManager = passwordManager self.dialog = None self.databasePasswordField = None self.ftpPasswordField = None self.passwordsEntered = False self.wantsSettings = False def getPasswordsAlert(self): self.dialog = QDialog() self.dialog.setWindowIcon(QIcon('images/icon.ico')) self.dialog.setWindowTitle("Login Details") self.dialog.setStyleSheet("background-color: rgb(69,90,100);") self.dialog.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowContextHelpButtonHint) mainLayout = QVBoxLayout(self.dialog) loginHeadLayout = QVBoxLayout() loginHeadLayout.setContentsMargins(25, 25, 25, 25) loginHeadLayout.addStretch() loginHeadLayout.setSpacing(0) loginLabel = ImageLable("images/tick.png", " Login Credentials") loginLabel.setWhatsThis( "To use the application we need to access the FTP directories & the database you set up" ) loginLabel.setStyleSheet( "background-color: rgb(0,188,212);font-size:16px;") loginLabel.setContentsMargins(25, 25, 25, 25) loginHeadLayout.addWidget(loginLabel.getWidget()) detailsFrame = QFrame() detailsFrame.setContentsMargins(25, 25, 25, 25) detailsLayout = QVBoxLayout() detailsLayout.setSpacing(10) self.databasePasswordField = IconLineEdit('./images/key.png', "Database Password", True) detailsLayout.addWidget(self.databasePasswordField.getWidget()) self.ftpPasswordField = IconLineEdit('./images/key.png', "FTP Password", True) detailsLayout.addWidget(self.ftpPasswordField.getWidget()) loginButton = QPushButton("Login") loginButton.setObjectName("loginButton") loginButton.setStyleSheet( "background-color: rgb(0,188,212); font-size:16px;") loginButton.clicked.connect(self.closeWindow) detailsLayout.addWidget(loginButton) settingsButton = QPushButton("Edit Settings") settingsButton.setObjectName("loginButton") settingsButton.setStyleSheet( "background-color: rgb(192,192,192); font-size:16px;") settingsButton.clicked.connect(self.initialiseSettings) detailsLayout.addWidget(settingsButton) detailsFrame.setLayout(detailsLayout) detailsFrame.setStyleSheet( "border: 1px solid black; background-color: rgb(96,125,139);") loginHeadLayout.addWidget(detailsFrame) mainLayout.addLayout(loginHeadLayout) self.dialog.setAttribute(Qt.WA_DeleteOnClose) self.dialog.exec_() def initialiseSettings(self): self.wantsSettings = True self.dialog.close() # when closing the window, check if the passwords are legal ones and if so then allow us to continue def closeWindow(self): tmpDbPassword = self.databasePasswordField.text() tmpFtpPassword = self.ftpPasswordField.text() if checkDatabaseConnection(tmpDbPassword): if checkFTPConnection(tmpFtpPassword): self.passwordManager.setDatabasePassword( self.databasePasswordField.text()) self.passwordManager.setFtpPassword( self.ftpPasswordField.text()) self.passwordsEntered = True self.dialog.close() else: messageWindow( "FTP: Connection Error", "Error raised when connecting to FTP, please check your details and try again", True) self.databasePasswordField.setText("") self.ftpPasswordField.setText("") else: messageWindow( "Database: Connection Error", "Error raised when connecting to Database server, please check your details and try again", True) self.databasePasswordField.setText("") self.ftpPasswordField.setText("")
class MaintenanceModule: def __init__(self, window, layout): self.window = window self.layout = layout self.blocked = False self.fileToPush = None self.pulledFilesContents = None self.fileToPull = None self.canUseCombobox = False # ensures combo box doesn't fire when not wanted self.confFiles = None self.currentFilesHistory = None self.dots = [] self.filesLinkedToDots = [] self.ftpPassword = window.passwordManager.getFtpPassword() self.databasePassword = window.passwordManager.getDatabasePassword() self.changed = None self.removed = None # Creating the maintenance window GUI def maintenanceUI(self, window): try: verticalContainer = QVBoxLayout() verticalContainer.setObjectName("verticalContainer") #layout for top bar topBarLayout = getTopBarLayout(self, window) verticalContainer.addLayout(topBarLayout) innerContainerFrame = QFrame() innerContainer = QHBoxLayout() #layout for login detail section commitDetailsLayout = QVBoxLayout() commitDetailsFrame = QFrame() self.openFileButton = QPushButton("Select File") self.openFileButton.setWhatsThis( "Select the file you're going to compare/push") self.openFileButton.setObjectName("openFile") self.openFileButton.setStyleSheet( "background-color: rgb(255,255,255); font-size:16px;") self.openFileButton.clicked.connect(self.openExplorer) commitDetailsLayout.addWidget(self.openFileButton) #spacing spacing = QLabel() spacing.setText("") spacing.setStyleSheet( "background-color: rgb(96,125,139); border: 1px solid rgb(96,125,139);" ) commitDetailsLayout.addWidget(spacing) self.commitTitle = IconLineEdit('./images/file.png', "Commit Title", False) self.commitTitle.setWhatsThis( "Choose a suitable title to give to the commit you're making") commitDetailsLayout.addWidget(self.commitTitle.getWidget()) self.commitDescription = QTextEdit() self.commitDescription.setWhatsThis( "Choose a suitable description to give to the commit you're making" ) self.commitDescription.setPlaceholderText("Commit Description...") self.commitDescription.setStyleSheet( "background-color: rgb(255,255,255); font-size:16px;") commitDetailsLayout.addWidget(self.commitDescription) addToRepoButton = QPushButton("Add to Repository") addToRepoButton.setObjectName("openFile") addToRepoButton.setWhatsThis( "Click this to push the file you selected to the chosen timeline" ) addToRepoButton.setStyleSheet( "background-color: rgb(0,188,212); font-size:16px;") addToRepoButton.clicked.connect(self.startPush) commitDetailsLayout.addWidget(addToRepoButton) commitDetailsFrame.setFixedWidth(200) commitDetailsFrame.setStyleSheet( "border: 1px solid rgb(96,125,139);") commitDetailsFrame.setLayout(commitDetailsLayout) innerContainer.addWidget(commitDetailsFrame) #bar to seperate 2 side lineLayout = QVBoxLayout() lineFrame = QFrame() lineFrame.setLayout(lineLayout) lineFrame.setStyleSheet( "background-color: rgb(0,188,212); border: 1px solid rgb(96,125,139);" ) lineFrame.setFixedWidth(10) innerContainer.addWidget(lineFrame) #Config comparison layout configLayout = QVBoxLayout() self.selectedConfig = QComboBox() self.selectedConfig.setWhatsThis( "This is a list of all the configs made to the devices you've deployed on this application" ) self.selectedConfig.setStyleSheet(getComboxboxStyle()) self.selectedConfig.activated.connect(self.getFileHistory) configLayout.addWidget(self.selectedConfig) self.startGrabber() #grab files from database self.whatsAdded = QTextEdit() self.whatsAdded.setWhatsThis( "This will show you what has been added to the file you've selected compared to what's on record" ) self.whatsAdded.setPlaceholderText("What's been added") self.whatsAdded.setReadOnly(True) self.whatsAdded.setStyleSheet( "QTextEdit {background-color: rgb(255,255,255); font-size:16px; color:green}" + getVerticalScrollStyle()) configLayout.addWidget(self.whatsAdded) self.whatsRemoved = QTextEdit() self.whatsRemoved.setWhatsThis( "This will show you what has been removed from the file that's on record" ) self.whatsRemoved.setPlaceholderText("What's been removed") self.whatsRemoved.setReadOnly(True) self.whatsRemoved.setStyleSheet( "QTextEdit {background-color: rgb(255,255,255); font-size:16px; color:red}" + getVerticalScrollStyle()) configLayout.addWidget(self.whatsRemoved) innerContainer.addLayout(configLayout) # Commit dot layout commitDotHeadingFrame = QFrame() commitDotHeadingFrame.setFixedWidth(250) commitDotHeadingFrame.setStyleSheet( "border: 1px solid rgb(96,125,139);") commitDotHeading = QVBoxLayout() commitDotHeading.setContentsMargins(0, 0, 0, 0) commitDotHeading.setSpacing(0) heading = QLabel() heading.setText("Commits") heading.setWhatsThis( "This will list out the timeline of commits made to files over time" ) heading.setStyleSheet( "background-color: rgb(0,188,212); font-size:12px;") commitDotHeading.addWidget(heading) self.commitDotLayout = QVBoxLayout() dot = QRadioButton() dot.setText("Commits Appear Here") dot.setStyleSheet("border: 1px solid rgb(96,125,139);") self.commitDotLayout.addWidget(dot) self.dots.append(dot) self.commitDotFrame = QFrame() self.commitDotFrame.setFixedWidth(230) self.commitDotFrame.setContentsMargins(0, 0, 0, 0) self.commitDotFrame.setStyleSheet( "border: 1px solid rgb(96,125,139);") self.commitDotFrame.setLayout(self.commitDotLayout) self.scrollArea = QScrollArea() self.scrollArea.setWidget(self.commitDotFrame) self.scrollArea.setStyleSheet(getHorizontalScrollStyle() + getVerticalScrollStyle()) commitDotHeading.addWidget(self.scrollArea) commitDotHeadingFrame.setLayout(commitDotHeading) innerContainer.addWidget(commitDotHeadingFrame) #entire inner window file config to layout innerContainerFrame.setLayout(innerContainer) innerContainerFrame.setStyleSheet( "background-color: rgb(96,125,139); border: 1px solid black; font-size:16px; " ) innerContainerEffect = QGraphicsDropShadowEffect() innerContainerEffect.setBlurRadius(15) innerContainerFrame.setGraphicsEffect(innerContainerEffect) verticalContainer.addWidget(innerContainerFrame) self.layout.setLayout(verticalContainer) self.canUseCombobox = True self.getFileHistory() except Exception as e: print(str(e)) def findLast(self, s, ch): #builds a list of all the occurences of a character list = [ index for index, currentChar in enumerate(s) if currentChar == ch ] #returns the last index return list[-1] # Pull file information form the database & start file comparing def displayFile(self): try: if not self.currentFilesHistory is None: timestampText = "" for i in range(len(self.dots)): if self.dots[i].isChecked(): timestampText = self.dots[i].text() if not "Commit" in timestampText: if not self.fileToPush is None: path = self.currentFilesHistory[timestampText] self.fileToPull = path # thread to compare files thread = FileComparer(self.window) thread.setup(self) thread.trigger.connect(self.updateChanges) thread.start() else: secondaryWindows.messageWindow( "Select File", "Please select a file first to compare them", False) except Exception as e: print(str(e)) # Get file timestamps and the FTP path def getFileHistory(self): if self.canUseCombobox: if not self.confFiles is None: nameList = list(self.confFiles.keys()) nameList.sort() self.startHistoryGrabber( nameList[self.selectedConfig.currentIndex()]) # Compares two configuration files def compareFiles(self): if self.canUseCombobox: self.getContentsOfFile( ) # first get the contents of the selected file if self.fileToPush is None: secondaryWindows.messageWindow( "No local file selected", "Need a local file to compare against", False) return else: try: ''' every line that changes means another has been removed we go through both files and compare them, keeping track of line numbers as we go for readibility ''' changed = [] removed = [] currentFile = self.pulledFilesContents.split("\n") newFile = self.fileToPush lineCount = 1 with open(newFile, 'r', encoding='utf-8') as f: for line in f: line = line.strip("\n") line = line.replace("\\\\", "") if len(currentFile) > 1: for i in range(0, len(currentFile)): if not line == currentFile[i]: changed.append("@" + str(lineCount) + ": " + line) removed.append("@" + str(lineCount) + ": " + currentFile[i]) del currentFile[i] break else: del currentFile[i] break else: changed.append("@" + str(lineCount) + ": " + line) lineCount += 1 if len(currentFile) > 1: for i in range(0, len(currentFile)): removed.append("@" + str(lineCount) + ": " + currentFile[i]) lineCount += 1 # go through and make sure it's not just moved to another line if len(changed) > 1 and len(removed) > 1: i = 0 while i < len(changed): line = changed[i] if len(line) > 1: start = line.index(":") line = line[start + 2:] for j in range(0, len(removed)): if line in removed[j]: del changed[i] del removed[j] i -= 1 break i += 1 self.changed = changed self.removed = removed except Exception as e: print(str(e)) # Checks if changes have been made based on a code passed def updateChanges(self, code): if code == 0 and not self.changed is None and not self.removed is None: self.whatsAdded.setText("") self.whatsRemoved.setText("") if len(self.changed) == 0: self.whatsAdded.append("Nothing Has Been Added!") else: for i in range(0, len(self.changed)): self.whatsAdded.append("+ " + self.changed[i]) if len(self.removed) == 0: self.whatsRemoved.append("Nothing Has Been Removed!") else: for i in range(0, len(self.removed)): self.whatsRemoved.append("- " + self.removed[i]) elif code == 1: secondaryWindows.messageWindow("Error", "Error comparing files", True) # Connect to the database def startDatabaseGrabber(self): # connect to database to pull down primary files thread = DatabaseGrabber(self.window) thread.setup(self, getDatabaseAddress(), getDatabaseUsername(), self.databasePassword, getDatabase()) thread.trigger.connect(self.fillComboBox) thread.start() # Get file timestamps def startHistoryGrabber(self, selectedFile): thread = SelectedFileGrabber(self.window) thread.setup(self, getDatabaseAddress(), getDatabaseUsername(), self.databasePassword, getDatabase(), selectedFile) thread.trigger.connect(self.updateDots) thread.start() # Refreshes the maintenance page def refreshPage(self): self.canUseCombobox = False if self.blocked: secondaryWindows.messageWindow("Process is currently running", "Cannot refresh", False) else: # clear fields self.commitDescription.setText("") self.commitTitle.setText("") self.whatsRemoved.setText("") self.whatsAdded.setText("") self.selectedConfig.clear() self.openFileButton.setText("Select File") self.fileToPush = None self.dots.clear() layout = self.commitDotLayout.layout() self.clearLayout(layout) dot = QRadioButton() dot.setText("Commits Appear Here") dot.setStyleSheet("border: 1px solid rgb(96,125,139);") layout.insertWidget(0, dot) self.dots.append(dot) self.startDatabaseGrabber() self.getFileHistory() # Gets the file from the FTP Server def startGrabber(self): self.selectedConfig.clear() # this is the users first step so get the password if we don't already have it for later # start the database grabber self.startDatabaseGrabber() def fillComboBox(self, code): self.canUseCombobox = False if code == 0 and not self.confFiles == None: # only deal with conf code from deployment class nameList = list(self.confFiles.keys()) nameList.sort() for index in range(len(nameList)): self.selectedConfig.addItem(nameList[index]) elif code == 1: # only deal with conf code from deployment class self.selectedConfig.addItem("None Present") elif code == -1: secondaryWindows.messageWindow( "Error", "An error occured pulling down info from the database, check your details and try again", True) elif self.confFiles == None: secondaryWindows.messageWindow( "Error", "An error occured pulling down info from the database, check your details and try again", True) self.canUseCombobox = True #clears the widgets out of the current layout def clearLayout(self, layout): while layout.count(): # while there are still widgets child = layout.takeAt(0) # take widget if child.widget() is not None: child.widget().deleteLater( ) # if there was one to take then delete it def swapIndexes(self, list, a, b): tmp = list[b] list[b] = list[a] list[a] = tmp def dateLessThan(self, a, b): # is the current year less than the min? if int(a[2]) < int(b[2]): return True # is the current month less than the min? if int(a[1]) < int(b[1]): return True # is the current date less than the min? if int(a[1]) == int(b[1]): if int(a[0]) < int(b[0]): return True return False def timeLessThan(self, a, b): # is the current hour less than the min? if int(a[0]) < int(b[0]): return True # is the current minute less than the min? if int(a[0]) == int(b[0]): if int(a[1]) < int(b[1]): return True # is the current second less than the min? if int(a[1]) == int(b[1]): if float(a[2]) < float(b[2]): return True return False # sort the timestamp list based on date/time def sortTimeStamps(self, timeStamps): if len(timeStamps) == 1: return timeStamps for j in range(0, len(timeStamps)): for i in range(1, len(timeStamps) - j): timeOne = timeStamps[i - 1] spaceIndex = timeOne.index(" ") timeOneDate = timeOne[:spaceIndex] timeOneDateData = timeOne[:spaceIndex].split('-') timeTwo = timeStamps[i] spaceIndex = timeTwo.index(" ") timeTwoDate = timeTwo[:spaceIndex] timeTwoDateData = timeTwo[:spaceIndex].split('-') if self.dateLessThan(timeTwoDateData, timeOneDateData): self.swapIndexes(timeStamps, i, i - 1) #are they the same date? Compare the time elif timeTwoDate == timeOneDate: currentTime = timeTwo[spaceIndex + 1:].split(':') minTime = timeOne[spaceIndex + 1:].split(':') if self.timeLessThan(currentTime, minTime): self.swapIndexes(timeStamps, i, i - 1) return timeStamps def updateDots(self, code): try: #first clear out layout #self.commitDotLayout self.dots.clear() layout = self.commitDotLayout.layout() self.clearLayout(layout) self.scrollArea.setWidgetResizable(True) if code == 0 and not self.currentFilesHistory == None: # only deal with conf code from deployment class historyList = list(self.currentFilesHistory.keys()) historyList = self.sortTimeStamps(historyList) for index in range(0, len(historyList)): dot = QRadioButton() dot.setText(historyList[index]) dot.setStyleSheet("border: 1px solid rgb(96,125,139);") dot.clicked.connect(self.displayFile) layout.insertWidget(0, dot) self.dots.append(dot) elif code == 1: # only deal with conf code from deployment class secondaryWindows.messageWindow( "Error", "An error occured pulling down info from the database, check your details and try again", True) elif self.currentFilesHistory == None: secondaryWindows.messageWindow( "Error", "An error occured pulling down info from the database, check your details and try again", True) except Exception as e: print(str(e)) def getContentsOfFile(self): returnString = StringIO() # IO object to be written to like a file ftpAddress = getFtpAddress() selectedFile = self.fileToPull ftp = FTP(ftpAddress) ftp.login(getFtpUsername(), self.ftpPassword) # write contents of file to object with new lines ftp.retrlines('RETR ' + selectedFile, lambda line: returnString.write(line + '\n')) self.pulledFilesContents = returnString.getvalue() # opens the explorer to get the file specified def openExplorer(self): try: #path returned as tuple though we just want the actual path name, _ = QFileDialog.getOpenFileName( self.window, 'Open File', options=QFileDialog.DontUseNativeDialog) if len(name) < 1: return start = self.findLast(name, "/") + 1 filename = name[start:] extension = filename[len(filename) - 5:] if not ".conf" == extension: secondaryWindows.messageWindow( "Not a configuration file", "Please select a configuration file to push", False) return self.openFileButton.setText(name[start:]) self.fileToPush = name except Exception: secondaryWindows.messageWindow( "Error", "Error parsing file, please ensure " "it's a .conf file with a suitable filename", True) def startPush(self): if not self.blocked: if self.fileToPush is None: secondaryWindows.messageWindow("No File Selected", "Please select a file to push", False) return elif len(self.commitTitle.text()) < 1: secondaryWindows.messageWindow( "No Commit Title", "Please enter a title for your commit", False) return elif len(self.commitDescription.toPlainText()) < 1: secondaryWindows.messageWindow( "No Commit description", "Please enter a description for your commit", False) return selectedTimeline = self.selectedConfig.currentText() #see if they want to commit to that files timeline reply = QMessageBox.question( self.window, 'Confirmation', "Are you sure you want to push to " + selectedTimeline + "'s timeline?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: self.blocked = True thread = RepoInterface(self.window) thread.setup(self) thread.trigger.connect(self.finishedPushingToRepo) thread.start() else: return else: secondaryWindows.messageWindow( "Process is currently running", "There is still a file being pushed", False) def finishedPushingToRepo(self, code): self.blocked = False if code == 0: self.refreshPage() secondaryWindows.messageWindow( "Success!", "Updated the repository successfully", False) else: secondaryWindows.messageWindow( "Error", "Error pushing the files to the repository", False)
def deploymentUI(self, window): try: self.consolePasswordField = IconLineEdit('./images/key.png', "Console Server Password",True) self.consolePasswordField.setWhatsThis("""This is the password for your console server it's required for the application to integrate with devices""") self.initialDevicePassword = IconLineEdit('./images/key.png', "Initial Device Password", True) self.initialDevicePassword.setWhatsThis("""You can choose what the initial password of each device will be, you can change individual device's password later on""") self.fromPortNo = IconLineEdit('./images/from.png', "From Port No.",False) self.fromPortNo.setWhatsThis("This is the FIRST port the devices are plugged into") self.toPortNo = IconLineEdit('./images/to.png', "To Port No.",False) self.toPortNo.setWhatsThis("This is the LAST port the devices are plugged into") self.willCloneToBackup = QCheckBox("Clone to Backup Partition") self.willCloneToBackup.setWhatsThis("If you would like to have each device clone the os to the backup partition then click here, if it's not available on the device then leave this box unchecked") self.osVersions = QComboBox() self.osVersions.setWhatsThis("Use this to select the OS you want to put on each device. it will be copied over from your FTP server to each device") self.fromConfiguration = QComboBox() self.fromConfiguration.setWhatsThis("Choose the FIRST in the list of configurations to apply to the devices") self.toConfiguration = QComboBox() self.fromConfiguration.setWhatsThis("Choose the LAST in the list of configurations to apply to the devices") verticalContainer = QVBoxLayout() verticalContainer.setObjectName("verticalContainer") topBarLayout = getTopBarLayout(self, window) verticalContainer.addLayout(topBarLayout) innerContainer = QHBoxLayout() innerContainer.setContentsMargins(0, 0, 0, 0) innerContainer.setObjectName("innerContainer") loginHeadLayout = QVBoxLayout() loginHeadLayout.addStretch() loginHeadLayout.setSpacing(0) loginLabel = ImageLable("images/hexagon.png", "Device Deployment Information ") loginLabel.setStyleSheet("background-color: rgb(0,188,212);font-size:16px;") loginHeadLayout.addWidget(loginLabel.getWidget()) loginFrame = QFrame() loginDetailsLayout = QGridLayout() loginDetailsLayout.setObjectName("loginDetailsLayout") loginDetailsLayout.setSpacing(36) self.osVersions.setObjectName("self.osVersions") self.osVersions.setStyleSheet(getComboxboxStyle()) # Connect to ftp and get files for updating os self.osVersions.clear() self.osVersions.addItem("Loading") thread = FileGrabber(self.window) thread.setup(self, ".tgz",self.ftpPassword) thread.trigger.connect(self.fillComboBox) thread.start() self.threads.append(thread) loginDetailsLayout.addWidget(self.osVersions, 0, 0, 1, 1) portNoLayout = QGridLayout() portNoLayout.setObjectName("portNoLayout") label = QLabel(" TO ") label.setObjectName("label") label.setStyleSheet("color:white; font-size:16px; border: 1px solid rgb(96,125,139);") portNoLayout.addWidget(label, 0, 1, 1, 1) portNoLayout.addWidget(self.fromPortNo.getWidget(), 0, 0, 1, 1) portNoLayout.addWidget(self.toPortNo.getWidget(), 0, 2, 1, 1) loginDetailsLayout.addLayout(portNoLayout, 1, 0, 1, 1) loginDetailsLayout.addWidget(self.consolePasswordField.getWidget(), 2, 0, 1, 1) loginDetailsLayout.addWidget(self.initialDevicePassword.getWidget(), 3, 0, 1, 1) checkboxLayout = QVBoxLayout() self.willCloneToBackup.setStyleSheet("color:white; font-size:16px; border: 1px solid rgb(96,125,139);") checkboxLayout.addWidget(self.willCloneToBackup) loginDetailsLayout.addLayout(checkboxLayout, 4, 0, 1, 1) configurationRangeFrame = QFrame() configurationRangeFrame.setContentsMargins(10, 1, 10, 1) configurationRangeLayout = QVBoxLayout() configurationRangeLayout.setObjectName("configurationRangeLayout") configurationRangeLayout.setSpacing(10) configurationRangeHeading = QLabel("Inital Configuration Range") configurationRangeHeading.setObjectName("configurationRangeHeading") configurationRangeHeading.setStyleSheet("background-color: rgb(0,188,212); font-size:16px;") configurationRangeLayout.addWidget(configurationRangeHeading) self.fromConfiguration.setObjectName("fromConfiguration") self.fromConfiguration.setStyleSheet(getComboxboxStyle()) self.toConfiguration.setObjectName("toConfiguration") self.toConfiguration.setStyleSheet(getComboxboxStyle()) # connect to ftp and get any files from ftp self.fromConfiguration.clear() self.toConfiguration.clear() self.fromConfiguration.addItem("Loading") self.toConfiguration.addItem("Loading") thread = FileGrabber(self.window) thread.setup(self, ".conf",self.ftpPassword) thread.trigger.connect(self.fillComboBox) thread.start() self.threads.append(thread) configurationRangeLayout.addWidget(self.fromConfiguration) configurationRangeLayout.addWidget(self.toConfiguration) configurationRangeFrame.setLayout(configurationRangeLayout) configurationRangeFrame.setStyleSheet("background-color: white; border: 1px solid black; font-size:16px; ") loginDetailsLayout.addWidget(configurationRangeFrame, 5, 0, 1, 1) loginDetailsLayout.setAlignment(Qt.AlignCenter) deploymentButton = QPushButton("Begin Deployment") deploymentButton.setObjectName("deploymentButton") deploymentButton.setStyleSheet("background-color: rgb(0,188,212); font-size:16px;") deploymentButton.clicked.connect(self.beginDeployment) loginDetailsLayout.addWidget(deploymentButton, 6, 0, 1, 1) displayDbButton = QPushButton("Display Database") displayDbButton.setObjectName("displayDbButton") displayDbButton.setStyleSheet("background-color: rgb(0,188,212); font-size:16px;") displayDbButton.clicked.connect(self.checkDatabase) loginDetailsLayout.addWidget(displayDbButton, 7, 0, 1, 1) loginFrame.setLayout(loginDetailsLayout) loginFrame.setStyleSheet("background-color: rgb(96,125,139); border: 1px solid black; font-size:16px; ") loginEffect = QGraphicsDropShadowEffect() loginEffect.setBlurRadius(15) loginFrame.setGraphicsEffect(loginEffect) loginHeadLayout.addWidget(loginFrame) innerContainer.addLayout(loginHeadLayout) progressBarLayout = QGridLayout() progressBarLayout.setObjectName("progressBarLayout") self.progressBar = QProgressBar() sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.progressBar.sizePolicy().hasHeightForWidth()) self.progressBar.setSizePolicy(sizePolicy) self.progressBar.setProperty("value", 0) self.progressBar.setOrientation(Qt.Vertical) self.progressBar.setInvertedAppearance(True) self.progressBar.setTextVisible(False) self.progressBar.setTextDirection(QProgressBar.TopToBottom) self.progressBar.setObjectName("self.progressBar") self.progressBar.setStyleSheet("QProgressBar::chunk:vertical { background-color: rgb(0,188,212)}") progressBarLayout.addWidget(self.progressBar, 0, 0, 1, 1) progressBarLayout.setContentsMargins(50, 0, 50, 0) innerContainer.addLayout(progressBarLayout) progressTextFrame = QFrame() progressTextLayout = QGridLayout() progressTextLayout.setObjectName("progressTextLayout") progressTextLayout.setSpacing(43) deploymentProgressHeaderLayout = QVBoxLayout() deploymentProgressHeaderLayout.setSpacing(0) deploymentProgressHeaderLayout.addStretch() deploymentProgressHeader = ImageLable('./images/tick.png', "Deployment Progress") deploymentProgressHeader.setObjectName("deploymentProgressHeader") deploymentProgressHeader.setStyleSheet( "background-color: rgb(0,188,212);font-size:16px; height: 20px;") deploymentProgressHeaderLayout.addWidget(deploymentProgressHeader.getWidget()) self.connectedToDevice = QLabel("Connect to the device") self.connectedToDevice.setObjectName("self.connectedToDevice") self.connectedToDevice.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.connectedToDevice, 2, 0, 1, 1) self.loggedIn = QLabel("Log in") self.loggedIn.setObjectName("self.loggedIn") self.loggedIn.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.loggedIn, 3, 0, 1, 1) self.downloadingOS = QLabel("Downloading OS") self.downloadingOS.setObjectName("self.downloadingOS") self.downloadingOS.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.downloadingOS, 4, 0, 1, 1) self.installingOS = QLabel("Installing OS") self.installingOS.setObjectName("self.installingOS") self.installingOS.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.installingOS, 5, 0, 1, 1) self.rebootingDevice = QLabel("Rebooting the device") self.rebootingDevice.setObjectName("self.rebootingDevice") self.rebootingDevice.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.rebootingDevice, 6, 0, 1, 1) self.loggedInAgain = QLabel("Logging into the device") self.loggedInAgain.setObjectName("self.loggedInAgain") self.loggedInAgain.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.loggedInAgain, 7, 0, 1, 1) self.applyingConfig = QLabel("Applying the configuration file") self.applyingConfig.setObjectName("self.applyingConfig") self.applyingConfig.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.applyingConfig, 8, 0, 1, 1) self.rebootingTheDeviceAgain = QLabel("Rebooting the device") self.rebootingTheDeviceAgain.setObjectName("self.rebootingTheDeviceAgain") self.rebootingTheDeviceAgain.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.rebootingTheDeviceAgain, 9, 0, 1, 1) self.deploymentSuccessful = QLabel("Deployment Successful") self.deploymentSuccessful.setObjectName("self.deploymentSuccessful") self.deploymentSuccessful.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.deploymentSuccessful, 10, 0, 1, 1) progressTextFrame.setLayout(progressTextLayout) progressTextFrame.setStyleSheet( "background-color: rgb(96,125,139); border: 1px solid black; font-size:16px; ") progressTextEffect = QGraphicsDropShadowEffect() progressTextEffect.setBlurRadius(15) progressTextFrame.setGraphicsEffect(progressTextEffect) deploymentProgressHeaderLayout.addWidget(progressTextFrame) innerContainer.addLayout(deploymentProgressHeaderLayout) verticalContainer.addLayout(innerContainer) self.layout.setLayout(verticalContainer) except Exception as e: print(str(e))
class DeploymentModule: def __init__(self, window, layout): self.layout = layout self.window = window self.blocked = False self.threads = [] global deploymentWindow deploymentWindow = self self.ftpPassword = window.passwordManager.getFtpPassword() self.databasePassword = window.passwordManager.getDatabasePassword() #PyQt5 GUI setup def deploymentUI(self, window): try: self.consolePasswordField = IconLineEdit('./images/key.png', "Console Server Password",True) self.consolePasswordField.setWhatsThis("""This is the password for your console server it's required for the application to integrate with devices""") self.initialDevicePassword = IconLineEdit('./images/key.png', "Initial Device Password", True) self.initialDevicePassword.setWhatsThis("""You can choose what the initial password of each device will be, you can change individual device's password later on""") self.fromPortNo = IconLineEdit('./images/from.png', "From Port No.",False) self.fromPortNo.setWhatsThis("This is the FIRST port the devices are plugged into") self.toPortNo = IconLineEdit('./images/to.png', "To Port No.",False) self.toPortNo.setWhatsThis("This is the LAST port the devices are plugged into") self.willCloneToBackup = QCheckBox("Clone to Backup Partition") self.willCloneToBackup.setWhatsThis("If you would like to have each device clone the os to the backup partition then click here, if it's not available on the device then leave this box unchecked") self.osVersions = QComboBox() self.osVersions.setWhatsThis("Use this to select the OS you want to put on each device. it will be copied over from your FTP server to each device") self.fromConfiguration = QComboBox() self.fromConfiguration.setWhatsThis("Choose the FIRST in the list of configurations to apply to the devices") self.toConfiguration = QComboBox() self.fromConfiguration.setWhatsThis("Choose the LAST in the list of configurations to apply to the devices") verticalContainer = QVBoxLayout() verticalContainer.setObjectName("verticalContainer") topBarLayout = getTopBarLayout(self, window) verticalContainer.addLayout(topBarLayout) innerContainer = QHBoxLayout() innerContainer.setContentsMargins(0, 0, 0, 0) innerContainer.setObjectName("innerContainer") loginHeadLayout = QVBoxLayout() loginHeadLayout.addStretch() loginHeadLayout.setSpacing(0) loginLabel = ImageLable("images/hexagon.png", "Device Deployment Information ") loginLabel.setStyleSheet("background-color: rgb(0,188,212);font-size:16px;") loginHeadLayout.addWidget(loginLabel.getWidget()) loginFrame = QFrame() loginDetailsLayout = QGridLayout() loginDetailsLayout.setObjectName("loginDetailsLayout") loginDetailsLayout.setSpacing(36) self.osVersions.setObjectName("self.osVersions") self.osVersions.setStyleSheet(getComboxboxStyle()) # Connect to ftp and get files for updating os self.osVersions.clear() self.osVersions.addItem("Loading") thread = FileGrabber(self.window) thread.setup(self, ".tgz",self.ftpPassword) thread.trigger.connect(self.fillComboBox) thread.start() self.threads.append(thread) loginDetailsLayout.addWidget(self.osVersions, 0, 0, 1, 1) portNoLayout = QGridLayout() portNoLayout.setObjectName("portNoLayout") label = QLabel(" TO ") label.setObjectName("label") label.setStyleSheet("color:white; font-size:16px; border: 1px solid rgb(96,125,139);") portNoLayout.addWidget(label, 0, 1, 1, 1) portNoLayout.addWidget(self.fromPortNo.getWidget(), 0, 0, 1, 1) portNoLayout.addWidget(self.toPortNo.getWidget(), 0, 2, 1, 1) loginDetailsLayout.addLayout(portNoLayout, 1, 0, 1, 1) loginDetailsLayout.addWidget(self.consolePasswordField.getWidget(), 2, 0, 1, 1) loginDetailsLayout.addWidget(self.initialDevicePassword.getWidget(), 3, 0, 1, 1) checkboxLayout = QVBoxLayout() self.willCloneToBackup.setStyleSheet("color:white; font-size:16px; border: 1px solid rgb(96,125,139);") checkboxLayout.addWidget(self.willCloneToBackup) loginDetailsLayout.addLayout(checkboxLayout, 4, 0, 1, 1) configurationRangeFrame = QFrame() configurationRangeFrame.setContentsMargins(10, 1, 10, 1) configurationRangeLayout = QVBoxLayout() configurationRangeLayout.setObjectName("configurationRangeLayout") configurationRangeLayout.setSpacing(10) configurationRangeHeading = QLabel("Inital Configuration Range") configurationRangeHeading.setObjectName("configurationRangeHeading") configurationRangeHeading.setStyleSheet("background-color: rgb(0,188,212); font-size:16px;") configurationRangeLayout.addWidget(configurationRangeHeading) self.fromConfiguration.setObjectName("fromConfiguration") self.fromConfiguration.setStyleSheet(getComboxboxStyle()) self.toConfiguration.setObjectName("toConfiguration") self.toConfiguration.setStyleSheet(getComboxboxStyle()) # connect to ftp and get any files from ftp self.fromConfiguration.clear() self.toConfiguration.clear() self.fromConfiguration.addItem("Loading") self.toConfiguration.addItem("Loading") thread = FileGrabber(self.window) thread.setup(self, ".conf",self.ftpPassword) thread.trigger.connect(self.fillComboBox) thread.start() self.threads.append(thread) configurationRangeLayout.addWidget(self.fromConfiguration) configurationRangeLayout.addWidget(self.toConfiguration) configurationRangeFrame.setLayout(configurationRangeLayout) configurationRangeFrame.setStyleSheet("background-color: white; border: 1px solid black; font-size:16px; ") loginDetailsLayout.addWidget(configurationRangeFrame, 5, 0, 1, 1) loginDetailsLayout.setAlignment(Qt.AlignCenter) deploymentButton = QPushButton("Begin Deployment") deploymentButton.setObjectName("deploymentButton") deploymentButton.setStyleSheet("background-color: rgb(0,188,212); font-size:16px;") deploymentButton.clicked.connect(self.beginDeployment) loginDetailsLayout.addWidget(deploymentButton, 6, 0, 1, 1) displayDbButton = QPushButton("Display Database") displayDbButton.setObjectName("displayDbButton") displayDbButton.setStyleSheet("background-color: rgb(0,188,212); font-size:16px;") displayDbButton.clicked.connect(self.checkDatabase) loginDetailsLayout.addWidget(displayDbButton, 7, 0, 1, 1) loginFrame.setLayout(loginDetailsLayout) loginFrame.setStyleSheet("background-color: rgb(96,125,139); border: 1px solid black; font-size:16px; ") loginEffect = QGraphicsDropShadowEffect() loginEffect.setBlurRadius(15) loginFrame.setGraphicsEffect(loginEffect) loginHeadLayout.addWidget(loginFrame) innerContainer.addLayout(loginHeadLayout) progressBarLayout = QGridLayout() progressBarLayout.setObjectName("progressBarLayout") self.progressBar = QProgressBar() sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.progressBar.sizePolicy().hasHeightForWidth()) self.progressBar.setSizePolicy(sizePolicy) self.progressBar.setProperty("value", 0) self.progressBar.setOrientation(Qt.Vertical) self.progressBar.setInvertedAppearance(True) self.progressBar.setTextVisible(False) self.progressBar.setTextDirection(QProgressBar.TopToBottom) self.progressBar.setObjectName("self.progressBar") self.progressBar.setStyleSheet("QProgressBar::chunk:vertical { background-color: rgb(0,188,212)}") progressBarLayout.addWidget(self.progressBar, 0, 0, 1, 1) progressBarLayout.setContentsMargins(50, 0, 50, 0) innerContainer.addLayout(progressBarLayout) progressTextFrame = QFrame() progressTextLayout = QGridLayout() progressTextLayout.setObjectName("progressTextLayout") progressTextLayout.setSpacing(43) deploymentProgressHeaderLayout = QVBoxLayout() deploymentProgressHeaderLayout.setSpacing(0) deploymentProgressHeaderLayout.addStretch() deploymentProgressHeader = ImageLable('./images/tick.png', "Deployment Progress") deploymentProgressHeader.setObjectName("deploymentProgressHeader") deploymentProgressHeader.setStyleSheet( "background-color: rgb(0,188,212);font-size:16px; height: 20px;") deploymentProgressHeaderLayout.addWidget(deploymentProgressHeader.getWidget()) self.connectedToDevice = QLabel("Connect to the device") self.connectedToDevice.setObjectName("self.connectedToDevice") self.connectedToDevice.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.connectedToDevice, 2, 0, 1, 1) self.loggedIn = QLabel("Log in") self.loggedIn.setObjectName("self.loggedIn") self.loggedIn.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.loggedIn, 3, 0, 1, 1) self.downloadingOS = QLabel("Downloading OS") self.downloadingOS.setObjectName("self.downloadingOS") self.downloadingOS.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.downloadingOS, 4, 0, 1, 1) self.installingOS = QLabel("Installing OS") self.installingOS.setObjectName("self.installingOS") self.installingOS.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.installingOS, 5, 0, 1, 1) self.rebootingDevice = QLabel("Rebooting the device") self.rebootingDevice.setObjectName("self.rebootingDevice") self.rebootingDevice.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.rebootingDevice, 6, 0, 1, 1) self.loggedInAgain = QLabel("Logging into the device") self.loggedInAgain.setObjectName("self.loggedInAgain") self.loggedInAgain.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.loggedInAgain, 7, 0, 1, 1) self.applyingConfig = QLabel("Applying the configuration file") self.applyingConfig.setObjectName("self.applyingConfig") self.applyingConfig.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.applyingConfig, 8, 0, 1, 1) self.rebootingTheDeviceAgain = QLabel("Rebooting the device") self.rebootingTheDeviceAgain.setObjectName("self.rebootingTheDeviceAgain") self.rebootingTheDeviceAgain.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.rebootingTheDeviceAgain, 9, 0, 1, 1) self.deploymentSuccessful = QLabel("Deployment Successful") self.deploymentSuccessful.setObjectName("self.deploymentSuccessful") self.deploymentSuccessful.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") progressTextLayout.addWidget(self.deploymentSuccessful, 10, 0, 1, 1) progressTextFrame.setLayout(progressTextLayout) progressTextFrame.setStyleSheet( "background-color: rgb(96,125,139); border: 1px solid black; font-size:16px; ") progressTextEffect = QGraphicsDropShadowEffect() progressTextEffect.setBlurRadius(15) progressTextFrame.setGraphicsEffect(progressTextEffect) deploymentProgressHeaderLayout.addWidget(progressTextFrame) innerContainer.addLayout(deploymentProgressHeaderLayout) verticalContainer.addLayout(innerContainer) self.layout.setLayout(verticalContainer) except Exception as e: print(str(e)) def clearProgressText(self): self.connectedToDevice.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") self.loggedIn.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") self.downloadingOS.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") self.installingOS.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") self.rebootingDevice.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") self.loggedInAgain.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") self.applyingConfig.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") self.rebootingTheDeviceAgain.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") self.deploymentSuccessful.setStyleSheet("color:white; font-size:16px;border: 1px solid rgb(96,125,139);") def updateProgress(self, percentage): self.progressBar.setValue(percentage) if percentage == 11: self.connectedToDevice.setStyleSheet("color:white; font-size:16px;") elif percentage == 22: self.loggedIn.setStyleSheet("color:white; font-size:16px;") elif percentage == 44: self.downloadingOS.setStyleSheet("color:white; font-size:16px;") self.installingOS.setStyleSheet("color:white; font-size:16px;") elif percentage == 55: self.rebootingDevice.setStyleSheet("color:white; font-size:16px;") elif percentage == 66: self.loggedInAgain.setStyleSheet("color:white; font-size:16px;") elif percentage == 77: self.applyingConfig.setStyleSheet("color:white; font-size:16px;") elif percentage == 88: self.rebootingTheDeviceAgain.setStyleSheet("color:white; font-size:16px;") else: self.blocked = False self.deploymentSuccessful.setStyleSheet("color:white; font-size:16px;") # fill appropriate combo box when code from thread is returned def fillComboBox(self, code): # deal with conf or tgz depending on code if code == 0: self.fromConfiguration.clear() self.toConfiguration.clear() for index in range(len(self.confFiles)): self.fromConfiguration.addItem(QIcon("images/from.png"),self.confFiles[index]) self.toConfiguration.addItem(QIcon("images/to.png"),self.confFiles[index]) elif code == 1: self.osVersions.clear() for index in range(len(self.osFiles)): self.osVersions.addItem(QIcon("images/device.png"),self.osFiles[index]) # Refresh current page def refreshPage(self): try: if self.blocked: secondaryWindows.messageWindow("Process is currently running", "Cannot refresh page when units are being updated", False) else: self.fromConfiguration.addItem("Loading") self.toConfiguration.addItem("Loading") self.osVersions.addItem("Loading") self.clearProgressText() self.fromConfiguration.clear() self.toConfiguration.clear() thread = FileGrabber(self.window) thread.setup(self, ".conf",self.ftpPassword) thread.trigger.connect(self.fillComboBox) thread.start() self.threads.append(thread) thread = FileGrabber(self.window) thread.setup(self, ".tgz",self.ftpPassword) thread.trigger.connect(self.fillComboBox) thread.start() self.threads.append(thread) self.initialDevicePassword.setText("") self.consolePasswordField.setText("") self.willCloneToBackup.setChecked(False) self.toPortNo.setText("") self.fromPortNo.setText("") except Exception as e: print(str(e)) secondaryWindows.messageWindow("Error Refreshing", "An error occured clearing page and connecting to FTP server, try again later", True) def checkDatabase(self): if self.blocked: secondaryWindows.messageWindow("Process Running", "You're currently runnning an update, wait till this is finished", True) return if not checkDatabaseConnection(self.databasePassword): secondaryWindows.messageWindow("Database: Connection Error", "Error raised when connecting to Database, please check your details and try again", True) return listing = getDatabaseListing(self.databasePassword) if not listing is None: secondaryWindows.displayDatabaseWindow(listing) elif listing is None: secondaryWindows.messageWindow("Database is empty", "There is no data to pull from your database", False) return elif listing is "Error": secondaryWindows.messageWindow("Database Error", "There was an error pulling data from your database", True) def isNumber(self,s): try: int(s) return True except ValueError: return False # makes sure there is at least one number in the password adn the length is > 6 def checkValidity(self,string): if len(string) < 6: return False for i in range(0,len(string)): if self.isNumber(string[i]): return True elif string[i].isupper(): return True return False def beginDeployment(self): try: # if the window is pressed twice if self.blocked: secondaryWindows.messageWindow("Process running.", "Please wait for deployment to finish.", True) return self.threads.clear() # Make sure fields aren't empty if self.fieldsEmpty(): secondaryWindows.messageWindow("Empty Fields", "Please ensure all the fields are filled", True) return # Make sure both port numbers are actually numbers if (not isNumber(self.toPortNo.text()) or not isNumber(self.fromPortNo.text())): secondaryWindows.messageWindow("Not a Number", "Please ensure ports are numbers", True) return # make sure configurations are the same amount as devices being updated fromConf = self.fromConfiguration.currentIndex() toConf = self.toConfiguration.currentIndex() fromPort = int(self.fromPortNo.text()) toPort = int(self.toPortNo.text()) if not (toConf >= fromConf): secondaryWindows.messageWindow("Config List Error", "Please ensure your starting configuration is before your final configuration", True) return if not ((toConf - fromConf) + 1 == (toPort - fromPort) + 1): secondaryWindows.messageWindow("Not Enough Configs", "Please ensure there are enough config files for each specified device", True) return devicePassword = self.initialDevicePassword.text() if not self.checkValidity(devicePassword): secondaryWindows.messageWindow("Password error", """ Please ensure the password is at least 6 characters and contains either a number or an uppercase letter """, True) return # apply patch patch_crypto_be_discovery() configurationsToUse = [] for index in range(fromConf, toConf + 1): configurationsToUse.append(self.confFiles[index]) willBackup = self.willCloneToBackup.isChecked() OsFile = self.osVersions.currentText() ftpPassword = self.ftpPassword consolePassword = self.consolePasswordField.text() databasePassword = self.databasePassword self.progressBar.setValue(0) # check if connections are accessible if not checkFTPConnection(ftpPassword): secondaryWindows.messageWindow("FTP: Connection Error", "Error raised when connecting to FTP server, please check your details and try again", True) return if not checkConsoleConnection(getConsoleAddress(), getConsoleName(), consolePassword): secondaryWindows.messageWindow("Console Server: Connection Error", "Error raised when connecting to Console server, please check your details and try again", True) return if not checkDatabaseConnection(databasePassword): secondaryWindows.messageWindow("Database: Connection Error", "Error raised when connecting to Database, please check your details and try again", True) return self.blocked = True confIndex = 0 # check to see how many devices we're updating if toPort - fromPort + 1 == 1: thread = Updater(self.window) thread.trigger.connect(self.updateProgress) thread.setup(toPort, ftpPassword, consolePassword, databasePassword, devicePassword,OsFile, configurationsToUse[confIndex], willBackup, True) thread.start() self.threads.append(thread) else: for index in range(fromPort, toPort): thread = Updater(self.window) thread.trigger.connect(self.updateProgress) thread.setup(index, ftpPassword, consolePassword, databasePassword, devicePassword, OsFile, configurationsToUse[confIndex], willBackup, False) thread.start() self.threads.append(thread) confIndex += 1 time.sleep(5) # staggered threads to avoid collision # make final thread the one to update GUI thread = Updater(self.window) thread.trigger.connect(self.updateProgress) thread.setup(toPort, ftpPassword, consolePassword, databasePassword, devicePassword, OsFile, configurationsToUse[confIndex], willBackup, True) thread.start() self.threads.append(thread) except Exception as e: print(str(e)) def fieldsEmpty(self): if len(self.fromPortNo.text()) < 1 or len(self.toPortNo.text()) < 1 or len( self.consolePasswordField.text()) < 1: return True else: return False
def settingsUI(self, window): effect = QGraphicsDropShadowEffect() effect.setBlurRadius(15) settingsVerticalContainer = QVBoxLayout() settingsVerticalContainer.setObjectName("verticalContainer") frame = QFrame() # Layout of top bar topBarLayout = QHBoxLayout() topBarLayout.setObjectName("topBarLayout") topBarLayout.setAlignment(Qt.AlignLeft) backButton = ImageButton(QPixmap("images/back.png")) backButton.setObjectName("backButton") backButton.clicked.connect(window.initialiseLauncher) topBarLayout.addWidget(backButton) frame.setLayout(topBarLayout) settingsVerticalContainer.addWidget(frame) # layout of below 3 boxes innerVerticalLayout = QVBoxLayout() innerVerticalLayout.setContentsMargins(0, 0, 0, 0) innerVerticalLayout.setObjectName("innerVerticalLayout") innerFrame = QFrame() innerContainer = QHBoxLayout() innerContainer.setContentsMargins(0, 0, 0, 0) innerContainer.setObjectName("innerContainer") ftpHeadingLayout = QVBoxLayout() ftpHeadingLayout.setSpacing(0) ftpHeadingLayout.addStretch() ftpConfigLabel = ImageLable('./images/hexagon.png', "FTP Configuration") ftpConfigLabel.setStyleSheet((""" background-color: rgb(0,188,212); font-size:16px; border-top-left-radius: 10px; border-top-right-radius: 10px; """)) ftpHeadingLayout.addWidget(ftpConfigLabel.getWidget()) ftpConfigLayout = QVBoxLayout() ftpConfigLayout.setObjectName("ftpConfigLayout") ftpConfigLayout.setSpacing(40) self.ftpServerAddress = IconLineEdit('./images/device.png', "Server Address", False) self.ftpServerAddress.setWhatsThis( "Input where you're FTP server is located") ftpConfigLayout.addWidget(self.ftpServerAddress.getWidget()) self.ftpUsername = IconLineEdit('./images/user.png', "FTP Username", False) self.ftpUsername.setWhatsThis( "This is your username for the FTP server") ftpConfigLayout.addWidget(self.ftpUsername.getWidget()) self.ftpOsPath = IconLineEdit('./images/device.png', "OS Directory Path", False) self.ftpOsPath.setWhatsThis( "Set the directory in your FTP server for where you keep your .tgz OS files so the application can point to them when deploying devices" ) ftpConfigLayout.addWidget(self.ftpOsPath.getWidget()) self.ftpConfPath = IconLineEdit('./images/device.png', "Configuration Path", False) self.ftpConfPath.setWhatsThis( "Set a directory in your FTP server for new .conf files to be pushed to" ) ftpConfigLayout.addWidget(self.ftpConfPath.getWidget()) self.ftpIniConfPath = IconLineEdit('./images/device.png', "Initial Config Path", False) self.ftpIniConfPath.setWhatsThis( "Set the directory in your FTP server for where you keep your .conf files that have yet to be applied to devices so the application can point to them when deploying devices" ) ftpConfigLayout.addWidget(self.ftpIniConfPath.getWidget()) ftpConfigLabel = QLabel( "*This will be used to push and pull config files for your device as you work" ) ftpConfigLabel.setWordWrap(True) ftpConfigLabel.setStyleSheet( "color: rgb(0,188,212); font-size:16px; background-color: rgb(255,255,255); border: 1px solid white;" ) ftpConfigLayout.addWidget(ftpConfigLabel) ftpFrame = QFrame() ftpFrame.setObjectName("ftpFrame") ftpFrame.setLayout(ftpConfigLayout) ftpFrame.setStyleSheet(""" QFrame#ftpFrame { background-color: rgb(255,255,255); border: 1px solid black; font-size:16px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px } """) ftpFrame.setContentsMargins(25, 0, 25, 5) ftpFrame.setGraphicsEffect(effect) ftpHeadingLayout.addWidget(ftpFrame) innerContainer.addLayout(ftpHeadingLayout) consoleHeadingLayout = QVBoxLayout() consoleHeadingLayout.setSpacing(0) consoleHeadingLayout.addStretch() consoleConfigLabel = ImageLable('./images/hexagon.png', "Console Server Configuration") consoleConfigLabel.setStyleSheet((""" background-color: rgb(0,188,212); font-size:16px; border-top-left-radius: 10px; border-top-right-radius: 10px; """)) consoleHeadingLayout.addWidget(consoleConfigLabel.getWidget()) consoleConfigLayout = QVBoxLayout() consoleConfigLayout.setObjectName("consoleConfigLayout") consoleConfigLayout.setSpacing(146) self.consoleAddress = IconLineEdit('./images/device.png', "Full Console Address", False) self.consoleAddress.setWhatsThis( "Set the address for your console server") consoleConfigLayout.addWidget(self.consoleAddress.getWidget()) self.consoleUsername = IconLineEdit('./images/user.png', "Username", False) self.consoleUsername.setWhatsThis( "Set the username for your console server") consoleConfigLayout.addWidget(self.consoleUsername.getWidget()) consoleConfigLabel = QLabel( "*To allow for bulk updates your console server's info will be required here" ) consoleConfigLabel.setStyleSheet( "color: rgb(0,188,212); font-size:16px; background-color: rgb(255,255,255); border: 1px solid white;" ) consoleConfigLabel.setWordWrap(True) consoleConfigLayout.addWidget(consoleConfigLabel) consoleFrame = QFrame() consoleFrame.setLayout(consoleConfigLayout) consoleFrame.setObjectName("consoleFrame") consoleFrame.setStyleSheet(""" QFrame#consoleFrame { background-color: rgb(255,255,255); border: 1px solid black; font-size:16px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px } """) consoleFrame.setContentsMargins(25, 0, 25, 5) consoleFrame.setGraphicsEffect(effect) consoleHeadingLayout.addWidget(consoleFrame) innerContainer.addLayout(consoleHeadingLayout) datbaseHeadingLayout = QVBoxLayout() datbaseHeadingLayout.setSpacing(0) datbaseHeadingLayout.addStretch() databaseConfigLabel = ImageLable('./images/hexagon.png', "Database Configuration") databaseConfigLabel.setStyleSheet((""" background-color: rgb(0,188,212); font-size:16px; border-top-left-radius: 10px; border-top-right-radius: 10px; """)) datbaseHeadingLayout.addWidget(databaseConfigLabel.getWidget()) databaseConfigLayout = QVBoxLayout() databaseConfigLayout.setObjectName("consoleConfigLayout") databaseConfigLayout.setSpacing(138) self.databseAddress = IconLineEdit('./images/device.png', "Full Database Address", False) self.databseAddress.setWhatsThis("Set the address for your database") databaseConfigLayout.addWidget(self.databseAddress.getWidget()) self.databseUsername = IconLineEdit('./images/user.png', "Username", False) self.databseUsername.setWhatsThis("Set the username for your database") databaseConfigLayout.addWidget(self.databseUsername.getWidget()) databaseConfigLabel = QLabel( "*This database will be used to track updated devices and their config files as you work" ) databaseConfigLabel.setWordWrap(True) databaseConfigLabel.setStyleSheet( "color: rgb(0,188,212); font-size:16px; background-color: rgb(255,255,255); border: 1px solid white;" ) databaseConfigLayout.addWidget(databaseConfigLabel) databaseFrame = QFrame() databaseFrame.setLayout(databaseConfigLayout) databaseFrame.setObjectName("databaseFrame") databaseFrame.setStyleSheet(""" QFrame#databaseFrame{ background-color: rgb(255,255,255); border: 1px solid black; font-size:16px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px } """) databaseFrame.setContentsMargins(25, 0, 25, 5) databaseFrame.setGraphicsEffect(effect) datbaseHeadingLayout.addWidget(databaseFrame) innerContainer.addLayout(datbaseHeadingLayout) innerFrame.setContentsMargins(25, 25, 25, 25) innerFrame.setObjectName("innerFrame") innerFrame.setStyleSheet( "QFrame#innerFrame{ background-color: rgb(96,125,139); border: 1px solid black; font-size:16px} " ) innerVerticalLayout.addLayout(innerContainer) bottomLayout = QHBoxLayout() bottomLayout.setObjectName("bottomLayout") applySettingsButton = QPushButton("Apply Settings") applySettingsButton.setStyleSheet( "background-color: rgb(0,188,212); font-size:16px;") applySettingsButton.clicked.connect(self.applySettings) bottomLayout.addWidget(applySettingsButton) innerVerticalLayout.addLayout(bottomLayout) innerFrame.setLayout(innerVerticalLayout) innerFrame.setGraphicsEffect(effect) settingsVerticalContainer.addWidget(innerFrame) settingsVerticalContainer.addStretch() self.layout.setLayout(settingsVerticalContainer) self.fillSettingsFields()
class SettingsModule: def __init__(self, window, layout): self.window = window self.layout = layout self.restart = False # Setting GUI def settingsUI(self, window): effect = QGraphicsDropShadowEffect() effect.setBlurRadius(15) settingsVerticalContainer = QVBoxLayout() settingsVerticalContainer.setObjectName("verticalContainer") frame = QFrame() # Layout of top bar topBarLayout = QHBoxLayout() topBarLayout.setObjectName("topBarLayout") topBarLayout.setAlignment(Qt.AlignLeft) backButton = ImageButton(QPixmap("images/back.png")) backButton.setObjectName("backButton") backButton.clicked.connect(window.initialiseLauncher) topBarLayout.addWidget(backButton) frame.setLayout(topBarLayout) settingsVerticalContainer.addWidget(frame) # layout of below 3 boxes innerVerticalLayout = QVBoxLayout() innerVerticalLayout.setContentsMargins(0, 0, 0, 0) innerVerticalLayout.setObjectName("innerVerticalLayout") innerFrame = QFrame() innerContainer = QHBoxLayout() innerContainer.setContentsMargins(0, 0, 0, 0) innerContainer.setObjectName("innerContainer") ftpHeadingLayout = QVBoxLayout() ftpHeadingLayout.setSpacing(0) ftpHeadingLayout.addStretch() ftpConfigLabel = ImageLable('./images/hexagon.png', "FTP Configuration") ftpConfigLabel.setStyleSheet((""" background-color: rgb(0,188,212); font-size:16px; border-top-left-radius: 10px; border-top-right-radius: 10px; """)) ftpHeadingLayout.addWidget(ftpConfigLabel.getWidget()) ftpConfigLayout = QVBoxLayout() ftpConfigLayout.setObjectName("ftpConfigLayout") ftpConfigLayout.setSpacing(40) self.ftpServerAddress = IconLineEdit('./images/device.png', "Server Address", False) self.ftpServerAddress.setWhatsThis( "Input where you're FTP server is located") ftpConfigLayout.addWidget(self.ftpServerAddress.getWidget()) self.ftpUsername = IconLineEdit('./images/user.png', "FTP Username", False) self.ftpUsername.setWhatsThis( "This is your username for the FTP server") ftpConfigLayout.addWidget(self.ftpUsername.getWidget()) self.ftpOsPath = IconLineEdit('./images/device.png', "OS Directory Path", False) self.ftpOsPath.setWhatsThis( "Set the directory in your FTP server for where you keep your .tgz OS files so the application can point to them when deploying devices" ) ftpConfigLayout.addWidget(self.ftpOsPath.getWidget()) self.ftpConfPath = IconLineEdit('./images/device.png', "Configuration Path", False) self.ftpConfPath.setWhatsThis( "Set a directory in your FTP server for new .conf files to be pushed to" ) ftpConfigLayout.addWidget(self.ftpConfPath.getWidget()) self.ftpIniConfPath = IconLineEdit('./images/device.png', "Initial Config Path", False) self.ftpIniConfPath.setWhatsThis( "Set the directory in your FTP server for where you keep your .conf files that have yet to be applied to devices so the application can point to them when deploying devices" ) ftpConfigLayout.addWidget(self.ftpIniConfPath.getWidget()) ftpConfigLabel = QLabel( "*This will be used to push and pull config files for your device as you work" ) ftpConfigLabel.setWordWrap(True) ftpConfigLabel.setStyleSheet( "color: rgb(0,188,212); font-size:16px; background-color: rgb(255,255,255); border: 1px solid white;" ) ftpConfigLayout.addWidget(ftpConfigLabel) ftpFrame = QFrame() ftpFrame.setObjectName("ftpFrame") ftpFrame.setLayout(ftpConfigLayout) ftpFrame.setStyleSheet(""" QFrame#ftpFrame { background-color: rgb(255,255,255); border: 1px solid black; font-size:16px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px } """) ftpFrame.setContentsMargins(25, 0, 25, 5) ftpFrame.setGraphicsEffect(effect) ftpHeadingLayout.addWidget(ftpFrame) innerContainer.addLayout(ftpHeadingLayout) consoleHeadingLayout = QVBoxLayout() consoleHeadingLayout.setSpacing(0) consoleHeadingLayout.addStretch() consoleConfigLabel = ImageLable('./images/hexagon.png', "Console Server Configuration") consoleConfigLabel.setStyleSheet((""" background-color: rgb(0,188,212); font-size:16px; border-top-left-radius: 10px; border-top-right-radius: 10px; """)) consoleHeadingLayout.addWidget(consoleConfigLabel.getWidget()) consoleConfigLayout = QVBoxLayout() consoleConfigLayout.setObjectName("consoleConfigLayout") consoleConfigLayout.setSpacing(146) self.consoleAddress = IconLineEdit('./images/device.png', "Full Console Address", False) self.consoleAddress.setWhatsThis( "Set the address for your console server") consoleConfigLayout.addWidget(self.consoleAddress.getWidget()) self.consoleUsername = IconLineEdit('./images/user.png', "Username", False) self.consoleUsername.setWhatsThis( "Set the username for your console server") consoleConfigLayout.addWidget(self.consoleUsername.getWidget()) consoleConfigLabel = QLabel( "*To allow for bulk updates your console server's info will be required here" ) consoleConfigLabel.setStyleSheet( "color: rgb(0,188,212); font-size:16px; background-color: rgb(255,255,255); border: 1px solid white;" ) consoleConfigLabel.setWordWrap(True) consoleConfigLayout.addWidget(consoleConfigLabel) consoleFrame = QFrame() consoleFrame.setLayout(consoleConfigLayout) consoleFrame.setObjectName("consoleFrame") consoleFrame.setStyleSheet(""" QFrame#consoleFrame { background-color: rgb(255,255,255); border: 1px solid black; font-size:16px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px } """) consoleFrame.setContentsMargins(25, 0, 25, 5) consoleFrame.setGraphicsEffect(effect) consoleHeadingLayout.addWidget(consoleFrame) innerContainer.addLayout(consoleHeadingLayout) datbaseHeadingLayout = QVBoxLayout() datbaseHeadingLayout.setSpacing(0) datbaseHeadingLayout.addStretch() databaseConfigLabel = ImageLable('./images/hexagon.png', "Database Configuration") databaseConfigLabel.setStyleSheet((""" background-color: rgb(0,188,212); font-size:16px; border-top-left-radius: 10px; border-top-right-radius: 10px; """)) datbaseHeadingLayout.addWidget(databaseConfigLabel.getWidget()) databaseConfigLayout = QVBoxLayout() databaseConfigLayout.setObjectName("consoleConfigLayout") databaseConfigLayout.setSpacing(138) self.databseAddress = IconLineEdit('./images/device.png', "Full Database Address", False) self.databseAddress.setWhatsThis("Set the address for your database") databaseConfigLayout.addWidget(self.databseAddress.getWidget()) self.databseUsername = IconLineEdit('./images/user.png', "Username", False) self.databseUsername.setWhatsThis("Set the username for your database") databaseConfigLayout.addWidget(self.databseUsername.getWidget()) databaseConfigLabel = QLabel( "*This database will be used to track updated devices and their config files as you work" ) databaseConfigLabel.setWordWrap(True) databaseConfigLabel.setStyleSheet( "color: rgb(0,188,212); font-size:16px; background-color: rgb(255,255,255); border: 1px solid white;" ) databaseConfigLayout.addWidget(databaseConfigLabel) databaseFrame = QFrame() databaseFrame.setLayout(databaseConfigLayout) databaseFrame.setObjectName("databaseFrame") databaseFrame.setStyleSheet(""" QFrame#databaseFrame{ background-color: rgb(255,255,255); border: 1px solid black; font-size:16px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px } """) databaseFrame.setContentsMargins(25, 0, 25, 5) databaseFrame.setGraphicsEffect(effect) datbaseHeadingLayout.addWidget(databaseFrame) innerContainer.addLayout(datbaseHeadingLayout) innerFrame.setContentsMargins(25, 25, 25, 25) innerFrame.setObjectName("innerFrame") innerFrame.setStyleSheet( "QFrame#innerFrame{ background-color: rgb(96,125,139); border: 1px solid black; font-size:16px} " ) innerVerticalLayout.addLayout(innerContainer) bottomLayout = QHBoxLayout() bottomLayout.setObjectName("bottomLayout") applySettingsButton = QPushButton("Apply Settings") applySettingsButton.setStyleSheet( "background-color: rgb(0,188,212); font-size:16px;") applySettingsButton.clicked.connect(self.applySettings) bottomLayout.addWidget(applySettingsButton) innerVerticalLayout.addLayout(bottomLayout) innerFrame.setLayout(innerVerticalLayout) innerFrame.setGraphicsEffect(effect) settingsVerticalContainer.addWidget(innerFrame) settingsVerticalContainer.addStretch() self.layout.setLayout(settingsVerticalContainer) self.fillSettingsFields() # Set placeholder text def fillSettingsFields(self): try: with open("Settings.xml") as file: settingsDict = xmltodict.parse(file.read()) self.ftpServerAddress.setText( settingsDict['Settings']['Ftp-Info']['ftpServerAddress']) self.ftpUsername.setText( settingsDict['Settings']['Ftp-Info']['ftpUsername']) self.ftpOsPath.setText( settingsDict['Settings']['Ftp-Info']['ftpOsPath']) self.ftpConfPath.setText( settingsDict['Settings']['Ftp-Info']['ftpConfPath']) self.ftpIniConfPath.setText( settingsDict['Settings']['Ftp-Info']['ftpIniConfPath']) self.consoleAddress.setText( settingsDict['Settings']['Console-Info']['consoleAddress']) self.consoleUsername.setText( settingsDict['Settings']['Console-Info']['consoleUsername']) self.databseAddress.setText( settingsDict['Settings']['Database-Info']['databseAddress']) self.databseUsername.setText( settingsDict['Settings']['Database-Info']['databseUsername']) file.close() return True except: return False # Check if all settings fiels have been filled def allSettingsFieldsFilled(self): if len(self.ftpServerAddress.text()) < 1 \ or len(self.ftpUsername.text()) < 1 \ or len(self.ftpOsPath.text()) < 1 \ or len(self.ftpConfPath.text()) < 1 \ or len(self.ftpIniConfPath.text()) < 1 \ or len(self.consoleAddress.text()) < 1 \ or len(self.consoleUsername.text()) < 1 \ or len(self.databseAddress.text()) < 1 \ or len(self.databseUsername.text()) < 1: return False else: return True # Save settings fields to a xml file def applySettings(self): if self.allSettingsFieldsFilled(): try: #settings are saved in xml file settings_file = open("Settings.xml", "w") #ensure paths are "legal" osPath = self.makeLegalPath(self.ftpOsPath.text()) confPath = self.makeLegalPath(self.ftpConfPath.text()) iniconfPath = self.makeLegalPath(self.ftpIniConfPath.text()) #construct dict to be translated into xml dict = { 'Settings': { 'Ftp-Info': { 'ftpServerAddress': self.ftpServerAddress.text(), 'ftpUsername': self.ftpUsername.text(), 'ftpOsPath': osPath, 'ftpConfPath': confPath, 'ftpIniConfPath': iniconfPath }, 'Console-Info': { 'consoleAddress': self.consoleAddress.text(), 'consoleUsername': self.consoleUsername.text() }, 'Database-Info': { 'databseAddress': self.databseAddress.text(), 'databseUsername': self.databseUsername.text() } } } #convert dict xml = xmltodict.unparse(dict, pretty=True) #write dict to file settings_file.write(xml) settings_file.close() #alert user to success if self.window.notSetup: heading = "Settings Saved! Restarting in 3...." message = "Your Settings are saved, The programme will restart and reload the changes" self.restart = True else: heading = "Settings Saved!" message = "Your Settings are saved" secondaryWindows.messageWindow(heading, message, False) if self.window.notSetup: time.sleep(3) self.window.close() else: self.window.initialiseLauncher() #catch any exceptions when writing to file and cope gracefully except Exception as e: secondaryWindows.messageWindow( "An Error Occured", "There was an error saving your settings the details are as follows: \n " + str(e), True) else: secondaryWindows.messageWindow( "Empty Fields", "Please fill in all fields provided", True) #Ensure that the paths being put in are legal (ie. slash at the start and end) def makeLegalPath(self, path): if "/" in path[0] and "/" in path[len(path) - 1]: return path elif "/" in path[0]: return path + "/" elif "/" in path[len(path) - 1]: return "/" + path else: return "/" + path + "/"