class FileSelector(Selector): def __init__(self, main, *args, **kwargs): super().__init__(*args, **kwargs) self.main = main self.current_path = '' label = QLabel('Виберіть файл ключа', self) label.move(6, 0) self.entry_for_path = QLineEdit(self) self.entry_for_path.setReadOnly(True) self.entry_for_path.move(5, 15) self.entry_for_path.setFixedSize(260, 17) but = QPushButton("...", self) but.setFixedSize(20, 25) but.move(270, 10) but.clicked.connect(lambda x: self.get_data_path()) def get_data_path(self): local_path = str( QFileDialog.getOpenFileName(self, "Select Directory", self.current_path)[0]) if len(local_path) == 0: return self.current_path = local_path self.entry_for_path.setText(local_path) def read_data(self): if self.current_path: self.main.show_key.setText( open(self.current_path, encoding='utf8').read())
def ui_components(self): # fonts font = QFont("Roboto", 15) # 'enter country name' label enter_country_label = QLabel("Enter country name: ", self) enter_country_label.setFont(font) enter_country_label.move(10, 10) enter_country_label.adjustSize() # 'country name' line edit country_name = QLineEdit(self) country_name.setFixedSize(200, 25) country_name.setFont(font) country_name.setPlaceholderText("Ex: Tunisia") country_name.move(10, 40) country_name_submit = QPushButton("Search", self) country_name_submit.setFixedSize(130, 25) country_name_submit.move(220, 40) # Displays worldwide data as default cases_label = QLabel( f"Current cases: {data.CoronaCases('').total_cases}", self) cases_label.setFont(font) cases_label.adjustSize() cases_label.move(10, 85) deaths_label = QLabel( f"Current deaths: {data.CoronaCases('').total_deaths}", self) deaths_label.setFont(font) deaths_label.adjustSize() deaths_label.move(10, 112.8) recovered_label = QLabel( f"Current recovered: {data.CoronaCases('').total_recovered}", self) recovered_label.setFont(font) recovered_label.adjustSize() recovered_label.move(10, 140) # Updates the labels with country specific data. def label_updater(): cases_label.setText( f"Current cases: {data.CoronaCases('country/'+country_name.text().lower()).total_cases}" ) deaths_label.setText( f"Current deaths: {data.CoronaCases('country/'+ country_name.text().lower()).total_deaths}" ) recovered_label.setText( f"Current recovered: {data.CoronaCases('country/'+ country_name.text().lower()).total_recovered}" ) country_name_submit.clicked.connect(label_updater)
class ApolloLabeledEntry(ApolloControl): def __init__(self, parent, text, value_text, lines=1, *args, **kwargs): super().__init__(parent, *args, **kwargs) # Make sure the text is bottom aligned in the specified number of lines text = "\n" * (lines - text.count("\n") - 1) + text self.label = QLabel(text, self) self.addWidget(self.label) self.layout.addSpacing(3) self.value = QLineEdit(self) self.value.setFixedSize(65, 32) self.value.setText(value_text) self.value.setAlignment(Qt.AlignCenter) self.layout.addWidget(self.value)
class LabelTextBox(QWidget): def __init__(self, label, orientation="V", read_only=True, line=False, *args, **kwargs): super(LabelTextBox, self).__init__(*args, **kwargs) self.layout = QVBoxLayout() if orientation == "V" else QHBoxLayout() self.label = QLabel(label) self.text_box = QLineEdit() if line else QTextEdit() self._read_only = read_only self._line_edit = line self._text = "" self._setup() def _setup(self): self.text_box.setReadOnly(self._read_only) if not self._line_edit: self.text_box.setFixedSize(400, 200) self.layout.addWidget(self.label) self.layout.addWidget(self.text_box) self.setLayout(self.layout) def text(self): return self.text_box.text() def set_text(self, text): self.text_box.setText(text) def init_update(self, data): print("Just joined? Let's set up all the data we know about") pass def update(self, data): print(f"Updating {self} with data - {data}") def setDisabled(self, disabled): self.text_box.setDisabled(disabled) def isEnabled(self): return self.text_box.isEnabled()
class colorPicker(QDialog): "custom colorDialog from Orthallelous" currentColorChanged = Signal(QColor) colorSelected = Signal(QColor) def __init__(self, initial=None, parent=None): super(colorPicker, self).__init__(parent) self.setup() self.setColor(initial) def currentColor(self): return self._color def setColor(self, qcolor=None): if qcolor is None: self._color = QColor('#ffffff') else: self._color = QColor(qcolor) self._colorEdited() @staticmethod def getColor(initial=None, parent=None, title=None): dialog = colorPicker(initial, parent) if title: dialog.setWindowTitle(title) result = dialog.exec_() color = dialog._color return color def closeValid(self): "emits colorSelected signal with valid color on OK" self.currentColorChanged.emit(self._color) self.colorSelected.emit(self._color) self.close() def closeInvalid(self): "emits colorSelected signal with invalid color on Cancel" self._color = QColor() self.colorSelected.emit(QColor()) self.close() def setOption(self, option, Bool=True): if option == QColorDialog.NoButtons: if not Bool: self.dialogButtons.blockSignals(False) self.dialogButtons.setEnabled(True) self.dialogButtons.show() else: self.dialogButtons.blockSignals(True) self.dialogButtons.setEnabled(False) self.dialogButtons.hide() self.setFixedSize(self.sizeHint()) def _colorEdited(self): "internal color editing" sender, color = self.sender(), self._color for i in self.inputs: i.blockSignals(True) # get values if sender in self.rgbInputs: # RGB color.setRgb(*[i.value() for i in self.rgbInputs]) elif sender in self.hsvInputs: # HSV color.setHsv(*[i.value() for i in self.hsvInputs]) elif sender in self.cmykInputs: # CMYK color.setCmyk(*[i.value() for i in self.cmykInputs]) elif sender is self.htmlInput: # HTML color.setNamedColor('#' + str(self.htmlInput.text()).lower()) elif sender is self.colorWheel: # WHEEL color = self._color = self.colorWheel.getColor() elif sender is self.colorNamesCB: # NAMED dat = self.colorNamesCB.itemData(self.colorNamesCB.currentIndex()) try: color = self._color = QColor(dat.toString()) # PyQt except: color = self._color = QColor(str(dat)) # PySide self.colorNamesCB.setToolTip(self.colorNamesCB.currentText()) else: pass # set values for i, j in zip(color.getRgb()[:-1], self.rgbInputs): j.setValue(i) for i, j in zip(color.getHsv()[:-1], self.hsvInputs): j.setValue(i) for i, j in zip(color.getCmyk()[:-1], self.cmykInputs): j.setValue(i) self.htmlInput.setText(color.name()[1:]) self.colorWheel.setColor(color) idx = self.colorNamesCB.findData(color.name()) self.colorNamesCB.setCurrentIndex(idx) # will be blank if not in list pal = self.colorDisplay.palette() pal.setColor(self.colorDisplay.backgroundRole(), color) self.colorDisplay.setPalette(pal) #self.colorDisplay.setStyleSheet('background:' + color.name()) for i in self.inputs: i.blockSignals(False) self.currentColorChanged.emit(color) def pickColor(self): "pick a color on the screen, part 1" # screenshot desktop self._img = QApplication.primaryScreen().grabWindow(0) self._view = QGraphicsView(self) scene = QGraphicsScene(self) # display screenshot at full size self._view.setWindowFlags(Qt.FramelessWindowHint) self._view.setWindowFlags(Qt.WindowType_Mask) self._view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) scene.addPixmap(self._img) #; self._view.setScene(scene) self._mag = magnifier() self._mag.setBackground(self._img) self._mag.setSize(11, 11) scene.addItem(self._mag) self._view.setScene(scene) self._appview = QApplication self._appview.setOverrideCursor(Qt.CrossCursor) self._view.showFullScreen() self._view.mousePressEvent = self._pickedColor def _pickedColor(self, event): "pick a color on the screen, part 2" color = QColor(self._img.toImage().pixel(event.globalPos())) self._view.hide() self._appview.restoreOverrideCursor() self._color = color self._colorEdited() self._mag = self._appview = self._view = self._img = None def showColors(self): "show location of colors on color wheel" if self.showButton.isChecked(): self.colorWheel.showNamedColors(True) else: self.colorWheel.showNamedColors(False) def useRandom(self, state=True): "toggles show colors button and random color button" if state: self.showButton.blockSignals(True) self.showButton.setChecked(False) self.showButton.hide() self.showColors() self.rndButton.blockSignals(False) self.rndButton.show() else: self.showButton.blockSignals(False) self.showButton.show() self.rndButton.blockSignals(True) self.rndButton.hide() def randomColor(self): "select a random color" rand = random.randint col = QColor() col.setHsv(rand(0, 359), rand(0, 255), rand(0, 255)) #col.setRgb(rand(0, 255), rand(0, 255), rand(0, 255)) self.setColor(col) return col def getNamedColors(self): "returns a list [(name, #html)] from the named colors combobox" lst = [] for i in range(self.colorNamesCB.count()): name = str(self.colorNamesCB.itemText(i)) try: # PyQt html = str(self.colorNamesCB.itemData(i).toString()) except AttributeError: # PySide html = str(self.colorNamesCB.itemData(i)) lst.append((name, html)) return lst def addNamedColors(self, lst): "add a list [('name', '#html'), ] of named colors (repeats removed)" col = self.getNamedColors() + lst lst = [(i[0], QColor(i[1])) for i in col] sen = set() add = sen.add # http://stackoverflow.com/a/480227 uni = [x for x in lst if not (x[1].name() in sen or add(x[1].name()))] self.colorNamesCB.clear() for i, j in sorted(uni, key=lambda q: q[1].getHsv()): icon = QPixmap(16, 16) icon.fill(j) self.colorNamesCB.addItem(QIcon(icon), i, j.name()) self.colorWheel.setNamedColors([(i, j.name()) for i, j in uni]) self.cNameLabel.setToolTip('Named colors\n{:,} colors'.format( len(uni))) def setup(self): self.setAttribute(Qt.WA_DeleteOnClose) fixed = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) rightCenter = (Qt.AlignRight | Qt.AlignVCenter) # all the input boxes self.inputGrid = QGridLayout() self.inputGrid.setSpacing(5) h_spc = self.inputGrid.horizontalSpacing() v_spc = self.inputGrid.verticalSpacing() # RGB self.redInput = QSpinBox() self.grnInput = QSpinBox() self.bluInput = QSpinBox() self.rgbInputs = [self.redInput, self.grnInput, self.bluInput] self.redLabel = QLabel('&R:') self.redLabel.setToolTip('Red') self.grnLabel = QLabel('&G:') self.grnLabel.setToolTip('Green') self.bluLabel = QLabel('&B:') self.bluLabel.setToolTip('Blue') self.rgbLabels = [self.redLabel, self.grnLabel, self.bluLabel] self.redLabel.setBuddy(self.redInput) self.grnLabel.setBuddy(self.grnInput) self.bluLabel.setBuddy(self.bluInput) # HSV self.hueInput = QSpinBox() self.satInput = QSpinBox() self.valInput = QSpinBox() self.hsvInputs = [self.hueInput, self.satInput, self.valInput] self.hueInput.setWrapping(True) self.hueLabel = QLabel('&H:') self.hueLabel.setToolTip('Hue') self.satLabel = QLabel('&S:') self.satLabel.setToolTip('Saturation') self.valLabel = QLabel('&V:') self.valLabel.setToolTip('Value') self.hsvLabels = [self.hueLabel, self.satLabel, self.valLabel] self.hueLabel.setBuddy(self.hueInput) self.satLabel.setBuddy(self.satInput) self.valLabel.setBuddy(self.valInput) # CMYK self.cInput = QSpinBox() self.mInput = QSpinBox() self.yInput = QSpinBox() self.kInput = QSpinBox() self.cmykInputs = [self.cInput, self.mInput, self.yInput, self.kInput] self.cLabel = QLabel('&C:') self.cLabel.setToolTip('Cyan') self.mLabel = QLabel('&M:') self.mLabel.setToolTip('Magenta') self.yLabel = QLabel('&Y:') self.yLabel.setToolTip('Yellow') self.kLabel = QLabel('&K:') self.kLabel.setToolTip('Black') self.cmykLabels = [self.cLabel, self.mLabel, self.yLabel, self.kLabel] self.cLabel.setBuddy(self.cInput) self.mLabel.setBuddy(self.mInput) self.yLabel.setBuddy(self.yInput) self.kLabel.setBuddy(self.kInput) for i in self.rgbInputs + self.hsvInputs + self.cmykInputs: i.setRange(0, 255) i.setFixedSize(35, 22) i.setAlignment(Qt.AlignCenter) i.setButtonSymbols(QAbstractSpinBox.NoButtons) self.hueInput.setRange(0, 359) # HTML self.htmlInput = QLineEdit() self.htmlInput.setFixedSize(35 + 22 + h_spc, 22) # spans 2 cols self.htmlInput.setPlaceholderText('html') self.htmlInput.setAlignment(Qt.AlignCenter) regex = QRegExp('[0-9A-Fa-f]{1,6}') valid = QRegExpValidator(regex) self.htmlInput.setValidator(valid) self.htmlLabel = QLabel('&#') self.htmlLabel.setToolTip('Web color') self.htmlLabel.setBuddy(self.htmlInput) self.inputLabels = (self.rgbLabels + self.hsvLabels + self.cmykLabels + [ self.htmlLabel, ]) for i in self.inputLabels: i.setFixedSize(22, 22) i.setAlignment(rightCenter) #i.setFrameShape(QFrame.Box) self.inputs = self.rgbInputs + self.hsvInputs + self.cmykInputs for i in self.inputs: i.valueChanged.connect(self._colorEdited) self.htmlInput.editingFinished.connect(self._colorEdited) # picker button self.pickButton = QPushButton('&Pick') self.pickButton.setToolTip('Pick a color from the screen') self.pickButton.setFixedSize(35, 22) self.pickButton.clicked.connect(self.pickColor) # color display self.colorDisplay = QFrame() self.colorDisplay.setFixedSize(55, 4 * 22 + 3 * v_spc) # spans 4 rows self.colorDisplay.setFrameShape(QFrame.Panel) self.colorDisplay.setFrameShadow(QFrame.Sunken) self.colorDisplay.setAutoFillBackground(True) # show button / random button self.showButton = QPushButton('Sho&w') self.showButton.setToolTip('Show named colors on color wheel') self.showButton.setFixedSize(35, 22) self.showButton.setCheckable(True) self.showButton.clicked.connect(self.showColors) self.rndButton = QPushButton('R&and') self.rndButton.setToolTip('Select a random color') self.rndButton.setFixedSize(35, 22) self.rndButton.clicked.connect(self.randomColor) # color wheel self.colorWheel = wheel() self.colorWheel.setFixedSize(256, 256) #265, 265) self.colorWheel.currentColorChanged.connect(self.setColor) # named colors combo box self.colorNamesCB = QComboBox() self.colorNamesCB.setFixedSize(70 + 66 + 4 * h_spc, 22) # spans 5 cols #self.colorNamesCB.addItem('- Color Names -') self.cNameLabel = QLabel('&Named:') self.cNameLabel.setBuddy(self.colorNamesCB) self.cNameLabel.setAlignment(rightCenter) #self.cNameLabel.setFrameShape(QFrame.Box) self.cNameLabel.setFixedSize(55, 22) lst = [i for i in QColor.colorNames() if str(i) != 'transparent'] lst = [(i, QColor(i)) for i in lst] lst.append(('Cosmic latte', '#fff8e7')) lst.append(('rebeccapurple', '#663399')) self.addNamedColors(lst) self.colorNamesCB.currentIndexChanged.connect(self._colorEdited) self.inputs += [self.htmlInput, self.colorWheel, self.colorNamesCB] # ok/cancel buttons self.dialogButtons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.dialogButtons.accepted.connect(self.closeValid) self.dialogButtons.rejected.connect(self.closeInvalid) self.dialogButtons.setCenterButtons(True) # pass QColorDialog.NoButtons, False to setOption to remove # assemble grid! # 0 1 2 3 4 5 6 # # color wheeeeeeeeeeeeellll 0 # disp r: rrr h: hhh c: ccc 1 # disp g: ggg s: sss m: mmm 2 # disp b: bbb v: vvv y: yyy 3 # disp ## -html- pic k: kkk 4 # name coooommmboooobox rnd 5 #.addWidget(widget, row, col, rspan, cspan) self.inputGrid.addWidget(self.colorWheel, 0, 0, 1, 7) self.inputGrid.addWidget(self.colorDisplay, 1, 0, 4, 1) for i, lab in enumerate(self.rgbLabels, 1): self.inputGrid.addWidget(lab, i, 1, 1, 1) self.inputGrid.addWidget(self.htmlLabel, 4, 1, 1, 1) for i, wid in enumerate(self.rgbInputs, 1): self.inputGrid.addWidget(wid, i, 2) self.inputGrid.addWidget(self.htmlInput, 4, 2, 1, 2) for i, lab in enumerate(self.hsvLabels, 1): self.inputGrid.addWidget(lab, i, 3, 1, 1) for i, wid in enumerate(self.hsvInputs, 1): self.inputGrid.addWidget(wid, i, 4, 1, 1) self.inputGrid.addWidget(self.pickButton, 4, 4, 1, 1) for i, lab in enumerate(self.cmykLabels, 1): self.inputGrid.addWidget(lab, i, 5, 1, 1) for i, wid in enumerate(self.cmykInputs, 1): self.inputGrid.addWidget(wid, i, 6, 1, 1) self.inputGrid.addWidget(self.colorNamesCB, 5, 1, 1, 5) self.inputGrid.addWidget(self.cNameLabel, 5, 0, 1, 1) self.inputGrid.addWidget(self.showButton, 5, 6, 1, 1) self.inputGrid.addWidget(self.rndButton, 5, 6, 1, 1) self.inputGrid.addWidget(self.dialogButtons, 6, 0, 1, 7) self.setWindowTitle('Select color') ico = self.style().standardIcon(QStyle.SP_DialogResetButton) self.setWindowIcon(ico) self.setLayout(self.inputGrid) self.setFixedSize(self.sizeHint()) self.useRandom() #False)
def initUI(self): """ Initialize the GUI. Does lots of stuff. """ self.grid = QGridLayout() self.setLayout(self.grid) rowi = 0 if self.op.level.currentText() == '10': for angle in self.op.levang[self.op.level.currentText()]: self.grid.addWidget( QLabel(self, text="Finishing at angle " + angle + ":\tWe bestow upon thee the ability to create"), rowi, 0) ulti = QComboBox(self) ulti.addItems(self.plist) if angle in self.op.link.finalpersona: ulti.setCurrentIndex( self.plist.index(self.op.link.finalpersona[angle])) self.ultis[angle] = ulti self.grid.addWidget(self.ultis[angle], rowi, 1) self.grid.addWidget( QLabel(self, text=", the ultimate form of the " + self.op.link.arcana + " arcana."), rowi, 2) rowi += 1 return for angle in self.op.levang[self.op.level.currentText()]: eang = QLabel(self, text=angle) self.eangs.append(eang) ptb = QLineEdit(self) ptb.setText("0") ptb.setFixedSize(20, 20) self.textboxes[angle] = ptb self.grid.addWidget(QLabel(self, text="Reaching angle"), rowi, 0) self.grid.addWidget(self.eangs[-1], rowi, 1) self.grid.addWidget(QLabel(self, text="requires"), rowi, 2) self.grid.addWidget(self.textboxes[angle], rowi, 3) self.grid.addWidget(QLabel(self, text="points and: Courage"), rowi, 4) courage = QComboBox(self) self.courages[angle] = courage self.courages[angle].addItems(["1", "2", "3", "4", "5"]) self.courages[angle].setCurrentIndex(0) self.grid.addWidget(self.courages[angle], rowi, 5) self.grid.addWidget(QLabel(self, text="Charm"), rowi, 6) charm = QComboBox(self) self.charms[angle] = charm self.charms[angle].addItems(["1", "2", "3", "4", "5"]) self.charms[angle].setCurrentIndex(0) self.grid.addWidget(self.charms[angle], rowi, 7) self.grid.addWidget(QLabel(self, text="Academics"), rowi, 8) acad = QComboBox(self) self.acads[angle] = acad self.acads[angle].addItems(["1", "2", "3", "4", "5"]) self.acads[angle].setCurrentIndex(0) self.grid.addWidget(self.acads[angle], rowi, 9) if self.op.level.currentText() in self.op.link.requiredPoints and \ angle in self.op.link.requiredPoints[self.op.level.currentText()]: self.textboxes[angle].setText( str(self.op.link.requiredPoints[ self.op.level.currentText()][angle]['points'])) self.acads[angle].setCurrentIndex(self.op.link.requiredPoints[ self.op.level.currentText()][angle]['acad'] - 1) self.charms[angle].setCurrentIndex(self.op.link.requiredPoints[ self.op.level.currentText()][angle]['charm'] - 1) self.courages[angle].setCurrentIndex( self.op.link.requiredPoints[ self.op.level.currentText()][angle]['courage'] - 1) rowi += 1
class EmailFrame(QWidget): """ EmailFrame is the view in which the user can send a message to me via SMTP. Builds itself directly into it's parent widget. :param QWidget op: parent widget """ def __init__(self, op): QWidget.__init__(self) self.op = op self.initUI() def initUI(self): """ Initializes the GUI. Does a lot of stuff. """ self.grid = QGridLayout() self.setLayout(self.grid) self.op.grid.addWidget(self, 1, 0, 1, 3) subL = QLabel(self, text="Subject:") subL.setAlignment(Qt.AlignHCenter) self.grid.addWidget(subL, 0, 0) self.subject = QLineEdit(self) self.subject.setFixedSize(150, 20) self.grid.addWidget(self.subject, 0, 1) bodL = QLabel(self, text="") bodL.setAlignment(Qt.AlignHCenter) self.body = QTextEdit(self) self.body.setFixedSize(400, 150) self.grid.addWidget(self.body, 1, 1, 1, 3) sem = QLabel(self, text="Your email:") sem.setAlignment(Qt.AlignHCenter) self.grid.addWidget(sem, 2, 0) self.semT = QLineEdit(self) self.semT.setFixedSize(150, 20) self.grid.addWidget(self.semT, 2, 1) send = QPushButton(self, text="Send") send.clicked.connect(self.send) self.grid.addWidget(send, 2, 2) self.addFiles = QCheckBox(self, text="Send submission") self.addFiles.setToolTip( "Check this box to send all Character, Persona and Social Link data along with your message" ) self.grid.addWidget(self.addFiles, 0, 2) self.op.back.clicked.disconnect() self.op.back.clicked.connect(self.back) def send(self): """ Send entered text as email to me via SMTP. """ if str(self.body.toPlainText()) == "" or \ str(self.body.toPlainText()).isspace() or \ str(self.subject.text()) == "" or \ str(self.subject.text()).isspace(): popup("Please enter a message and subject.", "Critical") return msg = MIMEMultipart() body = MIMEText( str(self.body.toPlainText() + "\n\nSent by " + self.semT.text())) msg.attach(body) msg['From'] = str(self.semT.text()) msg['To'] = "*****@*****.**" msg['Subject'] = str(self.subject.text()) if self.addFiles.isChecked(): print("Adding files") fileNames = glob(json_reader.buildPath("data/*.json")) + \ glob(json_reader.buildPath("data/pers/*.json")) + \ glob(json_reader.buildPath("data/chars/*.json")) print(fileNames) for file in fileNames: part = MIMEBase('application', "octet-stream") part.set_payload(open(file, "rb").read()) part.add_header( 'Content-Disposition', 'attachment; filename="%s"' % file[file.rfind("/"):]) msg.attach(part) serv = smtplib.SMTP("smtp.live.com", 587) serv.set_debuglevel(1) serv.ehlo() serv.starttls() serv.ehlo() serv.login("*****@*****.**", 'PersonaX') try: serv.sendmail(msg['From'], msg['To'], msg.as_string()) print("Message sent successfully") popup("Email was sent! Thank you!", "Information") serv.quit() return except smtplib.SMTPSenderRefused: popup( "You must provide your email address so that we may contact you if needed.\n\nYour email " "address will not be shared with any third parties.", "Critical") serv.quit() return except Exception as e: #pylint: disable=broad-except print(e) popup("Email failed to send, but not sure why...", "Critical") def back(self): """ Hide this view and return the parent widget to it's original state. """ self.close() self.op.text.show() self.op.back.clicked.disconnect() self.op.back.clicked.connect(self.op.backF) self.op.contact.clicked.connect(self.op.contactF)
class AddressRegister(QWidget): def __init__(self, parent, usbif, color): super().__init__(parent) self._setup_ui(color) usbif.poll("monitor", um.MonRegS()) usbif.poll("monitor", um.MonRegBB()) #usbif.poll("monitor", um.MonChanFEXT()) usbif.listen(self) def handle_msg(self, msg): if isinstance(msg, um.MonRegS): self.set_s_value(msg.s) elif isinstance(msg, um.MonRegBB): self.set_bank_values(msg.eb, msg.fb) elif isinstance(msg, um.MonChanFEXT): self.set_fext_value(msg.fext) def set_bank_values(self, eb, fb): self.eb.set_value(eb) self.fb.set_value(fb) self._update_addr_value() def set_s_value(self, x): self.s.set_value(x) self._update_addr_value() def set_fext_value(self, x): self.fext.set_value(x) self._update_addr_value() def _setup_ui(self, color): # Set up our basic layout layout = QHBoxLayout(self) self.setLayout(layout) layout.setSpacing(3) layout.setMargin(1) # Construct register groups for EB, FEXT, FB, and S self.eb = SubRegister(self, "EBANK", 3, color) self.fext = SubRegister(self, "FEXT", 3, color) self.fb = SubRegister(self, "FBANK", 5, color) self.s = SubRegister(self, "", 12, color) layout.addWidget(self.eb) layout.addWidget(self.fext) layout.addWidget(self.fb) layout.addWidget(self.s) # Create a grouping widget for the S label and decoded octal value box label_value_layout = QHBoxLayout() label_value_layout.setSpacing(3) label_value_layout.setMargin(1) label_value_layout.setContentsMargins(0, 33, 0, 0) layout.addLayout(label_value_layout) # Create a value box for displaying the overall decoded address self._addr_value = QLineEdit(self) self._addr_value.setFixedSize(70, 32) self._addr_value.setReadOnly(True) self._addr_value.setAlignment(Qt.AlignCenter) self._addr_value.setText('0000') self._addr_value.setStyleSheet("QLineEdit { color: #555; }") label_value_layout.addWidget(self._addr_value) # Create a label to show 'S' label = QLabel('S', self) label.setFixedWidth(20) label_value_layout.addWidget(label) def _update_addr_value(self): # Get the values of all tracked registers s = self.s.value eb = self.eb.value fb = self.fb.value fext = self.fext.value self._addr_value.setText(agc.format_addr(s, eb, fb, fext))
class MoveFrame(QWidget): """ Move frame. Represents the edit view of movement actions. :param QWidget op: parent widget :param object load: something to load or 0 """ def __init__(self, op, load): QWidget.__init__(self) self.op = op self.load = load self.initUI() self.op.grid.addWidget(self, 1, 0, 1, 5) def initUI(self): """ Initializes the GUI. Does lots of stuff. """ self.grid = QGridLayout() self.setLayout(self.grid) self.animations = json_reader.data_list("animations") self.characs = json_reader.readCharNames() self.textl = QLabel(self, text="Go to x:") self.grid.addWidget(self.textl, 1, 0) self.lx = QLineEdit(self) self.lx.setFixedSize(20, 20) self.grid.addWidget(self.lx, 1, 1) self.textl = QLabel(self, text="Go to y:") self.grid.addWidget(self.textl, 2, 0) self.ly = QLineEdit(self) self.ly.setFixedSize(20, 20) self.grid.addWidget(self.ly, 2, 1) self.speakerl = QLabel(self, text="Person:") self.grid.addWidget(self.speakerl, 1, 3) self.speaker = QComboBox(self) self.speaker.addItems(self.characs) self.speaker.setCurrentIndex(0) self.grid.addWidget(self.speaker, 1, 4) self.anil = QLabel(self, text="Animation:") self.grid.addWidget(self.anil, 2, 3) self.ani = QComboBox(self) self.ani.addItems(self.animations) self.ani.setCurrentIndex(self.animations.index("Idle")) self.grid.addWidget(self.ani, 2, 4) if self.load != 0: self.ani.setCurrentIndex( self.animations.index(self.load.getAnimation())) self.speaker.setCurrentIndex( self.characs.index(self.load.getSubject())) self.lx.setText(self.load.getDestination()[0]) self.ly.setText(self.load.getDestination()[1]) def save(self): """ Save this movement action to the cutscene. """ print("Saving") moveSlide = Movement() moveSlide.setSubject(self.speaker.currentText()) moveSlide.setAnimation(self.ani.currentText()) print("...") try: (int)(self.lx.text()) (int)(self.ly.text()) except ValueError: popup("Destination coordinates (x, y) must be entered as integers", "Critical") return moveSlide.setDestination( ((int)(self.lx.text()), (int)(self.ly.text()))) self.op.op.link.addItem(moveSlide, self.op.op.i) print("Saved") self.op.op.linkstored.setLink(self.op.op.link, self.op.op.level, self.op.op.angle) self.op.op.linkstored.save() self.op.updateElementList() popup("Saved!", "Information")
def initUI(self): """ Initializes the GUI. Does lots of stuff. """ self.grid = QGridLayout() self.setLayout(self.grid) self.characs = json_reader.readCharNames() self.arcanas = json_reader.data_list("arcanas") self.arcanas.extend([""]) self.textl = QLabel(self, text="Text:") self.grid.addWidget(self.textl, 1, 0) self.infoBox = QTextEdit(self) self.infoBox.setFixedSize(300, 150) self.grid.addWidget(self.infoBox, 1, 1, 3, 3) self.textl = QLabel(self, text="Points:") self.grid.addWidget(self.textl, 2, 4, 1, 2) self.pointBox = QLineEdit(self) self.pointBox.setFixedSize(20, 20) self.grid.addWidget(self.pointBox, 3, 4) self.pointvec.append(self.pointBox) pointOM = QComboBox(self) pointOM.addItems(self.arcanas) pointOM.setCurrentIndex(pointOM.count() - 1) self.grid.addWidget(pointOM, 3, 5) self.pointvar.append(pointOM) self.textl = QLabel(self, text="Angle:") self.grid.addWidget(self.textl, 2, 6, 1, 2) angleBox = QLineEdit(self) angleBox.setFixedSize(20, 20) self.grid.addWidget(angleBox, 3, 6) self.anglevec.append(angleBox) angleOM = QComboBox(self) angleOM.addItems(self.arcanas) angleOM.setCurrentIndex(angleOM.count() - 1) self.grid.addWidget(angleOM, 3, 7) self.anglevar.append(angleOM) self.speakerl = QLabel(self, text="Speaker:") self.grid.addWidget(self.speakerl, 1, 4) self.speaker = QComboBox(self) self.speaker.addItems(self.characs) self.grid.addWidget(self.speaker, 1, 5) self.emotionL = QLabel(self, text="Emotion:") #emotionL memes self.grid.addWidget(self.emotionL, 1, 6) self.s_emotions = json_reader.data_list('sprite_emotions') self.emotion = QComboBox(self) self.emotion.addItems(self.s_emotions) self.grid.addWidget(self.emotion, 1, 7) self.addp = QPushButton(self, text="Add points") self.addp.clicked.connect(self.extendP) self.grid.addWidget(self.addp, 30, 4, 1, 2) self.adda = QPushButton(self, text="Add angles") self.adda.clicked.connect(self.extendA) self.grid.addWidget(self.adda, 30, 6, 1, 2) if self.load != 0: self.infoBox.setText(self.load.getText()) self.speaker.setCurrentIndex( self.characs.index(self.load.getSpeaker())) self.emotion.setCurrentIndex( self.s_emotions.index(self.load.emotion)) first = True for arcana, points in self.load.getPoints().items(): if first: first = False else: self.extendP() self.pointvec[-1].setText(str(points)) self.pointvar[-1].setCurrentIndex(self.arcanas.index(arcana)) first = True for arcana, angle in self.load.getAngle().items(): if first: first = False else: self.extendA() self.anglevec[-1].setText(str(angle)) self.anglevar[-1].setCurrentIndex(self.arcanas.index(arcana))
class Register(QWidget): def __init__(self, parent, usbif, name, has_parity, color): super().__init__(parent) self._has_parity = has_parity self._indicators = [] self._parity_inds = [] # Set up the UI self._setup_ui(name, color) # Set up register reading and updates self.msg = getattr(um, 'MonReg' + name) usbif.poll("monitor", self.msg()) usbif.listen(self) if has_parity: usbif.poll("monitor", um.MonRegParity()) self._gp = name.lower() + '_gp' self._sp = name.lower() + '_sp' else: self._gp = None self._sp = None def handle_msg(self, msg): if isinstance(msg, self.msg): self.set_value(msg[0]) elif isinstance(msg, um.MonRegParity) and self._gp is not None: gp = getattr(msg, self._gp) sp = getattr(msg, self._sp) self._parity_inds[0].set_on(gp) self._parity_inds[1].set_on(sp) def set_value(self, x): # Toggle each of the 16 value indicators to match the new value for i in range(0, len(self._indicators)): self._indicators[i].set_on((x & (1 << i)) != 0) # Update the octal decoding of the indicators. Bit 15 is ignored # in the actual value, so mask it out and shift down bit 16. value = ((x & 0o100000) >> 1) | (x & 0o37777) self._value_box.setText('%05o' % value) # Instead we will convey overflow information with text color. # Positive overflow is red, and negative overflow is purple. sign1 = (x & 0o100000) != 0 sign2 = (x & 0o040000) != 0 if not sign1 and sign2: self._value_box.setStyleSheet('color: red;') elif sign1 and not sign2: self._value_box.setStyleSheet('color: purple;') else: self._value_box.setStyleSheet('color: #555;') def _setup_ui(self, name, color): # Set up the overall horizontal layout layout = QHBoxLayout(self) self.setLayout(layout) layout.setSpacing(3) layout.setMargin(1) # Construct a frame to hold the 16 indicators bit_frame = QFrame(self) bit_frame.setStyleSheet("QFrame { color: #666 }") bit_layout = QHBoxLayout(bit_frame) bit_layout.setSpacing(1) bit_layout.setContentsMargins(1, 0, 2, 0) bit_frame.setLayout(bit_layout) bit_frame.setFrameStyle(QFrame.Panel | QFrame.Plain) layout.addWidget(bit_frame) # Add sensed and generated parity bits, if this register has them if self._has_parity: for i in range(2, 0, -1): ind = ApolloIndicator(bit_frame, QColor(220, 240, 0)) ind.setFixedSize(20, 32) bit_layout.addWidget(ind) self._parity_inds.insert(0, ind) sep = QFrame(bit_frame) sep.setFrameStyle(QFrame.VLine | QFrame.Plain) bit_layout.addWidget(sep) # Add the 16 bit indicators to the frame, from 16 to 1. for i in range(16, 0, -1): if (i == 15): indcolor = QColor(220, 240, 0) else: indcolor = color ind = ApolloIndicator(bit_frame, indcolor) ind.setFixedSize(20, 32) bit_layout.addWidget(ind) self._indicators.insert(0, ind) # Add separators between every group of 3 bits (except between # bits 15 and 16). if (i < 16) and (i > 1) and ((i % 3) == 1): sep = QFrame(bit_frame) sep.setFrameStyle(QFrame.VLine | QFrame.Plain) bit_layout.addWidget(sep) # Add a box to display the octal decoded value in self._value_box = QLineEdit(self) self._value_box.setFixedSize(70, 32) self._value_box.setReadOnly(True) self._value_box.setAlignment(Qt.AlignCenter) self._value_box.setText('00000') self._value_box.setStyleSheet("QLineEdit { color: #555; }") layout.addWidget(self._value_box) # Add a label showing the name of the register label = QLabel(name, self) label.setFixedWidth(20) layout.addWidget(label)
class SummaryWidget(QWidget): def __init__(self, plugin_manager): super(SummaryWidget, self).__init__() self.plugin_manager = plugin_manager icon_path = os.path.join(c.ICON_PATH, "neutral", "quote.png") self.setWindowIcon(QIcon(icon_path)) self.setWindowTitle("Summary") self.settings = QSettings(c.SETTINGS_PATH, QSettings.IniFormat) self.font = QFont(self.settings.value(c.FONT, defaultValue="Arial", type=str)) self.font.setPointSize(12) self.summary_text = QPlainTextEdit() self.summary_text.setReadOnly(True) self.summary_text.setFont(self.font) self.refresh_btn = QPushButton("Refresh") self.refresh_btn.clicked.connect(self.get_summary) self.threshold_value = 1.2 self.threshold = QLineEdit(str(self.threshold_value)) self.threshold.setFixedSize(40, 25) self.validator = QDoubleValidator() self.validator.setLocale(QLocale.English) self.threshold.setValidator(self.validator) self.threshold.textChanged.connect(self.threshold_changed) self.h_box = QHBoxLayout() self.h_box.addWidget(self.refresh_btn) self.h_box.addWidget(self.threshold) self.v_box = QVBoxLayout() self.v_box.addWidget(self.summary_text) self.v_box.addLayout(self.h_box) self.setLayout(self.v_box) self.resize(500, 500) def get_summary(self): if "de" in self.plugin_manager.get_language(): language = "german" elif "en" in self.plugin_manager.get_language(): language = "english" else: return text = self.plugin_manager.get_text() stop_words = set(stopwords.words(language)) words = word_tokenize(text=text, language=language) # count word frequency freq = dict() for word in words: word = word.lower() if word in stop_words: continue if word in freq: freq[word] += 1 else: freq[word] = 1 sentences = sent_tokenize(text, language) sentence_freq = dict() # sum frequency of words in each sentence for word, freq in freq.items(): for sentence in sentences: if word in sentence.lower(): if sentence in sentence_freq: sentence_freq[sentence] += freq else: sentence_freq[sentence] = freq # calculate avg freq per word in sentence so long sentences dont have an advantage for sentence in sentences: sentence_freq[sentence] = sentence_freq[sentence] / len(sentence.split()) # calc average word-frequency per sentence sum_sentece_freq = 0 for sentence in sentence_freq: sum_sentece_freq += sentence_freq[sentence] avg = int(sum_sentece_freq / len(sentence_freq)) # filter sentences that doesn't reach the threshold summary = "" for sentence in sentence_freq: if sentence_freq[sentence] > (self.threshold_value * avg): summary += " " + sentence self.summary_text.setPlainText(summary.strip()) def threshold_changed(self): validator = self.threshold.validator() validator_state = validator.validate(self.threshold.text(), 0)[0] if validator_state == QValidator.Acceptable: color = '#006600' self.threshold_value = float(self.threshold.text()) else: color = '#800000' self.threshold.setStyleSheet('QLineEdit { background-color: %s }' % color) def show(self): super(SummaryWidget, self).show() self.get_summary()
class Socket(QFrame): """One socket with label and text entry""" def __init__(self, master, letter, connect_plug, charset): """ :param master: Qt parent object :param letter: Letter to serve as the label :param connect_plug: calls parent to connect with the letter typed in the entry box :param charset: {str} Allowed letters """ super().__init__(master) # QT WINDOW SETTINGS =================================================== layout = QVBoxLayout(self) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) # ATTRIBUTES =========================================================== self.connect_plug = connect_plug self.letter = letter self.connected_to = None self.marking = None self.charset = charset # ENTRY ================================================================ label = QLabel(letter) label.setStyleSheet("font-size: 30px; text-align: center;") self.entry = QLineEdit() self.entry.setMaxLength(1) self.entry.textChanged.connect(self.entry_event) self.entry.setFixedSize(40, 40) self.entry.setAlignment(Qt.AlignCenter) # SHOW WIDGETS layout.addWidget(label, alignment=Qt.AlignCenter) layout.addWidget(self.entry, alignment=Qt.AlignCenter) def pair(self): """Returns currently wired pair.""" if self.connected_to: return self.letter + self.connected_to return None def entry_event(self): """Responds to a event when something changes in the plug entry""" letter = self.entry.text().upper() if letter not in self.charset: self.set_text("", True) elif self.entry.isModified(): # Prevents recursive event calls if letter: self.connect_plug(self.letter, letter) else: self.connect_plug(self.letter, None) def set_text(self, letter, block_event=False, marking=None, uhr=False): """ Sets text to the plug entrybox and sets white (vacant) or black (occupied) background color :param letter: Sets text to the newly selected letter :param block_event: {bool} Starts blocking Qt signals if True :param marking: {str} Uhr marking (like 1a, 3b, ...) :param uhr: {bool} Colors sockets differently when True (when Uhr connected) """ stylesheet = ( "background-color: %s; color: %s; text-align: center; font-size: 30px;" ) if block_event: self.entry.blockSignals(True) self.setToolTip(None) if letter: color = ("black", "white") self.marking = marking else: color = ("white", "black") self.marking = None if uhr: if "a" in marking: color = ("red", "white") else: color = ("gray", "white") self.setToolTip(str(marking[0]) + marking[1]) self.entry.setStyleSheet(stylesheet % color) self.entry.setText(letter) self.connected_to = letter if block_event: self.entry.blockSignals(False)
class SLUI(QWidget): """ Widget containing all arcanas, descriptions of them, and the level/angles available. :param MainFrame mainframe: application mainframe :param QWidget op: parent widget """ def __init__(self, mainframe, op): QWidget.__init__(self) self.mainframe = mainframe self.op = op # Initialized gui items... self.levelOM = None self.angleOM = None self.addAngB = None self.newAng = None self.go = None self.delang = None self.angs = None self.initUI() def initUI(self): """ Initializes the GUI. Does a lot of stuff. """ self.mainframe.setWindowTitle("Social Link Creator") self.grid = QGridLayout() self.setLayout(self.grid) arcanaList = json_reader.data_list("arcanas") self.arcSel = QComboBox(self) self.arcSel.addItem("Select Arcana") self.arcSel.activated.connect(self.showText) self.arcSel.addItems(arcanaList) self.arcSel.setCurrentIndex(0) self.grid.addWidget(self.arcSel, 1, 1) select = QPushButton(self, text="Select") select.clicked.connect(self.context) self.grid.addWidget(select, 2, 1) info = QPushButton(self, text="Info") info.clicked.connect(self.infoF) self.grid.addWidget(info, 3, 1) back = QPushButton(self, text="Back") back.clicked.connect(self.back) self.grid.addWidget(back, 4, 1) self.card = QLabel(self) defaultCard = QPixmap(json_reader.buildPath("int/cards/card.png")) self.card.setPixmap(defaultCard) self.card.setAlignment(Qt.AlignHCenter) self.grid.addWidget(self.card, 0, 0) self.text = QLabel(self, text="") self.text.setFixedSize(400, 250) self.text.setWordWrap(True) self.text.setAlignment(Qt.AlignHCenter) self.grid.addWidget(self.text, 1, 0, 4, 1) def infoF(self): """ Enter the social link edit gui. """ if self.arcSel.currentText() == "Select Arcana": return self.mainframe.changeState( LinkInfo(self.mainframe, self, SocialLink(self.arcSel.currentText()))) def context(self): """ Once an arcana is selected, spawn this view to add the level/angle information as an additional widget. """ self.destroyContext() if self.arcSel.currentText() == "Select Arcana": return levs = [] for i in range(1, 11): levs.append("Level " + str(i)) self.levelOM = QComboBox(self) self.levelOM.addItems(levs) self.levelOM.setCurrentIndex(0) self.levelOM.activated.connect(self.fetchangles) self.grid.addWidget(self.levelOM, 1, 2, 1, 2) self.angleOM = QComboBox(self) self.fetchangles() self.grid.addWidget(self.angleOM, 2, 2, 1, 2) self.addAngB = QPushButton(self, text="Add Angle") self.addAngB.clicked.connect(self.addAngle) self.grid.addWidget(self.addAngB, 3, 2) self.newAng = QLineEdit(self) self.newAng.setFixedSize(20, 20) self.grid.addWidget(self.newAng, 3, 3) self.go = QPushButton(self, text="Go") self.go.clicked.connect(self.begin) self.grid.addWidget(self.go, 5, 2, 1, 2) def fetchangles(self): """ Fetch the angles at a certain level for the display. """ try: self.delang.close() except: #pylint: disable=bare-except print("Failed to close delang") self.angs = [] try: tempLink = json_reader.readLink(str(self.arcSel.currentText())) for decon in tempLink["cutscenes"]: if str(decon)[:str(decon).index("_")] == \ self.levelOM.currentText()[str(self.levelOM.currentText()).index(" ") + 1:]: self.angs.append("Angle " + str(decon)[str(decon).index("_") + 1:]) except: #pylint: disable=bare-except pass if self.angs: print("There are angles for this level") self.delang = QPushButton(self, text="Delete Angle") self.delang.clicked.connect(self.deleteangle) self.grid.addWidget(self.delang, 4, 2, 1, 2) else: self.angs.append("No angles") self.angleOM.clear() self.angleOM.addItems(self.angs) self.angleOM.setCurrentIndex(0) def addAngle(self): """ Add a potential angle to this link/level. """ try: (int)(self.newAng.text()) if self.angs[0] == "No angles": self.angleOM.clear() self.delang = QPushButton(self, text="Delete Angle") self.delang.clicked.connect(self.deleteangle) self.grid.addWidget(self.delang, 4, 2, 1, 2) self.angleOM.addItem("Angle " + str(self.newAng.text())) self.angleOM.setCurrentIndex(self.angleOM.count() - 1) self.newAng.clear() except ValueError: popup("The Angle must be an integer", "Critical") def deleteangle(self): """ Completely delete a certain level/angle combo. This will remove all info, the cutscene, etc. Dangerous. """ if not popup( "WARNING!!!\n\nThis will COMPLETELY ERASE this cutscene. It is HIGHLY RECOMMENDED that " "you back up your data by going to the Support/Contact page and choose \"Export\".", "Warning"): return link = SocialLink(self.arcSel.currentText()) print(link.cutscenes) key = self.levelOM.currentText()[self.levelOM.currentText().index(" ")+1:] + \ "_" + \ self.angleOM.currentText()[self.angleOM.currentText().index(" ")+1:] print(key) if key in link.cutscenes: link.cutscenes.pop(key) link.save() self.angleOM.removeItem(self.angleOM.currentIndex()) if self.angleOM.count() == 0: self.angleOM.addItem("No angles") self.delang.close() print(link.cutscenes) print("Deleted") def showText(self): """ Show the arcana's descriptive text upon selection. """ temp = [self.arcSel.itemText(i) for i in range(self.arcSel.count())] if "Select Arcana" in temp: self.arcSel.removeItem(temp.index("Select Arcana")) self.text.setText( json_reader.readArcDesc(str(self.arcSel.currentText()))) self.card.setPixmap( QPixmap( json_reader.buildPath("int/cards/" + str(self.arcSel.currentText()) + ".png"))) self.destroyContext() def destroyContext(self): """ Make sure all widgets are close when leaving the context. """ try: self.levelOM.close() self.angleOM.close() self.addAngB.close() self.newAng.close() self.go.close() self.delang.close() except: #pylint: disable=bare-except pass def begin(self): """ Enter the social link cutscene editor. """ if self.angleOM.currentText() == "No angles": popup( "An Angle must be selected.\nCreate angles by entering a number in the text box below and " "clicking \"Add Angle\"", "Critical") return enter_level = str(self.levelOM.currentText() )[str(self.levelOM.currentText()).index(" ") + 1:] enter_angle = str(self.angleOM.currentText() )[str(self.angleOM.currentText()).index(" ") + 1:] print("Entered SL creation mode for arcana " + str(self.arcSel.currentText())) self.mainframe.changeState( SLFrame(self.mainframe, self, str(self.arcSel.currentText()), int(enter_level), int(enter_angle))) def back(self): """ Return to the parent widget. """ print("Returned to main screen") self.mainframe.changeState(self.op)
class PersonaUI(QWidget): """ Widget for Persona creation view. :param MainFrame mainframe: application mainframe :param QWidget op: parent widget """ def __init__(self, mainframe, op): QWidget.__init__(self) self.mainframe = mainframe self.op = op self.grid = QGridLayout() self.setLayout(self.grid) self.listP = None self.listLS = None self.listEL1 = None self.listEL2 = None self.nameT = None self.levelT = None self.textT = None self.strT = None self.magT = None self.endT = None self.agiT = None self.luckT = None self.createFrame = None self.buttonFrame = None self.bfgrid = None # Actual create frame variables. self.cfgrid = None self.lsdic = None self.slashO = None self.strikeO = None self.pierceO = None self.fireO = None self.iceO = None self.windO = None self.elecO = None self.darkO = None self.lightO = None self.arcO = None self.iSpellOs = None self.lsSpellO = None self.lslevel = None self.initUI(True) def initUI(self, infoDump): """ Initializes the basic UI showing the list of Personas. Does a lot of stuff. :param dict infoDump: not sure lol """ self.mainframe.setWindowTitle("Persona Creator") if not infoDump: self.createFrameDraw() self.initButtonFrame(infoDump) self.listP = QListWidget(self) self.grid.addWidget(self.listP, 0, 3, 2, 1) temp = json_reader.readPerNames() self.listP.addItems(temp) def initButtonFrame(self, infoDump): """ Initializes the buttonframes that are present in all Persona creator views. :param dict infoDump: not sure lol """ self.buttonFrame = QWidget(self) self.bfgrid = QGridLayout() self.buttonFrame.setLayout(self.bfgrid) self.grid.addWidget(self.buttonFrame, 3, 0, 1, 4) new = QPushButton(self.buttonFrame, text="New") new.clicked.connect(self.new) self.bfgrid.addWidget(new, 4, 0) back = QPushButton(self.buttonFrame, text="Back") back.clicked.connect(self.back) self.bfgrid.addWidget(back, 4, 4) remove = QPushButton(self.buttonFrame, text="Remove") remove.clicked.connect(self.remove) self.bfgrid.addWidget(remove, 4, 3) edit = QPushButton(self.buttonFrame, text="Edit") edit.clicked.connect(self.edit) self.bfgrid.addWidget(edit, 4, 2) if not infoDump: save = QPushButton(self.buttonFrame, text="Save") save.clicked.connect(self.save) self.bfgrid.addWidget(save, 4, 1) def createFrameDraw(self): """ Initializes the GUI of the actual creation frame view. Does a LOT of stuff. """ self.createFrame = QWidget(self) self.cfgrid = QGridLayout() self.createFrame.setLayout(self.cfgrid) self.grid.addWidget(self.createFrame, 0, 0, 2, 2) self.lsdic = {} nameL = QLabel(self.createFrame, text="Name:") self.cfgrid.addWidget(nameL, 0, 0) self.nameT = QLineEdit(self.createFrame) self.nameT.setFixedSize(100, 20) self.cfgrid.addWidget(self.nameT, 0, 1) strL = QLabel(self.createFrame, text="Str") self.cfgrid.addWidget(strL, 0, 2) self.strT = QLineEdit(self.createFrame) self.strT.setFixedSize(20, 20) self.cfgrid.addWidget(self.strT, 0, 3) magL = QLabel(self.createFrame, text="Mag") self.cfgrid.addWidget(magL, 1, 2) self.magT = QLineEdit(self.createFrame) self.magT.setFixedSize(20, 20) self.cfgrid.addWidget(self.magT, 1, 3) endL = QLabel(self.createFrame, text="End") self.cfgrid.addWidget(endL, 2, 2) self.endT = QLineEdit(self.createFrame) self.endT.setFixedSize(20, 20) self.cfgrid.addWidget(self.endT, 2, 3) agiL = QLabel(self.createFrame, text="Agi") self.cfgrid.addWidget(agiL, 3, 2) self.agiT = QLineEdit(self.createFrame) self.agiT.setFixedSize(20, 20) self.cfgrid.addWidget(self.agiT, 3, 3) luckL = QLabel(self.createFrame, text="Luck") self.cfgrid.addWidget(luckL, 4, 2) self.luckT = QLineEdit(self.createFrame) self.luckT.setFixedSize(20, 20) self.cfgrid.addWidget(self.luckT, 4, 3) resList = json_reader.data_list("resistances") resL = QLabel(self.createFrame, text="Resistance:") self.cfgrid.addWidget(resL, 0, 5) slashL = QLabel(self.createFrame, text="Slash") self.cfgrid.addWidget(slashL, 1, 5) self.slashO = QComboBox(self.createFrame) self.slashO.addItems(resList) self.slashO.setCurrentIndex(1) self.cfgrid.addWidget(self.slashO, 1, 6) strikeL = QLabel(self.createFrame, text="Strike") self.cfgrid.addWidget(strikeL, 2, 5) self.strikeO = QComboBox(self.createFrame) self.strikeO.addItems(resList) self.strikeO.setCurrentIndex(1) self.cfgrid.addWidget(self.strikeO, 2, 6) pierceL = QLabel(self.createFrame, text="Pierce") self.cfgrid.addWidget(pierceL, 3, 5) self.pierceO = QComboBox(self.createFrame) self.pierceO.addItems(resList) self.pierceO.setCurrentIndex(1) self.cfgrid.addWidget(self.pierceO, 3, 6) fireL = QLabel(self.createFrame, text="Fire") self.cfgrid.addWidget(fireL, 4, 5) self.fireO = QComboBox(self.createFrame) self.fireO.addItems(resList) self.fireO.setCurrentIndex(1) self.cfgrid.addWidget(self.fireO, 4, 6) iceL = QLabel(self.createFrame, text="Ice") self.cfgrid.addWidget(iceL, 5, 5) self.iceO = QComboBox(self.createFrame) self.iceO.addItems(resList) self.iceO.setCurrentIndex(1) self.cfgrid.addWidget(self.iceO, 5, 6) elecL = QLabel(self.createFrame, text="Elec") self.cfgrid.addWidget(elecL, 6, 5) self.elecO = QComboBox(self.createFrame) self.elecO.addItems(resList) self.elecO.setCurrentIndex(1) self.cfgrid.addWidget(self.elecO, 6, 6) windL = QLabel(self.createFrame, text="Wind") self.cfgrid.addWidget(windL, 7, 5) self.windO = QComboBox(self.createFrame) self.windO.addItems(resList) self.windO.setCurrentIndex(1) self.cfgrid.addWidget(self.windO, 7, 6) lightL = QLabel(self.createFrame, text="Light") self.cfgrid.addWidget(lightL, 8, 5) self.lightO = QComboBox(self.createFrame) self.lightO.addItems(resList) self.lightO.setCurrentIndex(1) self.cfgrid.addWidget(self.lightO, 8, 6) darkL = QLabel(self.createFrame, text="Dark") self.cfgrid.addWidget(darkL, 9, 5) self.darkO = QComboBox(self.createFrame) self.darkO.addItems(resList) self.darkO.setCurrentIndex(1) self.cfgrid.addWidget(self.darkO, 9, 6) spellList = json_reader.data_list("spells") self.listLS = QListWidget(self.createFrame) self.listLS.setFixedSize(200, 300) self.cfgrid.addWidget(self.listLS, 3, 7, 8, 2) newLS = QPushButton(self.createFrame, text="+") newLS.clicked.connect(self.addLS) self.cfgrid.addWidget(newLS, 2, 7) delLS = QPushButton(self.createFrame, text="DEL") delLS.clicked.connect(self.delLS) self.cfgrid.addWidget(delLS, 2, 8) lsl = QLabel(self.createFrame, text="Learned Spells:") self.cfgrid.addWidget(lsl, 0, 7, 1, 2) arcanaL = QLabel(self.createFrame, text="Arcana:") self.cfgrid.addWidget(arcanaL, 1, 0) arc_list = json_reader.data_list("arcanas") self.arcO = QComboBox(self.createFrame) self.arcO.addItems(arc_list) self.arcO.setCurrentIndex(0) self.cfgrid.addWidget(self.arcO, 1, 1) levelL = QLabel(self.createFrame, text="Level:") self.cfgrid.addWidget(levelL, 2, 0) self.levelT = QLineEdit(self.createFrame) self.levelT.setFixedSize(20, 20) self.cfgrid.addWidget(self.levelT, 2, 1) heritageL = QLabel(self.createFrame, text="Inherits:") self.cfgrid.addWidget(heritageL, 3, 0, 1, 2) elements = json_reader.data_list("elements") elements.append("Support") self.listEL1 = QComboBox(self.createFrame) self.listEL1.addItems(elements) self.cfgrid.addWidget(self.listEL1, 4, 0) self.listEL2 = QComboBox(self.createFrame) self.listEL2.addItems(elements) self.cfgrid.addWidget(self.listEL2, 4, 1) iSpellL = QLabel(self.createFrame, text="Initial Spells:") self.cfgrid.addWidget(iSpellL, 5, 0, 1, 2) self.iSpellOs = [] for i in range(6, 9): temp = QComboBox(self.createFrame) temp.addItems(spellList) temp2 = QComboBox(self.createFrame) temp2.addItems(spellList) self.cfgrid.addWidget(temp, i, 0, 1, 2) self.cfgrid.addWidget(temp2, i, 2, 1, 2) self.iSpellOs.extend([temp, temp2]) textL = QLabel(self.createFrame, text="Info:") self.cfgrid.addWidget(textL, 10, 0) self.textT = QTextEdit(self.createFrame) self.textT.setFixedSize(300, 100) self.cfgrid.addWidget(self.textT, 10, 1, 1, 5) self.lslevel = QLineEdit(self.createFrame) self.lslevel.setFixedSize(40, 20) self.lsSpellO = QComboBox(self.createFrame) self.lsSpellO.addItems(spellList) self.cfgrid.addWidget(self.lsSpellO, 1, 7) self.cfgrid.addWidget(self.lslevel, 1, 8) def addLS(self): """ Add a learned spell to the list, based on what was entered. """ print("Adding learned spell") chosenSpell = self.lsSpellO.currentText() if (int)(self.lslevel.text()) <= (int)(self.levelT.text()): popup("You cannot add a spell at an earlier level than the Persona's base level", "Critical") return if chosenSpell != "": print("Ok") self.lsdic[chosenSpell] = self.lslevel.text() self.listLS.addItem(chosenSpell + " at level " + self.lslevel.text()) self.lslevel.setText("") self.lsSpellO.setCurrentIndex(0) return popup("You must choose a spell", "Critical") def delLS(self): """ Remove the selected learned spell from the list """ print("Deleting learned spell") key = "" i = 0 while len(self.listLS.currentItem().text()) > i: if self.listLS.currentItem().text()[i] == " " and \ self.listLS.currentItem().text()[i+1] == "a" and \ self.listLS.currentItem().text()[i+2] == "t": # TODO EWWWWWW break key += self.listLS.currentItem().text()[i] i = i + 1 print(key) print(self.lsdic.pop(key)) self.listLS.takeItem(self.listLS.currentRow()) def loadPer(self, name): """ Load a certain Persona from file. :param str name: name of Persona to load """ data = json_reader.readOne(name, 'pers') self.nameT.setText(data["name"]) self.textT.setText(data["desc"]) self.strT.setText(data["stats"][0]) self.magT.setText(data["stats"][1]) self.endT.setText(data["stats"][2]) self.agiT.setText(data["stats"][3]) self.luckT.setText(data["stats"][4]) self.levelT.setText(data["level"]) self.arcO.setCurrentIndex( [self.arcO.itemText(i) for i in range(self.arcO.count())].index(data["arcana"]) ) self.listEL1.setCurrentIndex( [self.listEL1.itemText(i) for i in range(self.listEL1.count())].index(data["heritage"][0]) ) self.listEL2.setCurrentIndex( [self.listEL2.itemText(i) for i in range(self.listEL2.count())].index(data["heritage"][1]) ) self.slashO.setCurrentIndex( [self.slashO.itemText(i) for i in range(self.slashO.count())].index(data["resistance"][0]) ) self.strikeO.setCurrentIndex( [self.strikeO.itemText(i) for i in range(self.strikeO.count())].index(data["resistance"][1]) ) self.pierceO.setCurrentIndex( [self.pierceO.itemText(i) for i in range(self.pierceO.count())].index(data["resistance"][2]) ) self.fireO.setCurrentIndex( [self.fireO.itemText(i) for i in range(self.fireO.count())].index(data["resistance"][3]) ) self.iceO.setCurrentIndex( [self.iceO.itemText(i) for i in range(self.iceO.count())].index(data["resistance"][4]) ) self.elecO.setCurrentIndex( [self.elecO.itemText(i) for i in range(self.elecO.count())].index(data["resistance"][5]) ) self.windO.setCurrentIndex( [self.windO.itemText(i) for i in range(self.windO.count())].index(data["resistance"][6]) ) self.lightO.setCurrentIndex( [self.lightO.itemText(i) for i in range(self.lightO.count())].index(data["resistance"][7]) ) self.darkO.setCurrentIndex( [self.darkO.itemText(i) for i in range(self.darkO.count())].index(data["resistance"][8]) ) i = 0 for combobox in self.iSpellOs: combobox.setCurrentIndex( [combobox.itemText(j) for j in range(combobox.count()-1)].index(data["spellDeck"][i]) ) i += 1 self.lsdic = data["spellLearn"] self.listLS.clear() for spell, level in self.lsdic.items(): self.listLS.addItem(spell + " at level " + level) print("Loaded " + data["name"]) def edit(self): """ Switch to edit view, also loads the selected Persona. """ try: if self.listP.currentItem().text() != "": if self.createFrame and not popup("Override any unsaved changes?", "Warning"): return self.loadPer(self.listP.currentItem().text()) except AttributeError: # To initialize createFrame UI before load if self.listP.currentItem().text() != "": temp = self.listP.currentItem().text() self.buttonFrame.close() self.initUI(False) self.loadPer(temp) else: return self.createFrame.show() self.mainframe.center() print("Changed to edit frame") def save(self): """ Validate all info and save to file on disk. """ if os.path.exists(json_reader.buildPath("data/pers/"+self.nameT.text()+".json")): if not popup("Override existing Persona "+self.nameT.text()+"?", "Question"): return print("Saving") spellDeck = [] for combobox in self.iSpellOs: spellDeck.append(combobox.currentText()) stats = [self.strT.text(), self.magT.text(), self.endT.text(), self.agiT.text(), self.luckT.text()] res = [self.slashO.currentText(), self.strikeO.currentText(), self.pierceO.currentText(), self.fireO.currentText(), self.iceO.currentText(), self.elecO.currentText(), self.windO.currentText(), self.lightO.currentText(), self.darkO.currentText()] try: (int)(self.levelT.text()) (int)(self.strT.text()) (int)(self.magT.text()) (int)(self.endT.text()) (int)(self.agiT.text()) (int)(self.luckT.text()) except ValueError: popup("There is a number entry that isn't valid.\nEntries requiring numbers are:\nLEVEL\nSTR" "\nMAG\nEND\nAGI\nLUCK", "Critical") print("Not Saved") return if not (self.nameT.text() and not self.nameT.text().isspace()): popup("No name entered for your Persona. Name is a required field.", "Critical") print("No Name, not saved") return toWrite = Persona( self.nameT.text(), self.arcO.currentText(), self.levelT.text(), self.textT.toPlainText(), spellDeck, self.lsdic, stats, res, [self.listEL1.currentText(), self.listEL2.currentText()] ) json_reader.writeOne(toWrite, 'pers') temp = self.nameT.text() if (temp not in [self.listP.item(i).text() for i in range(self.listP.count())]): self.listP.addItem(temp) self.loadPer(temp) print("Saved Persona") def remove(self): """ Remove a created Persona from the list and delete the file on disk. """ if self.listP.currentItem().text() == "": return if not popup( "Are you certain you want to completely remove this Persona?\n(Cannot be undone)", "Warning" ): return print("Removing Persona " + self.listP.currentItem().text()) json_reader.deletePer(self.listP.currentItem().text()) self.listP.takeItem( [self.listP.item(i).text() for i in range(self.listP.count())].index( self.listP.currentItem().text()) ) def new(self): """ Open an empty Persona edit view. """ if self.createFrame and not popup("Override any unsaved changes?", "Warning"): return if self.createFrame: self.createFrame.close() self.buttonFrame.close() self.initUI(False) self.createFrame.show() self.mainframe.center() print("Created") def back(self): """ Return to the parent widget. """ print("Returned to main screen") self.mainframe.changeState(self.op)
class InstructionRegister(QWidget): def __init__(self, parent, usbif, color): super().__init__(parent) self._status_inds = {} self._setup_ui(color) usbif.poll("monitor", um.MonRegI()) usbif.listen(self) def handle_msg(self, msg): if isinstance(msg, um.MonRegI): self.set_i_values(msg.br, msg.st, msg.sqext, msg.sq) elif isinstance(msg, um.MonRegStatus): self._status_inds['iip'].indicator.set_on(msg.iip) self._status_inds['inhl'].indicator.set_on(msg.inhl) self._status_inds['inkl'].indicator.set_on(msg.inkl) #elif isinstance(msg, um.StatusPeripheral): # self._status_inds['ld'].indicator.set_on(msg.ld) # self._status_inds['chld'].indicator.set_on(msg.chld) # self._status_inds['rd'].indicator.set_on(msg.rd) # self._status_inds['chrd'].indicator.set_on(msg.chrd) def set_i_values(self, br, st, sqext, sq): self.br.set_value(br) self.st.set_value(st) self.sq.set_value(sqext << 6 | sq) self._inst_value.setText(agc.disassemble_subinst(sqext, sq, st)) def _setup_ui(self, color): # Set up our basic layout layout = QHBoxLayout(self) self.setLayout(layout) layout.setSpacing(3) layout.setMargin(1) # Construct register groups for BR, ST, and SQ self.br = SubRegister(self, "BR", 2, color) self.st = SubRegister(self, "ST", 3, color) self.sq = SubRegister(self, "SQ", 7, color) layout.addWidget(self.br) layout.addWidget(self.st) layout.addWidget(self.sq) # Status indicators wl = QHBoxLayout() wl.setSpacing(1) wl.setContentsMargins(2, 3, 3, 2) layout.addLayout(wl) for name, label in STATUS_INDS.items(): w = ApolloLabeledIndicator(self, label, QColor(0, 255, 255), lines=2, labelwidth=35) wl.addWidget(w) self._status_inds[name] = w # Create a grouping widget for the I label and decoded instruction value box label_value_layout = QHBoxLayout() label_value_layout.setSpacing(3) label_value_layout.setContentsMargins(0, 33, 0, 0) layout.addLayout(label_value_layout) # Create a value box for displaying the overall decoded instruction self._inst_value = QLineEdit(self) self._inst_value.setFixedSize(70, 32) self._inst_value.setReadOnly(True) self._inst_value.setAlignment(Qt.AlignCenter) self._inst_value.setText('TC0') self._inst_value.setStyleSheet("QLineEdit { color: #555; }") label_value_layout.addWidget(self._inst_value) # Create a label to show 'I' label = QLabel('I', self) label.setFixedWidth(20) label_value_layout.addWidget(label)
if __name__ == '__main__': # Path to the stylesheets directory stylesheet_directory = pathlib.Path().resolve().parent / 'rc/stylesheet' # The name of the stylesheet qssimport creates main_stylesheet = stylesheet_directory / 'Style.qss' # Stylesheet with the import statements imports_stylesheet = stylesheet_directory / 'import.qss' stylesheet = StyleSheet(base_dir=stylesheet_directory, import_def_file=imports_stylesheet, main_stylesheet=main_stylesheet) app = QApplication([]) widget = QWidget() stylesheet.style_widget(widget) layout = QGridLayout() widget.setLayout(layout) le = QLineEdit(widget) btn = QPushButton('Push Button') le.setText('wubalubadubdub') size = QSize(116, 25) le.setFixedSize(size) btn.setFixedSize(size) layout.addWidget(btn) layout.addWidget(le) widget.setFixedSize(140, 80) widget.show() app.exit(app.exec_())
class SpeakFrame(QWidget): """ Speak frame. Represents the edit view of speak actions. :param QWidget op: parent widget :param object load: something to load or 0 """ def __init__(self, op, load): QWidget.__init__(self) self.op = op self.load = load self.pointvec = [] self.pointvar = [] self.anglevec = [] self.anglevar = [] self.addPAtIndex = 4 self.addAAtIndex = 4 self.initUI() self.op.grid.addWidget(self, 1, 0, 1, 5) def initUI(self): """ Initializes the GUI. Does lots of stuff. """ self.grid = QGridLayout() self.setLayout(self.grid) self.characs = json_reader.readCharNames() self.arcanas = json_reader.data_list("arcanas") self.arcanas.extend([""]) self.textl = QLabel(self, text="Text:") self.grid.addWidget(self.textl, 1, 0) self.infoBox = QTextEdit(self) self.infoBox.setFixedSize(300, 150) self.grid.addWidget(self.infoBox, 1, 1, 3, 3) self.textl = QLabel(self, text="Points:") self.grid.addWidget(self.textl, 2, 4, 1, 2) self.pointBox = QLineEdit(self) self.pointBox.setFixedSize(20, 20) self.grid.addWidget(self.pointBox, 3, 4) self.pointvec.append(self.pointBox) pointOM = QComboBox(self) pointOM.addItems(self.arcanas) pointOM.setCurrentIndex(pointOM.count() - 1) self.grid.addWidget(pointOM, 3, 5) self.pointvar.append(pointOM) self.textl = QLabel(self, text="Angle:") self.grid.addWidget(self.textl, 2, 6, 1, 2) angleBox = QLineEdit(self) angleBox.setFixedSize(20, 20) self.grid.addWidget(angleBox, 3, 6) self.anglevec.append(angleBox) angleOM = QComboBox(self) angleOM.addItems(self.arcanas) angleOM.setCurrentIndex(angleOM.count() - 1) self.grid.addWidget(angleOM, 3, 7) self.anglevar.append(angleOM) self.speakerl = QLabel(self, text="Speaker:") self.grid.addWidget(self.speakerl, 1, 4) self.speaker = QComboBox(self) self.speaker.addItems(self.characs) self.grid.addWidget(self.speaker, 1, 5) self.emotionL = QLabel(self, text="Emotion:") #emotionL memes self.grid.addWidget(self.emotionL, 1, 6) self.s_emotions = json_reader.data_list('sprite_emotions') self.emotion = QComboBox(self) self.emotion.addItems(self.s_emotions) self.grid.addWidget(self.emotion, 1, 7) self.addp = QPushButton(self, text="Add points") self.addp.clicked.connect(self.extendP) self.grid.addWidget(self.addp, 30, 4, 1, 2) self.adda = QPushButton(self, text="Add angles") self.adda.clicked.connect(self.extendA) self.grid.addWidget(self.adda, 30, 6, 1, 2) if self.load != 0: self.infoBox.setText(self.load.getText()) self.speaker.setCurrentIndex( self.characs.index(self.load.getSpeaker())) self.emotion.setCurrentIndex( self.s_emotions.index(self.load.emotion)) first = True for arcana, points in self.load.getPoints().items(): if first: first = False else: self.extendP() self.pointvec[-1].setText(str(points)) self.pointvar[-1].setCurrentIndex(self.arcanas.index(arcana)) first = True for arcana, angle in self.load.getAngle().items(): if first: first = False else: self.extendA() self.anglevec[-1].setText(str(angle)) self.anglevar[-1].setCurrentIndex(self.arcanas.index(arcana)) def extendP(self): """ Add an extra line to the points/arcana list. """ self.pointvec.extend([QLineEdit(self)]) self.pointvec[-1].setFixedSize(20, 20) self.pointvar.extend([QComboBox(self)]) self.grid.addWidget(self.pointvec[-1], self.addPAtIndex, 4) self.pointvar[-1].addItems(self.arcanas) self.pointvar[-1].setCurrentIndex(self.pointvar[-1].count() - 1) self.grid.addWidget(self.pointvar[-1], self.addPAtIndex, 5) self.addPAtIndex += 1 def extendA(self): """ Add an extra line to the angle/arcana list. """ self.anglevec.extend([QLineEdit(self)]) self.anglevec[-1].setFixedSize(20, 20) self.anglevar.extend([QComboBox(self)]) self.grid.addWidget(self.anglevec[-1], self.addAAtIndex, 6) self.anglevar[-1].addItems(self.arcanas) self.anglevar[-1].setCurrentIndex(self.anglevar[-1].count() - 1) self.grid.addWidget(self.anglevar[-1], self.addAAtIndex, 7) self.addAAtIndex += 1 def save(self): """ Save this speak action to the cutscene. """ print("Saving") print("...") speakSlide = Speak() speakSlide.setText(self.infoBox.toPlainText()) speakSlide.setSpeaker(self.speaker.currentText()) speakSlide.emotion = self.emotion.currentText() for i in range(len(self.pointvec)): if self.pointvar[i].currentText() != "": try: amount = (int)(self.pointvec[i].text()) speakSlide.putPoints(self.pointvar[i].currentText(), amount) except ValueError: popup( "All Points must be integers.\nTo discard one line, empty the text field and set " "the arcana to blank.", "Critical") print("Amount must be an integer") for i in range(len(self.anglevec)): if self.anglevar[i].currentText() != "": try: amount = (int)(self.anglevec[i].text()) speakSlide.putAngle(self.anglevar[i].currentText(), amount) except ValueError: popup( "All Points and Angles must be integers.\nTo discard one line, set empty the text " "field and set the arcana to blank.", "Critical") print("Amount must be an integer") self.op.op.link.addItem(speakSlide, self.op.op.i) print("Saved") self.op.op.linkstored.setLink(self.op.op.link, self.op.op.level, self.op.op.angle) self.op.op.linkstored.save() self.op.updateElementList() popup("Saved!", "Information")
class SubComparator(QWidget): def __init__(self, parent, width, on_change=None, include_values=True, item_width=20, separators=True): super().__init__(parent) self.width = width self.on_change = on_change self.include_values = include_values self.item_width = item_width self.separators = separators self._reg_switches = [] self._ign_switches = [] self.updating_switches = False self._setup_ui() @property def reg_value(self): if self.include_values: text = self.reg_box.text() if text == '': return 0 return int(text, 8) else: return self._get_switch_value(self._reg_switches) def set_reg_value(self, value): self._update_switches(value, self._reg_switches) if self.include_values: self._update_reg_box() @property def ign_value(self): if self.include_values: text = self.ign_box.text() if text == '': return 0 return int(text, 8) else: return self._get_switch_value(self._ign_switches) def _setup_ui(self): self.setStyleSheet("QFrame { color: #666; }") layout = QVBoxLayout(self) self.setLayout(layout) layout.setMargin(0) layout.setSpacing(0) if self.include_values: # Value boxes vw = QWidget(self) vl = QHBoxLayout() vl.setSpacing(2) vl.setContentsMargins(0, 0, 0, 2) vw.setLayout(vl) layout.addWidget(vw) layout.setAlignment(vw, Qt.AlignRight) # Create textboxes to show the register's value and ignore mask in octal n_digits = int((self.width + 2) / 3) if n_digits == 1: value_width = 25 elif n_digits == 2: value_width = 30 else: value_width = 45 self.reg_box = QLineEdit(vw) self.reg_box.setFixedSize(value_width, 32) self.reg_box.setText(n_digits * '0') self.reg_box.setAlignment(Qt.AlignCenter) self.reg_box.setValidator(OctalValidator(2**self.width - 1)) self.reg_box.setMaxLength(n_digits) self.reg_box.returnPressed.connect(self._update_reg_switches) vl.addWidget(self.reg_box) self.ign_box = QLineEdit(vw) self.ign_box.setMaximumSize(value_width, 32) self.ign_box.setText(n_digits * '0') self.ign_box.setAlignment(Qt.AlignCenter) self.ign_box.setValidator(OctalValidator(2**self.width - 1)) self.ign_box.setMaxLength(n_digits) self.ign_box.returnPressed.connect(self._update_ign_switches) vl.addWidget(self.ign_box) # Switches ssf = QFrame(self) ssf.setFrameStyle(QFrame.Panel | QFrame.Plain) ssf.setStyleSheet( 'QCheckBox::indicator { subcontrol-position: center; }') ssl = QHBoxLayout() ssl.setSpacing(1) ssl.setContentsMargins(1, 0, 2, 0) ssf.setLayout(ssl) layout.addWidget(ssf) layout.setAlignment(ssf, Qt.AlignRight) for i in range(self.width, 0, -1): sw = QWidget(ssf) sl = QVBoxLayout() sl.setSpacing(1) sl.setContentsMargins(0, 1, 0, 1) sw.setLayout(sl) s1 = QCheckBox(sw) s1.setFixedSize(self.item_width, 20) sl.addWidget(s1) sl.setAlignment(s1, Qt.AlignCenter) s1.stateChanged.connect(self._update_reg_value) self._reg_switches.insert(0, s1) s2 = QCheckBox(sw) s2.setFixedSize(self.item_width, 20) sl.addWidget(s2) sl.setAlignment(s2, Qt.AlignCenter) s2.stateChanged.connect(self._update_ign_value) self._ign_switches.insert(0, s2) ssl.addWidget(sw) # Add separators between each group of 3 bits if self.separators and i in [17, 13, 10, 7, 4]: sep = QFrame(ssf) sep.setFrameStyle(QFrame.VLine | QFrame.Plain) ssl.addWidget(sep) def _get_switch_value(self, switches): val = 0 for i, s in enumerate(switches): if s.isChecked(): val |= (1 << i) return val def _update_reg_switches(self): self._update_switches(self.reg_value, self._reg_switches) def _update_ign_switches(self): self._update_switches(self.ign_value, self._ign_switches) def _update_switches(self, val, switches): self.updating_switches = True for i, s in enumerate(switches): s.setChecked((val & (1 << i)) != 0) self.updating_switches = False self._on_change() def _update_reg_value(self): if self.updating_switches: return if self.include_values: self._update_box(self.reg_box, self._reg_switches) self._on_change() def _update_ign_value(self): if self.updating_switches: return if self.include_values: self._update_box(self.ign_box, self._ign_switches) self._on_change() def _update_box(self, box, switches): val = self._get_switch_value(switches) max_length = box.maxLength() fmt = '%%0%uo' % max_length box.setText(fmt % val) if not self.updating_switches: self._on_change() def _on_change(self): if self.on_change is not None: self.on_change()
class CameraFrame(QWidget): """ Camera frame. Represents the edit view of camera actions. :param QWidget op: parent widget :param object load: something to load or 0 """ def __init__(self, op, load): QWidget.__init__(self) self.op = op self.load = load self.initUI() self.op.grid.addWidget(self, 1, 0, 1, 5) def initUI(self): """ Initializes the GUI. Does lots of stuff. """ self.grid = QGridLayout() self.setLayout(self.grid) self.locations = json_reader.data_list("locations") self.textl = QLabel(self, text="Camera's position x:") self.grid.addWidget(self.textl, 1, 0) self.cx = QLineEdit(self) self.cx.setFixedSize(20, 20) self.grid.addWidget(self.cx, 1, 1) self.textl = QLabel(self, text="Camera's position y:") self.grid.addWidget(self.textl, 2, 0) self.cy = QLineEdit(self) self.cy.setFixedSize(20, 20) self.grid.addWidget(self.cy, 2, 1) self.textl = QLabel(self, text="Camera's position z:") self.grid.addWidget(self.textl, 3, 0) self.cz = QLineEdit(self) self.cz.setFixedSize(20, 20) self.grid.addWidget(self.cz, 3, 1) self.textl = QLabel(self, text="Look at x:") self.grid.addWidget(self.textl, 1, 2) self.lx = QLineEdit(self) self.lx.setFixedSize(20, 20) self.grid.addWidget(self.lx, 1, 3) self.textl = QLabel(self, text="Look at y:") self.grid.addWidget(self.textl, 2, 2) self.ly = QLineEdit(self) self.ly.setFixedSize(20, 20) self.grid.addWidget(self.ly, 2, 3) self.textl = QLabel(self, text="Look at z:") self.grid.addWidget(self.textl, 3, 2) self.lz = QLineEdit(self) self.lz.setFixedSize(20, 20) self.grid.addWidget(self.lz, 3, 3) self.locationl = QLabel(self, text="Location:") self.grid.addWidget(self.locationl, 1, 4) self.locationO = QComboBox(self) self.locationO.addItems(self.locations) self.locationO.setCurrentIndex(0) self.grid.addWidget(self.locationO, 1, 5) if self.load != 0: self.locationO.setCurrentIndex( self.locations.index(self.load.getPlace())) cp = self.load.getCameraPosition() la = self.load.getLookAt() self.cx.setText(str(cp[0])) self.cy.setText(str(cp[1])) self.cz.setText(str(cp[2])) self.lx.setText(str(la[0])) self.ly.setText(str(la[1])) self.lz.setText(str(la[2])) def save(self): """ Save this camera action to the cutscene. """ print("Saving") cameraSlide = Camera() cameraSlide.setPlace(self.locationO.currentText()) print("...") try: (int)(self.lx.text()) (int)(self.ly.text()) (int)(self.lz.text()) (int)(self.cx.text()) (int)(self.cy.text()) (int)(self.cz.text()) except ValueError: popup( "Camera position (x, y, z) and look direction (x, y, z) must be entered as whole numbers", "Critical") return cameraSlide.setLookAt(((int)(self.lx.text()), (int)(self.ly.text()), (int)(self.lz.text()))) cameraSlide.setCameraPosition( ((int)(self.cx.text()), (int)(self.cy.text()), (int)(self.cz.text()))) self.op.op.link.addItem(cameraSlide, self.op.op.i) print("Saved") self.op.op.linkstored.setLink(self.op.op.link, self.op.op.level, self.op.op.angle) self.op.op.linkstored.save() self.op.updateElementList() popup("Saved!", "Information")
class SComparator(QWidget): def __init__(self, parent, usbif, num): super().__init__(parent) self._usbif = usbif self.num = num self._eb = 0 self._eb_ign = 0 self._fext = 0 self._fext_ign = 0 self._fb = 0 self._fb_ign = 0 self._s = 0 self._s_ign = 0 self._setup_ui() self._write_s_msg = getattr(um, f'ControlS{num}S') self._write_bank_msg = getattr(um, f'ControlS{num}Bank') self._write_s_ign_msg = getattr(um, f'ControlS{num}SIgnore') self._write_bank_ign_msg = getattr(um, f'ControlS{num}BankIgnore') usbif.send(self._write_s_msg(s=0)) usbif.send(self._write_bank_msg(eb=0, fb=0, fext=0)) usbif.send(self._write_s_ign_msg(s=0)) usbif.send(self._write_bank_ign_msg(eb=0, fb=0, fext=0)) def _setup_ui(self): layout = QHBoxLayout(self) self.setLayout(layout) layout.setSpacing(3) layout.setMargin(1) self.ebank = SubComparator(self, 3, on_change=self._update_address) layout.addWidget(self.ebank) self.fext = SubComparator(self, 3, on_change=self._update_address) layout.addWidget(self.fext) self.fbank = SubComparator(self, 5, on_change=self._update_address) layout.addWidget(self.fbank) self.s = SubComparator(self, 12, on_change=self._update_address) layout.addWidget(self.s) # Create a grouping widget for the S label and decoded octal value box label_value_layout = QHBoxLayout() label_value_layout.setSpacing(3) label_value_layout.setMargin(1) label_value_layout.setContentsMargins(0, 33, 0, 0) layout.addLayout(label_value_layout) # Create a value box for displaying the overall decoded address self._addr_value = QLineEdit(self) label_value_layout.addWidget(self._addr_value) self._addr_value.setFixedSize(70, 32) self._addr_value.setReadOnly(True) self._addr_value.setAlignment(Qt.AlignCenter) self._addr_value.setText('0000') self._addr_value.setStyleSheet("QLineEdit { color: #555; }") # Create a label to show 'S' label = QLabel(f"S{self.num}", self) label.setFixedWidth(20) label_value_layout.addWidget(label) def _update_address(self): eb = self.ebank.reg_value fext = self.fext.reg_value fb = self.fbank.reg_value s = self.s.reg_value eb_ign = self.ebank.ign_value fext_ign = self.fext.ign_value fb_ign = self.fbank.ign_value s_ign = self.s.ign_value if self._s != s: self._s = s msg = self._write_s_msg(s=s) print(msg) self._usbif.send(msg) if (self._eb != eb) or (self._fb != fb) or (self._fext != fext): self._eb = eb self._fext = fext self._fb = fb self._usbif.send(self._write_bank_msg(eb=eb, fext=fext, fb=fb)) if self._s_ign != s_ign: self._s_ign = s_ign msg = self._write_s_ign_msg(s=s_ign) print(msg) self._usbif.send(msg) if (self._eb_ign != eb_ign) or (self._fb_ign != fb_ign) or ( self._fext_ign != fext_ign): self._eb_ign = eb_ign self._fext_ign = fext_ign self._fb_ign = fb_ign msg = self._write_bank_ign_msg(eb=eb_ign, fext=fext_ign, fb=fb_ign) print(msg) self._usbif.send(msg) self._addr_value.setText(agc.format_addr(s, eb, fb, fext))
class IComparator(QWidget): def __init__(self, parent, usbif): super().__init__(parent) self._usbif = usbif self._br = 0 self._st = 0 self._sqext = 0 self._sq = 0 self._br_ign = 0 self._st_ign = 0 self._sqext_ign = 0 self._sq_ign = 0 self._setup_ui() def _setup_ui(self): layout = QHBoxLayout(self) self.setLayout(layout) layout.setSpacing(3) layout.setMargin(1) self.br = SubComparator(self, 2, on_change=self._update_instruction) layout.addWidget(self.br) self.st = SubComparator(self, 3, on_change=self._update_instruction) layout.addWidget(self.st) self.sq = SubComparator(self, 7, on_change=self._update_instruction) layout.addWidget(self.sq) self.status = SubComparator(self, 7, on_change=self._update_status, include_values=False, item_width=35, separators=False) layout.addWidget(self.status) layout.setAlignment(self.status, Qt.AlignBottom) # Create a grouping widget for the I label and decoded octal value box label_value_layout = QHBoxLayout() label_value_layout.setSpacing(3) label_value_layout.setMargin(1) label_value_layout.setContentsMargins(0, 33, 0, 0) layout.addLayout(label_value_layout) # Create a value box for displaying the overall decoded address self._instr_value = QLineEdit(self) self._instr_value.setFixedSize(70, 32) self._instr_value.setReadOnly(True) self._instr_value.setAlignment(Qt.AlignCenter) self._instr_value.setText('TC0') self._instr_value.setStyleSheet("QLineEdit { color: #555; }") label_value_layout.addWidget(self._instr_value) # Create a label to show 'I' label = QLabel(f"I", self) label.setFixedWidth(20) label_value_layout.addWidget(label) def _update_instruction(self): br = self.br.reg_value st = self.st.reg_value sq = self.sq.reg_value sqext = (sq >> 6) & 0o1 sq &= 0o77 br_ign = self.br.ign_value st_ign = self.st.ign_value sq_ign = self.sq.ign_value sqext_ign = (sq_ign >> 6) & 0o1 sq_ign &= 0o77 if (self._br != br) or (self._st != st) or (self._sq != sq) or ( self._sqext != sqext): self._br = br self._st = st self._sq = sq self._sqext = sqext msg = um.ControlICompVal(br=br, st=st, sqext=sqext, sq=sq) self._usbif.send(msg) if (self._br_ign != br_ign) or (self._st_ign != st_ign) or ( self._sq_ign != sq_ign) or (self._sqext_ign != sqext_ign): self._br_ign = br_ign self._st_ign = st_ign self._sq_ign = sq_ign self._sqext_ign = sqext_ign msg = um.ControlICompIgnore(br=br_ign, st=st_ign, sqext=sqext_ign, sq=sq_ign) self._usbif.send(msg) self._instr_value.setText(agc.disassemble_subinst(sqext, sq, st)) def _update_status(self): reg_states = [s.isChecked() for s in self.status._reg_switches] ign_states = [s.isChecked() for s in self.status._ign_switches] reg_keys = list(STATUS_INDS.keys()) ign_keys = [k + "_ign" for k in reg_keys] status_reg = dict(zip(reg_keys, reversed(reg_states))) status_ign = dict(zip(ign_keys, reversed(ign_states))) status_bits = {**status_reg, **status_ign} msg = um.ControlICompStatus(**status_bits) self._usbif.send(msg)
class CharUI(QWidget): """ Main widget for the Character creator view. :param MainFrame mainframe: the application mainframe :param QWidget op: parent widget """ def __init__(self, mainframe, op): print("Starting...") QWidget.__init__(self) self.mainframe = mainframe self.op = op self.nameT = None self.infoT = None self.importantB = None self.initUI() def initUI(self): """ Initializes the GUI. Does a lot of stuff. """ self.mainframe.setWindowTitle("Character Creator") grid = QGridLayout() self.setLayout(grid) nameL = QLabel(self, text="Name:") grid.addWidget(nameL, 1, 1) self.nameT = QLineEdit(self) self.nameT.setFixedSize(200, 20) grid.addWidget(self.nameT, 1, 2, 1, 2) self.importantB = QCheckBox(self, text="Important?") grid.addWidget(self.importantB, 1, 4) infoL = QLabel(self, text="Info:") grid.addWidget(infoL, 2, 1) self.infoT = QTextEdit(self) self.infoT.setFixedSize(300, 150) grid.addWidget(self.infoT, 2, 2, 1, 3) save = QPushButton(self, text="Save") save.clicked.connect(self.save) grid.addWidget(save, 4, 1) remove = QPushButton(self, text="Remove") remove.clicked.connect(self.remove) grid.addWidget(remove, 4, 2) back = QPushButton(self, text="Back") back.clicked.connect(self.back) grid.addWidget(back, 4, 3) names = json_reader.readCharNames() names.append("New") self.allChars = QComboBox(self) self.allChars.activated.connect((lambda: self.loadChar(self.allChars.currentText()))) self.allChars.addItems(names) self.allChars.setCurrentIndex(self.allChars.count()-1) grid.addWidget(self.allChars, 4, 4) def loadChar(self, name): """ Load one character from file based on the name. :param str name: name of character to load """ print("Loading...") if self.importantB.isChecked(): self.importantB.toggle() self.nameT.clear() self.infoT.clear() if name == "New": return characterL = json_reader.readOne(name, 'chars') charTL = Character(characterL["name"], characterL["desc"], characterL["important"]) if charTL.getImportant(): self.importantB.toggle() self.nameT.setText(charTL.getName()) self.infoT.setText(charTL.getDesc()) print("Loaded character " + self.allChars.currentText()) def remove(self): """ Remove a character from the list, and remove them from disk. """ if not popup("Are you certain you want to completely remove this character?\n(Cannot be undone)", "Warning"): return print("Removing character " + self.allChars.currentText()) json_reader.deleteChar(self.allChars.currentText()) self.allChars.removeItem(self.allChars.currentIndex()) self.allChars.setCurrentIndex(self.allChars.count()-1) self.loadChar("New") def save(self): """ Save a character to disk from the information entered in the GUI. """ if self.nameT.text() in ["New", ""]: popup("Sorry, your character cannot be called \""+self.nameT.text()+"\". That is a reserved " "keyword (and it's also a dumb name)", "Critical") return print("Saving") try: toWrite = Character(self.nameT.text(), self.infoT.toPlainText(), self.importantB.isChecked()) except UnicodeEncodeError as e: print(e) print(type(e)) popup("Sorry, unicode characters are not supported.", "Critical") return json_reader.writeOne(toWrite, 'chars') if toWrite.getName() not in [self.allChars.itemText(i) for i in range(self.allChars.count())]: self.allChars.insertItem(self.allChars.count()-1, self.nameT.text()) self.allChars.setCurrentIndex(self.allChars.count()-2) print("Saved") def back(self): """ Return the view to the calling widget. """ self.mainframe.changeState(self.op)
class LinkInfo(QWidget): """ Social Link general information view. :param MainFrame mainframe: the application's mainframe :param QWidget op: parent widget :param SocialLink link: the social link :param int linklevel: the level at which to add level-specific information :param int linkangle: the angle at which to add angle-specific information """ def __init__(self, mainframe, op, link, linklevel=None, linkangle=None): QWidget.__init__(self) self.mainframe = mainframe self.op = op self.link = link self.linklevel = linklevel self.linkangle = linkangle self.reqs = None self.initUI() def initUI(self): """ Initializes the GUI. Does a lot of stuff. """ self.grid = QGridLayout() self.setLayout(self.grid) self.levang = {} elev = [] for key, _ in self.link.cutscenes.items(): if key[:key.index("_")] in self.levang: self.levang[key[:key.index("_")]].append(key[key.index("_") + 1:]) else: self.levang[key[:key.index("_")]] = [key[key.index("_") + 1:]] if key[:key.index("_")] not in elev: elev.append(key[:key.index("_")]) for _, angle in self.levang.items(): angle.sort(key=lambda angle: (int)(angle)) #pylint: disable=unnecessary-lambda elev.sort(key=lambda level: (int)(level)) #pylint: disable=unnecessary-lambda infoL = QLabel(self, text="Social Link Information") self.grid.addWidget(infoL, 0, 0, 1, 12) self.level = QComboBox(self) if len(elev) != 0: elev.insert(0, "") self.level.addItems(elev) self.level.activated.connect(self.recs) if self.linklevel: self.level.setCurrentIndex((int)(self.linklevel)) self.recs() else: self.level.addItems(["No cutscenes have been created"]) self.grid.addWidget(self.level, 1, 1, 1, 1) atlevel = QLabel(self, text="At " + self.link.arcana + " level ") self.grid.addWidget(atlevel, 1, 0, 1, 1) arcanainfo = QLabel(self, text=self.link.arcana + " Social Link info") self.aitext = QTextEdit(self) self.aitext.setText(self.link.info) self.aitext.setFixedSize(300, 100) self.save = QPushButton(self, text="Save") self.back = QPushButton(self, text="Back") self.save.clicked.connect(self.saveinfo) self.back.clicked.connect(self.endedit) if self.linklevel and self.linkangle: self.grid.addWidget(arcanainfo, 4, 0, 1, 6) self.grid.addWidget(self.aitext, 5, 0, 1, 6) thisinfo = QLabel(self, text=self.link.arcana + " info for level: " + self.linklevel + ", angle: " + self.linkangle) self.grid.addWidget(thisinfo, 4, 6, 1, 6) self.titext = QTextEdit(self) self.titext.setFixedSize(300, 100) try: self.titext.setText( self.link.cutinfo[self.level.currentText() + "_" + str(self.linkangle)]) except: #pylint: disable=bare-except # TODO why? Backwards compatibility? pass self.grid.addWidget(self.titext, 5, 6, 1, 6) self.grid.setAlignment(thisinfo, Qt.AlignHCenter) self.grid.setAlignment(self.titext, Qt.AlignHCenter) else: self.grid.addWidget(arcanainfo, 4, 0, 1, 12) self.grid.addWidget(self.aitext, 5, 0, 1, 12) pseudoL = QLabel(self, text="Social Link's Pseudoname") youhave = QLabel(self, text="You have established the ") ofthe = QLabel(self, text="Social Link of the " + self.link.arcana + " arcana!") self.grid.addWidget(pseudoL, 2, 0, 1, 12) self.grid.addWidget(youhave, 3, 0, 1, 5) self.grid.addWidget(ofthe, 3, 7, 1, 6) self.grid.addWidget(self.save, 6, 0, 1, 1) self.grid.addWidget(self.back, 6, 1, 1, 1) self.pseudoname = QLineEdit(self) self.pseudoname.setFixedSize(150, 20) self.pseudoname.setText(self.link.pseudoname) self.grid.addWidget(self.pseudoname, 3, 5, 1, 2) self.grid.setAlignment(infoL, Qt.AlignHCenter) self.grid.setAlignment(self.aitext, Qt.AlignHCenter) self.grid.setAlignment(arcanainfo, Qt.AlignHCenter) self.grid.setAlignment(self.save, Qt.AlignRight) self.grid.setAlignment(self.back, Qt.AlignLeft) self.grid.setAlignment(youhave, Qt.AlignRight) self.grid.setAlignment(ofthe, Qt.AlignLeft) self.grid.setAlignment(pseudoL, Qt.AlignHCenter) self.grid.setAlignment(self.pseudoname, Qt.AlignHCenter) def saveinfo(self): """ Set the info in the social link object and save it. """ try: for angle, data in self.reqs.textboxes.items(): (int)(data.text()) if data.text() != "": if self.level.currentText( ) not in self.link.requiredPoints: self.link.requiredPoints[self.level.currentText()] = {} if angle not in self.link.requiredPoints[ self.level.currentText()]: self.link.requiredPoints[ self.level.currentText()][angle] = {} self.link.requiredPoints[ self.level.currentText()][angle]['points'] = int( data.text()) for angle, data in self.reqs.courages.items(): self.link.requiredPoints[ self.level.currentText()][angle]['courage'] = int( data.currentText()) for angle, data in self.reqs.charms.items(): self.link.requiredPoints[ self.level.currentText()][angle]['charm'] = int( data.currentText()) for angle, data in self.reqs.acads.items(): self.link.requiredPoints[ self.level.currentText()][angle]['acad'] = int( data.currentText()) for angle, data in self.reqs.ultis.items(): self.link.finalpersona[angle] = data.currentText() self.link.pseudoname = self.pseudoname.text() self.link.info = self.aitext.toPlainText() if self.linklevel: if str(self.linklevel) + "_" + str( self.linkangle) not in self.link.cutinfo: self.link.cutinfo[str(self.linklevel) + "_" + str(self.linkangle)] = "" self.link.cutinfo[str(self.linklevel) + "_" + str( self.linkangle)] = self.titext.toPlainText() except ValueError: popup("Points must be integers.\nNot saved.", "Critical") return self.link.save() popup("Saved", "Information") def endedit(self): """ We're done. Return to the calling widget. """ self.mainframe.changeState(self.op) def recs(self): """ Handle addition and removal of requirements window. """ try: self.reqs.close() except Exception as e: #pylint: disable=broad-except print(e) print("Can't close oudated req widget") if self.level.currentText() == "": return if self.level.itemText(0) == "": self.level.removeItem(0) self.reqs = Requirements(self) self.grid.addWidget(self.reqs, 1, 2, 1, 10)
class MainWidget(QWidget): # CONSTANTS EMPTY_STRING = "" # TOGGLE BUTTON CONSTANTS BUTTON_CLOSED_ICON_PATH = 'resources/menu_closed_button_icon.png' BUTTON_OPENED_ICON_PATH = 'resources/menu_opened_button_icon.png' TOOGLE_BUTTON_CSS_PROPERTY = "QPushButton {background-color: rgb(1,150,250); border: none ; qproperty-iconSize: 80px}" CURRENT_PATH_LINE_EDIT_PROPERTY = "QLineEdit {background-color: rgba(240, 240, 240, 1);}" TOOGLE_CLOSED_COLOR = "background-color: rgb(1,150,250);" TOOGLE_OPENED_COLOR = "background-color: rgba(44, 53, 57, 0.2);" WHITE = "background-color: rgb(255, 255, 255);" FRAME_BUTTON_STYLE = "background-color: rgb(0, 191, 255); color: rgb(255, 255, 255);" FRAME_LINE_EDIT_STYLE = "background-color: rgb(255, 255, 255); color: rgb(0, 0, 0);" FRAME_LABEL_STYLE = "QLabel { background-color : rgba(44, 53, 57, 0); }" SEARCH_ICON_STYLE = "QPushButton {background-color: rgb(1,150,250);}" BACK_ICON_STYLE = "QPushButton {background-color: rgb(1,150,250);} QPushButton:pressed {background-color: rgb(40,170,250);}" WIDTH = 1440 HEIGHT = 900 # Size of the operations widget buttons OPERATION_BUTTON_WIDTH = 40 OPERATION_BUTTON_HEIGHT = 40 FILES_LIST_VIEW_WIDTH = 820 FILES_LIST_VIEW_HEIGHT = 680 TOGGLE_BUTTON_ANIMATION_DURATION = 200 RIGHT_MENU_ANIMATION_DURATION = 250 # ICONS PATHS # Actions icons ADD_FILE_ICON_PATH = "resources/add_file_icon.png" ADD_DIRECTORY_ICON_PATH = "resources/add_directory_icon.png" COPY_ELEMENT_ICON_PATH = "resources/copy_element_icon.png" MOVE_ELEMENT_ICON_PATH = "resources/move_element_icon.png" DELETE_ELEMENT_ICON_PATH = "resources/delete_element_icon.png" SEARCH_ICON_PATH = "resources/search_icon_white.png" CREATE_ARCHIVE_ICON_PATH = "resources/create_archive_icon.png" UNARCHIVE_FILE_ICON_PATH = "resources/unarchive_file_icon.png" RENAME_ELEMENT_ICON_PATH = "resources/rename_icon_white.png" BACK_ICON_PATH = "resources/back_icon.png" # Elements icons FILE_ICON_PATH = "resources/file_icon.png" FOLDER_ICON_PATH = "resources/folder_icon.png" ZIP_ICON_PATH = "resources/zip_icon.png" # Tooltips COPY_TOOLTIP = "Copy files / folders" MOVE_TOOLTIP = "Move files / folders" DELETE_TOOLTIP = "Delete files / folders" ARCHIVE_TOOLTIP = "Archive files / folders" UNARCHIVE_TOOLTIP = "Unarchive files / folders" CREATE_FILE_TOOLTIP = "Create a new text file" CREATE_DIRECTORY_TOOLTIP = "Create a new folder" RENAME_TOOLTIP = "Rename a file / folder" BACK_TOOLTIP = "Move up one directory" # Buttons name COPY = "Copy" MOVE = "Move" DELETE = "Delete" ARCHIVE = "Archive" UNARCHIVE = "Unarchive" RENAME = "Rename" CREATE_FILE = "Create file" CREATE_FOLDER = "Create folder" # Labels SELECTED_ITEMS_TEXT = "Selected items:" ARCHIVE_NAME_TEXT = "Archive name:" CREATE_FILE_NAME_TEXT = "File name:" CREATE_FOLDER_NAME_TEXT = "Folder name:" RENAME_ELEMENT_TEXT = "New name:" def __init__(self, parent, model, controller): super(MainWidget, self).__init__(parent) self._model = model self._controller = controller # FILES LIST VIEW self.filesListView = FilesListView(self.FILES_LIST_VIEW_WIDTH, self.FILES_LIST_VIEW_HEIGHT, self._model, self._controller, self) self.filesListView.move(230, 120) # TREE VIEW FOR SYSTEM DIRECTORY HIERARCHY self.treeView = TreeView(self._model, self._controller, self) self.treeView.setFixedSize(200, 820) self.treeView.move(0, 60) # DISC SELECTION COMBO BOX self.discSelectionComboBox = QComboBox(self) self.discSelectionComboBox.setFixedSize(100, 30) self.discSelectionComboBox.move(230, 60) self.discSelectionComboBox.addItems(self._model.combo_box_list) # CONNECT WIDGETS TO CONTROLLER self.discSelectionComboBox.currentTextChanged.connect( self._controller.change_combo_box_selection) # LISTEN FOR MODEL EVENT SIGNALS self._model.combo_box_selection_changed.connect( self.on_combo_box_selection_changed) self.frameRightMenu = QWidget(self) self.frameRightMenu.setFixedSize(360, self.HEIGHT) self.frameRightMenu.move(1450, 15) self.frameRightMenu.setStyleSheet(self.TOOGLE_CLOSED_COLOR) # BUTTON WHICH TOOGLE ON/OFF THE TREE VIEW CONTAINING THE SELECTED ITEMS TREE VIEW self.toggleButton = QPushButton(QIcon(self.BUTTON_CLOSED_ICON_PATH), self.EMPTY_STRING, self) self.toggleButton.setFixedSize(100, 70) self.toggleButton.move(1300, 0) self.toggleButton.setStyleSheet(self.TOOGLE_BUTTON_CSS_PROPERTY) self._enable = True self.toggleButton.clicked.connect( lambda: Animations.toggleMenu(self, self._enable)) # Label that shows "Selected items:" self.selectedItemsLabel = QLabel(self.SELECTED_ITEMS_TEXT, self.frameRightMenu) self.selectedItemsLabel.move(100, 20) self.selectedItemsLabel.setStyleSheet(self.FRAME_LABEL_STYLE) # The list with selected elements from FilesListView self.selectedFilesListWidget = QListWidget(self.frameRightMenu) self.selectedFilesListWidget.setFixedSize(320, 500) self.selectedFilesListWidget.move(23, 60) self.selectedFilesListWidget.setStyleSheet(self.WHITE) # ACTIONS BUTTONS # Copy button self.copyElementButton = OperationsWidgetButton( QIcon(self.COPY_ELEMENT_ICON_PATH), self.EMPTY_STRING, self) self.copyElementButton.clicked.connect(self.doCopy) self.copyElementButton.move(230, 0) self.copyElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH, self.OPERATION_BUTTON_HEIGHT) self.copyElementButton.setToolTip(self.COPY_TOOLTIP) # Move button self.moveElementButton = OperationsWidgetButton( QIcon(self.MOVE_ELEMENT_ICON_PATH), self.EMPTY_STRING, self) self.moveElementButton.clicked.connect(self.doMove) self.moveElementButton.move(290, 0) self.moveElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH, self.OPERATION_BUTTON_HEIGHT) self.moveElementButton.setToolTip(self.MOVE_TOOLTIP) # Delete button self.deleteElementButton = OperationsWidgetButton( QIcon(self.DELETE_ELEMENT_ICON_PATH), self.EMPTY_STRING, self) self.deleteElementButton.clicked.connect(self.doDelete) self.deleteElementButton.move(350, 0) self.deleteElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH, self.OPERATION_BUTTON_HEIGHT) self.deleteElementButton.setToolTip(self.DELETE_TOOLTIP) # Archive button self.archiveElementButton = OperationsWidgetButton( QIcon(self.CREATE_ARCHIVE_ICON_PATH), self.EMPTY_STRING, self) self.archiveElementButton.clicked.connect(self.doArchive) self.archiveElementButton.move(410, 0) self.archiveElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH, self.OPERATION_BUTTON_HEIGHT) self.archiveElementButton.setToolTip(self.ARCHIVE_TOOLTIP) # Unarchive button self.unarchiveElementButton = OperationsWidgetButton( QIcon(self.UNARCHIVE_FILE_ICON_PATH), self.EMPTY_STRING, self) self.unarchiveElementButton.clicked.connect(self.doUnarchive) self.unarchiveElementButton.move(470, 0) self.unarchiveElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH, self.OPERATION_BUTTON_HEIGHT) self.unarchiveElementButton.setToolTip(self.UNARCHIVE_TOOLTIP) # Add file button self.addFileButton = OperationsWidgetButton( QIcon(self.ADD_FILE_ICON_PATH), self.EMPTY_STRING, self) self.addFileButton.clicked.connect(self.doCreateFile) self.addFileButton.move(530, 0) self.addFileButton.setFixedSize(self.OPERATION_BUTTON_WIDTH, self.OPERATION_BUTTON_HEIGHT) self.addFileButton.setToolTip(self.CREATE_FILE_TOOLTIP) # Add directory button self.addDirectoryButton = OperationsWidgetButton( QIcon(self.ADD_DIRECTORY_ICON_PATH), self.EMPTY_STRING, self) self.addDirectoryButton.clicked.connect(self.doCreateFolder) self.addDirectoryButton.move(590, 0) self.addDirectoryButton.setFixedSize(self.OPERATION_BUTTON_WIDTH, self.OPERATION_BUTTON_HEIGHT) self.addDirectoryButton.setToolTip(self.CREATE_DIRECTORY_TOOLTIP) # Move button self.renameElementButton = OperationsWidgetButton( QIcon(self.RENAME_ELEMENT_ICON_PATH), self.EMPTY_STRING, self) self.renameElementButton.clicked.connect(self.doRename) self.renameElementButton.move(650, 0) self.renameElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH, self.OPERATION_BUTTON_HEIGHT) self.renameElementButton.setToolTip(self.RENAME_TOOLTIP) # Text field needed for displaying the current path self.currentPathLineEdit = QLineEdit(self.EMPTY_STRING, self) self.currentPathLineEdit.move(350, 80) self.currentPathLineEdit.setFixedSize(400, 27) self.currentPathLineEdit.setStyleSheet( self.CURRENT_PATH_LINE_EDIT_PROPERTY) self.currentPathLineEdit.setReadOnly(True) self.currentPathLineEdit.setText(self._model.current_path) self.currentPathLineEdit.textChanged.connect( self._controller.change_current_path_text) self._model.current_path_changed.connect(self.on_current_path_changed) # Text field needed for searching file / folder by the name self.searchLineEdit = QLineEdit(self.EMPTY_STRING, self) self.searchLineEdit.move(810, 80) self.searchLineEdit.setFixedSize(200, 27) self.searchLineEdit.textChanged.connect( self._controller.change_search_text) self._model.current_search_changed.connect( self.on_current_search_changed) self.searchIconButton = OperationsWidgetButton( QIcon(self.SEARCH_ICON_PATH), self.EMPTY_STRING, self) self.searchIconButton.move(1015, 78) self.searchIconButton.setFixedSize(30, 30) self.searchIconButton.setStyleSheet(self.SEARCH_ICON_STYLE) self.searchIconButton.setEnabled(False) self.backButton = OperationsWidgetButton(QIcon(self.BACK_ICON_PATH), self.EMPTY_STRING, self) self.backButton.clicked.connect(self.doBack) self.backButton.move(765, 80) self.backButton.setFixedSize(25, 25) self.backButton.setStyleSheet(self.BACK_ICON_STYLE) self.backButton.setToolTip(self.BACK_TOOLTIP) self.backButton.setEnabled(True) # ACTIONS LABELS self.archiveLabel = QLabel(self.ARCHIVE_NAME_TEXT, self.frameRightMenu) self.createFolderLabel = QLabel(self.CREATE_FOLDER_NAME_TEXT, self.frameRightMenu) self.createFileLabel = QLabel(self.CREATE_FILE_NAME_TEXT, self.frameRightMenu) self.renameElementLabel = QLabel(self.RENAME_ELEMENT_TEXT, self.frameRightMenu) # ACTIONS LINE EDITS self.archiveNameEditLine = QLineEdit(self.EMPTY_STRING, self.frameRightMenu) self.createFileEditLine = QLineEdit(self.EMPTY_STRING, self.frameRightMenu) self.createFolderEditLine = QLineEdit(self.EMPTY_STRING, self.frameRightMenu) self.renameElementEditLine = QLineEdit(self.EMPTY_STRING, self.frameRightMenu) # ACTIONS BUTTONS self.copyButton = ToggleMenuButton(self.COPY, self.frameRightMenu) self.moveButton = ToggleMenuButton(self.MOVE, self.frameRightMenu) self.deleteButton = ToggleMenuButton(self.DELETE, self.frameRightMenu) self.archiveButton = ToggleMenuButton(self.ARCHIVE, self.frameRightMenu) self.unarchiveButton = ToggleMenuButton(self.UNARCHIVE, self.frameRightMenu) self.createFileButton = ToggleMenuButton(self.CREATE_FILE, self.frameRightMenu) self.createFolderButton = ToggleMenuButton(self.CREATE_FOLDER, self.frameRightMenu) self.renameElementButton = ToggleMenuButton(self.RENAME, self.frameRightMenu) self.__createFrameLayoutElements() @Slot(str) def on_current_path_changed(self, path): self._model.elements_list.clear() self._model.selected_items.clear() self.selectedFilesListWidget.clear() self._model.elements_list = Directory.get_all_subelements(path) self.filesListView.model().populateList() @Slot(str) def on_current_search_changed(self, name): print(name) def removeFromSelectedItems(self, item): Animations.toggleMenu(self, True) count = self.selectedFilesListWidget.count() index = 0 for i in range(count): if item.text() == self.selectedFilesListWidget.item(i).text(): index = i break self.selectedFilesListWidget.takeItem(index) def appendToSelectedItems(self, item): Animations.toggleMenu(self, True) listItem = ListWidgetItem(item) self.selectedFilesListWidget.insertItem(0, listItem) def setCurrentPath(self, path): self.currentPathLineEdit.setText(path) @Slot(str) def on_combo_box_selection_changed(self, value): index = self.discSelectionComboBox.findText(value) self.discSelectionComboBox.setCurrentIndex(index) Slot() def doBack(self): path = self.currentPathLineEdit.text() parentPath = os.path.dirname(path) self.setCurrentPath(parentPath) @Slot() def doCopy(self): self.__setCopyLayout(True) Animations.toggleMenu(self, True) @Slot() def doMove(self): self.__setMoveLayout(True) Animations.toggleMenu(self, True) @Slot() def doDelete(self): self.__setDeleteLayout(True) Animations.toggleMenu(self, True) @Slot() def doArchive(self): self.__setArchiveLayout(True) Animations.toggleMenu(self, True) @Slot() def doUnarchive(self): self.__setUnarchiveLayout(True) Animations.toggleMenu(self, True) @Slot() def doCreateFile(self): self.__setCreateFileLayout(True) Animations.toggleMenu(self, True) @Slot() def doCreateFolder(self): self.__setCreateFolderLayout(True) Animations.toggleMenu(self, True) @Slot() def doRename(self): self.__setRenameLayout(True) Animations.toggleMenu(self, True) # Method that creates all layout object from the frame layout def __createFrameLayoutElements(self): # ================= COPY ACTION ======================= # Copy button on right frame self.copyButton.setStyleSheet(self.FRAME_BUTTON_STYLE) self.copyButton.move(120, 600) self.copyButton.setFixedSize(120, 32) self.copyButton.setVisible(False) # ================= MOVE ACTION ======================= # Move button on right frame self.moveButton.setStyleSheet(self.FRAME_BUTTON_STYLE) self.moveButton.move(120, 600) self.moveButton.setFixedSize(120, 32) self.moveButton.setVisible(False) # ================= DELETE ACTION ======================= # Delete button on right frame self.deleteButton.setStyleSheet(self.FRAME_BUTTON_STYLE) self.deleteButton.move(120, 600) self.deleteButton.setFixedSize(120, 32) self.deleteButton.setVisible(False) # ================= UNARCHIVE ACTION ======================= # Unarchive button on right frame self.unarchiveButton.setStyleSheet(self.FRAME_BUTTON_STYLE) self.unarchiveButton.move(120, 600) self.unarchiveButton.setFixedSize(120, 32) self.unarchiveButton.setVisible(False) # ================= ARCHIVE ACTION ======================= self.archiveLabel.move(100, 590) self.archiveLabel.setStyleSheet(self.FRAME_LABEL_STYLE) self.archiveLabel.setVisible(False) self.archiveNameEditLine.move(55, 620) self.archiveNameEditLine.setFixedSize(250, 30) self.archiveNameEditLine.setStyleSheet(self.FRAME_LINE_EDIT_STYLE) self.archiveNameEditLine.setVisible(False) self.archiveButton.setStyleSheet(self.FRAME_BUTTON_STYLE) self.archiveButton.move(120, 700) self.archiveButton.setFixedSize(120, 32) self.archiveButton.setVisible(False) # ================= CREATE NEW FILE ACTION ======================= self.createFileLabel.move(120, 590) self.createFileLabel.setStyleSheet(self.FRAME_LABEL_STYLE) self.createFileLabel.setVisible(False) self.createFileEditLine.move(55, 620) self.createFileEditLine.setFixedSize(250, 30) self.createFileEditLine.setStyleSheet(self.FRAME_LINE_EDIT_STYLE) self.createFileEditLine.setVisible(False) self.createFileButton.setStyleSheet(self.FRAME_BUTTON_STYLE) self.createFileButton.move(120, 700) self.createFileButton.setFixedSize(120, 32) self.createFileButton.setVisible(False) # ================= CREATE NEW FOLDER ACTION ======================= self.createFolderLabel.move(120, 590) self.createFolderLabel.setStyleSheet(self.FRAME_LABEL_STYLE) self.createFolderLabel.setVisible(False) self.createFolderEditLine.move(55, 620) self.createFolderEditLine.setFixedSize(250, 30) self.createFolderEditLine.setStyleSheet(self.FRAME_LINE_EDIT_STYLE) self.createFolderEditLine.setVisible(False) self.createFolderButton.setStyleSheet(self.FRAME_BUTTON_STYLE) self.createFolderButton.move(120, 700) self.createFolderButton.setFixedSize(120, 32) self.createFolderButton.setVisible(False) # ================= RENAME ELEMENT ACTION ======================= self.renameElementLabel.move(120, 590) self.renameElementLabel.setStyleSheet(self.FRAME_LABEL_STYLE) self.renameElementLabel.setVisible(False) self.renameElementEditLine.move(55, 620) self.renameElementEditLine.setFixedSize(250, 30) self.renameElementEditLine.setStyleSheet(self.FRAME_LINE_EDIT_STYLE) self.renameElementEditLine.setVisible(False) self.renameElementButton.setStyleSheet(self.FRAME_BUTTON_STYLE) self.renameElementButton.move(120, 700) self.renameElementButton.setFixedSize(120, 32) self.renameElementButton.setVisible(False) # Method that sets the frame layout for rename operation def __setRenameLayout(self, shown): if shown == True: self.renameElementLabel.setVisible(True) self.renameElementEditLine.setVisible(True) self.renameElementButton.setVisible(True) self.__setCopyLayout(False) self.__setDeleteLayout(False) self.__setMoveLayout(False) self.__setCreateFileLayout(False) self.__setCreateFolderLayout(False) self.__setArchiveLayout(False) self.__setUnarchiveLayout(False) else: self.renameElementLabel.setVisible(False) self.renameElementEditLine.setVisible(False) self.renameElementButton.setVisible(False) # Method that sets the frame layout for archive operation def __setCreateFileLayout(self, shown): if shown == True: self.createFileLabel.setVisible(True) self.createFileEditLine.setVisible(True) self.createFileButton.setVisible(True) self.__setCopyLayout(False) self.__setDeleteLayout(False) self.__setMoveLayout(False) self.__setRenameLayout(False) self.__setCreateFolderLayout(False) self.__setArchiveLayout(False) self.__setUnarchiveLayout(False) else: self.createFileLabel.setVisible(False) self.createFileEditLine.setVisible(False) self.createFileButton.setVisible(False) # Method that sets the frame layout for archive operation def __setCreateFolderLayout(self, shown): if shown == True: self.createFolderLabel.setVisible(True) self.createFolderEditLine.setVisible(True) self.createFolderButton.setVisible(True) self.__setCopyLayout(False) self.__setDeleteLayout(False) self.__setMoveLayout(False) self.__setRenameLayout(False) self.__setCreateFileLayout(False) self.__setArchiveLayout(False) self.__setUnarchiveLayout(False) else: self.createFolderLabel.setVisible(False) self.createFolderEditLine.setVisible(False) self.createFolderButton.setVisible(False) # Method that sets the frame layout for archive operation def __setArchiveLayout(self, shown): if shown == True: self.archiveLabel.setVisible(True) self.archiveNameEditLine.setVisible(True) self.archiveButton.setVisible(True) self.__setCopyLayout(False) self.__setDeleteLayout(False) self.__setMoveLayout(False) self.__setRenameLayout(False) self.__setCreateFileLayout(False) self.__setCreateFolderLayout(False) self.__setUnarchiveLayout(False) else: self.archiveLabel.setVisible(False) self.archiveNameEditLine.setVisible(False) self.archiveButton.setVisible(False) # Method that sets the frame layout for copy operation def __setCopyLayout(self, shown): if shown == True: self.copyButton.setVisible(True) self.__setMoveLayout(False) self.__setDeleteLayout(False) self.__setRenameLayout(False) self.__setCreateFileLayout(False) self.__setCreateFolderLayout(False) self.__setArchiveLayout(False) self.__setUnarchiveLayout(False) else: self.copyButton.setVisible(False) # Method that sets the frame layout for move operation def __setMoveLayout(self, shown): if shown == True: self.moveButton.setVisible(True) self.__setDeleteLayout(False) self.__setCopyLayout(False) self.__setRenameLayout(False) self.__setCreateFileLayout(False) self.__setCreateFolderLayout(False) self.__setArchiveLayout(False) self.__setUnarchiveLayout(False) else: self.moveButton.setVisible(False) # Method that sets the frame layout for delete operation def __setDeleteLayout(self, shown): if shown == True: self.deleteButton.setVisible(True) self.__setCopyLayout(False) self.__setMoveLayout(False) self.__setRenameLayout(False) self.__setCreateFileLayout(False) self.__setCreateFolderLayout(False) self.__setArchiveLayout(False) self.__setUnarchiveLayout(False) else: self.deleteButton.setVisible(False) # Method that sets the frame layout for unarchive operation def __setUnarchiveLayout(self, shown): if shown == True: self.unarchiveButton.setVisible(True) self.__setCopyLayout(False) self.__setMoveLayout(False) self.__setRenameLayout(False) self.__setCreateFileLayout(False) self.__setCreateFolderLayout(False) self.__setArchiveLayout(False) self.__setDeleteLayout(False) else: self.unarchiveButton.setVisible(False)