def _init_option_ui(self): label_start_time = QLabel("Start time: ") self._line_edit_start_time = QLineEdit() label_end_time = QLabel("End time: ") self._line_edit_end_time = QLineEdit() label_duration = QLabel("Duration: ") self._line_edit_duration = QLineEdit() label_num_clip = QLabel("No. of clips: ") self._line_edit_num_clip = QLineEdit() button_preview = QPushButton("Preview") button_preview.clicked.connect(self.button_preview_clicked) hbox = QHBoxLayout() hbox.addWidget(label_start_time) hbox.addWidget(self._line_edit_start_time) hbox.addWidget(label_end_time) hbox.addWidget(self._line_edit_end_time) hbox.addWidget(label_duration) hbox.addWidget(self._line_edit_duration) hbox.addWidget(label_num_clip) hbox.addWidget(self._line_edit_num_clip) hbox.addWidget(button_preview) for i in range(hbox.count() - 1): hbox.itemAt(i).widget().setObjectName("option") self.vbox.addLayout(hbox)
class ShipSlot(QWidget): sloticon_table = None type_table = {1: 'MainCanonLight', 2: 'MainCanonMedium', 3: 'MainCanonHeavy', 4: 'SecondaryCanon', 5: 'Torpedo', 6: 'Fighter', 7: 'DiveBomber', 8: 'TorpedoBomber', 9: 'ReconPlane', 10:'ReconSeaplane', 11:'Rader', 12:'AAShell', 13:'APShell', 14:'DamageControl', 15:'AAGun', 16:'HighAngleGun', 17:'ASW', 18:'Soner', 19:'EngineImprovement', 20:'LandingCraft', 21:'Autogyro', 22:'ArtillerySpotter', 23:'AntiTorpedoBulge', 24:'SearchLight', 25:'DrumCanister', 26:'Facility', 27:'Flare', 28:'FleetCommandFacility', 29:'MaintenancePersonnel', 30:'AntiAircraftFireDirector', 31:'RocketLauncher', 32:'SurfaceShipPersonnel', 33:'FlyingBoat' } def __init__(self,parent): super(ShipSlot, self).__init__(parent) if self.sloticon_table is None: self.sloticon_table = slotitem.create_sloticontable() self.box = QHBoxLayout() self.box.setSpacing(3) self.box.setContentsMargins(0,5,0,5) self.setLayout(self.box) def set_slot(self, types): # remove all icon for i in reversed(list(range(self.box.count()))): self.box.itemAt(i).widget().setParent(None) for t in types: type_name = self.type_table.get(t, 'unknown') if not type_name in self.sloticon_table: type_name = 'unknown' self.box.addWidget(slotitem.IconBox(self.sloticon_table[type_name]))
def _init_browse_ui(self): label_file_name = QLabel("File name: ") self._list_widget_file_names = QListWidget() self._list_widget_file_names.setFixedHeight(100) button_browse = QPushButton("Browse") button_browse.clicked.connect(self.button_browse_clicked) button_add = QPushButton("Add") button_add.clicked.connect(self.button_add_clicked) button_remove = QPushButton("Remove") button_remove.clicked.connect(self.button_remove_clicked) vbox = QVBoxLayout() vbox.addWidget(button_browse) vbox.addWidget(button_add) vbox.addWidget(button_remove) hbox = QHBoxLayout() hbox.addWidget(label_file_name) hbox.addWidget(self._list_widget_file_names) hbox.addLayout(vbox) for i in range(hbox.count()): hbox.setAlignment(hbox.itemAt(i).widget(), Qt.AlignTop) self.vbox.addLayout(hbox)
class MenuBar(QTabWidget): def __init__(self, parent=None): super(MenuBar, self).__init__(parent) tabbar = TabBar(parent) self.setTabBar(tabbar) self.setMinimumHeight(135) self.setMouseTracking(True) self._drop = False self.currentChanged.connect(self.currentChangedFunc) def currentChangedFunc(self, index): tab_text = self.tabText(index) menu = self.findChild(MenuWidget, tab_text) self.anim = QPropertyAnimation(menu, b'_height') self.anim.setDuration(100) self.anim.setStartValue(0) self.anim.setEndValue(100) self.anim.start() def addMenu(self, p_str): p_str = " {p_str} ".format(p_str=p_str) menu = MenuWidget() menu.setObjectName(p_str) self.addTab(menu, p_str) self.hlayout = QHBoxLayout(menu) self.hlayout.setObjectName(p_str) self.hlayout.setContentsMargins(0, 0, 0, 0) self.hlayout.setSpacing(0) hs = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.hlayout.addItem(hs) return (menu) def addGroup(self, p_str, menu): group = GroupWidget(p_str, menu) group.setObjectName('group') insert_index = len(menu.findChildren(GroupWidget, 'group')) - 1 self.hlayout.insertWidget(insert_index, group) return (group) def listGroups(self, menu): self.group_list = [] for i in range(self.hlayout.count()): try: w = self.hlayout.itemAt(i).widget() self.group_list.append(w._title) except: AttributeError return (self.group_list) def addSliderChoiceWidget(self, menu): slider_choice = SliderChoiceWidget() insert_index = len(menu.findChildren(GroupWidget, 'group')) self.hlayout.insertWidget(insert_index, slider_choice) return (slider_choice)
class ThumbnailRow(QWidget): def __init__(self): super().__init__() self.labels = [] self.layout = QHBoxLayout() self.layout.setSpacing(3) self.layout.setContentsMargins(3, 0, 0, 3) self.setLayout(self.layout) self.items = [] def add_items(self, items): self.items = items self.draw_items() def draw_items(self): self.clear() for item in self.items: thumbnail = Thumbnail(item) self.layout.addWidget(thumbnail, 0) self.layout.addWidget(QWidget(), 1) def clear(self): for i in reversed(range(self.layout.count())): widget = self.layout.itemAt(i).widget() # remove it from the layout list self.layout.removeWidget(widget) # remove it from the gui widget.setParent(None) def zoom(self, scale): for i in reversed(range(self.layout.count())): widget = self.layout.itemAt(i).widget() if isinstance(widget, Thumbnail): widget.zoom(scale) def mousePressEvent(self, a0: QtGui.QMouseEvent): print("Mouse Press") def mouseDoubleClickEvent(self, a0: QtGui.QMouseEvent): print("Mouse Double Click")
def _init_info_ui(self): self._text_edit = QTextEdit() self._text_edit.setFixedHeight(80) self._text_edit.setReadOnly(True) button_create = QPushButton("Create") button_create.clicked.connect(self.button_create_clicked) button_upload = QPushButton("Upload") button_upload.clicked.connect(self.button_upload_clicked) vbox = QVBoxLayout() vbox.addWidget(button_create) vbox.addWidget(button_upload) hbox = QHBoxLayout() hbox.addWidget(self._text_edit) hbox.addLayout(vbox) for i in range(hbox.count()): hbox.setAlignment(hbox.itemAt(i).widget(), Qt.AlignTop) self.vbox.addLayout(hbox)
class HorizontalImageScrollArea(QScrollArea): def __init__(self, parent=None): super(HorizontalImageScrollArea, self).__init__(parent) self.setWidgetResizable(True) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.setFrameShape(QFrame.NoFrame) self.layout = QHBoxLayout() scroll = QWidget() scroll.setLayout(self.layout) self.setWidget(scroll) def eventFilter(self, obj, event): if obj == self.widget() and event.type() == QEvent.Resize: self.widget().resize(self.calcNewSize()) return True return super(HorizontalImageScrollArea, self).eventFilter(obj, event) def calcNewSize(self): height = self.viewport().height() layoutMargins = self.layout.contentsMargins() heightForCalc = height - layoutMargins.top() - layoutMargins.bottom() width = self.calcWidthForHeight(heightForCalc) return QSize(width, height) def calcWidthForHeight(self, height): width = 0 for wgt in range(self.layout.count()): width += self.layout.itemAt(wgt).widget().widthForHeight(height) if self.layout.count() > 1: width += self.layout.spacing() * (self.layout.count() - 1) return width
class Widgetboard(QWidget): def __init__(self): super().__init__() self.initUI() # イベントループ def initUI(self): self.resize(400, 400) # 横, 縦 # self.move(300, 300) self.setWindowTitle('sample') self.mainlayout = QHBoxLayout() self.mode = "board" # 画面左側のレイアウト self.rightlayout = QVBoxLayout() self.setallcard() # 画面右側のレイアウト self.leftlayout = QVBoxLayout() # ボードに関するレイアウト self.boardlayout = QHBoxLayout() self.boardtoplayout = QHBoxLayout() self.boardtitle = QLabel("board") self.boardsetbutton = QPushButton("setboard") self.boardsetbutton.clicked.connect(self.setmode) self.boardclearbutton = QPushButton("clearboard") self.boardclearbutton.clicked.connect(self.clearmethod) self.boardtoplayout.addWidget(self.boardtitle) self.boardtoplayout.addWidget(self.boardsetbutton) self.boardtoplayout.addWidget(self.boardclearbutton) # ホールカードの関するレイアウト self.holllayout = QHBoxLayout() self.holltoplayout = QHBoxLayout() self.holltitle = QLabel("hollcard") self.hollsetbutton = QPushButton("sethollcard") self.hollsetbutton.clicked.connect(self.setmode) self.hollclearbutton = QPushButton("clearhollcard") self.hollclearbutton.clicked.connect(self.clearmethod) self.holltoplayout.addWidget(self.holltitle) self.holltoplayout.addWidget(self.hollsetbutton) self.holltoplayout.addWidget(self.hollclearbutton) # 全体レイアウト self.leftlayout.addLayout(self.boardtoplayout) self.leftlayout.addLayout(self.boardlayout) self.leftlayout.addLayout(self.holltoplayout) self.leftlayout.addLayout(self.holllayout) self.boardcardlist = [] self.hollcardlist = [] # メインのレイアウトを作る self.mainlayout.addLayout(self.rightlayout) self.mainlayout.addLayout(self.leftlayout) self.setLayout(self.mainlayout) self.show() def setallcard(self): rank = [ "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A" ] suit = ["s", "h", "d", "c"] for r in rank: layout = QHBoxLayout() for s in suit: exec(f"self.button{r}{s} = QPushButton('{r}{s}')") exec(f"self.button{r}{s}.setIcon(QIcon('./PNG/{r}{s}.png'))") exec(f"self.button{r}{s}.setIconSize(QSize(40, 40))") exec(f"self.button{r}{s}.clicked.connect(self.button_clicked)") exec(f"layout.addWidget(self.button{r}{s})") self.rightlayout.addLayout(layout) def button_clicked(self): sender = self.sender() text = sender.text() if self.mode == "board": if len(self.boardcardlist) < 5: self.boardcardlist.append(text) self.addcard(text) elif self.mode == "hollcard": if len(self.hollcardlist) < 2: self.hollcardlist.append(text) self.addcard(text) # print(f"board: {self.boardcardlist}") # print(f"hollcard: {self.hollcardlist}") def setmode(self): sender = self.sender() text = sender.text() if text == "setboard": self.mode = "board" elif text == "sethollcard": self.mode = "hollcard" def addcard(self, text): pixmap = QPixmap(f'./PNG/{text}.png').scaled(QSize(150, 150), Qt.KeepAspectRatio, Qt.FastTransformation) imagelabel = QLabel() imagelabel.setPixmap(pixmap) if self.mode == "board": self.boardlayout.addWidget(imagelabel) elif self.mode == "hollcard": self.holllayout.addWidget(imagelabel) def clearmethod(self): sender = self.sender() text = sender.text() if text == "clearboard": self.boardcardlist = [] for i in reversed(range(self.boardlayout.count())): self.boardlayout.itemAt(i).widget().setParent(None) elif text == "clearhollcard": self.hollcardlist = [] for i in reversed(range(self.holllayout.count())): self.holllayout.itemAt(i).widget().setParent(None) else: pass
class Window(QWidget): def __init__(self, login_id, login_password): super().__init__() self.id = login_id self.password = login_password self.inbox = "" self.init_ui() def inbox_mails(self, mail): self.incoming_mail = QGroupBox() self.incoming_mail_group = QVBoxLayout(self.incoming_mail) self.inbox_subject = QLabel("Subject: " + mail[0]) self.inbox_from = QLabel("From: " + mail[1]) self.incoming_mail_group.addWidget(self.inbox_subject) self.incoming_mail_group.addWidget(self.inbox_from) self.box_palette = QPalette() self.box_palette.setColor(QPalette.Background, QColor(100, 100, 100)) self.setPalette(self.box_palette) return self.incoming_mail def inbox_container(self): self.scrollArea = QScrollArea(self) self.scrollArea.setMaximumWidth(250) self.scrollArea.setMinimumWidth(100) self.scrollArea.setWidgetResizable(True) self.widget = QWidget() self.scrollArea.setWidget(self.widget) self.layoutScrollArea = QVBoxLayout() self.inbox = MailSettings.inbox_getter(self.id, self.password) for index, mail_in_inbox in enumerate(self.inbox): self.layoutScrollArea.addWidget(self.inbox_mails(mail_in_inbox)) self.widget.setLayout(self.layoutScrollArea) def init_ui(self): self.mail_address = QLineEdit() self.send_button = QPushButton("Send!") self.mail_text = QTextEdit() self.mail_subject = QLineEdit() self.label_to = QLabel("To:") self.label_subject = QLabel("Subject:") self.label_text = QLabel("Text:") self.label_text.setFixedWidth(50) self.attached_file_paths = [] self.warning_label = QLabel("") self.warning_label_head = QLabel("") self.hidden_inbox_button = QPushButton("<", self) self.hidden_inbox_button.setFixedSize(30, 70) self.file_open_button = QPushButton("Attach") self.file_open_button.setIcon(QIcon('attach-paperclip-symbol.png')) self.delete_all_files = QPushButton("Delete All") self.delete_all_files.hide() self.delete_all_files.clicked.connect(self.del_all_files) self.hidden_inbox_button.clicked.connect(self.hidden_inbox) self.file_open_button.clicked.connect(self.file_open) v_box1 = QVBoxLayout() v_box1.addWidget(self.label_to) v_box1.addWidget(self.label_subject) v_box2 = QVBoxLayout() v_box2.addWidget(self.mail_address) v_box2.addWidget(self.mail_subject) h_box1 = QHBoxLayout() h_box1.addLayout(v_box1) h_box1.addLayout(v_box2) h_box2 = QHBoxLayout() h_box2.addWidget(self.label_text) h_box2.addWidget(self.mail_text) v_box_attach = QVBoxLayout() v_box_attach.addWidget(self.file_open_button) self.h_box_files = QHBoxLayout() h_box3 = QHBoxLayout() h_box3.addLayout(self.h_box_files) h_box3.addStretch() h_box3.addWidget(self.delete_all_files) h_box3.addWidget(self.file_open_button) self.v_box = QVBoxLayout() self.v_box.addLayout(h_box1) self.v_box.addLayout(h_box2) self.v_box.addLayout(h_box3) self.v_box.addWidget(self.warning_label_head) self.v_box.addWidget(self.warning_label) self.v_box.addWidget(self.send_button, 10) self.inbox_container() h_box4 = QHBoxLayout() h_box4.addWidget(self.scrollArea) h_box4.addWidget(self.hidden_inbox_button) h_box5 = QHBoxLayout() h_box5.addLayout(h_box4) h_box5.addLayout(self.v_box) self.setLayout(h_box5) self.send_button.clicked.connect(self.send) def send(self): to = self.mail_address.text() subject = self.mail_subject.text() text = self.mail_text.toPlainText() file = self.attached_file_paths mail = MailSettings(to, subject, text, file, self.id, self.password) warnings = mail.mail_sender() if warnings: warning = "\n".join(warnings) self.warning_label_head.setText("Invalid e-mail addresses:\n") self.warning_label_head.setStyleSheet( "color: red; border: 2px solid red; border-radius: 5px") self.warning_label.setText(warning) def hidden_inbox(self): if self.scrollArea.isHidden(): self.scrollArea.show() self.hidden_inbox_button.setText("<") self.setGeometry(self.x() + 1, self.y() + 1, self.width() + 1, self.height() + 1) self.update() else: self.scrollArea.hide() self.hidden_inbox_button.setText(">") self.setGeometry(self.x() + 1, self.y() + 1, self.width() + 1, self.height() + 1) self.update() def file_open(self): file_name = QFileDialog.getOpenFileName(self, "Select File", os.getenv("HOME")) if file_name[0] not in self.attached_file_paths and file_name[0] != "": self.attached_file_paths.append(str(file_name[0])) self.h_box_files.addWidget( QLabel("{}-)".format(len(self.attached_file_paths)) + file_name[0].split("/")[-1] + " ")) # print(self.attached_file_paths) self.delete_all_files.show() else: pass def del_all_files(self): self.attached_file_paths = [] self.delete_all_files.hide() for i in reversed(range(self.h_box_files.count())): self.h_box_files.itemAt(i).widget().setParent(None) self.setGeometry(self.x() + 1, self.y() + 1, self.width() + 1, self.height() + 1) self.update()
class Controller(QWidget): def __init__(self): super().__init__() # game details self._player = 0 self._players = None self._round = None self._cards_played = 0 # child processes self._server = None self._client = None self._parent_conn = None # connection to child # set graphics properties self.setWindowTitle('500') self.setGeometry(50, 50, WIDTH, HEIGHT) self.setFixedSize(self.size()) # check for background image if os.path.exists("bkg.jpg"): bg = QtGui.QPixmap("bkg.jpg") palette = QtGui.QPalette() palette.setBrush(10, QtGui.QBrush(bg)) self.setPalette(palette) else: print( "No background image found. Copy bkg.jpg to the directory to add one." ) # default font self.setFont(QtGui.QFont("Book Antiqua", 11, QtGui.QFont.Bold)) # create main menu self._main_menu = QWidget() self.create_main_menu_view() # create game options view self._options_type = None # which options screen to display self._port = None self._username = None self._ip = None self._password = None self._player_types = [None] * 3 self._game_options_view = QWidget() self.create_game_options_view() # create game view self._game_view = QWidget() self._card_layout = [None] * NUMBER_PLAYERS # array of players cards self._played_cards = None # four cards in center of screen self._player_info = [None ] * NUMBER_PLAYERS # info label for each player self._bet_controls = [] self._card_winning = None self.create_game_view() # create stacked layout self._stacked_layout = QStackedWidget(self) self._stacked_layout.addWidget(self._main_menu) self._stacked_layout.addWidget(self._game_options_view) self._stacked_layout.addWidget(self._game_view) self.show() # create main menu and add it to _main_menu layout def create_main_menu_view(self): menu = QVBoxLayout() menu.setAlignment(QtCore.Qt.AlignHCenter) menu.addStretch(1) # create a pretty title layout title_layout = QHBoxLayout() title_layout.addStretch(1) # add some bowers for nice looks svgWidget = QtSvg.QSvgWidget('img/JH.svg') svgWidget.setMinimumHeight(CARD_HEIGHT) svgWidget.setMaximumHeight(CARD_HEIGHT) svgWidget.setMinimumWidth(CARD_WIDTH) svgWidget.setMaximumWidth(CARD_WIDTH) title_layout.addWidget(svgWidget) title_layout.addStretch(1) # create title title = QLabel("500 Online!") font = QtGui.QFont("Book Antiqua", 50, QtGui.QFont.Bold) title.setFont(font) title_layout.addWidget(title) title_layout.addStretch(1) svgWidget = QtSvg.QSvgWidget('img/JD.svg') svgWidget.setMinimumHeight(CARD_HEIGHT) svgWidget.setMaximumHeight(CARD_HEIGHT) svgWidget.setMinimumWidth(CARD_WIDTH) svgWidget.setMaximumWidth(CARD_WIDTH) title_layout.addWidget(svgWidget) title_layout.addStretch(1) menu.addLayout(title_layout) menu.addStretch(1) # create layout layout = QVBoxLayout() layout.setAlignment(QtCore.Qt.AlignCenter) # bots button button = QPushButton('Play against bots', self) button.clicked.connect(lambda: self.goto_game_options(0)) layout.addWidget(button) # join server button = QPushButton('Join a server', self) button.clicked.connect(lambda: self.goto_game_options(1)) layout.addWidget(button) # host and play button = QPushButton('Host and play', self) button.clicked.connect(lambda: self.goto_game_options(2)) layout.addWidget(button) # options TODO # button = QPushButton('Options', self) # layout.addWidget(button) # exit button = QPushButton('Exit', self) button.clicked.connect(self.close) layout.addWidget(button) menu.addLayout(layout) menu.addStretch(2) # title = QLabel("By Gareth Booth") TODO # font = QtGui.QFont("Book Antiqua", 8, QtGui.QFont.Bold) # title.setFont(font) # menu.addWidget(title) # add to layout self._main_menu.setLayout(menu) # go to the game options screen # type is which screen button you came from: # 0 for bots # 1 for join server # 2 for host and play def goto_game_options(self, options_type): self._options_type = options_type self._stacked_layout.setCurrentIndex(1) self.reset_game_options() # hide layouts depending on which options type we are if options_type == 0: self._ip.hide() self._password.hide() for index in range(0, 3): self._player_types[index].hide() elif options_type == 1: for index in range(0, 3): self._player_types[index].hide() elif options_type == 2: self._ip.hide() # unhide all game options (note port and username are never hidden) def reset_game_options(self): self._ip.show() self._password.show() for index in range(0, 3): self._player_types[index].show() # create the options for joining game menu def create_game_options_view(self): # create layout layout = QVBoxLayout() layout.setAlignment(QtCore.Qt.AlignCenter) # username edit = QLineEdit() edit.setText("Jimmy") edit.setMaximumWidth(200) self._username = QWidget() self._username.setLayout(create_menu_entry("Username: "******"Port: ", port)) layout.addWidget(self._port) # ip ip = QLineEdit() ip.setMaximumWidth(200) self._ip = QWidget() self._ip.setLayout(create_menu_entry("Ip Address: ", ip)) layout.addWidget(self._ip) # password password = QLineEdit() password.setMaximumWidth(200) self._password = QWidget() self._password.setLayout(create_menu_entry("Password: "******"Human", "lvl 1 bot", "lvl 2 bot"]) player_type.setMaximumWidth(200) self._player_types[index] = QWidget() self._player_types[index].setLayout( create_menu_entry("Player " + str(index + 2) + " is a :", player_type)) layout.addWidget(self._player_types[index]) # join button button = QPushButton('Go', self) button.clicked.connect(self.create_game) layout.addWidget(button) # back button button = QPushButton('Back to Menu', self) button.clicked.connect(lambda: self._stacked_layout.setCurrentIndex(0)) layout.addWidget(button) # create layout with stretch to force center the controls hcentered_layout = QHBoxLayout() hcentered_layout.addStretch(1) hcentered_layout.addLayout(layout) hcentered_layout.addStretch(1) self._game_options_view.setLayout(hcentered_layout) # returns username from the game options screen def get_username(self): return self._username.layout().itemAt(1).widget().text() # returns port from the game options screen def get_port(self): return self._port.layout().itemAt(1).widget().value() # returns password from the game options screen def get_password(self): return self._password.layout().itemAt(1).widget().text() # returns password from the game options screen def get_ip(self): return self._ip.layout().itemAt(1).widget().text() # returns player type from the game options screen for given player def get_player_type(self, index): return self._player_types[index].layout().itemAt( 1).widget().currentIndex() # creates game view and adds it to _game_view layout def create_game_view(self): # layout game_layout = QVBoxLayout() self._card_layout[2] = QHBoxLayout() # create card iamges for teammate for _ in range(0, 10): svgWidget = QtSvg.QSvgWidget('img/BACK.svg') svgWidget.setFixedSize(CARD_WIDTH, CARD_HEIGHT) self._card_layout[2].addWidget(svgWidget) # add this card layout game_layout.addLayout(self._card_layout[2]) # Hbox for center of the screen middle_layout = QHBoxLayout() # player on other team self._card_layout[1] = QVBoxLayout() self._card_layout[1].setAlignment(QtCore.Qt.AlignLeft) for _ in range(0, 10): svgWidget = QtSvg.QSvgWidget('img/BACK.svg') svgWidget.setFixedSize(CARD_WIDTH / 2, CARD_HEIGHT / 2) self._card_layout[1].addWidget(svgWidget) # add this card layout middle_layout.addLayout(self._card_layout[1]) # add other team info label self._player_info[1] = QLabel(self) self._player_info[1].setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) middle_layout.addWidget(self._player_info[1]) # layout in middle center (for teammate and your info) middle_center_layout = QVBoxLayout() # add teammate info label self._player_info[2] = QLabel(self) self._player_info[2].setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) middle_center_layout.addWidget(self._player_info[2]) middle_center_layout.addStretch(1) # add where the 4 cards will go during play self._played_cards = QHBoxLayout() for _ in range(0, NUMBER_PLAYERS): # layout containing this tricks details sublayout = QVBoxLayout() sublayout.setAlignment(QtCore.Qt.AlignVCenter) # text top_text = QLabel() sublayout.addWidget(top_text) # card image svgWidget = QtSvg.QSvgWidget('img/BACK.svg') svgWidget.setFixedSize(CARD_WIDTH, CARD_HEIGHT) sublayout.addWidget(svgWidget) # text bottom_text = QLabel() sublayout.addWidget(bottom_text) self._played_cards.addLayout(sublayout) # add this card layout middle_center_layout.addLayout(self._played_cards) middle_center_layout.addStretch(1) # add player info label self._player_info[0] = QLabel(self) self._player_info[0].setAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignCenter) middle_center_layout.addWidget(self._player_info[0]) # add middle center layout to middle layout middle_layout.addLayout(middle_center_layout) # add other team info label self._player_info[3] = QLabel(self) self._player_info[3].setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) middle_layout.addWidget(self._player_info[3]) # set player info as waiting for index in range(0, 4): self._player_info[index].setText("Waiting for player") self._card_layout[3] = QVBoxLayout() self._card_layout[3].setAlignment(QtCore.Qt.AlignRight) # create card iamges for other team for _ in range(0, 10): svgWidget = QtSvg.QSvgWidget('img/BACK.svg') svgWidget.setFixedSize(CARD_WIDTH / 2, CARD_HEIGHT / 2) self._card_layout[3].addWidget(svgWidget) # add this card layout middle_layout.addLayout(self._card_layout[3]) # add the middle layout game_layout.addLayout(middle_layout) # create card iamges for player self._card_layout[0] = QHBoxLayout() self._card_layout[0].setAlignment(QtCore.Qt.AlignBottom) for index in range(0, 13): svgWidget = QtSvg.QSvgWidget('img/BACK.svg') svgWidget.setFixedSize(CARD_WIDTH, CARD_HEIGHT) if index >= 10: svgWidget.hide() self._card_layout[0].addWidget(svgWidget) # add this card layout game_layout.addLayout(self._card_layout[0]) # add to layout game_layout.addLayout(self.create_bet_controls()) self._game_view.setLayout(game_layout) # returns layout containing all bet controls def create_bet_controls(self): # create layout for betting actions layout = QHBoxLayout() # number bet choice button number_bet = QComboBox() number_bet.addItems(["6", "7", "8", "9", "10"]) layout.addWidget(number_bet) self._bet_controls.append(number_bet) # suit bet choice button suit_bet = QComboBox() suit_bet.addItems( ["Spades", "Clubs", "Diamonds", "Hearts", "No Trumps"]) layout.addWidget(suit_bet) self._bet_controls.append(suit_bet) # bet button, sends bet based on what we entered in the choice boxes above button = QPushButton('Bet', self) button.clicked.connect(lambda: self.send_to_client( number_bet.currentText() + suit_to_letter(suit_bet.currentText()))) layout.addWidget(button) self._bet_controls.append(button) # pass button button = QPushButton('Pass', self) button.clicked.connect(lambda: self.send_to_client("PASS")) layout.addWidget(button) self._bet_controls.append(button) # misere button button = QPushButton('Bet Misere', self) button.clicked.connect(lambda: self.send_to_client("MISERE")) layout.addWidget(button) self._bet_controls.append(button) # open misere button (TODO functionality, such as seeing persons hand) button = QPushButton('Bet Open Misere', self) button.clicked.connect(lambda: self.send_to_client("OPENMISERE")) layout.addWidget(button) self._bet_controls.append(button) layout.addStretch(1) # main menu button button = QPushButton('Exit to menu', self) layout.addWidget(button) button.clicked.connect(lambda: self.exit_to_menu()) self._bet_controls.append(button) # disable bet buttons by default self.activate_bet_controls(set=False) return layout # toggles button activation # leave bool as None to toggle bet def activate_bet_controls(self, set=None): for elem in self._bet_controls[:len(self._bet_controls) - 1]: elem.setEnabled(not elem.isEnabled() if set == None else set) # reset bet controls def reset_bet_controls(self): self.activate_bet_controls(set=False) self._bet_controls[0].setCurrentIndex(0) self._bet_controls[1].setCurrentIndex(0) # given deck, updates the players hand def update_player_hand(self, deck, setEvent=False): # update each card for i, card in enumerate(deck): widget = self._card_layout[self._player].itemAt(i).widget() widget.load('img/' + card + '.svg') # show kitty cards if we are in kitty round if i >= 10: widget.show() # we only need this set after it is possible to choose a card if setEvent: # note the extra card=card argument to stop each # lambda using local variable card # if we are in the kitty round, you can't # choose an invalid card, so remove it instantly widget.mouseReleaseEvent = ( lambda event, card=card: self.send_card( card, remove=bool(len(deck) > 10))) # resets all players hands def reset_players_hands(self): # show each players cards again for i in range(0, NUMBER_PLAYERS): for j in range(0, 10): widget = self._card_layout[i].itemAt(j).widget() widget.load('img/BACK.svg') widget.show() # hide kitty cards again for i in range(10, 13): self._card_layout[self._player].itemAt(i).widget().hide() # reset card layout to what it was before self.rearrange_card_layout( -int(self._player)) # int to remove pylint errors # show the players first 10 cards and hide the last 3 def reset_player_hand_after_kitty(self): for i in range(0, 10): self._card_layout[self._player].itemAt(i).widget().show() for i in range(10, 13): self._card_layout[self._player].itemAt(i).widget().hide() # sends card to client, optionally remove them def send_card(self, card, remove=False): self.send_to_client(card) if remove == True: self.remove_card_from_hand(self._player, card) # toggles card controls # supply set to give them a value def activate_card_controls(self, set=None): for i in range(0, self._card_layout[self._player].count()): widget = self._card_layout[self._player].itemAt(i).widget() widget.setEnabled(not widget.isEnabled() if set == None else set) # removes given card from our hand # note closing the widget does not decrease the count of cards in the layout def remove_card_from_hand(self, player, card): # find location of card in our deck and close that widget if player == self._player: index = self._players[self._player]["deck"].index(card) else: index = self._round self._card_layout[player].itemAt(index).widget().hide() # resets the cards played interface def reset_cards_played(self): self._cards_played = 0 # reset image and text for i in range(0, self._played_cards.count()): self._played_cards.itemAt(i).layout().itemAt(0).widget().setText( "") self._played_cards.itemAt(i).layout().itemAt(1).widget().load( 'img/BACK.svg') self.reset_card_winning() # reset the winning text def reset_card_winning(self): for i in range(0, self._played_cards.count()): self._played_cards.itemAt(i).layout().itemAt(2).widget().setText( "") # adds the card to the center def add_card_played(self, card, player, winning): self._played_cards.itemAt(self._cards_played).layout().\ itemAt(0).widget().setText("Player " + str(player + 1)) self._played_cards.itemAt(self._cards_played).layout().\ itemAt(1).widget().load('img/' + card + '.svg') # update winning text if winning: self.reset_card_winning() self._played_cards.itemAt(self._cards_played).layout().\ itemAt(2).widget().setText("WINNING") self._cards_played += 1 # reset player info def reset_player_info(self): # set player info as waiting for index in range(0, 4): self._player_info[index].setText("Waiting for player") # change the card layout so that number is the player at the base of the # interface. player 0 is there by default. def rearrange_card_layout(self, number): b = self._card_layout[-number:] b.extend(self._card_layout[:-number]) self._card_layout = b # same for self._player_info c = self._player_info[-number:] c.extend(self._player_info[:-number]) self._player_info = c # check for new input from our Client regularly # this means that our GUI is not being blocked for waiting # also note that multiprocess poll is not the same as subprocess poll, # hence the need for Client on seperate process # see MsgTypes enum for details on message contents def handle_client_input(self): # slow down interaction for when you are playing with bots after = POLL_DELAY # check if game is still going if self._parent_conn == None: return # attempt to poll try: self._parent_conn.poll() except: # if we cannot poll it is because we could not connect to the server QMessageBox.information(self, '500', "Failed to connect") self.exit_to_menu() return # repeatedly poll if we have input from Client while self._parent_conn.poll(): data = self.recieve_from_client() print(data) # recieve game details if data["type"] is MsgType.PLAYER: self._player = data["player"] self._players = data["players"] # reset details in case we are restarting self.reset_players_hands() self.reset_player_info() self.reset_cards_played() self.reset_bet_controls() # we want to arrange the self._card_layout indexes so that # index 0 becomes the new index self._player. self.rearrange_card_layout(self._player) # update deck on screen # we only will add the click event either during choosing the kitty # or when the first round begins self.update_player_hand(data["players"][self._player]["deck"]) self.activate_card_controls(set=False) # update all info on screen for index in range(0, NUMBER_PLAYERS): self._player_info[index].setText( str(index + 1) + ": " + data["players"][index]["name"] + os.linesep) # enable bet controls on our bet elif data["type"] is MsgType.BETOURS: # activate bet controls self.activate_bet_controls(set=True) elif data["type"] is MsgType.BETINFO: # reset error text and disable bet controls if this was us if data["player"] == self._player: self.activate_bet_controls(set=False) # add betting text self._player_info[data["player"]].setText( self._player_info[data["player"]].text() + os.linesep + string_to_bet(data["bet"])) if MIN_TIME_BETWEEN_MOVES: after = MIN_TIME_BETWEEN_MOVES break # display why the users bet failed elif data["type"] is MsgType.BETFAILED: QMessageBox.information(self, '500', data["message"]) # disable controls after betting is done elif data["type"] is MsgType.BETWON: self.activate_bet_controls(set=False) if MIN_TIME_BETWEEN_MOVES: after = MIN_TIME_BETWEEN_MOVES break # update the deck with the kitty cards elif data["type"] is MsgType.KITTYDECK: self._players[self._player]["deck"] = data["deck"] self.update_player_hand(data["deck"], setEvent=True) # activate card controls on kitty elif data["type"] is MsgType.KITTYCHOOSE: self.activate_card_controls(set=True) # we are required to choose a joker suit elif data["type"] is MsgType.JOKERCHOOSE: # create message box with suit choices msg = QMessageBox() msg.setWindowTitle('500') msg.setText('Choose a joker suit.') msg.addButton(QPushButton('Spades'), QMessageBox.YesRole) msg.addButton(QPushButton('Clubs'), QMessageBox.YesRole) msg.addButton(QPushButton('Diamonds'), QMessageBox.YesRole) msg.addButton(QPushButton('Hearts'), QMessageBox.YesRole) ret = msg.exec_() # send our chosen suit to the client if ret == 0: ret = "S" elif ret == 1: ret = "C" elif ret == 2: ret = "D" elif ret == 3: ret = "H" self.send_to_client(ret) # waiting on another player to choose joker suit elif data["type"] is MsgType.JOKERSTART: QMessageBox.information(self, '500', "A player is choosing joker suit.") # joker suit chosen elif data["type"] is MsgType.JOKERDONE: QMessageBox.information( self, '500', "The joker is a " + letter_to_suit(data["suit"]) + ".") # update bet (cards are now sorted by suit) elif data["type"] is MsgType.GAMESTART: self.reset_player_hand_after_kitty() self._players[self._player]["deck"] = data["deck"] self.update_player_hand(data["deck"], setEvent=True) # new round elif data["type"] is MsgType.ROUNDNEW: # reset number of cards played self.reset_cards_played() self._round = data["round"] # we can play a card, activate card controls elif data["type"] is MsgType.ROUNDCHOOSE: self.activate_card_controls(set=True) # card has been played elif data["type"] is MsgType.ROUNDCARDPLAYED: # remove card from the hand self.activate_card_controls(set=False) self.remove_card_from_hand(data["player"], data["card"]) # play card to self._played_cards, updating winning text # if the winning card is different self.add_card_played( data["card"], data["player"], bool(self._card_winning != data["winningcard"])) self._card_winning = data["winningcard"] # only have a break if we are not next if MIN_TIME_BETWEEN_MOVES and \ not (data["player"] + 1) % NUMBER_PLAYERS == self._player: after = MIN_TIME_BETWEEN_MOVES break # player played bad card, show them a message elif data["type"] is MsgType.ROUNDBAD: QMessageBox.information(self, '500', data["message"]) # also case that we are in the last round of play elif data["type"] is MsgType.ROUNDWON: # remove card from the hand self.activate_card_controls(set=False) self.remove_card_from_hand(data["player"], data["card"]) # play card to self._played_cards self.add_card_played( data["card"], data["player"], bool(self._card_winning != data["winningcard"])) self._card_winning = None if MIN_TIME_BETWEEN_MOVES: after = MIN_TIME_BETWEEN_MOVES break # game over elif data["type"] is MsgType.GAMEOVER: QMessageBox.information(self, '500', "Game over!") self.exit_to_menu() return # repeat QtCore.QTimer.singleShot(after, self.handle_client_input) # when user presses join def join(self, port, password, ip, username): # communication self._parent_conn, child_conn = Pipe() # this call is blocking if the game loop method is in our controller class! self._client = Process(target=Client, args=( [ip, port, password, username], child_conn, )) self._client.start() # switch to game view self._stacked_layout.setCurrentIndex(2) # check for new data sent by Client in regular intervals QtCore.QTimer.singleShot(POLL_DELAY, self.handle_client_input) # sends data to the client, must be a string (non blocking) def send_to_client(self, data): if self._parent_conn != None: self._parent_conn.send(data) # recieves data from client (blocking) def recieve_from_client(self): if self._parent_conn != None: return self._parent_conn.recv() return None # when user presses the go button def create_game(self): # these details are always required details port = str(self.get_port()) if port == "" or port == "0": QMessageBox.information(self, '500', "Please enter a valid port") return username = self.get_username() if username == "": QMessageBox.information(self, '500', "Please enter a username") return # rest of the details are different for each options type if self._options_type == 0: password = "******" ptypes = "0222" ip = get_localhost_ip() self.create_server(port, password, ptypes) else: # get password for next 2 cases password = self.get_password() if password == "": QMessageBox.information(self, '500', "Please enter a password") return if self._options_type == 1: ip = self.get_ip() # check if ip is valid, ensure it is seperated by 4 dots and # all are numbers between 0 and 255 check = ip.split('.') error = 0 if len(check) == 4: for index in range(0, 4): if (check[index].isnumeric() == True and int(check[index]) >= 0 and int(check[index]) < 256): error += 1 if error != 4: QMessageBox.information(self, '500', "Please enter a valid IP address") return elif self._options_type == 2: ip = get_localhost_ip() ptypes = ["0"] for index in range(0, 3): ptypes.append(str(self.get_player_type(index))) self.create_server(port, password, ''.join(ptypes)) self.join(port, password, ip, username) # ensure we exit only after cleaning up def closeEvent(self, event): self.close_subprocesses() return QWidget.closeEvent(self, event) # closes server and client subprocesses def close_subprocesses(self): if self._server != None: self._server.kill() self._server = None self._parent_conn = None print("Server Terminated") if self._client != None: self._client.terminate() self._client = None print("Client Terminated") # change layout and close server and client subprocesses def exit_to_menu(self): self._stacked_layout.setCurrentIndex(0) self.close_subprocesses() self.reset() # reset game variables def reset(self): # reset all parts of gui self.reset_player_info() self.reset_bet_controls() self.reset_cards_played() self.reset_player_hand_after_kitty() self.activate_card_controls(set=False) # the below resets the hand locations, so ensure all card # related resetting done before this self.reset_players_hands() # reset all player details self._player = 0 self._players = None self._round = None self._cards_played = 0 # creates the server def create_server(self, port, password, playertypes): # create server args srvargs = ["./server", port, password, playertypes] # create server self._server = subprocess.Popen(srvargs, stdout=subprocess.DEVNULL) print("Server Created.")
class QRuleEditor(QDialog): def __init__(self, project, editor, rule): # Rule is some fontFeatures object self.project = project self.editor = editor self.inputslots = [] self.precontextslots = [] self.postcontextslots = [] self.outputslots = [] self.buffer_direction = "RTL" self.buffer_script = "Latin" self.all_valuerecord_editors = [] self.index = None if rule: self.backup_rule = Rule.fromXML(rule.toXML()) # Deep copy else: self.backup_rule = None super(QRuleEditor, self).__init__() splitter = QSplitter() self.slotview = QHBoxLayout() scroll = QScrollArea() scroll.setLayout(self.slotview) self.outputview_before = QBufferRenderer( project, VariationAwareBuffer(self.project.font)) self.outputview_after = QBufferRenderer( project, VariationAwareBuffer(self.project.font)) self.before_after = QWidget() self.before_after_layout_v = QVBoxLayout() self.asFea = QLabel() featureButtons = QWidget() self.featureButtonLayout = QHBoxLayout() featureButtons.setLayout(self.featureButtonLayout) self.selectedFeatures = [] layoutarea = QWidget() self.before_after_layout_h = QHBoxLayout() self.before_after_layout_h.addWidget(self.outputview_before) self.before_after_layout_h.addWidget(self.outputview_after) layoutarea.setLayout(self.before_after_layout_h) if self.project.variations: self.master_selection = QComboBox() for mastername in self.project.variations.masters: self.master_selection.addItem(mastername) self.master_selection.currentTextChanged.connect( self.masterChanged) self.before_after_layout_v.addWidget(self.master_selection) else: self.master_selection = None self.before_after_layout_v.addWidget(featureButtons) self.before_after_layout_v.addWidget(self.asFea) self.before_after_layout_v.addWidget(layoutarea) self.before_after.setLayout(self.before_after_layout_v) splitter.setOrientation(Qt.Vertical) splitter.addWidget(scroll) splitter.addWidget(self.before_after) buttons = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) for button in buttons.buttons(): button.setDefault(False) button.setAutoDefault(False) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) v_box_1 = QVBoxLayout() self.setLayout(v_box_1) v_box_1.addWidget(splitter) v_box_1.addWidget(buttons) self.setRule(rule) @property def currentMaster(self): if not self.master_selection: return None return self.master_selection.currentText() def masterChanged(self): for qvre in self.all_valuerecord_editors: qvre.change_master(self.currentMaster) self.resetBuffer() def keyPressEvent(self, evt): return def accept(self): self.editor.fontfeaturespanel.lookuplist.update(self.index) self.editor.setWindowModified(True) self.editor.showDebugger() def reject(self): for k in dir(self.backup_rule): self.rule = getattr(self.backup_rule, k) self.editor.fontfeaturespanel.lookuplist.update() self.editor.showDebugger() def setRule(self, rule, index=None): self.rule = rule self.index = index self.arrangeSlots() self.representative_string = self.makeRepresentativeString() self.resetBuffer() @property def location(self): sourceIndex = list(self.project.variations.masters.keys()).index( self.currentMaster) return self.project.variations.designspace.sources[ sourceIndex].location def resetBuffer(self): if self.rule: try: self.asFea.setText(self.rule.asFea()) except Exception as e: print("Can't serialize", e) self.outputview_before.set_buf(self.makeBuffer("before")) self.outputview_after.set_buf(self.makeBuffer("after")) if self.currentMaster: self.outputview_before.set_location(self.location) self.outputview_after.set_location(self.location) @pyqtSlot() def changeRepresentativeString(self): l = self.sender() if l.text().startswith("@"): self.representative_string[ l.slotnumber] = self.project.fontfeatures.namedClasses[ l.text()[1:]][0] else: self.representative_string[l.slotnumber] = l.text() self.resetBuffer() @pyqtSlot() def replacementChanged(self): l = self.sender() replacements = l.text().split() self.rule.replacement = [[x] for x in replacements] self.resetBuffer() @pyqtSlot() def addGlyphToSlot(self): l = self.sender() glyphname = l.text() # Check for class names if (glyphname.startswith("@") and glyphname[1:] in self.project.fontfeatures.namedClasses.keys()): # It's OK pass elif glyphname not in self.project.font.keys(): print(f"{glyphname} not found") l.setText("") return print("Adding ", glyphname) l.owner.contents[l.owner.slotindex].append(glyphname) self.arrangeSlots() self.representative_string = self.makeRepresentativeString() self.resetBuffer() @pyqtSlot() def removeGlyphFromSlot(self): l = self.sender() del l.contents[l.slotindex][l.indexWithinSlot] self.arrangeSlots() self.representative_string = self.makeRepresentativeString() self.resetBuffer() @pyqtSlot() def addRemoveSlot(self): sender = self.sender() action = sender.text() if action == "<+": sender.contents.insert(0, []) # If these are input glyphs, add another replacement etc. if sender.contents == self.rule.shaper_inputs(): if isinstance(self.rule, Positioning): self.rule.valuerecords.insert(0, ValueRecord()) elif (isinstance(self.rule, Substitution) and len(self.rule.shaper_inputs()) == 1): self.rule.replacement.insert(0, []) elif isinstance(self.rule, Chaining): self.rule.lookups.insert(0, []) elif action == "+>": sender.contents.append([]) # If these are input glyphs, add another replacement etc. if sender.contents == self.rule.shaper_inputs(): if isinstance(self.rule, Positioning): self.rule.valuerecords.append(ValueRecord()) elif (isinstance(self.rule, Substitution) and len(self.rule.shaper_inputs()) == 1): self.rule.replacement.append([]) elif isinstance(self.rule, Chaining): self.rule.lookups.append([]) elif action == "-": del sender.contents[self.sender().ix] self.arrangeSlots() self.representative_string = self.makeRepresentativeString() self.resetBuffer() def makeASlot(self, slotnumber, contents, style=None, editingWidgets=None): for ix, glyphslot in enumerate(contents): slot = QWidget() slotLayout = QVBoxLayout() if style: slot.setStyleSheet(style) scroll = QScrollArea() scroll.setWidgetResizable(True) scrollWidget = QWidget() scrollLayout = QVBoxLayout() scrollWidget.setLayout(scrollLayout) scroll.setWidget(scrollWidget) for ixWithinSlot, glyph in enumerate(glyphslot): glyphHolder = QWidget() glyphHolderLayout = QHBoxLayout() glyphHolder.setLayout(glyphHolderLayout) l = QPushButton(glyph) l.setDefault(False) l.setAutoDefault(False) l.slotnumber = slotnumber l.clicked.connect(self.changeRepresentativeString) glyphHolderLayout.addWidget(l) remove = QPushButton("x") remove.slotindex = ix remove.indexWithinSlot = ixWithinSlot remove.contents = contents remove.clicked.connect(self.removeGlyphFromSlot) glyphHolderLayout.addWidget(remove) scrollLayout.addWidget(glyphHolder) slotLayout.addWidget(scroll) # This is the part that adds a new glyph to a slot newglyph = QGlyphName(self.project, allow_classes=True) newglyph.slotindex = ix newglyph.contents = contents newglyph.glyphline.returnPressed.connect(self.addGlyphToSlot) slotLayout.addWidget(newglyph) slotLayout.addStretch() if editingWidgets and ix < len(editingWidgets): slotLayout.addWidget(editingWidgets[ix]) pushbuttonsArea = QWidget() pushbuttonsLayout = QHBoxLayout() pushbuttonsArea.setLayout(pushbuttonsLayout) if ix == 0: addASlotLeft = QPushButton("<+") addASlotLeft.contents = contents addASlotLeft.clicked.connect(self.addRemoveSlot) pushbuttonsLayout.addWidget(addASlotLeft) pushbuttonsLayout.addStretch() if not (editingWidgets and len(contents) == 1): removeASlot = QPushButton("-") removeASlot.contents = contents removeASlot.ix = ix removeASlot.clicked.connect(self.addRemoveSlot) pushbuttonsLayout.addWidget(removeASlot) pushbuttonsLayout.addStretch() if ix == len(contents) - 1: addASlotRight = QPushButton("+>") addASlotRight.contents = contents addASlotRight.clicked.connect(self.addRemoveSlot) pushbuttonsLayout.addWidget(addASlotRight) slotLayout.addWidget(pushbuttonsArea) slotnumber = slotnumber + 1 slot.setLayout(slotLayout) self.slotview.addWidget(slot) return slotnumber def lookupCombobox(self, current, warning): c = QComboBox() c.warning = warning names = [ x.name for x in self.project.fontfeatures.routines if not hasattr(x, "comment") ] names = ["--- No lookup ---"] + names for name in names: c.addItem(name) if current in names: c.setCurrentIndex(names.index(current)) self.setComboboxWarningIfNeeded(c) return c @pyqtSlot() def chainingLookupChanged(self): l = self.sender() if l.currentIndex() == 0: self.rule.lookups[l.ix] = [] else: self.rule.lookups[l.ix] = [RoutineReference(name=l.currentText())] self.setComboboxWarningIfNeeded(l) self.resetBuffer() def changesGlyphstringLength(self, routine, depth=1): if depth > 10: return False for r in routine.rules: if isinstance(r, Substitution) and len(r.input) != len(r.replacement): return True elif isinstance(r, Chaining): for lus in r.lookups: for l in (lus or []): if self.changesGlyphstringLength(l.routine, depth + 1): return True return False def setComboboxWarningIfNeeded(self, combobox): # Find routine rname = combobox.currentText() warningNeeded = False if rname: routine = None for r in self.project.fontfeatures.routines: if r.name == rname: routine = r if routine and self.changesGlyphstringLength(routine): stdicon = self.style().standardIcon(QStyle.SP_MessageBoxWarning) combobox.warning.setPixmap( stdicon.pixmap(stdicon.actualSize(QSize(16, 16)))) combobox.warning.setToolTip( "<qt>This lookup may change the length of the glyph stream. Subsequent lookups may not fire at the glyph slots you expect.</qt>" ) else: combobox.warning.clear() combobox.warning.setToolTip("") def addPrecontext(self): self.rule.precontext = [[]] self.arrangeSlots() def addPostcontext(self): self.rule.postcontext = [[]] self.arrangeSlots() def makeEditingWidgets(self): editingWidgets = [] if isinstance(self.rule, Substitution): replacements = [x[0] for x in self.rule.replacement if x] widget = QGlyphName(self.project, multiple=len(self.rule.shaper_inputs()) < 2) widget.setText(" ".join(replacements) or "") widget.position = 0 widget.returnPressed.connect(self.replacementChanged) editingWidgets.append(widget) else: for ix, i in enumerate(self.rule.shaper_inputs()): if isinstance(self.rule, Positioning): widget = QValueRecordEditor(self.rule.valuerecords[ix], vf=self.project.variations, master=self.currentMaster) widget.changed.connect(self.resetBuffer) editingWidgets.append(widget) self.all_valuerecord_editors.append(widget) elif isinstance(self.rule, Chaining): lookup = self.rule.lookups[ix] and self.rule.lookups[ix][ 0].name w = QWidget() wl = QHBoxLayout(w) w.setLayout(wl) warning = QLabel() widget = self.lookupCombobox(lookup, warning) widget.ix = ix widget.currentTextChanged.connect( self.chainingLookupChanged) wl.addWidget(widget) wl.addWidget(warning) editingWidgets.append(w) return editingWidgets def clearLayout(self, layout): if layout is not None: while layout.count(): item = layout.takeAt(0) widget = item.widget() if widget is not None: widget.deleteLater() else: self.clearLayout(item.layout()) def arrangeSlots(self): self.all_valuerecord_editors = [] self.clearLayout(self.slotview) if not self.rule: return slotnumber = 0 if not hasattr(self.rule, "precontext") or not self.rule.precontext: widget = QPushButton("<<+") widget.clicked.connect(self.addPrecontext) self.slotview.addWidget(widget) else: self.slotview.addStretch() slotnumber = self.makeASlot(slotnumber, self.rule.precontext, precontext_style) editingWidgets = self.makeEditingWidgets() slotnumber = self.makeASlot(slotnumber, self.rule.shaper_inputs(), editingWidgets=editingWidgets) if not hasattr(self.rule, "postcontext") or not self.rule.postcontext: widget = QPushButton("+>>") widget.clicked.connect(self.addPostcontext) self.slotview.addWidget(widget) else: self.makeASlot(slotnumber, self.rule.postcontext, postcontext_style) self.slotview.addStretch() def makeRepresentativeString(self): inputglyphs = [] if not self.rule: return inputglyphs # "x and x[0]" thing because slots may be empty if newly added if hasattr(self.rule, "precontext"): inputglyphs.extend([x and x[0] for x in self.rule.precontext]) inputglyphs.extend([x and x[0] for x in self.rule.shaper_inputs()]) if hasattr(self.rule, "postcontext"): inputglyphs.extend([x and x[0] for x in self.rule.postcontext]) representative_string = [x for x in inputglyphs if x] for ix, g in enumerate(representative_string): if (g.startswith("@") and g[1:] in self.project.fontfeatures.namedClasses.keys()): representative_string[ ix] = self.project.fontfeatures.namedClasses[g[1:]][0] # We use this representative string to guess information about # how the *real* shaping process will take place; buffer direction # and script, and hence choice of complex shaper, and hence from # that choice of features to be processed. unicodes = [ self.project.font.codepointForGlyph(x) for x in representative_string ] unicodes = [x for x in unicodes if x] tounicodes = "".join(map(chr, unicodes)) bufferForGuessing = Buffer(self.project.font, unicodes=tounicodes) self.buffer_direction = bufferForGuessing.direction self.buffer_script = bufferForGuessing.script # print("Guessed buffer direction ", self.buffer_direction) # print("Guessed buffer script ", self.buffer_script) shaper = Shaper(self.project.fontfeatures, self.project.font) bufferForGuessing = Buffer(self.project.font, glyphs=representative_string) shaper.execute(bufferForGuessing) self.availableFeatures = [] for stage in shaper.stages: if not isinstance(stage, list): continue for f in stage: if (f not in self.availableFeatures and f in self.project.fontfeatures.features): self.availableFeatures.append(f) self.makeFeatureButtons() return representative_string def makeFeatureButtons(self): self.clearLayout(self.featureButtonLayout) for f in self.availableFeatures: self.selectedFeatures.append(f) featureButton = QCheckBox(f) featureButton.setChecked(True) featureButton.stateChanged.connect(self.resetBuffer) self.featureButtonLayout.addWidget(featureButton) def makeShaperFeatureArray(self): features = [] for i in range(self.featureButtonLayout.count()): item = self.featureButtonLayout.itemAt(i).widget() features.append({"tag": item.text(), "value": item.isChecked()}) return features def makeBuffer(self, before_after="before"): buf = VariationAwareBuffer( self.project.font, direction=self.buffer_direction, ) if self.project.variations: buf.location = self.location buf.vf = self.project.variations buf.items = [ VariationAwareBufferItem.new_glyph(g, self.project.font, buf) for g in self.representative_string ] shaper = Shaper(self.project.fontfeatures, self.project.font) shaper.execute(buf, features=self.makeShaperFeatureArray()) routine = Routine(rules=[self.rule]) # print("Before shaping: ", buf.serialize()) if before_after == "after" and self.rule: print("Before application: ", buf.serialize()) print(self.rule.asFea()) buf.clear_mask() # XXX try: routine.apply_to_buffer(buf) except Exception as e: print("Couldn't shape: " + str(e)) print("After application: ", buf.serialize()) return buf
class Connect_Directions(QObject): """ This class is used to connect the directions modifications at the GUI level. It modifies the module according to the newly selected parameter value. """ signal_paramChanged = pyqtSignal(str, list) # ---------------------------------------------------------------------- def __init__(self, paramName, chosen_value, all_Values, nb_directions): """ Constructor """ super().__init__() self.paramName = paramName self.l = QHBoxLayout() self.chosen_value = chosen_value self.create_the_comboBoxes(chosen_value, all_Values, nb_directions) # ---------------------------------------------------------------------- def create_the_comboBoxes(self, chosen_value, all_Values, nb_directions): """ Creates nb_directions directions, list the possible values and select the chosen_value. paramName = Name of the parameter corresponding to the widget to create chosen_value = the subject's specific parameter values. all_Values = list of all possible values for a parameter nb_directions = number of directions to add. """ nb_val = range(len(chosen_value)) for i in nb_val: self.l.addWidget( self.add_To_ComboBox(all_Values, chosen_value[i], i)) # Add a vertical separator if i != nb_directions: add_v_separator(self.l) nb_val = range(len(chosen_value), nb_directions) for i in nb_val: self.l.addWidget(self.add_To_ComboBox(all_Values, None, i)) # Add a vertical separator if i != nb_val[-1]: add_v_separator(self.l) # ---------------------------------------------------------------------- def add_To_ComboBox(self, values, chosenValue, pos): """ Add the possibles values found in the structure file to a QComboBox. Highlight the subject's specific value. values = list of values. chosenValue = subject's specific value. pos = QComboBox position in the directions list """ templateChoices = QComboBox_Directions(pos) # Iterates over the possible choices for val in values: templateChoices.addItem(str(val), val) if val == chosenValue: templateChoices.setCurrentText(val) templateChoices.signal_paramChanged[int, object].connect(self.on_modify) return templateChoices #---------------------------------------------------------------------- def clear_hBoxLayout(self): """ #Removes all the widgets added to the layout """ for i in reversed(range(self.l.count())): self.l.itemAt(i).widget().setParent(None) @pyqtSlot(str, str) #---------------------------------------------------------------------- def on_new_tdef_file(self, key, trigger_file): """ Update the QComboBox with the new events from the new tdef file. """ self.clear_hBoxLayout() tdef = trigger_def(trigger_file) nb_directions = 4 # Convert 'None' to real None (real None is removed when selected in the GUI) tdef_values = [None if i == 'None' else i for i in list(tdef.by_name)] self.create_the_comboBoxes(self.chosen_value, tdef_values, nb_directions) @pyqtSlot(int, object) # ---------------------------------------------------------------------- def on_modify(self, pos, new_Value): """ Slot connected to comboBox param value change pos = QComboBox position in the directions list new_value = direction new_value """ if pos >= len(self.chosen_value): self.chosen_value.append(new_Value) else: self.chosen_value[pos] = (new_Value) try: self.chosen_value.remove(None) except: pass self.signal_paramChanged[str, list].emit(self.paramName, self.chosen_value)
class App(QDialog): def __init__(self, parent=None): super(App, self).__init__(parent) self.title = "DALI app data regressor" self.attriNum = 0 self.currOutcome = " " # initialize the attribute list self.attriList = [ "heightInches", "happiness", "stressed", "sleepPerNight", "socialDinnerPerWeek", "alcoholDrinksPerWeek", "caffeineRating", "affiliated", "numOfLanguages", "gymPerWeek", "hoursOnScreen" ] # initialize the variable list self.variabList = [] # initialize the regression results self.res = Result() # create group boxes self.createOutcomeBox() self.createScrollBox() self.createAttriLabelBox() self.createErrorBox() self.createCalcBox() self.createResultsLabel() self.createModelLabel() self.createRMSEbox() self.createErrorTwo() self.createResuScroll() self.createPredictBox() self.createOutcomePred() # layout all the boxes mainLayout = QGridLayout() mainLayout.addLayout(self.outcomeBox, 0, 0) mainLayout.addLayout(self.attriLabelBox, 1, 0) mainLayout.addLayout(self.errorBox, 2, 0) mainLayout.addLayout(self.scrollBox, 3, 0) mainLayout.addLayout(self.calcBox, 4, 0) mainLayout.addLayout(self.resBox, 0, 1) mainLayout.addLayout(self.modelBox, 1, 1) mainLayout.addLayout(self.rmseBox, 2, 1) mainLayout.addLayout(self.errorTwo, 3, 1) mainLayout.addLayout(self.resuScroll, 4, 1) mainLayout.addLayout(self.predBox, 5, 1) mainLayout.addLayout(self.outcomePred, 6, 1) self.setLayout(mainLayout) # initialize the UI self.initUI() # initializes the UI def initUI(self): self.setWindowTitle(self.title) self.show() # create a outcome selector box def createOutcomeBox(self): self.outcomeBox = QHBoxLayout() #create combo box and label widgets outcomeCombo = QComboBox() outcomeCombo.addItems(self.attriList) outcomeLabel = QLabel("&Outcome variable:") outcomeLabel.setBuddy(outcomeCombo) # add all the widgets to the box self.outcomeBox.addWidget(outcomeLabel) self.outcomeBox.addStretch(1) self.outcomeBox.addWidget(outcomeCombo) # create a box that contains buttons and labels def createAttriLabelBox(self): self.attriLabelBox = QHBoxLayout() # create an attribute label attributeLab = QLabel("Attributes:") # create both add and remove buttons addButton = QPushButton('Add', self) addButton.setToolTip('Adds more attribute boxes') addButton.clicked.connect(self.clickAdd) rmButton = QPushButton('Remove', self) rmButton.setToolTip('Removes more attribute boxes') rmButton.clicked.connect(self.clickRM) # add all the widgets to the box self.attriLabelBox.addWidget(attributeLab) self.attriLabelBox.addStretch(1) self.attriLabelBox.addWidget(addButton) self.attriLabelBox.addWidget(rmButton) # create an error box def createErrorBox(self): self.errorBox = QHBoxLayout() # create error label errorLabel = QLabel(' ') self.errorBox.addWidget(errorLabel) # creates a scroll box for attribute boxes def createScrollBox(self): self.scrollBox = QVBoxLayout() # create central widget central = QWidget() # create scroll area widget scrollArea = QScrollArea() scrollArea.setWidget(central) scrollArea.setWidgetResizable(True) # create box layout within the box scrollInbox = QVBoxLayout(central) # set box layout self.scrollBox.addWidget(scrollArea) # create box that contains calculate button def createCalcBox(self): self.calcBox = QHBoxLayout() # create calculate button modelButton = QPushButton('Model Regression', self) modelButton.setToolTip("Calculates regression models") modelButton.clicked.connect(self.clickModel) self.calcBox.addWidget(modelButton) # create box that contains the results label def createResultsLabel(self): self.resBox = QHBoxLayout() # create label resLabel = QLabel("Results:") self.resBox.addWidget(resLabel) # create box that contains the model label def createModelLabel(self): self.modelBox = QHBoxLayout() # create label modelLabel = QLabel("Model used:") self.modelBox.addWidget(modelLabel) # create box that contains rmse label def createRMSEbox(self): self.rmseBox = QHBoxLayout() rmseLabel = QLabel("RMSE:") self.rmseBox.addWidget(rmseLabel) # create box that contains error label 2 def createErrorTwo(self): self.errorTwo = QHBoxLayout() errorTwoLabel = QLabel(" ") self.errorTwo.addWidget(errorTwoLabel) # creates a second scroll box for attribute boxes def createResuScroll(self): self.resuScroll = QVBoxLayout() # create central widget central2 = QWidget() # create scroll area widget scrollSpace = QScrollArea() scrollSpace.setWidget(central2) scrollSpace.setWidgetResizable(True) # create box layout within the box scrollInbox = QVBoxLayout(central2) # add the scroll space to the box self.resuScroll.addWidget(scrollSpace) # creates a box for predict button def createPredictBox(self): self.predBox = QHBoxLayout() # create predict button predButton = QPushButton('Predict', self) predButton.setToolTip("Predicts outcome based on model") predButton.clicked.connect(self.clickPredict) self.predBox.addWidget(predButton) # create box that contains outcome prediction def createOutcomePred(self): self.outcomePred = QHBoxLayout() outcomeLabel = QLabel('Outcome prediction:') self.outcomePred.addWidget(outcomeLabel) # what to do when the add button is pushed @pyqtSlot() def clickAdd(self): # if there are too many attribute boxes, display error if self.attriNum <= 9: # add a new combo box newCombo = QComboBox() newCombo.addItems(self.attriList) self.scrollBox.itemAt(0).widget().widget().layout().addWidget( newCombo) self.attriNum += 1 else: error1 = "Error: Too many attributes. Leave as be or decrease." self.errorBox.itemAt(0).widget().setText(error1) # what to do when the remove button is pushed @pyqtSlot() def clickRM(self): # if there are boxes to remove, remove them if self.attriNum > 0: # clear the error box error0 = " " self.errorBox.itemAt(0).widget().setText(error0) # remove the newest combo box self.scrollBox.itemAt(0).widget().widget().layout().itemAt( self.attriNum - 1).widget().deleteLater() self.attriNum -= 1 # what to do when the modelling button is pushed @pyqtSlot() def clickModel(self): # make sure there are attributes to model with if self.attriNum > 0: # make sure there are no duplicates with either the outcome variable or the attributes self.variabList.clear() self.variabList.append( self.outcomeBox.itemAt(2).widget().currentText()) noDupli = True i = 0 # while there attributes to be appended and there are no duplicates while i < self.attriNum and noDupli: # append the selected attribute comboText = self.scrollBox.itemAt(0).widget().widget().layout( ).itemAt(i).widget().currentText() self.variabList.append(comboText) i += 1 # if the length of the set of the current list is not equal to the length of the current list if len(self.variabList) != len(set(self.variabList)): noDupli = False # if there was no duplicates, proceed with the current list of outcome variable and attributes if noDupli: # clear the error box error0 = " " self.errorBox.itemAt(0).widget().setText(error0) # if there was only one attribute selected perform single attribute regression if self.attriNum == 1: self.res = singleAttriReg(self.variabList[0], self.variabList[1]) # otherwise perform multi attribute regression else: attributes = self.variabList[1:] self.res = multiAttriReg(attributes, self.variabList[0]) # post the results model = "Model used: " + self.res.strat rmse = "RMSE: " + str(self.res.rmse) self.modelBox.itemAt(0).widget().setText(model) self.rmseBox.itemAt(0).widget().setText(rmse) # clear the previous resuScroll for i in reversed( range( self.resuScroll.itemAt( 0).widget().widget().layout().count())): self.resuScroll.itemAt(0).widget().widget().layout( ).itemAt(i).widget().setParent(None) # set the current outcome variable so it doesn't get affected by changing # on the screen elsewhere self.currOutcome = self.variabList[0] # create appropriate attribute variable input editors for i in range(self.attriNum): placeholder = QWidget() inputBox = QHBoxLayout() attributes = self.variabList[1:] label = QLabel(attributes[i] + ": ") lineEdit = QLineEdit() inputBox.addWidget(label) inputBox.addWidget(lineEdit) placeholder.setLayout(inputBox) self.resuScroll.itemAt( 0).widget().widget().layout().addWidget(placeholder) # if there were duplicates post error else: error3 = "Error: no duplicate variables allowed" self.errorBox.itemAt(0).widget().setText(error3) else: error2 = "Error: cannot model without attribute variables" self.errorBox.itemAt(0).widget().setText(error2) # what to do when the prediction button is pushed @pyqtSlot() def clickPredict(self): attriCount = self.resuScroll.itemAt( 0).widget().widget().layout().count() newAttriList = [] # make sure there are attributes to use to predict if attriCount > 0: # make sure all the inputted texts are integers numbers = True for j in range(attriCount): try: num = int( self.resuScroll.itemAt(0).widget().widget().layout(). itemAt(j).widget().layout().itemAt(1).widget().text()) newAttriList.append(num) except ValueError: numbers = False # if all inputs were integers if numbers: # clear error message notErr = " " self.errorTwo.itemAt(0).widget().setText(notErr) # predict newAttriList = [newAttriList] # to account for special cases where polynomials screw up the code if self.res.strat == "polynomial regression": poly = PolynomialFeatures(5) newAttriList = poly.fit_transform(newAttriList) prediction = self.res.reg.predict(newAttriList) else: prediction = self.res.reg.predict(newAttriList) # if there is only 1 attribute if attriCount == 1: # set results of prediction predResult = "Outcome - " + self.currOutcome + ": " + str( round(prediction[0][0], 4)) self.outcomePred.itemAt(0).widget().setText(predResult) # if there are more than 1 attribute else: # set results of prediction predResult = "Outcome - " + self.currOutcome + ": " + str( round(prediction[0], 4)) self.outcomePred.itemAt(0).widget().setText(predResult) # set error accordingly else: error5 = "Error: One or more inputs not integers" self.errorTwo.itemAt(0).widget().setText(error5) # set error accordingly else: error4 = "Error: No attributes to use to predict." self.errorTwo.itemAt(0).widget().setText(error4)
class cover_search_widget(QWidget): finished = pyqtSignal() canceled = pyqtSignal() result = pyqtSignal(QPixmap) _arrow_style = 'background-color: {}; border: 0'.format(BACKGROUND_COLOR) _button_style = ''' QPushButton { background-color: #888; color: #F7F7F7; border: 0; width: 6em; height: 2em; border-radius: 5px; } QPushButton:hover { background-color: #666; color: #FFFFFF; } QPushButton:pressed { background-color: #444; color: #FFFFFF; } ''' def __init__(self, artist_name, album_name, parent=None): super(cover_search_widget, self).__init__(parent) self._artist_name = artist_name self._album_name = album_name self.setWindowTitle('{}: {}'.format(artist_name, album_name)) self.resize(SEARCH_WINDOW_WIDTH, SEARCH_WINDOW_HEIGHT) self.setStyleSheet('background-color: {}'.format(BACKGROUND_COLOR)) self._cover_start_index = 1 self._selected_cover_index = -1 self._cover_pixmaps = [] self._cover_resolutions = [] self._init_layout() self.setLayout(self._layout) self._set_state_loading() def _init_layout(self): self._layout = QVBoxLayout() self._layout.setContentsMargins(0, 0, 0, 30) self._init_search_layout() self._layout.addLayout(self._search_layout) self._init_button_layout() self._layout.addLayout(self._button_layout) def _init_search_layout(self): self._search_layout = QHBoxLayout() self._search_layout.setContentsMargins(5, 30, 5, 10) left_pixmap = QPixmap('icons/prev_icon.png') left_dummy_pixmap = QPixmap('icons/prev_dummy_icon.png') self._left_icon = QIcon(left_pixmap) self._left_dummy_icon = QIcon(left_dummy_pixmap) left = QPushButton('') left.setStyleSheet(self._arrow_style) left.setIcon(self._left_dummy_icon) left.setIconSize(QSize(72, 72)) self._search_layout.addWidget(left, alignment=Qt.AlignCenter) self._search_layout.addStretch(1) self._init_cover_layout() for cover_layout in self._cover_layouts: self._search_layout.addLayout(cover_layout) self._search_layout.addStretch(1) right_pixmap = QPixmap('icons/next_icon.png') right = QPushButton('') right.setStyleSheet(self._arrow_style) right.setIcon(QIcon(right_pixmap)) right.setIconSize(QSize(72, 72)) self._search_layout.addWidget(right, alignment=Qt.AlignCenter) for cover_layout in self._cover_layouts: left.clicked.connect(cover_layout.itemAt(0).widget().unselected) right.clicked.connect(cover_layout.itemAt(0).widget().unselected) left.clicked.connect(self._prev) right.clicked.connect(self._next) def _init_cover_layout(self): self._cover_layouts = [] for i in range(N_QUERY): cover = searched_cover_widget() resolution_label = QLabel() layout = QVBoxLayout() layout.addWidget(cover, alignment=Qt.AlignCenter) layout.addWidget(resolution_label, alignment=Qt.AlignCenter) layout.setContentsMargins(0, 0, 0, 0) self._cover_layouts.append(layout) for i in range(len(self._cover_layouts)): self._cover_layouts[i].itemAt(0).widget().clicked.connect( lambda x=i: self._set_selected_cover_index(x)) for j in range(len(self._cover_layouts)): if i == j: continue self._cover_layouts[i].itemAt(0).widget().clicked.connect( self._cover_layouts[j].itemAt(0).widget().unselected) def _init_button_layout(self): self._button_layout = QHBoxLayout() self._button_layout.setContentsMargins(0, 0, 30, 0) self._button_layout.addStretch(1) ok_button = QPushButton('OK') ok_button.setStyleSheet(self._button_style) cancel_button = QPushButton('Cancel') cancel_button.setStyleSheet(self._button_style) self._button_layout.addWidget(ok_button) self._button_layout.addWidget(cancel_button) ok_button.clicked.connect(self._ok) cancel_button.clicked.connect(self._cancel) def _set_state_loading(self): for cover_layout in self._cover_layouts: cover_layout.itemAt(0).widget().setPixmap(QPixmap()) center_index = N_QUERY // 2 self._cover_layouts[center_index].itemAt(0).widget().setText( 'Loading...') def search(self): pixmaps = download_cover_images(self._artist_name, self._album_name, self._cover_start_index, N_QUERY) for p in pixmaps: resolution = p.size() self._cover_pixmaps.append(p) self._cover_resolutions.append(resolution) self._set_state_showing() def _set_state_showing(self): for i in range(len(self._cover_layouts)): pixmap_index = i + self._cover_start_index - 1 self._cover_layouts[i].itemAt(0).widget().setPixmap( self._cover_pixmaps[pixmap_index]) width = self._cover_resolutions[pixmap_index].width() height = self._cover_resolutions[pixmap_index].height() self._cover_layouts[i].itemAt(1).widget().setText('{}x{}'.format( width, height)) def _show_selected_cover(self): for i, cover_layout in enumerate(self._cover_layouts): if (self._cover_start_index + i) == self._selected_cover_index: cover_layout.itemAt(0).widget().selected() @pyqtSlot() def _set_selected_cover_index(self, cover_layout_index): self._selected_cover_index = self._cover_start_index + cover_layout_index - 1 @pyqtSlot() def _prev(self): self._cover_start_index = max(1, self._cover_start_index - N_QUERY) if self._cover_start_index == 1: self._search_layout.itemAt(0).widget().setIcon( self._left_dummy_icon) self._set_state_showing() self._show_selected_cover() @pyqtSlot() def _next(self): self._cover_start_index += N_QUERY if self._cover_start_index > len(self._cover_pixmaps): self._set_state_loading() self.search() else: self._set_state_showing() self._search_layout.itemAt(0).widget().setIcon(self._left_icon) self._show_selected_cover() @pyqtSlot() def _ok(self): if self._selected_cover_index != -1: self.result.emit(self._cover_pixmaps[self._selected_cover_index]) self.finished.emit() self.close() @pyqtSlot() def _cancel(self): self.canceled.emit() self.close()
class Ui_Widget(object): """ Klasa definiująca GUI """ def setupUi(self, Widget): # widgety rysujące kształty, instancje klasy Ksztalt self.ksztalt1 = Ksztalt(self, Ksztalty.Polygon) self.ksztalt2 = Ksztalt(self, Ksztalty.Ellipse) self.ksztaltAktywny = self.ksztalt1 # przyciski CheckBox ### uklad = QVBoxLayout() # układ pionowy self.grupaChk = QButtonGroup() for i, v in enumerate(('Kwadrat', 'Koło', 'Trójkąt', 'Linia')): self.chk = QCheckBox(v) self.grupaChk.addButton(self.chk, i) uklad.addWidget(self.chk) self.grupaChk.buttons()[self.ksztaltAktywny.ksztalt].setChecked(True) # CheckBox do wyboru aktywnego kształtu self.ksztaltChk = QCheckBox('<=') self.ksztaltChk.setChecked(True) uklad.addWidget(self.ksztaltChk) # układ poziomy dla kształtów oraz przycisków CheckBox ukladH1 = QHBoxLayout() ukladH1.addWidget(self.ksztalt1) ukladH1.addLayout(uklad) ukladH1.addWidget(self.ksztalt2) # koniec CheckBox ### # Slider i LCDNumber ### self.suwak = QSlider(Qt.Horizontal) self.suwak.setMinimum(0) self.suwak.setMaximum(255) self.lcd = QLCDNumber() self.lcd.setSegmentStyle(QLCDNumber.Flat) # układ poziomy (splitter) dla slajdera i lcd ukladH2 = QSplitter(Qt.Horizontal, self) ukladH2.addWidget(self.suwak) ukladH2.addWidget(self.lcd) ukladH2.setSizes((125, 75)) # przyciski RadioButton ### self.ukladR = QHBoxLayout() for v in ('R', 'G', 'B'): self.radio = QRadioButton(v) self.ukladR.addWidget(self.radio) self.ukladR.itemAt(0).widget().setChecked(True) # grupujemy przyciski self.grupaRBtn = QGroupBox('Opcje RGB') self.grupaRBtn.setLayout(self.ukladR) self.grupaRBtn.setObjectName('Radio') self.grupaRBtn.setCheckable(True) # układ poziomy dla grupy Radio ukladH3 = QHBoxLayout() ukladH3.addWidget(self.grupaRBtn) # koniec RadioButton ### # główny układ okna, pionowy ### ukladOkna = QVBoxLayout() ukladOkna.addLayout(ukladH1) ukladOkna.addWidget(ukladH2) ukladOkna.addLayout(ukladH3) self.setLayout(ukladOkna) # przypisanie układu do okna głównego self.setWindowTitle('Widżety')
class TableDialog(QDialog): def __init__(self, parent, path, datemode): super().__init__(parent, Qt.WindowCloseButtonHint | Qt.WindowSystemMenuHint) self.path = path self.datemode = datemode self.setWindowTitle(self.tr("Select columns")) self.hlayout = QHBoxLayout() buttonBox = QDialogButtonBox(Qt.Horizontal) buttonBox.addButton(QDialogButtonBox.Ok) buttonBox.accepted.connect(self.accept) self.table = QTableWidget(self) self.table.setEditTriggers(QTableWidget.NoEditTriggers) layout = QVBoxLayout() layout.addLayout(self.hlayout) layout.addWidget(self.table) layout.addWidget(buttonBox) self.setLayout(layout) def comboChanged(self, _index): labels = [] for i in range(1, self.hlayout.count()): combo = self.hlayout.itemAt(i).widget() labels.append(combo.currentText()) self.table.setHorizontalHeaderLabels(labels) for i in range(1, self.hlayout.count()): combo = self.hlayout.itemAt(i).widget() field = combo.currentData() if not field: continue if field.type == Type.Date: for row in range(self.table.rowCount()): item = self.table.item(row, i - 1) val = item.text() try: y, m, d, _h, _m, _s = xlrd.xldate_as_tuple( float(val), self.datemode) date = "%d-%02d-%02d" % (y, m, d) item.setText(date) except ValueError: pass elif field.type in Type.ImageTypes: for row in range(self.table.rowCount()): item = self.table.item(row, i - 1) fileName = item.text() image = QImage() if fileName.startswith('http'): try: # Wikipedia require any header req = urllib.request.Request( fileName, headers={'User-Agent': version.AppName}) data = urllib.request.urlopen(req).read() result = image.loadFromData(data) if result: pixmap = QPixmap.fromImage(image) item.setData(Qt.DecorationRole, pixmap) except: pass else: if not os.path.isabs(fileName): fileName = os.path.join(self.path, fileName) result = image.load(fileName) if result: pixmap = QPixmap.fromImage(image) item.setData(Qt.DecorationRole, pixmap)
class ParameterContainer(QWidget, object): """Container to hold Parameter Widgets.""" def __init__( self, parameters=None, description_text='', extra_parameters=None, parent=None, vertical=True): """Constructor .. versionadded:: 2.2 :param parameters: List of Parameter Widget :type parameters: list :param description_text: Text for description of the parameter container. :type description_text: str """ super().__init__(parent) # attributes if not parameters: self.parameters = [] else: self.parameters = parameters self.description_text = description_text self.extra_parameters = extra_parameters self.parent = parent self.validators = [] self.validators_kwargs = [] # UI if vertical: self.vertical_layout = QVBoxLayout() else: self.vertical_layout = QHBoxLayout() self.widget = QWidget() self.description_label = QLabel() self.description_label.setWordWrap(True) self.scroll_area = QScrollArea() self.group_frame = QFrame() self.qt5_parameter_factory = Qt5ParameterFactory() self.main_layout = QGridLayout() # NOTES(IS) : These functions are commented since the architecture is not # ready yet. # def register_widget(self, parameter, parameter_widget): # """Register new custom widget. # # :param parameter: # :type parameter: GenericParameter # # :param parameter_widget: # :type parameter_widget: GenericParameterWidget # """ # self.qt5_parameter_factory.register_widget( # parameter, parameter_widget) # # def remove_widget(self, parameter): # """Register new custom widget. # # :param parameter: # :type parameter: GenericParameter # """ # if parameter.__name__ in self.dict_widget.keys(): # self.dict_widget.pop(parameter.__name__) def get_parameters(self, validate=True): """Return list of parameters from the current state of widget. :param validate: If true, run validator, else no. :type validate: bool :returns: List of parameter :rtype: list """ if validate: validation_result = self.validate() if not validation_result['valid']: raise InvalidValidationException(validation_result['message']) parameter_widgets = self.get_parameter_widgets() parameters = [] for widget_item in parameter_widgets: parameter_widget = widget_item.widget() parameter = parameter_widget.get_parameter() parameters.append(parameter) # returns based on the object type of self.parameters if isinstance(self.parameters, list): return parameters else: # just return single parameter return parameters[0] def get_parameter_widgets(self): """Return list of parameter widgets from the current state of widget. :returns: List of parameter widget :rtype: list """ parameter_widgets = [self.vertical_layout.itemAt(i) for i in range( self.vertical_layout.count())] return parameter_widgets def setup_ui(self, must_scroll=True): """Setup the UI of this parameter container. """ # Vertical layout to place the parameter widgets self.vertical_layout.setContentsMargins(0, 0, 0, 0) self.vertical_layout.setSpacing(0) # Widget to hold the vertical layout self.widget = QWidget() self.widget.setLayout(self.vertical_layout) # Label for description self.description_label.setText(self.description_text) self.group_frame.setLineWidth(0) self.group_frame.setFrameStyle(QFrame.NoFrame) vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.setSpacing(0) self.group_frame.setLayout(vlayout) if must_scroll: vlayout.addWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) self.scroll_area.setWidget(self.widget) else: vlayout.addWidget(self.widget) # Main layout of the container if self.description_text: self.main_layout.addWidget(self.description_label) self.main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.main_layout) self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) if not isinstance(self.parameters, list): parameters = [self.parameters] else: parameters = self.parameters if len(parameters) == 0: self.set_empty_parameters() return self.main_layout.addWidget(self.group_frame) self.qt5_parameter_factory = Qt5ParameterFactory() if self.extra_parameters is not None: for extra_parameter in self.extra_parameters: if (type(extra_parameter) == tuple and len(extra_parameter) == 2): self.qt5_parameter_factory.register_widget( extra_parameter[0], extra_parameter[1]) for parameter in parameters: parameter_widget = self.qt5_parameter_factory.get_widget(parameter) parameter_widget.setAutoFillBackground(True) self.vertical_layout.addWidget(parameter_widget) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) def set_description(self, description): """Set description of the parameter container. :param description: A new description fot the parameter container. :type description: str """ self.description_text = description self.description_label.setText(self.description_text) def set_empty_parameters(self): """Update UI if there is no parameters in the container. """ new_description = self.description_text new_description += '\n' new_description += 'But, currently there is no parameters available.' self.description_label.setText(new_description) def add_validator(self, validator, **kwargs): """Add validator for this parameter container. :param validator: validator function for this parameter container. :type validator: function """ validator.parent = self self.validators.append(validator) if kwargs: self.validators_kwargs.append(kwargs) else: self.validators_kwargs.append({}) def validate(self): """Validate of all rule for all parameter in this container. :return: True if all valid, False :rtype: dict """ for i in range(len(self.validators)): validator = self.validators[i] validator_kwargs = self.validators_kwargs[i] validation_result = validator(self, **validator_kwargs) if not validation_result['valid']: return validation_result return { 'valid': True, 'message': '' } def get_parameter_by_guid(self, parameter_guid): """Return a parameter based on its uuid :param parameter_guid: The parameter uuid :type parameter_guid: str :returns: The parameter or None if not exist :rtype: GenericParameter, None """ parameters = self.get_parameters(validate=False) for parameter in parameters: if parameter.guid == parameter_guid: return parameter return None def get_parameter_widget_by_guid(self, parameter_guid): """Return a parameter widget based on its uuid :param parameter_guid: The parameter uuid :type parameter_guid: str :returns: The parameter widget or None if not exist :rtype: GenericParameterWidget, None """ parameter_widgets = self.get_parameter_widgets() for parameter_widget in parameter_widgets: if (parameter_widget.widget().get_parameter().guid == parameter_guid): return parameter_widget.widget() return None
class TaskGeneratorDialog(QDialog): def __init__(self, nbprocessors): QDialog.__init__(self) self.layout = QVBoxLayout(self) self.taskset = None # Utilizations: vbox_utilizations = QVBoxLayout() group = QGroupBox("Task Utilizations:") hbox = QHBoxLayout() hbox.addWidget(QLabel("Generator:", self)) self.comboGenerator = QComboBox() self.comboGenerator.addItem("RandFixedSum") self.comboGenerator.addItem("UUniFast-Discard") self.comboGenerator.addItem("Kato's method") self.comboGenerator.currentIndexChanged.connect(self.generator_changed) hbox.addWidget(self.comboGenerator) vbox_utilizations.addLayout(hbox) # Load slider + spinner: hbox_load = QHBoxLayout() sld = _DoubleSlider(QtCore.Qt.Horizontal, self) sld.setMinimum(0) sld.setMaximum(32) self.spin_load = QDoubleSpinBox(self) self.spin_load.setMinimum(0) self.spin_load.setMaximum(32) self.spin_load.setSingleStep(0.1) hbox_load.addWidget(QLabel("Total utilization: ", self)) hbox_load.addWidget(sld) hbox_load.addWidget(self.spin_load) sld.doubleValueChanged.connect(self.spin_load.setValue) self.spin_load.valueChanged.connect(sld.setValue) self.spin_load.setValue(nbprocessors / 2.) vbox_utilizations.addLayout(hbox_load) # Number of periodic tasks: self.hbox_tasks = QHBoxLayout() self.spin_tasks = QSpinBox(self) self.spin_tasks.setMinimum(0) self.spin_tasks.setMaximum(999) # That's arbitrary. self.hbox_tasks.addWidget(QLabel("Number of periodic tasks: ", self)) self.hbox_tasks.addStretch(1) self.hbox_tasks.addWidget(self.spin_tasks) vbox_utilizations.addLayout(self.hbox_tasks) # Number of sporadic tasks: self.hbox_sporadic_tasks = QHBoxLayout() self.spin_sporadic_tasks = QSpinBox(self) self.spin_sporadic_tasks.setMinimum(0) self.spin_sporadic_tasks.setMaximum(999) # That's arbitrary. self.hbox_sporadic_tasks.addWidget( QLabel("Number of sporadic tasks: ", self)) self.hbox_sporadic_tasks.addStretch(1) self.hbox_sporadic_tasks.addWidget(self.spin_sporadic_tasks) vbox_utilizations.addLayout(self.hbox_sporadic_tasks) # Min / Max utilizations self.hbox_utilizations = QHBoxLayout() self.hbox_utilizations.addWidget(QLabel("Min/Max utilizations: ", self)) self.interval_utilization = IntervalSpinner( self, min_=0, max_=1, step=.01, round_option=False) self.hbox_utilizations.addWidget(self.interval_utilization) vbox_utilizations.addLayout(self.hbox_utilizations) group.setLayout(vbox_utilizations) self.layout.addWidget(group) # Periods: vbox_periods = QVBoxLayout() group = QGroupBox("Task Periods:") # Log uniform self.lunif = QRadioButton("log-uniform distribution between:") vbox_periods.addWidget(self.lunif) self.lunif.setChecked(True) self.lunif_interval = IntervalSpinner(self) self.lunif_interval.setEnabled(self.lunif.isChecked()) self.lunif.toggled.connect(self.lunif_interval.setEnabled) vbox_periods.addWidget(self.lunif_interval) # Uniform self.unif = QRadioButton("uniform distribution between:") vbox_periods.addWidget(self.unif) self.unif_interval = IntervalSpinner(self) self.unif_interval.setEnabled(self.unif.isChecked()) self.unif.toggled.connect(self.unif_interval.setEnabled) vbox_periods.addWidget(self.unif_interval) # Discrete discrete = QRadioButton("chosen among these (space separated) values:") vbox_periods.addWidget(discrete) self.periods = QLineEdit(self) self.periods.setValidator(QRegExpValidator( QRegExp("^\\d*(\.\\d*)?( \\d*(\.\\d*)?)*$"))) vbox_periods.addWidget(self.periods) self.periods.setEnabled(discrete.isChecked()) discrete.toggled.connect(self.periods.setEnabled) vbox_periods.addStretch(1) group.setLayout(vbox_periods) self.layout.addWidget(group) buttonBox = QDialogButtonBox() cancel = buttonBox.addButton(QDialogButtonBox.Cancel) generate = buttonBox.addButton("Generate", QDialogButtonBox.AcceptRole) cancel.clicked.connect(self.reject) generate.clicked.connect(self.generate) self.layout.addWidget(buttonBox) self.show_randfixedsum_options() def generator_changed(self, value): if value == 2: self.show_kato_options() else: self.show_randfixedsum_options() def show_randfixedsum_options(self): for i in range(self.hbox_utilizations.count()): self.hbox_utilizations.itemAt(i).widget().hide() for i in range(self.hbox_tasks.count()): if self.hbox_tasks.itemAt(i).widget(): self.hbox_tasks.itemAt(i).widget().show() for i in range(self.hbox_sporadic_tasks.count()): if self.hbox_sporadic_tasks.itemAt(i).widget(): self.hbox_sporadic_tasks.itemAt(i).widget().show() def show_kato_options(self): for i in range(self.hbox_utilizations.count()): if self.hbox_utilizations.itemAt(i).widget(): self.hbox_utilizations.itemAt(i).widget().show() for i in range(self.hbox_tasks.count()): if self.hbox_tasks.itemAt(i).widget(): self.hbox_tasks.itemAt(i).widget().hide() for i in range(self.hbox_sporadic_tasks.count()): if self.hbox_sporadic_tasks.itemAt(i).widget(): self.hbox_sporadic_tasks.itemAt(i).widget().hide() def get_min_utilization(self): return self.interval_utilization.getMin() def get_max_utilization(self): return self.interval_utilization.getMax() def generate(self): n = self.get_nb_tasks() if (n == 0): QMessageBox.warning( self, "Generation failed", "Please check the utilization and the number of tasks.") return if self.comboGenerator.currentIndex() == 0: u = StaffordRandFixedSum(n, self.get_utilization(), 1) elif self.comboGenerator.currentIndex() == 1: u = UUniFastDiscard(n, self.get_utilization(), 1) else: u = gen_kato_utilizations(1, self.get_min_utilization(), self.get_max_utilization(), self.get_utilization()) n = len(u[0]) p_types = self.get_periods() if p_types[0] == "unif": p = gen_periods_uniform(n, 1, p_types[1], p_types[2], p_types[3]) elif p_types[0] == "lunif": p = gen_periods_loguniform(n, 1, p_types[1], p_types[2], p_types[3]) else: p = gen_periods_discrete(n, 1, p_types[1]) if u and p: self.taskset = gen_tasksets(u, p)[0] self.accept() elif not u: QMessageBox.warning( self, "Generation failed", "Please check the utilization and the number of tasks.") else: QMessageBox.warning( self, "Generation failed", "Pleache check the periods.") def get_nb_tasks(self): return self.spin_tasks.value() + self.spin_sporadic_tasks.value() def get_nb_periodic_tasks(self): return self.spin_tasks.value() def get_nb_sporadic_tasks(self): return self.spin_sporadic_tasks.value() def get_utilization(self): return self.spin_load.value() def get_periods(self): if self.unif.isChecked(): return ("unif", self.unif_interval.getMin(), self.unif_interval.getMax(), self.unif_interval.getRound()) elif self.lunif.isChecked(): return ("lunif", self.lunif_interval.getMin(), self.lunif_interval.getMax(), self.lunif_interval.getRound()) else: return ("discrete", map(float, str(self.periods.text()).split()))
class Ui_Widget(object): """ Klasa definiująca GUI """ def setupUi(self, Widget): # widgety rysujące kształty, instancje klasy Ksztalt self.ksztalt1 = Ksztalt(self, Ksztalty.Polygon) self.ksztalt2 = Ksztalt(self, Ksztalty.Ellipse) self.ksztaltAktywny = self.ksztalt1 # przyciski CheckBox ### uklad = QVBoxLayout() # układ pionowy self.grupaChk = QButtonGroup() for i, v in enumerate(('Kwadrat', 'Koło', 'Trójkąt', 'Linia')): self.chk = QCheckBox(v) self.grupaChk.addButton(self.chk, i) uklad.addWidget(self.chk) self.grupaChk.buttons()[self.ksztaltAktywny.ksztalt].setChecked(True) # CheckBox do wyboru aktywnego kształtu self.ksztaltChk = QCheckBox('<=') self.ksztaltChk.setChecked(True) uklad.addWidget(self.ksztaltChk) # układ poziomy dla kształtów oraz przycisków CheckBox ukladH1 = QHBoxLayout() ukladH1.addWidget(self.ksztalt1) ukladH1.addLayout(uklad) ukladH1.addWidget(self.ksztalt2) # koniec CheckBox ### # Slider i LCDNumber ### self.suwak = QSlider(Qt.Horizontal) self.suwak.setMinimum(0) self.suwak.setMaximum(255) self.lcd = QLCDNumber() self.lcd.setSegmentStyle(QLCDNumber.Flat) # układ poziomy (splitter) dla slajdera i lcd ukladH2 = QSplitter(Qt.Horizontal, self) ukladH2.addWidget(self.suwak) ukladH2.addWidget(self.lcd) ukladH2.setSizes((125, 75)) # przyciski RadioButton ### self.ukladR = QHBoxLayout() for v in ('R', 'G', 'B'): self.radio = QRadioButton(v) self.ukladR.addWidget(self.radio) self.ukladR.itemAt(0).widget().setChecked(True) # grupujemy przyciski self.grupaRBtn = QGroupBox('Opcje RGB') self.grupaRBtn.setLayout(self.ukladR) self.grupaRBtn.setObjectName('Radio') self.grupaRBtn.setCheckable(True) # układ poziomy dla grupy Radio ukladH3 = QHBoxLayout() ukladH3.addWidget(self.grupaRBtn) # koniec RadioButton ### # Lista ComboBox i SpinBox ### self.listaRGB = QComboBox(self) for v in ('R', 'G', 'B'): self.listaRGB.addItem(v) self.listaRGB.setEnabled(False) # SpinBox self.spinRGB = QSpinBox() self.spinRGB.setMinimum(0) self.spinRGB.setMaximum(255) self.spinRGB.setEnabled(False) # układ pionowy dla ComboBox i SpinBox uklad = QVBoxLayout() uklad.addWidget(self.listaRGB) uklad.addWidget(self.spinRGB) # do układu poziomego grupy Radio dodajemy układ ComboBox i SpinBox ukladH3.insertSpacing(1, 25) ukladH3.addLayout(uklad) # koniec ComboBox i SpinBox ### # przyciski PushButton ### uklad = QHBoxLayout() self.grupaP = QButtonGroup() self.grupaP.setExclusive(False) for v in ('R', 'G', 'B'): self.btn = QPushButton(v) self.btn.setCheckable(True) self.grupaP.addButton(self.btn) uklad.addWidget(self.btn) # grupujemy przyciski self.grupaPBtn = QGroupBox('Przyciski RGB') self.grupaPBtn.setLayout(uklad) self.grupaPBtn.setObjectName('Push') self.grupaPBtn.setCheckable(True) self.grupaPBtn.setChecked(False) # koniec PushButton ### # główny układ okna, wertykalny ### ukladOkna = QVBoxLayout() ukladOkna.addLayout(ukladH1) ukladOkna.addWidget(ukladH2) ukladOkna.addLayout(ukladH3) ukladOkna.addWidget(self.grupaPBtn) self.setLayout(ukladOkna) # przypisanie układu do okna głównego self.setWindowTitle('Widżety')
class EstimhabW(StatModUseful): """ The Estimhab class provides the graphical interface for the version of the Estimhab model written in HABBY. The Estimhab model is described elsewhere. EstimhabW() just loads the data for Estimhab given by the user. """ save_signal_estimhab = pyqtSignal() """ PyQtsignal to save the Estimhab data. """ def __init__(self, path_prj, name_prj): super().__init__() self.tab_name = "estimhab" self.tab_position = 7 self.model_type = "Estimhab" self.eq50 = QLineEdit() self.esub = QLineEdit() self.path_prj = path_prj self.name_prj = name_prj self.path_bio_estimhab = os.path.join(self.path_bio, 'estimhab') self.total_lineedit_number = 1 self.init_iu() self.process_manager = MyProcessManager( "estimhab_plot") # SC (Suitability Curve) self.read_estimhab_dict() self.fill_input_data() self.fill_fish_name() self.check_if_ready_to_compute() self.eq1.textChanged.connect(self.check_if_ready_to_compute) self.eq2.textChanged.connect(self.check_if_ready_to_compute) self.ew1.textChanged.connect(self.check_if_ready_to_compute) self.ew2.textChanged.connect(self.check_if_ready_to_compute) self.eh1.textChanged.connect(self.check_if_ready_to_compute) self.eh2.textChanged.connect(self.check_if_ready_to_compute) self.eq50.textChanged.connect(self.check_if_ready_to_compute) self.eqmin.textChanged.connect(self.check_if_ready_to_compute) self.eqmax.textChanged.connect(self.check_if_ready_to_compute) self.esub.textChanged.connect(self.check_if_ready_to_compute) self.selected_aquatic_animal_qtablewidget.model().rowsInserted.connect( self.check_if_ready_to_compute) self.selected_aquatic_animal_qtablewidget.model().rowsRemoved.connect( self.check_if_ready_to_compute) def init_iu(self): """ This function is used to initialized an instance of the EstimhabW() class. It is called by __init__(). **Technical comments and walk-through** First we looked if some data for Estimhab was saved before by an user. If yes, we will fill the GUI with the information saved before. Estimhab information is saved in hdf5 file format and the path/name of the hdf5 file is saved in the xml project file. So we open the xml project file and look if the name of an hdf5 file was saved for Estimhab. If yes, the hdf5 file is read. The format of hdf5 file is relatively simple. Each input data for Estimhab has its own dataset (qmes, hmes, wmes, q50, qrange, and substrate). Then, we have a list of string which are a code for the fish species which were analyzed. All the data contained in hdf5 file is loaded into variable. The different label are written on the graphical interface. Then, two QListWidget are modified. The first list contains all the fish species on which HABBY has info (see XML Estimhab format for more info). The second list is the fish selected by the user on which Estimhab will be run. Here, we link these lists with two functions so that the user can select/deselect fish using the mouse. The function name are add_fish() and remove_fish(). Then, we fill the first list. HABBY look up all file of xml type in the “Path_bio” folder (the one indicated in the xml project file under the attribute “Path_bio”). The name are them modified so that the only the name of species appears (and not the full path). We set the layout with all the different QLineEdit where the user can write the needed data. Estimhab model is saved using a function situated in MainWindows_1.py (frankly, I am not so sure why I did put the save function there, but anyway). So the save button just send a signal to MainWindows here, which save the data. """ available_model_label = QLabel(self.tr('Available')) selected_model_label = QLabel(self.tr('Selected')) self.lineedit_width = 50 self.spacer_width = 50 # input q1_layout = QHBoxLayout() q1_layout.addWidget(QLabel('Q1 [m<sup>3</sup>/s]')) q1_layout.addWidget(self.eq1) q1_layout.addItem(QSpacerItem(self.spacer_width, 1)) self.eq1.setFixedWidth(self.lineedit_width) q2_layout = QHBoxLayout() q2_layout.addWidget(QLabel('Q2 [m<sup>3</sup>/s]')) q2_layout.addWidget(self.eq2) q2_layout.addItem(QSpacerItem(self.spacer_width, 1)) self.eq2.setFixedWidth(self.lineedit_width) w1_layout = QHBoxLayout() w1_layout.addWidget(QLabel(self.tr("Width1 [m]"))) w1_layout.addWidget(self.ew1) w1_layout.addItem(QSpacerItem(self.spacer_width, 1)) self.ew1.setFixedWidth(self.lineedit_width) w2_layout = QHBoxLayout() w2_layout.addWidget(QLabel(self.tr("Width2 [m]"))) w2_layout.addWidget(self.ew2) w2_layout.addItem(QSpacerItem(self.spacer_width, 1)) self.ew2.setFixedWidth(self.lineedit_width) h1_layout = QHBoxLayout() h1_layout.addWidget(QLabel(self.tr("Height1 [m]"))) h1_layout.addWidget(self.eh1) self.eh1.setFixedWidth(self.lineedit_width) h2_layout = QHBoxLayout() h2_layout.addWidget(QLabel(self.tr("Height2 [m]"))) h2_layout.addWidget(self.eh2) self.eh2.setFixedWidth(self.lineedit_width) q50_layout = QHBoxLayout() q50_layout.addWidget(QLabel('Qmedian/Q50 [m<sup>3</sup>/s]')) q50_layout.addWidget(self.eq50) q50_layout.addItem(QSpacerItem(self.spacer_width, 1)) self.eq50.setFixedWidth(self.lineedit_width) sub_layout = QHBoxLayout() sub_layout.addWidget(QLabel(self.tr('Mean substrate size [m]'))) sub_layout.addWidget(self.esub) sub_layout.addItem(QSpacerItem(self.spacer_width, 1)) self.esub.setFixedWidth(self.lineedit_width) # output q1out_layout = QHBoxLayout() q1out_layout.addWidget(QLabel(self.tr("Qmin [m<sup>3</sup>/s]"))) q1out_layout.addWidget(self.eqmin) q1out_layout.addItem(QSpacerItem(self.spacer_width, 1)) self.eqmin.setFixedWidth(self.lineedit_width) q2out_layout = QHBoxLayout() q2out_layout.addWidget(QLabel(self.tr("Qmax [m<sup>3</sup>/s]"))) q2out_layout.addWidget(self.eqmax) q2out_layout.addItem(QSpacerItem(self.spacer_width, 1)) self.eqmax.setFixedWidth(self.lineedit_width) self.q2target_layout = QHBoxLayout() self.q2target_layout.addWidget( QLabel(self.tr("Qtarget [m<sup>3</sup>/s]"))) self.q2target_layout.addWidget(self.add_qtarget_button) self.q2target_layout.addWidget(self.remove_qtarget_button) self.add_qtarget_button.clicked.connect(self.add_new_qtarget) self.remove_qtarget_button.clicked.connect(self.remove_one_qtarget) # create lists with the possible fishes self.list_f.setSelectionMode(QAbstractItemView.ExtendedSelection) self.list_f.setDragDropMode(QAbstractItemView.DragDrop) self.list_f.setDefaultDropAction(Qt.MoveAction) self.list_f.setAcceptDrops(True) self.list_f.setSortingEnabled(True) self.selected_aquatic_animal_qtablewidget.setSelectionMode( QAbstractItemView.ExtendedSelection) self.selected_aquatic_animal_qtablewidget.setDragDropMode( QAbstractItemView.DragDrop) self.selected_aquatic_animal_qtablewidget.setDefaultDropAction( Qt.MoveAction) self.selected_aquatic_animal_qtablewidget.setAcceptDrops(True) self.selected_aquatic_animal_qtablewidget.setSortingEnabled(True) # insist on white background color (for linux, mac) self.setAutoFillBackground(True) p = self.palette() p.setColor(self.backgroundRole(), Qt.white) self.setPalette(p) # send model self.run_stop_button = QPushButton(self.tr('Run Estimhab'), self) self.run_stop_button.clicked.connect(self.run_estmihab) change_button_color(self.run_stop_button, "#47B5E6") self.run_stop_button.setEnabled(False) # empty frame scrolable content_widget = QFrame() # hydraulic_data_group hydraulic_data_group = QGroupBox(self.tr('Hydraulic data input')) hydraulic_data_group.setToolTip( self.tr("Double click to reset the input data group.")) hydraulic_data_layout = QGridLayout(hydraulic_data_group) hydraulic_data_layout.addLayout(q1_layout, 0, 0) hydraulic_data_layout.addLayout(w1_layout, 0, 1) hydraulic_data_layout.addLayout(h1_layout, 0, 2) hydraulic_data_layout.addLayout(q2_layout, 1, 0) hydraulic_data_layout.addLayout(w2_layout, 1, 1) hydraulic_data_layout.addLayout(h2_layout, 1, 2) hydraulic_data_layout.addLayout(q50_layout, 2, 0) hydraulic_data_layout.addLayout(sub_layout, 2, 1) hydraulic_data_group.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.doubleclick_input_group = DoubleClicOutputGroup() hydraulic_data_group.installEventFilter(self.doubleclick_input_group) self.doubleclick_input_group.double_clic_signal.connect( self.reset_hydraulic_data_input_group) # hydraulic_data_output_group hydraulic_data_output_group = QGroupBox( self.tr('Desired hydraulic output data')) hydraulic_data_output_group.setToolTip( self.tr("Double click to reset the outpout data group.")) hydraulic_data_layout = QGridLayout(hydraulic_data_output_group) hydraulic_data_layout.addLayout(q1out_layout, 0, 0) hydraulic_data_layout.addLayout(q2out_layout, 0, 1) hydraulic_data_layout.addLayout(self.q2target_layout, 0, 2) hydraulic_data_output_group.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.doubleclick_output_group = DoubleClicOutputGroup() hydraulic_data_output_group.installEventFilter( self.doubleclick_output_group) self.doubleclick_output_group.double_clic_signal.connect( self.reset_hydraulic_data_output_group) # models_group models_group = QGroupBox(self.tr('Biological models')) models_layout = QGridLayout(models_group) models_layout.addWidget(available_model_label, 0, 0) models_layout.addWidget(selected_model_label, 0, 1) models_layout.addWidget(self.list_f, 1, 0) models_layout.addWidget(self.selected_aquatic_animal_qtablewidget, 1, 1) models_layout.addWidget(self.run_stop_button, 2, 1) self.doubleclick_models_group = DoubleClicOutputGroup() models_group.installEventFilter(self.doubleclick_models_group) self.doubleclick_models_group.double_clic_signal.connect( self.reset_models_group) # gereral_layout self.layout3 = QVBoxLayout(content_widget) self.layout3.addWidget(hydraulic_data_group, Qt.AlignLeft) self.layout3.addWidget(hydraulic_data_output_group) self.layout3.addWidget(models_group) # self.setLayout(self.layout3) self.setWidgetResizable(True) self.setFrameShape(QFrame.NoFrame) self.setWidget(content_widget) def add_new_qtarget(self): # count existing number of lineedit total_widget_number = self.q2target_layout.count() self.total_lineedit_number = total_widget_number - 2 # - first : qlabel and plus and moins button + New lineedit lineedit_name = 'new_qtarget' + str(self.total_lineedit_number) setattr(self, lineedit_name, QLineEdit()) getattr(self, lineedit_name).setFixedWidth(self.lineedit_width) self.target_lineedit_list.append(getattr(self, lineedit_name)) self.q2target_layout.insertWidget(total_widget_number - 2, getattr(self, lineedit_name)) def remove_one_qtarget(self): # count existing number of lineedit total_widget_number = self.q2target_layout.count() self.total_lineedit_number = total_widget_number - 3 # - first : qlabel and plus and moins button - New lineedit if self.total_lineedit_number > 0: self.target_lineedit_list.pop(-1) self.q2target_layout.itemAt(total_widget_number - 3).widget().setParent(None) self.total_lineedit_number = self.total_lineedit_number - 1 def reset_hydraulic_data_input_group(self): # remove txt in lineedit self.eq1.setText("") self.eq2.setText("") self.ew1.setText("") self.ew2.setText("") self.eh1.setText("") self.eh2.setText("") self.eq50.setText("") self.esub.setText("") def reset_hydraulic_data_output_group(self): # remove txt in lineedit self.eqmin.setText("") self.eqmax.setText("") # remove lineedits qtarget for i in reversed(range(1, self.q2target_layout.count() - 1)): self.q2target_layout.itemAt(i).widget().setParent(None) self.total_lineedit_number = self.total_lineedit_number - 1 self.target_lineedit_list = [] def reset_models_group(self): if self.selected_aquatic_animal_qtablewidget.count() > 0: self.selected_aquatic_animal_qtablewidget.clear() self.fill_fish_name() def read_estimhab_dict(self): """ This function opens the json data created by estimhab """ # load_project_properties self.estimhab_dict = load_specific_properties(self.path_prj, [self.model_type])[0] def fill_fish_name(self): """ This function reads all latin fish name from the xml files which are contained in the biological directory related to estimhab and fill GUI fish names """ all_xmlfile = glob.glob(os.path.join(self.path_bio_estimhab, r'*.xml')) if self.estimhab_dict: selected_fish = self.estimhab_dict["fish_list"] else: selected_fish = [] for f in all_xmlfile: # open xml try: try: docxml = ET.parse(f) root = docxml.getroot() except IOError: self.send_log.emit( self.tr("Warning: ") + self.tr("The .habby project file ") + f + self.tr(" could not be open.\n")) return except ET.ParseError: self.send_log.emit( self.tr("Warning: ") + self.tr("The .habby project file ") + f + self.tr(" is not well-formed.\n")) return # find fish name fish_name = root.find(".//LatinName") # None is null for python 3 if fish_name is not None: fish_name = fish_name.text.strip() # find fish stage stage = root.find(".//estimhab/stage") # None is null for python 3 if stage is not None: stage = stage.text.strip() if stage != 'all_stage': fish_name += ' ' + stage # check if not selected if fish_name not in selected_fish: # add to the list item = QListWidgetItem(fish_name) item.setData(1, f) self.list_f.addItem(item) else: # add to the list item2 = QListWidgetItem(fish_name) item2.setData(1, f) self.selected_aquatic_animal_qtablewidget.addItem(item2) def fill_input_data(self): if self.estimhab_dict: # input data self.eq1.setText(str(self.estimhab_dict["q"][0])) self.eq2.setText(str(self.estimhab_dict["q"][1])) self.eh1.setText(str(self.estimhab_dict["h"][0])) self.eh2.setText(str(self.estimhab_dict["h"][1])) self.ew1.setText(str(self.estimhab_dict["w"][0])) self.ew2.setText(str(self.estimhab_dict["w"][1])) self.eq50.setText(str(self.estimhab_dict["q50"])) self.eqmin.setText(str(self.estimhab_dict["qrange"][0])) self.eqmax.setText(str(self.estimhab_dict["qrange"][1])) self.esub.setText(str(self.estimhab_dict["substrate"])) # qtarg if len(self.estimhab_dict["qtarg"]) > 0: while self.total_lineedit_number != len( self.estimhab_dict["qtarg"]): self.add_new_qtarget() for qtarg_num, qtarg_value in enumerate( self.estimhab_dict["qtarg"][1:]): getattr(self, 'new_qtarget' + str(qtarg_num + 2)).setText( str(qtarg_value)) def check_if_ready_to_compute(self): all_string_selection = (self.eq1.text(), self.eq2.text(), self.ew1.text(), self.ew2.text(), self.eh1.text(), self.eh2.text(), self.eq50.text(), self.eqmin.text(), self.eqmax.text(), self.esub.text()) # minimum one fish and string in input lineedits to enable run_stop_button if self.selected_aquatic_animal_qtablewidget.count( ) > 0 and "" not in all_string_selection: self.run_stop_button.setEnabled(True) else: self.run_stop_button.setEnabled(False) def change_folder(self): """ A small method to change the folder which indicates where is the biological data """ # user find new path self.path_bio_estimhab = QFileDialog.getExistingDirectory( self, self.tr("Open Directory"), os.getenv('HOME')) # update list self.list_f.clear() all_file = glob.glob(os.path.join(self.path_bio_estimhab, r'*.xml')) # make it look nicer for i in range(0, len(all_file)): all_file[i] = all_file[i].replace(self.path_bio_estimhab, "") all_file[i] = all_file[i].replace("\\", "") all_file[i] = all_file[i].replace(".xml", "") item = QListWidgetItem(all_file[i]) # add them to the menu self.list_f.addItem(item) def run_estmihab(self): """ A function to execute Estimhab by calling the estimhab function. **Technical comment** This is the function making the link between the GUI and the source code proper. The source code for Estimhab is in src/Estimhab.py. This function loads in memory the data given in the graphical interface and call sthe Estimhab model. The data could be written by the user now or it could be data which was saved in the hdf5 file before and loaded when HABBY was open (and the init function called). We check that all necessary data is present and that the data given makes sense (e.g.,the minimum discharge should not be bigger than the maximal discharge, the data should be a float, etc.). We then remove the duplicate fish species (in case the user select one specie twice) and the Estimhab model is called. The log is then written (see the paragraph on the log for more information). Next, the figures created by Estimmhab are shown. As there is only a short number of outputs for Estimhab, we create a figure in all cases (it could be changed by adding a checkbox on the GUI like in the Telemac or other hydrological class). """ # prepare data try: q = [ float(self.eq1.text().replace(",", ".")), float(self.eq2.text().replace(",", ".")) ] w = [ float(self.ew1.text().replace(",", ".")), float(self.ew2.text().replace(",", ".")) ] h = [ float(self.eh1.text().replace(",", ".")), float(self.eh2.text().replace(",", ".")) ] q50 = float(self.eq50.text().replace(",", ".")) qrange = [ float(self.eqmin.text().replace(",", ".")), float(self.eqmax.text().replace(",", ".")) ] qtarget_values_list = [] for qtarg_lineedit in self.target_lineedit_list: if qtarg_lineedit.text(): qtarget_values_list.append( float(qtarg_lineedit.text().replace(",", "."))) substrate = float(self.esub.text().replace(",", ".")) except ValueError: self.send_log.emit('Error: ' + self.tr( 'Some data are empty or not float. Cannot run Estimhab')) return # get the list of xml file fish_list = [] fish_name2 = [] for i in range(0, self.selected_aquatic_animal_qtablewidget.count()): fish_item = self.selected_aquatic_animal_qtablewidget.item(i) fish_item_str = fish_item.text() fish_list.append(os.path.basename(fish_item.data(1))) fish_name2.append(fish_item_str) # check internal logic if not fish_list: self.send_log.emit( 'Error: ' + self.tr('No fish selected. Cannot run Estimhab.')) return if qrange[0] >= qrange[1]: self.send_log.emit('Error: ' + self.tr( 'Minimum discharge bigger or equal to max discharge. Cannot run Estimhab.' )) return if qtarget_values_list: for qtarg in qtarget_values_list: if qtarg < qrange[0] or qtarg > qrange[1]: self.send_log.emit('Error: ' + self.tr( 'Target discharge is not between Qmin and Qmax. Cannot run Estimhab.' )) return if q[0] == q[1]: self.send_log.emit( 'Error: ' + self.tr('Estimhab needs two differents measured discharges.')) return if h[0] == h[1]: self.send_log.emit( 'Error: ' + self.tr('Estimhab needs two different measured height.')) return if w[0] == w[1]: self.send_log.emit( 'Error: ' + self.tr('Estimhab needs two different measured width.')) return if (q[0] > q[1] and h[0] < h[1]) or (q[0] > q[1] and w[0] < w[1]) or (q[1] > q[0] and h[1] < h[0]) \ or (q[1] > q[0] and w[1] < w[0]): self.send_log.emit( 'Error: ' + self.tr('Discharge, width, and height data are not coherent.')) return if q[0] <= 0 or q[1] <= 0 or w[0] <= 0 or w[1] <= 0 or h[0] <= 0 or h[1] <= 0 or qrange[0] <= 0 or qrange[1] <= 0 \ or substrate <= 0 or q50 <= 0: self.send_log.emit('Error: ' + self.tr( 'Negative or zero data found. Could not run Estimhab.')) return if substrate > 3: self.send_log.emit( 'Error: ' + self.tr('Substrate is too large. Could not run Estimhab.')) return self.send_log.emit(self.tr('# Computing: Estimhab...')) # check if the discharge range is realistic with the result self.qall = [q[0], q[1], qrange[0], qrange[1], q50] self.check_all_q() # run and save project_properties = load_project_properties(self.path_prj) sys.stdout = mystdout = StringIO() self.estimhab_dict = dict(q=q, w=w, h=h, q50=q50, qrange=qrange, qtarg=qtarget_values_list, substrate=substrate, path_bio=self.path_bio_estimhab, xml_list=fish_list, fish_list=fish_name2) # change_specific_properties change_specific_properties(self.path_prj, ["Estimhab"], [self.estimhab_dict]) # process state = Value("d", 0) self.p = Process(target=estimhab_mod.estimhab_process, args=(self.estimhab_dict, project_properties, self.path_prj, state), name="Estimhab") self.p.start() self.p.join() # plot plot_attr = lambda: None plot_attr.name_hdf5 = self.name_prj + '_ESTIMHAB' + '.hab' plot_attr.nb_plot = 1 self.process_manager.set_estimhab_plot_mode( self.path_prj, plot_attr, load_project_properties(self.path_prj)) self.process_manager.start() # log info str_found = mystdout.getvalue() str_found = str_found.split('\n') for i in range(0, len(str_found)): if len(str_found[i]) > 1: self.send_log.emit(str_found[i]) self.send_log.emit( self. tr("Estimhab computation done. Figure and text files created in output project folder." )) self.send_log.emit("py data = [" + str(q) + ',' + str(w) + ',' + str(h) + ',' + str(q50) + ',' + str(substrate) + ']') self.send_log.emit("py qrange =[" + str(qrange[0]) + ',' + str(qrange[1]) + ']') self.send_log.emit( "py path1= os.path.join(os.path.dirname(path_bio),'" + self.path_bio_estimhab + "')") fish_list_str = "py fish_list = [" for i in range(0, len(fish_list)): fish_list_str += "'" + fish_list[i] + "'," fish_list_str = fish_list_str[:-1] + ']' self.send_log.emit(fish_list_str) self.send_log.emit( "py [OSI, WUA] = estimhab.estimhab(data[0], data[1], data[2], data[3] ," " qrange, data[4], path1, fish_list, '.', True, {}, '.')\n")
class ColorChangeHue(QMainWindow): def __init__(self, parent_win, dom_colors): super().__init__() self.title = 'Interactively change the color by hue matching' self.left = 50 self.top = 50 self.width = 480 self.height = 150 self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.wid = QWidget(self) self.setCentralWidget(self.wid) self.mainlayout = QVBoxLayout() self.wid.setLayout(self.mainlayout) print(dom_colors) self.h_dom_colors = [] for dc in dom_colors: self.h_dom_colors.append( transfer_lab.rgb2hue_opencv(transfer_lab.lab2rgb_opencv(dc))[0] * 2) self.parent_win = parent_win self.add_hue_matchings() self.source_hue_idx = None self.target_hue_idx = None self.src_tar_mp = {} self.setStyleSheet( "QLabel{background:white;}" "QLabel{color:rgb(100,100,100,250);font-size:15px;font-weight:bold;font-family:Roman times;}" "QLabel:hover{color:rgb(100,100,100,120);}") def add_hue_matchings(self): self.top_hue_layout = QHBoxLayout() self.mid_hue_layout = QHBoxLayout() self.bottom_hue_layout = QHBoxLayout() self.mainlayout.addLayout(self.top_hue_layout) self.mainlayout.addLayout(self.mid_hue_layout) self.mainlayout.addLayout(self.bottom_hue_layout) bin_size = 10 self.binsz = bin_size for idx, w in enumerate(range(0, 360, bin_size)): mid_h = int((idx + 0.5) * bin_size) if mid_h >= 360: break q = QLabel() q.setAutoFillBackground(True) q.setText(" ") q.setMargin(5) p = q.palette() ss = False for hu_range in range(int(mid_h - bin_size * 0.5), int(mid_h + bin_size * 0.5)): if hu_range in self.h_dom_colors: ss = True if ss: # p.setColor(q.backgroundRole(),QColor.fromHsl(mid_h,255,128)) q.setStyleSheet("background-color: %s" % (QColor.fromHsl(mid_h, 255, 128).name())) else: # p.setColor(q.backgroundRole(), QColor.fromHsl(mid_h, 255, 128,alpha=0)) q.setStyleSheet("background-color: %s" % (QColor.fromHsl( mid_h, 255, 128, alpha=0).name(QColor.HexArgb))) q.setPalette(p) q.mousePressEvent = functools.partial(self.choose_source_hue, source_object=q, index=idx) self.top_hue_layout.addWidget(q) for idx, w in enumerate(range(0, 360, bin_size)): if int((idx + 0.5) * bin_size) >= 360: break q = QLabel() q.setAutoFillBackground(True) q.setText(" ") q.setMargin(5) p = q.palette() # p.setColor(q.backgroundRole(),QColor.fromHsl(int((idx+0.5)*bin_size), 255, 128, alpha=0)) q.setPalette(p) qc = QColor.fromHsl(int((idx + 0.5) * bin_size), 255, 128, alpha=0) q.setStyleSheet("background-color: %s" % (qc.name(QColor.HexArgb))) self.mid_hue_layout.addWidget(q) for idx, w in enumerate(range(0, 360, bin_size)): if int((idx + 0.5) * bin_size) >= 360: break q = QLabel() q.setAutoFillBackground(True) q.setMargin(5) p = q.palette() p.setColor(q.backgroundRole(), QColor.fromHsl(int((idx + 0.5) * bin_size), 255, 128)) q.setPalette(p) q.setStyleSheet("background-color: %s" % (QColor.fromHsl(int( (idx + 0.5) * bin_size), 255, 128).name())) q.mousePressEvent = functools.partial(self.choose_target_hue, source_object=q, index=idx) self.bottom_hue_layout.addWidget(q) def choose_source_hue(self, event, source_object=None, index=None): self.source_hue_idx = index pass def choose_target_hue(self, event, source_object=None, index=None): self.target_hue_idx = index if self.source_hue_idx is not None: q = self.mid_hue_layout.itemAt(self.source_hue_idx).widget() p = q.palette() p.setColor( q.backgroundRole(), QColor.fromHsl(int((self.target_hue_idx + 0.5) * self.binsz), 255, 128, alpha=255)) q.setPalette(p) qc = QColor.fromHsl(int((self.target_hue_idx + 0.5) * self.binsz), 255, 128, alpha=255) q.setStyleSheet("background-color: %s" % (qc.name(QColor.HexArgb))) self.src_tar_mp[self.source_hue_idx] = self.target_hue_idx #更新目标颜色 并刷新结果 self.parent_win.update_target_colors(self.src_tar_mp, self.binsz) pass
class ProblemPage(QWidget): def __init__(self, mode, timer): super().__init__() self.solution_stack = [] self.start_time = 0 self.timer = timer self.mode = mode self.numbers = [] self.target = 0 self.back_button = QPushButton("Back") self.big_number_count = QSpinBox() self.big_number_count.setRange(1, 4) self.generate_number_box = QPushButton("Generate") self.reset_button = QPushButton("Reset") self.reset_button.setDisabled(True) self.number_group = QHBoxLayout() self.set_numbers = QPushButton("Set Numbers") self.set_numbers.setDisabled(True) self.number_line() self.target_window = QLineEdit("Target") self.set_target = QPushButton("Set Target") self.set_target.setDisabled(True) self.target_check = QLabel("Target should be between 100 and 999") self.timer_bar = QProgressBar() self.timer_bar.setRange(0, 100) self.time_keeper = QTimer() self.counter = 0 self.time_keeper.timeout.connect(lambda: self.timer_props()) self.setLayout(self.set_layout()) if self.mode == 0: self.generate_number_box.clicked.connect( lambda: self.generate_button_mode0_action()) self.set_numbers.clicked.connect(lambda: self.set_numbers_action()) self.reset_button.clicked.connect(lambda: self.reset_actions()) self.set_target.clicked.connect( lambda: self.target_button_action()) self.back_button.clicked.connect(lambda: self.reset_actions()) def solve(self): solver = CountDownSolver(self.big_number_count.value(), self.numbers, self.target) print('Solver started') start_time = time.time() solver.solve() self.solution_stack = solver.solution_stack print('solver done') end_time = time.time() print('solver took :', round(end_time - start_time, 3), 'secs') def timer_props(self): self.counter += 1 value = (self.counter / 100) / self.timer * 100 self.timer_bar.setValue(value) if value > 100: self.time_keeper.stop() self.solve() print(self.solution_stack) def target_button_action(self): try: if 100 <= int(self.target_window.text()) <= 999: self.set_target.setDisabled(True) self.target = int(self.target_window.text()) print('valid target: ', self.target) self.time_keeper.start(1) else: self.target = 0 print('target not in range') except ValueError: print('invalid target') def reset_actions(self): self.generate_number_box.setDisabled(False) self.set_numbers.setDisabled(True) self.set_target.setDisabled(True) for i in range(self.number_group.count()): item = self.number_group.itemAt(i).widget() if isinstance(item, QComboBox): for j in range(item.count()): item.removeItem(0) def set_numbers_action(self): self.numbers = [] for i in range(self.number_group.count()): item = self.number_group.itemAt(i).widget() if isinstance(item, QComboBox): self.numbers.append(int(item.currentText())) print(self.numbers) self.set_target.setDisabled(False) def generate_button_mode0_action(self): big = self.big_number_count.value() box = 0 for i in range(self.number_group.count()): item = self.number_group.itemAt(i).widget() if isinstance(item, QComboBox): if box < big: item.addItems(str(25 * j) for j in [1, 2, 3, 4]) elif big <= box < 6: item.addItems(str(j) for j in range(1, 11)) box += 1 self.generate_number_box.setDisabled(True) self.set_numbers.setDisabled(False) self.reset_button.setDisabled(False) def set_layout(self): back_line = QHBoxLayout() back_line.addStretch(1) back_line.addWidget(self.back_button) back_line.addStretch(1) big_number_line = QHBoxLayout() big_number_line.addWidget(QLabel("Big Number Count : ")) big_number_line.addStretch(1) big_number_line.addWidget(self.big_number_count) big_number_line.addStretch(1) big_number_line.addWidget(self.generate_number_box) big_number_line.addStretch(1) big_number_line.addWidget(self.reset_button) target_line = QHBoxLayout() target_line.addWidget(self.target_window) target_line.addStretch(1) target_line.addWidget(self.set_target) target_line.addStretch(1) target_line.addWidget(self.target_check) main_layout = QVBoxLayout() main_layout.addLayout(back_line) main_layout.addStretch(1) main_layout.addLayout(big_number_line) main_layout.addStretch(1) main_layout.addLayout(self.number_group) main_layout.addStretch(1) main_layout.addLayout(target_line) main_layout.addStretch(1) main_layout.addWidget(self.timer_bar) main_layout.addStretch(1) return main_layout def number_line(self): for i in range(6): if self.mode == 1: self.number_group.addWidget(QLabel(" ")) self.number_group.addStretch(1) elif self.mode == 0: self.number_group.addWidget(QComboBox()) self.number_group.addStretch(1) self.number_group.addWidget(self.set_numbers)
class App(QDialog): def __init__(self, parent=None): super(App, self).__init__(parent) self.title = 'Stock/ETF Historical Investment Strategy Calculator' # create group boxes self.createTickerBoxes() self.createInstructionBox() self.createStratBoxes() self.createInitialBox() self.createStaticNumbersBoxes() self.createIncomeBox() self.createAIGRBox() self.createInvesFracBox() self.createCalculateBox() self.createResultsBox() self.createExtraBasicBox() self.createExtraDateBox() self.createErrorBox() self.createFinalIncomeBox() # create and organize the layout mainLayout = QGridLayout() mainLayout.addLayout(self.tickerBoxes, 0, 0) mainLayout.addLayout(self.instructBoxes, 1, 0) mainLayout.addLayout(self.stratBoxes, 2, 0) mainLayout.addLayout(self.initialBox, 3, 0) mainLayout.addLayout(self.staticNumbersBoxes, 4, 0) mainLayout.addLayout(self.incomeBox, 5, 0) mainLayout.addLayout(self.aigrBox, 6, 0) mainLayout.addLayout(self.investFracBox, 7, 0) mainLayout.addLayout(self.calculateBox, 8, 0) mainLayout.addLayout(self.errorBox, 9, 0) mainLayout.addLayout(self.resultsBox, 0, 1, 7, 10) mainLayout.addLayout(self.extraBasicBox, 7, 1) mainLayout.addLayout(self.extraDateBox, 8, 1) mainLayout.addLayout(self.finalIncomeBox, 9, 1) mainLayout.setColumnStretch(0, 1) mainLayout.setColumnStretch(1, 10) self.createTabs(mainLayout) centralLayout = QGridLayout() centralLayout.addWidget(self.tabWidget, 0, 0) self.setLayout(centralLayout) # initializing the app self.initUI() # initializes the UI def initUI(self): self.setWindowTitle(self.title) self.show() # creates the tabs def createTabs(self, layout): self.tabWidget = QTabWidget() tab1 = QWidget() tab1.setLayout(layout) tab2 = QWidget() guideLabel = QLabel("Check boxes for data to be updated:") stockLineEdit = QLineEdit("") stockCheck = QCheckBox("Ticker: ") notesCheck = QCheckBox("Treasury Notes") tickerCheck = QCheckBox("Ticker List") refreshButton = QPushButton("Update Data") refreshButton.clicked.connect(self.clickRefresh) errorMessage = QLabel("") tab2Box = QVBoxLayout() tab2miniBox = QHBoxLayout() tab2miniBox.addWidget(stockCheck) tab2miniBox.addWidget(stockLineEdit) tab2Box.addWidget(guideLabel) tab2Box.addLayout(tab2miniBox) tab2Box.addWidget(notesCheck) tab2Box.addWidget(tickerCheck) tab2Box.addWidget(refreshButton) tab2Box.addWidget(errorMessage) tab2.setLayout(tab2Box) tab3 = QWidget() inveStratTextEdit = QTextEdit() inveStratTextEdit.setPlainText( "Investment strategies\n" "by ComradeAkko\n\n" "The following are the investment strategies that can be used with the\n" "function. Static strategies are ones where the only capital used is\n" "the initial capital. Active strategies include monthly payments.\n\n\n" "Static Strategies\n\n" "Buy and Hold (BH):\n" "After an initial investment, the shares are held for the entirety of\n" "its period. Dividends are not reinvested.\n\n" "Regular Momentum Trading (MT):\n" "After an intial investment, the shares are held as long as the price\n" "is above its 200-day moving average. If the price is below its 200-day\n" "moving average, it is sold and transferred to bonds. Dividends are reinvested\n" "when a trade is made.\n\n" "Golden-Cross Momentum Trading (GX):\n" "After an initial investment, shares are held when the price is above\n" "both its 200-day and 50-day moving average. If the 50-day moving average\n" "crosses below the 200-day moving average, the shares are sold and\n" "transferred to bonds. Dividends are reinvested\n" "when a trade is made.\n\n\n" "Active Strategies\n\n" "Dollar-cost Averaging (DCA):\n" "After the initial lump-sum investment, every month on the 10th,\n" "as many shares as many are allowed are bought regardless of whether\n" "prices are high or low. Shares are never sold.\n\n" "Parallel Momentum Trading (PMT):\n" "After the intial lump-sum investment,every month on the 10th,\n" "shares are bought as long as the current price is higher than the 200-day\n" "moving average. If the current price drops below the 200-day moving\n" "average, the shares are sold and transferred to bonds. Subsequent\n" "investment income will be directed to bonds (**parallel** with current\n" "investments) until the price of the shares rises above the 200-day\n" "moving average again.\n\n" "Divergent Momentum Trading (DMT):\n" "After the initial lump-sum investment, every month on the 10th,\n" "shares are bought as long as the current price is higher than the 200-day\n" "moving average. If the current price drops below the 200-day moving\n" "average, the shares are sold and transferred to bonds. Subsequent\n" "investment income will be directed to stocks (**divergent** with\n" "current investmenets) until the price of the shares rises above the\n" "200-day moving average again.\n\n" "Golden-Cross Parallel Momentum Trading (GPM):\n" "A combination of PMT and using both 200-day and 50-day moving averages.\n\n" "Golden-Cross Divergent Momentum Trading (GDM):\n" "A combination of DMT and using both 200-day and 50-day moving averages." ) tab3hbox = QHBoxLayout() tab3hbox.setContentsMargins(5, 5, 5, 5) tab3hbox.addWidget(inveStratTextEdit) tab3.setLayout(tab3hbox) self.tabWidget.addTab(tab1, "&Main") self.tabWidget.addTab(tab2, "&Updating Data") self.tabWidget.addTab(tab3, "&Investment Strategies") # creates a ticker box def createTickerBoxes(self): self.tickerBoxes = QHBoxLayout() # create ticker line edit tickerLineEdit = QLineEdit('') tickerLabel = QLabel("&Ticker:") tickerLabel.setBuddy(tickerLineEdit) # create startdate line edit startDLineEdit = QLineEdit('') startDLabel = QLabel("&Starting Date (MM/DD/YYYY):") startDLabel.setBuddy(startDLineEdit) # create enddate line edit endDLineEdit = QLineEdit('') endDLabel = QLabel("&Ending Date (MM/DD/YYYY):") endDLabel.setBuddy(endDLineEdit) # adding all widgets to the boxlayout self.tickerBoxes.addWidget(tickerLabel) self.tickerBoxes.addWidget(tickerLineEdit) self.tickerBoxes.addStretch(1) self.tickerBoxes.addWidget(startDLabel) self.tickerBoxes.addWidget(startDLineEdit) self.tickerBoxes.addWidget(endDLabel) self.tickerBoxes.addWidget(endDLineEdit) # creates an instruction box def createInstructionBox(self): self.instructBoxes = QHBoxLayout() instructLabel = QLabel( "^Note: Dates also accept the answer 'MAX' to indicate the earliest/latest date in both start/end dates.\n" ) self.instructBoxes.addWidget(instructLabel) # creates a strategy box def createStratBoxes(self): self.stratBoxes = QHBoxLayout() # create list of strategies stratList = ["BH", "MT", "GX", "DCA", "DMT", "PMT", "GDM", "GPM"] # create a strat1 combo box strat1ComboBox = QComboBox() strat1ComboBox.addItems(stratList) strat1Label = QLabel("&Strategy 1:") strat1Label.setBuddy(strat1ComboBox) # create a strat2 combo box strat2ComboBox = QComboBox() strat2ComboBox.addItems(stratList) strat2Label = QLabel("&Strategy 2:") strat2Label.setBuddy(strat2ComboBox) # create a strat3 combo box strat3ComboBox = QComboBox() strat3ComboBox.addItems(stratList) strat3Label = QLabel("&Strategy 3:") strat3Label.setBuddy(strat3ComboBox) # adding all widgets to the boxlayout self.stratBoxes.addWidget(strat1Label) self.stratBoxes.addWidget(strat1ComboBox) self.stratBoxes.addStretch(1) self.stratBoxes.addWidget(strat2Label) self.stratBoxes.addWidget(strat2ComboBox) self.stratBoxes.addStretch(1) self.stratBoxes.addWidget(strat3Label) self.stratBoxes.addWidget(strat3ComboBox) # creates a box that contains the initial capital def createInitialBox(self): self.initialBox = QHBoxLayout() # create a intial capital line edit initialLineEdit = QLineEdit('10000') initialLabel = QLabel("&Initial capital:") initialLabel.setBuddy(initialLineEdit) # add the widget self.initialBox.addWidget(initialLabel) self.initialBox.addWidget(initialLineEdit) # creates a box that contains the baseSMA and the commission values def createStaticNumbersBoxes(self): self.staticNumbersBoxes = QHBoxLayout() # create baseSMA line edit baseSMALineEdit = QLineEdit('200') baseSMALabel = QLabel("&Base moving average period (days):") baseSMALabel.setBuddy(baseSMALineEdit) # create commission line edit commissionLineEdit = QLineEdit('5') commissionLabel = QLabel("Commission:") commissionLabel.setBuddy(commissionLineEdit) # adding all widgets to the boxlayout self.staticNumbersBoxes.addWidget(baseSMALabel) self.staticNumbersBoxes.addWidget(baseSMALineEdit) self.staticNumbersBoxes.addStretch(1) self.staticNumbersBoxes.addWidget(commissionLabel) self.staticNumbersBoxes.addWidget(commissionLineEdit) # creates a box that contains the income def createIncomeBox(self): self.incomeBox = QHBoxLayout() # create income line edit incomeLineEdit = QLineEdit('0') incomeLabel = QLabel("&Annual pre-taxed income:") incomeLabel.setBuddy(incomeLineEdit) # adding all widgets to the boxlayout self.incomeBox.addWidget(incomeLabel) self.incomeBox.addWidget(incomeLineEdit) # creates a box containing the aigr def createAIGRBox(self): self.aigrBox = QHBoxLayout() # create annual income growth rate line edit aigrLineEdit = QLineEdit('0') aigrLabel = QLabel( "&Annual income growth rate in decimal (i.e. 0.02):") aigrLabel.setBuddy(aigrLineEdit) # add the widget self.aigrBox.addWidget(aigrLabel) self.aigrBox.addWidget(aigrLineEdit) # creates a box containing the investment fraction box def createInvesFracBox(self): self.investFracBox = QHBoxLayout() # create the investment fraction line edit invesFracLineEdit = QLineEdit('0') invesFracLabel = QLabel( "&Fraction of income reserved to investment in decimal (i.e. 0.5):" ) invesFracLabel.setBuddy(invesFracLineEdit) # add the widget self.investFracBox.addWidget(invesFracLabel) self.investFracBox.addWidget(invesFracLineEdit) # create a box that contains the calculate button def createCalculateBox(self): self.calculateBox = QHBoxLayout() # create calculate line edit calculateButton = QPushButton('Calculate', self) calculateButton.setToolTip('This is an example button') calculateButton.clicked.connect(self.clickCalculate) self.calculateBox.addWidget(calculateButton) # create a box that contains the results def createResultsBox(self): self.resultsBox = QHBoxLayout() # create a table for results resultsTable = QTableWidget(7, 3) resultsTable.horizontalHeader().setStretchLastSection(True) # Inputting info header0 = QTableWidgetItem("Commission:") headerz = QTableWidgetItem("Commission:") header1 = QTableWidgetItem("Taxes:") header2 = QTableWidgetItem("Treasury Yield:") header3 = QTableWidgetItem("Dividend received:") header4 = QTableWidgetItem("Profit/loss from trading:") header5 = QTableWidgetItem("Final Assets:") header6 = QTableWidgetItem("CAGR:") header7 = QTableWidgetItem("strategy1") header8 = QTableWidgetItem("strategy2") header9 = QTableWidgetItem("strategy3") resultsTable.setVerticalHeaderItem(0, header0) resultsTable.setVerticalHeaderItem(1, header1) resultsTable.setVerticalHeaderItem(2, header2) resultsTable.setVerticalHeaderItem(3, header3) resultsTable.setVerticalHeaderItem(4, header4) resultsTable.setVerticalHeaderItem(5, header5) resultsTable.setVerticalHeaderItem(6, header6) resultsTable.setHorizontalHeaderItem(0, header7) resultsTable.setHorizontalHeaderItem(1, header8) resultsTable.setHorizontalHeaderItem(2, header9) self.resultsBox.addWidget(resultsTable) # create more results boxes that contain the ticker and initial capital info def createExtraBasicBox(self): self.extraBasicBox = QHBoxLayout() # create labels to contain the basic info basicTickerLabel = QLabel("Ticker: ") basicInitialLabel = QLabel("Initial Capital: ") self.extraBasicBox.addWidget(basicTickerLabel) self.extraBasicBox.addWidget(basicInitialLabel) # create more results boxes that contain the start/end date info def createExtraDateBox(self): self.extraDateBox = QHBoxLayout() # create labels to contain the basic info basicStartDate = QLabel("Start Date: ") basicEndDate = QLabel("End date: ") self.extraDateBox.addWidget(basicStartDate) self.extraDateBox.addWidget(basicEndDate) # create error boxes that display errors def createErrorBox(self): self.errorBox = QHBoxLayout() errorLabel = QLabel(" ") self.errorBox.addWidget(errorLabel) # creates an error box that displays final incomes def createFinalIncomeBox(self): self.finalIncomeBox = QHBoxLayout() finalIncomeLabel = QLabel("Final Income: ") self.finalIncomeBox.addWidget(finalIncomeLabel) # what to do when calculate button is pushed @pyqtSlot() def clickCalculate(self): # get all the inputs ticker = self.tickerBoxes.itemAt(1).widget().text() startDate = self.tickerBoxes.itemAt(4).widget().text() endDate = self.tickerBoxes.itemAt(6).widget().text() strat1 = self.stratBoxes.itemAt(1).widget().currentText() strat2 = self.stratBoxes.itemAt(4).widget().currentText() strat3 = self.stratBoxes.itemAt(7).widget().currentText() # make sure the values are all numbers numbers = True try: capital = float(self.initialBox.itemAt(1).widget().text()) sma = int(self.staticNumbersBoxes.itemAt(1).widget().text()) commission = float( self.staticNumbersBoxes.itemAt(4).widget().text()) income = float(self.incomeBox.itemAt(1).widget().text()) aigr = float(self.aigrBox.itemAt(1).widget().text()) invesFrac = float(self.investFracBox.itemAt(1).widget().text()) except ValueError: numbers = False if numbers: # get the results results = investCalc(ticker, startDate, endDate, capital, income, strat1, strat2, strat3, sma, commission, invesFrac, aigr) if results.errorBoo == False: # sort out the data data1 = results.strat1 data2 = results.strat2 data3 = results.strat3 # print the results table = self.resultsBox.itemAt(0).widget() # for strategy 1 strat1 = QTableWidgetItem(data1.type) assets1 = QTableWidgetItem(str(round(data1.assets, 2))) cagr1 = QTableWidgetItem(str(round(data1.cagr, 4))) taxes1 = QTableWidgetItem(str(round(data1.taxes, 2))) commission1 = QTableWidgetItem(str(round(data1.comissions, 2))) pl1 = QTableWidgetItem(str(round(data1.pl, 2))) div1 = QTableWidgetItem(str(round(data1.div, 2))) treasury1 = QTableWidgetItem(str(round(data1.treasury, 2))) table.setHorizontalHeaderItem(0, strat1) table.setItem(0, 0, commission1) table.setItem(1, 0, taxes1) table.setItem(2, 0, treasury1) table.setItem(3, 0, div1) table.setItem(4, 0, pl1) table.setItem(5, 0, assets1) table.setItem(6, 0, cagr1) # for strategy 2 strat2 = QTableWidgetItem(data2.type) assets2 = QTableWidgetItem(str(round(data2.assets, 2))) cagr2 = QTableWidgetItem(str(round(data2.cagr, 4))) taxes2 = QTableWidgetItem(str(round(data2.taxes, 2))) commission2 = QTableWidgetItem(str(round(data2.comissions, 2))) pl2 = QTableWidgetItem(str(round(data2.pl, 2))) div2 = QTableWidgetItem(str(round(data2.div, 2))) treasury2 = QTableWidgetItem(str(round(data2.treasury, 2))) table.setHorizontalHeaderItem(1, strat2) table.setItem(0, 1, commission2) table.setItem(1, 1, taxes2) table.setItem(2, 1, treasury2) table.setItem(3, 1, div2) table.setItem(4, 1, pl2) table.setItem(5, 1, assets2) table.setItem(6, 1, cagr2) # for strategy 3 strat3 = QTableWidgetItem(data3.type) assets3 = QTableWidgetItem(str(round(data3.assets, 2))) cagr3 = QTableWidgetItem(str(round(data3.cagr, 4))) taxes3 = QTableWidgetItem(str(round(data3.taxes, 2))) commission3 = QTableWidgetItem(str(round(data3.comissions, 2))) pl3 = QTableWidgetItem(str(round(data3.pl, 2))) div3 = QTableWidgetItem(str(round(data3.div, 2))) treasury3 = QTableWidgetItem(str(round(data3.treasury, 2))) table.setHorizontalHeaderItem(2, strat3) table.setItem(0, 2, commission3) table.setItem(1, 2, taxes3) table.setItem(2, 2, treasury3) table.setItem(3, 2, div3) table.setItem(4, 2, pl3) table.setItem(5, 2, assets3) table.setItem(6, 2, cagr3) # set the other basic info tickerBasics = "Ticker: " + results.ticker initialBasics = "Initial Capital: " + str(round(capital, 2)) startBasics = "Start Date: " + data1.iDate endBasics = "End Date: " + data1.pDate incomeBasics = "Final Income: " + str(round(results.income, 2)) self.extraBasicBox.itemAt(0).widget().setText(tickerBasics) self.extraBasicBox.itemAt(1).widget().setText(initialBasics) self.extraDateBox.itemAt(0).widget().setText(startBasics) self.extraDateBox.itemAt(1).widget().setText(endBasics) self.finalIncomeBox.itemAt(0).widget().setText(incomeBasics) error = " " self.errorBox.itemAt(0).widget().setText(error) else: error = "Error: " + results.errorMess self.errorBox.itemAt(0).widget().setText(error) else: error = "Error: One or more of the number inputs do not contain valid numbers, please try again." self.errorBox.itemAt(0).widget().setText(error) # what to do when the refresh button is pushed def clickRefresh(self): ticker = self.tabWidget.widget(1).layout().itemAt(1).layout().itemAt( 1).widget().text() stockBool = self.tabWidget.widget(1).layout().itemAt( 1).layout().itemAt(0).widget().isChecked() notesBool = self.tabWidget.widget(1).layout().itemAt( 2).widget().isChecked() tickerBool = self.tabWidget.widget(1).layout().itemAt( 3).widget().isChecked() # if the stock check box is checked if stockBool: # if the ticker exists if tickerExists(ticker): getStockData(ticker) if notesBool: getTreasuryData() if tickerBool: getTickerList() self.tabWidget.widget(1).layout().itemAt(5).widget().setText( "Update done.") else: self.tabWidget.widget(1).layout().itemAt(5).widget().setText( "Error: ticker does not exist") else: if notesBool: getTreasuryData() if tickerBool: getTickerList() self.tabWidget.widget(1).layout().itemAt(5).widget().setText( "Update done.")
class Game(QWidget): add_number_signal = pyqtSignal(tuple) pop_number_signal = pyqtSignal() rotate_signal = pyqtSignal() def __init__(self): super().__init__() self.move(20, 20) self.hbox = QHBoxLayout() self.grid = Grid(self) self.vbox = QVBoxLayout() self.actual_piece = Piece("blank", self) self.rotate_button = QPushButton('Rotar', self) self.end_game_button = QPushButton('Terminar Juego', self) self.back_button = QPushButton('Retroceder', self) self.save_button = QPushButton('Guardar', self) self.state_grid = StateGrid(self) self.p1_points = QLabel(self) self.p2_points = QLabel(self) self.set_points(1, 0) self.set_points(2, 0) def initUi(self): self.setWindowTitle('Best Tarea Ever :P') self.setMouseTracking(True) self.setLayout(self.hbox) self.hbox.addStretch(1) self.hbox.addWidget(self.grid) self.hbox.addStretch(1) self.hbox.addLayout(self.vbox) self.hbox.addStretch(1) self.grid.show() self.piece_layout = QHBoxLayout(self) self.piece_layout.addStretch(1) self.piece_layout.addWidget(self.actual_piece) self.piece_layout.addStretch(1) self.vbox.addStretch(1) self.vbox.addLayout(self.piece_layout) self.vbox.addStretch(1) hlayout = QHBoxLayout(self) self.vbox.addLayout(hlayout, 1) hlayout.addWidget(self.save_button, 1) hlayout.addWidget(self.rotate_button, 1) hlayout.addWidget(self.end_game_button, 1) hlayout.addWidget(self.back_button, 1) self.vbox.addStretch(1) self.vbox.addWidget(self.state_grid, 1) hlayout_points = QHBoxLayout(self) self.vbox.addLayout(hlayout_points, 1) self.p1_points.show() self.p2_points.show() hlayout_points.addWidget(self.p1_points) hlayout_points.addWidget(self.p2_points) self.rotate_button.clicked.connect(self.rotate_piece) self.back_button.clicked.connect(self.back_move) self.end_game_button.clicked.connect(self.end_game) self.save_button.clicked.connect(self.save_game) self.add_number_signal.connect(self.state_grid.add_number) self.pop_number_signal.connect(self.state_grid.pop_number) self.rotate_signal.connect(self.rotate_piece) self.grid.initUI() self.new_piece() @staticmethod def back_move(): variables.GAME_INTERFACE.retroceder() @staticmethod def end_game(): variables.GAME_INTERFACE.terminar_juego() @staticmethod def save_game(): variables.GAME_INTERFACE.guardar_juego() def user_rotate(self): self.rotate_signal.emit() def add_number(self, number, color): self.add_number_signal.emit((number, color)) def pop_number(self): self.pop_number_signal.emit() def new_piece(self, color=None, piece_type=None): if piece_type is None: piece_type = choice(variables.TYPES) if color is None and piece_type != "hint": color = choice(variables.COLORS) self.piece_layout.removeItem(self.piece_layout.itemAt(2)) self.piece_layout.removeWidget(self.actual_piece) self.actual_piece.hide() self.actual_piece.deleteLater() self.actual_piece = Piece(piece_type, color, self) self.piece_layout.addWidget(self.actual_piece) self.piece_layout.addStretch(1) def addPiece(self, i, j, color=None, piece_type=None, on_move_ended=None): if piece_type is None: self.grid.addPiece(i, j, self.actual_piece, on_move_ended) elif piece_type == 'blank' or piece_type == 'hint': self.grid.addPiece(i, j, Piece(piece_type, color, self.grid)) else: raise TypeError('No es un tipo valido') def getPiece(self, i, j): return self.grid.getPiece(i, j) def popPiece(self, i, j): pop_piece = self.grid.popPiece(i, j) self.addPiece(i, j, piece_type='blank') return pop_piece def movePiece(self, i, j, piece, on_move_end=None): self.grid.movePiece(i, j, piece, on_move_end) def set_points(self, player_numb, points): # self.label_puntaje.setText(str(points)) if player_numb == 1: self.p1_points.setText("Jugador 1: {}".format(points)) elif player_numb == 2: self.p2_points.setText("Jugador 2: {}".format(points)) def rotate_piece(self): self.actual_piece.rotate() variables.GAME_INTERFACE.rotar_pieza('Derecha') def keyPressEvent(self, event): if event.key() == Qt.Key_H: variables.GAME_INTERFACE.hint_asked()
class MainWindow(QMainWindow): def __init__(self, dataBaseName): super().__init__() self._dataBase = myDatabase.MyDataBase(dataBaseName) self._dictexe = { "первый запрос": (self.firstQuery, self.firstExe), "второй запрос": (self.secondQuery, self.secondExe), "третий запрос": (self.thirdQuery, self.thirdExe) } self._view = QTreeView() self._buttonAdd = QPushButton("Добавить") self._buttonAdd.clicked.connect(self.getItems) self._addSpinBox = QSpinBox() self._addComboBox = QComboBox() self._addComboBox.addItems(self._dataBase.dishes()) self._layout = QHBoxLayout() self._qSpinBox = QSpinBox() self._qComboBox = QComboBox() self._qLineEdit = QLineEdit() self._qCalendarWidget = QCalendarWidget() self._queryDisc = QLabel() self._buttonExe = QPushButton("Исполнить") self._buttonExe.clicked.connect(self.onButtonExe) self._combox = QComboBox() self._combox.currentTextChanged.connect(self.comboChanged) self._combox.addItems(self._dictexe.keys()) self.initUi() def initUi(self): self.setGeometry(300, 300, 200, 200) self.setWindowTitle('Ресторан') #self.setWindowIcon(QIcon('')) w = QWidget() mainLayout = QVBoxLayout() w.setLayout(mainLayout) self.setCentralWidget(w) mainLayout.addWidget(self._view) tmpLayout = QHBoxLayout() mainLayout.addLayout(tmpLayout) tmpLayout.addWidget(QLabel("Добавления ингредиента")) tmpLayout.addWidget(self._addSpinBox) tmpLayout.addWidget(self._addComboBox) tmpLayout.addWidget(self._buttonAdd) mainLayout.addWidget(self._queryDisc) tmpLayout = QHBoxLayout() mainLayout.addLayout(tmpLayout) tmpLayout.addWidget(self._combox) tmpLayout.addLayout(self._layout) tmpLayout.addWidget(self._buttonExe) self.adjustSize() def comboChanged(self, text): self._dictexe[text][0]() def clearLayout(self): while self._layout.count() > 0: self._layout.itemAt(0).widget().setParent(None) #Названия и калорийность блюд по рецептам автора X def firstQuery(self): self._queryDisc.setText( "Названия и калорийность блюд по рецептам автора X") self.clearLayout() #self._qSpinBox.setValue(0) #self._layout.insertWidget(1,self._qSpinBox) self._qComboBox.clear() self._qComboBox.addItems(self._dataBase.authors()) self._layout.insertWidget(1, self._qComboBox) def firstExe(self): model = self._dataBase.first(self._qComboBox.currentText()) self.setModel(model) #Названия ресторанов, к которым относятся повара, готовящие блюда содержащие в #названии подстроку X (например, «картофельный»), отсортированные по алфавиту def secondQuery(self): self._queryDisc.setText( "Названия ресторанов, к которым относятся повара,\n готовящие блюда содержащие в названии подстроку X (например, «картофельный»),\n отсортированные по алфавиту" ) self.clearLayout() self._qLineEdit.clear() self._layout.insertWidget(1, self._qLineEdit) def secondExe(self): model = self._dataBase.second(self._qLineEdit.text()) self.setModel(model) #Названия и количества ингредиентов и названия мероприятий, на которых разливают #напитки в количестве меньше X после даты Y def thirdQuery(self): self._queryDisc.setText( "Названия и количества ингредиентов и названия мероприятий, на которых разливают\n напитки в количестве меньше X после даты Y" ) self.clearLayout() self._layout.insertWidget(1, self._qCalendarWidget) self._qSpinBox.setMaximum(self._dataBase.maxDrinkCount() * 10) self._qSpinBox.setValue(0) self._layout.insertWidget(1, self._qSpinBox) def thirdExe(self): model = self._dataBase.third( self._qSpinBox.value(), self._qCalendarWidget.selectedDate().toPyDate()) self.setModel(model) def setModel(self, model): if model is None: return self._view.setVisible(False) self._view.setModel(model) for i in range(model.columnCount()): self._view.resizeColumnToContents(i) self._view.setVisible(True) self.adjustSize() def onButtonExe(self): self._dictexe[self._combox.currentText()][1]() def getItems(self): name, ok = QInputDialog.getText(self, "Ингредиент", "Введите название") if not ok: return self._dataBase.add(self._addSpinBox.value(), self._addComboBox.currentText(), name)
class ProjectsWindow(QMdiSubWindow): def __init__(self, app, OAuth_token, parent): super().__init__() self.app = app self.token = OAuth_token self.parent = parent self.open_windows = self.parent.open_windows self.initFig() self.initUI() def initFig(self): """ Initialize Figshare information """ self.project_list = self.get_project_list(self.token) def initUI(self): self.format_window() # Create a horizontal box layout to hold the project buttons self.project_buttons_box = QHBoxLayout() # Create a vertical box layout to hold the project window widgets and layouts self.vbox = QVBoxLayout() # Add the Projects button to the vertical box layout init_finish = len(self.project_list) if init_finish > 4: init_finish = 4 self.create_project_bar(0, init_finish) self.vbox.addLayout(self.project_buttons_box) # Add the scroll bar to the vertical box layout self.s_bar = self.scroll_bar() self.vbox.addWidget(self.s_bar) self.hbox = QHBoxLayout() temp = QVBoxLayout() temp.addWidget(self.search_bar()) temp.addLayout(self.management_buttons()) self.hbox.addLayout(temp) self.hbox.addLayout(self.vbox) # Create a central widget for the projects window window_widget = QWidget() # Add the vertical box layout window_widget.setLayout(self.hbox) # Set the projects window widget self.setWidget(window_widget) ##### # Window Formatting ##### def format_window(self): """ Formats the Projects window """ # Gets the QRect of the main window geom = self.parent.geometry() # Gets the Qrect of the sections window section_geom = self.parent.section_geom # Define geometries for the projects window x0 = section_geom.x() + section_geom.width() y0 = section_geom.y() w = geom.width() - x0 h = ((geom.height() - y0) / 6) self.setGeometry(x0, y0, w, h) # Remove frame from projects window self.setWindowFlags(Qt.FramelessWindowHint) ##### # Window Widgets ##### def scroll_bar(self): """ Creates a scroll bar set to the size of the projects list :return: QScrollBar Object """ s_bar = QScrollBar(Qt.Horizontal) s_bar.setMaximum(len(self.project_list) - 4) s_bar.sliderMoved.connect(self.slider_val) s_bar.valueChanged.connect(self.slider_val) return s_bar def create_proj_thumb(self, title, published_date, project_id): """ Creates a large pushbutton for a project :param title: string. Project title :param published_date: string. project published date :param id: int. figshare project id number :return: QPushButton object """ geom = self.geometry() # Get the scalig ratios for the current window w_ratio, f_ratio = scaling_ratio(self.app) # Scale the font sizes title_fnt_size = 12 * f_ratio date_ftn_size = 8 * f_ratio # Create the title label title_lbl = QLabel() title_lbl.setText("{}".format(title)) title_lbl_fnt = QFont('SansSerif', title_fnt_size) title_lbl_fnt.setBold(True) title_lbl.setFont(title_lbl_fnt) title_lbl.setWordWrap(True) # Create the date label date_lbl = QLabel() if published_date is None: published_date = 'Private' date_lbl.setText("Published: {}".format(published_date)) date_lbl_fnt = QFont('SansSerif', date_ftn_size) date_lbl.setFont(date_lbl_fnt) date_lbl.setStyleSheet('color: gray') date_lbl.setWordWrap(True) # Create a layout to hold the labels lbl_box = QVBoxLayout() # Add labels to layout lbl_box.addWidget(title_lbl) lbl_box.addWidget(date_lbl) # Create a button for the project btn = QPushButton(self) checkable_button(self.app, btn) btn.setLayout(lbl_box) btn.clicked[bool].connect(lambda: self.on_project_pressed(project_id)) self.project_buttons_box.addWidget(btn) def create_project_bar(self, start, finish): """ Creates a series of Project push buttons :param start: start position in projects list :param finish: finish position in projects list """ self.buttons = {} i = 0 for project_pos in range(start, finish): title = self.project_list[project_pos]['title'] pub_date = self.project_list[project_pos]['published_date'] project_id = self.project_list[project_pos]['id'] self.create_proj_thumb(title, pub_date, project_id) self.buttons[project_id] = self.project_buttons_box.itemAt( i).widget() i += 1 def management_buttons(self): """ Creates a layout that holds buttons to be used for creating and deleting projects :return: QVBoxLayout holding the create, and delete projects buttons """ # Create New Project Button np_btn = QPushButton() np_btn.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding) np_btn.setIcon( QIcon(os.path.abspath(__file__ + '/../..' + '/img/Folder-48.png'))) np_btn.setToolTip('Create a new Figshare Project') np_btn.setToolTipDuration(1) np_btn.pressed.connect(self.on_projects_btn_pressed) # Create Delete Project Button del_btn = QPushButton() del_btn.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding) del_btn.setIcon( QIcon(os.path.abspath(__file__ + '/../..' + '/img/del_folder.png'))) del_btn.setToolTip('Delete Selected Project') del_btn.setToolTipDuration(1) del_btn.pressed.connect(self.on_delete_btn_pressed) # Create layout to hold buttons hbox = QHBoxLayout() # Add Buttons to layout hbox.addWidget(np_btn) hbox.addWidget(del_btn) return hbox def search_bar(self): """ Creates a QLineEdit object for the user to enter a search query :return: Edits the projects list object according to the filter """ # Create text box edit = QLineEdit() # Set font style search_bar(self.app, edit) # Set place holder text edit.setPlaceholderText('Search') # Add a clear button to the line edit edit.setClearButtonEnabled(True) # Add mouse over text edit.setToolTip('Search for specific Figshare Projects') edit.setToolTipDuration(1) # Connect search function to the return key edit.returnPressed.connect(lambda: self.search_on_return(edit.text())) edit.textChanged.connect(lambda: self.search_on_clear(edit.text())) return edit ##### # Widget Actions ##### def slider_val(self): """ Called when the projects button slider is changed. Removes all existing buttons and regenerates from the new position :return: """ while self.project_buttons_box.count(): item = self.project_buttons_box.takeAt(0) item.widget().deleteLater() s_bar_pos = self.s_bar.value() if 1 < len(self.project_list) < 4: number = len(self.project_list) else: number = 4 self.s_bar.setMaximum(len(self.project_list) - number) self.create_project_bar(s_bar_pos, s_bar_pos + number) def search_init(self): """ Called when the projects search bar is used. Removes all existing buttons and regenerates from new projects list :return: """ while self.project_buttons_box.count(): item = self.project_buttons_box.takeAt(0) item.widget().deleteLater() if 1 <= len(self.project_list) <= 4: number = len(self.project_list) else: number = 4 self.s_bar.setMaximum(len(self.project_list) - number) self.create_project_bar(0, number) def search_on_return(self, search_text): """ Called when return is pressed in the search bar. :return: """ if search_text != '': self.project_list = self.search_projects(search_text, self.token) self.search_init() def search_on_clear(self, lineedit_text): """ Called when the search bar is cleared :return: """ if lineedit_text == '': self.project_list = self.get_project_list(self.token) self.slider_val() def on_projects_btn_pressed(self): """ Called when the create new project button is pressed """ if 'new_project_window' in self.open_windows: self.open_windows.remove('new_project_window') self.parent.new_project_window.close() else: self.open_windows.remove('projects_window') self.close() if 'project_info_window' in self.open_windows: self.parent.project_info_window.close() self.open_windows.remove('project_info_window') if 'project_articles_window' in self.open_windows: self.parent.project_articles_window.close() self.open_windows.remove('project_articles_window') if 'article_edit_window' in self.open_windows: self.open_windows.remove('article_edit_window') self.parent.article_edit_window.close() self.open_windows.add('new_project_window') self.parent.new_project_window = NewProjectWindow( self.app, self.token, self.parent) self.parent.mdi.addSubWindow(self.parent.new_project_window) self.parent.new_project_window.show() def on_project_pressed(self, project_id): """ Called when a project is clicked. :return: """ # For if there is already a project info window open if 'project_info_window' in self.open_windows: # Get the project id number of the current window open_proj = self.parent.project_info_window.project_id # For a different project than the currently open project if open_proj != project_id: # If the current project is in the current view of project buttons (it may have been scrolled away from) if open_proj in self.buttons: # If that button is checked, uncheck it if self.buttons[open_proj].isChecked(): self.buttons[open_proj].toggle() # Close the currently open project info window self.parent.project_info_window.close() # Create a new project info window for the different project self.parent.project_info_window = ProjectInfoWindow( self.app, self.token, self.parent, project_id) # Add it as a sub window to the framing window self.parent.mdi.addSubWindow(self.parent.project_info_window) self.parent.project_info_window.show() # If the current projects button is pressed else: # Close the window and remove from the open window list self.open_windows.remove('project_info_window') self.parent.project_info_window.close() # If any sub windows are open close them as well if 'project_articles_window' in self.open_windows: self.open_windows.remove('project_articles_window') self.parent.project_articles_window.close() if 'article_edit_window' in self.open_windows: self.open_windows.remove('article_edit_window') self.parent.article_edit_window.close() # For when no project info window is open else: self.open_windows.add('project_info_window') self.parent.project_info_window = ProjectInfoWindow( self.app, self.token, self.parent, project_id) self.parent.mdi.addSubWindow(self.parent.project_info_window) self.parent.project_info_window.show() def on_delete_btn_pressed(self): """ Called when the project delete button is pressed/ :return: """ open_proj = self.parent.project_info_window.project_id project_title = self.parent.project_info_window.project_info['title'] msg = "Are you sure you want to delete Figshare Project: {}".format( project_title) msg_box = QMessageBox.question(self, 'Message', msg, QMessageBox.Yes, QMessageBox.No) if msg_box == QMessageBox.Yes: successful = self.delete_project(self.token, open_proj) if successful: con_reply = QMessageBox.information( self, 'Deletion Confirmation', 'Project successfully deleted', QMessageBox.Ok) if con_reply == QMessageBox.Ok: self.reopen_projects() else: self.reopen_projects() else: con_reply = QMessageBox.warning( self, 'Deletion Confirmation', 'Unknown error occurred.\n Project may not have been deleted.', QMessageBox.Ok) if con_reply == QMessageBox.Ok: self.reopen_projects() else: self.reopen_projects() def reopen_projects(self): """ Called to open and close the projects window. :return: """ for i in range(2): self.parent.section_window.on_projects_btn_pressed() ##### # Figshare API Interface Calls ##### def get_project_list(self, token): """ Returns the users private project list :param token: Figshare OAuth token :return: array of project """ projects = Projects(token) return projects.get_list() def search_projects(self, search_text, token): """ Returns a list of projects matching the users search criteria :param search_text: String. Figshare style elastic search string :param token: Figshare OAuth token :return: """ projects = Projects(token) result = projects.search(search_text) if len(result) == 0: result = projects.get_list() return result def delete_project(self, token, project_id): """ Deletes the given project from Figshare :param token: :param project_id: Int. Figshare project ID number :return: """ projects = Projects(token) try: projects.delete( project_id, safe=False ) # Suppresses command line requirement for acknowledgement return True except: return False
def __init__(self, parent=None): super().__init__(parent) self.record = -1 self.inspected = None self.oob_update = False prefs = QSettings() prefs.beginGroup("/General") timeout = prefs.value("/Timeout") dark_mode = prefs.value("/DarkMode") prefs.endGroup() # Instantiate core objects self.timeout_timer = QTimer() self.timeout_timer.setTimerType(Qt.VeryCoarseTimer) self.timeout_timer.setInterval(timeout * 1000) self.timeout_timer.setSingleShot(True) self.timeout_timer.timeout.connect(self.update_temp_log) self.systems = ActionsWidget(LogSource.SYSTEM) self.systems.acted.connect(self.log_item) self.events = ActionsWidget(LogSource.EVENT) self.events.acted.connect(self.log_item) self.compass = Compass() self.compass_widget = QWidget() compass_layout = QHBoxLayout() self.compass_widget.setLayout(compass_layout) compass_layout.addWidget(self.compass) self.compass.angle_event.connect(self.log_item) self.exact_angle = ExactAngle() self.exact_angle_widget = QWidget() exact_angle_layout = QHBoxLayout() self.exact_angle_widget.setLayout(exact_angle_layout) exact_angle_layout.addWidget(self.exact_angle) self.exact_angle.btn_event.connect(self.reset_timer) self.exact_angle.angle_event.connect(self.log_item) tab_widget = QTabWidget() tab_bar = tab_widget.tabBar() tab_bar.setFont(QFont('Consolas', 12, 3)) tab_widget.addTab(self.compass_widget, "Compass") tab_widget.addTab(self.exact_angle_widget, "Precise Angle") tab_widget.setStyleSheet(""" QTabWidget::pane { border-top: 2px solid #C2C7CB; } /* Style the tab using the tab sub-control. Note that it reads QTabBar _not_ QTabWidget */ QTabBar::tab { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); border: 2px solid #C4C4C3; border-bottom-color: #C2C7CB; /* same as the pane color */ border-top-left-radius: 4px; border-top-right-radius: 4px; min-width: 8ex; padding: 2px; color: black; } QTabBar::tab:selected, QTabBar::tab:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fafafa, stop: 0.4 #f4f4f4, stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); } QTabBar::tab:selected { border-color: #ff0000; border-bottom-color: #C2C7CB; /* same as pane color */ } QTabBar::tab:!selected { margin-top: 2px; /* make non-selected tabs look smaller */ } """) header_layout = QHBoxLayout() self.zulu_time_label = QLabel() self.assessor_label = QLabel() self.date_label = QLabel() self.dl_label = QLabel() self.mnemonic_label = QLabel() header_layout.addWidget(self.zulu_time_label) header_layout.addWidget(self.assessor_label) header_layout.addWidget(self.date_label) header_layout.addWidget(self.dl_label) header_layout.addWidget(self.mnemonic_label) res = QApplication.primaryScreen().size() w, h = res.width(), res.height() if w > 1920 or h > 1080: hdr_font = QFont("Consolas", 16, 2) end_font = QFont("Consolas", 32, 5) else: hdr_font = QFont("Consolas", 14, 2) end_font = QFont("Consolas", 28, 5) for index in range(header_layout.count()): widget = header_layout.itemAt(index).widget() widget.setSizePolicy( QSizePolicy.Preferred, QSizePolicy.Maximum ) widget.setFont(hdr_font) widget.setAlignment(Qt.AlignCenter) # Setup logging state machine self.init_log_sm() # Setup splitters actions_splitter = QSplitter( Qt.Horizontal, frameShape=QFrame.StyledPanel, frameShadow=QFrame.Plain ) actions_splitter.addWidget(self.systems) actions_splitter.addWidget(self.events) actions_splitter.addWidget(tab_widget) actions_splitter.setChildrenCollapsible(False) main_splitter = QSplitter( Qt.Vertical, frameShape=QFrame.StyledPanel, frameShadow=QFrame.Plain ) self.log_area = QTableWidget(0, 3) self.log_area.cellDoubleClicked.connect(self.entry_inspected) self.log_area.cellChanged.connect(self.entry_changed) self.log_area.setHorizontalHeaderLabels( ["Time", "System", "Events"] ) self.log_area.horizontalHeader().setStretchLastSection(True) self.set_dark_mode(dark_mode) end_msn_btn = QPushButton("END\r\nMISSION") end_msn_btn.clicked.connect(self.end_mission) end_msn_btn.setFont(end_font) end_msn_btn.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) end_msn_btn.setStyleSheet("background-color: red; color: white") bottom_layout = QGridLayout() bottom_widget = QWidget() bottom_widget.setLayout(bottom_layout) bottom_layout.addWidget(self.log_area, 0, 0, 1, 7) bottom_layout.addWidget(end_msn_btn, 0, 8, 1, 1) main_splitter.addWidget(actions_splitter) main_splitter.addWidget(bottom_widget) main_splitter.setChildrenCollapsible(False) handle_css = """ QSplitter::handle { background-image: url(:/imgs/dot_pattern.png); background-repeat: repeat-xy; background-color: none; border: 1px solid gray; } QSplitter::handle:pressed { background-image: url(:/imgs/pressed.png); } """ actions_splitter.setStyleSheet(handle_css) main_splitter.setStyleSheet(handle_css) # Finalize layout main_layout = QVBoxLayout() main_layout.addLayout(header_layout) main_layout.addWidget(main_splitter) self.setLayout(main_layout)
class NeuralBoard(QWidget): def __init__(self, size, Parent=None): ''' Constructor ''' super().__init__(Parent) self.__InitData() #先初始化數據,再初始化界面 self.__InitView(size) def __InitData(self): self.__size = QSize(360, 560) def __InitView(self, size): #設置界面的尺寸爲__size self.setFixedSize(self.__size) self.board = QHBoxLayout(self) for layer_size in size: layer = self.addLayer() for neural_size in range(layer_size): self.addNeural(layer) def addNeural(self, layer): neural = QPushButton() #neural.setGeometry(-2, -2, 1, 1) neural.setMaximumSize(QSize(24, 24)) #neural.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) neural.setStyleSheet( 'background-color: rgb(0,0,255);border-radius:12; border:2px solid black' ) layer.addWidget(neural) def addLayer(self): layer = QVBoxLayout(self) self.board.addLayout(layer) return layer def setActivate(self, layer, index, value): #self.clear() neural = self.getNeural((layer, index)) color = str(int(value * 255)) neural.setStyleSheet('background-color: rgb(' + color + ',' + color + ',255); border-radius:12; border:2px solid black') def clear(self): layers = self.board.findChildren(QVBoxLayout) for layer in layers: for index in range(layer.count()): neural = layer.itemAt(index).widget() neural.setStyleSheet( 'background-color: rgb(0,0,255);border-radius:12; border:2px solid black' ) def paintEvent(self, event): painter = QPainter(self) layers = self.board.findChildren(QVBoxLayout) for i in range(len(layers) - 1): layer1 = layers[i] layer2 = layers[i + 1] for j in range(layer1.count()): n1 = layer1.itemAt(j).widget() for k in range(layer2.count()): n2 = layer2.itemAt(k).widget() painter.setPen(Qt.gray) painter.drawLine( QLine(n1.pos().x() + 12, n1.pos().y() + 12, n2.pos().x() + 12, n2.pos().y() + 12)) def skeleton(self): layers = self.board.findChildren(QVBoxLayout) for layer in layers: for index in range(layer.count()): layer.itemAt(index).widget() def getNeural(self, n_index): [l_index, n_index] = n_index layer = self.board.itemAt(l_index) neural = layer.itemAt(n_index).widget() return neural
class Weijiejue(QDialog): def __init__(self,list,i,parent = None): super(Weijiejue,self).__init__(parent) #设置界面大小、名称、背景 #self.resize(800,900) self.setWindowTitle('故障诊断专家系统') self.setStyleSheet("background-image:url(tubiao_meitu.jpg)") QApplication.setStyle("Fusion") font = QtGui.QFont('微软雅黑',20) font1 = QtGui.QFont('微软雅黑light', 15) #窗体属性 self.i1=i self.list1=list # #查询self.list1[self.i1],得到cankaoziliao字符串,转换为列表 db = pymysql.connect("localhost", "root", "123456", "expertsy", charset='utf8') cur=db.cursor() #self.ckzl= ["手册1.pdf","图片1.jpg"] vbj = QVBoxLayout() vbj.setAlignment(Qt.AlignCenter) vbj.setSpacing(50) self.hbj1=QHBoxLayout() hbj2=QHBoxLayout() # self.setWindowFlags(Qt.Widget) self.paichatishi = QLabel(self.list1[self.i1]) self.paichatishi.setFont(font) sql = 'SELECT 参考资料 FROM 问题关联 WHERE 问题="%s"' % self.list1[self.i1] cur.execute(sql) string = cur.fetchone() print(string) if len(string)!=0: string0 = string[0] self.ckzl = string0.split(",") for fuzu in self.ckzl: self.title1= QPushButton(fuzu) self.title1.setStyleSheet(''' QPushButton{ border:none; color:blue; font-size:15px; height:30px; padding-left:5px; padding-right:5px; text-align:center; } QPushButton:hover{ color:black; border:1px solid #F3F3F5; border-radius:10px; background:LightGray; } ''') file_path= fuzu self.title1.clicked.connect(partial(self.lianjie)) #title1.clicked.connect(lambda :self.lianjie(file_path)) self.hbj1.addWidget(self.title1) self.jiejuebut=QPushButton("解决了") self.jiejuebut.setFont(font1) self.weijiejuebut = QPushButton("未解决") self.weijiejuebut.setFont(font1) self.weijiejuebut.clicked.connect(partial(self.tonext)) self.jiejuebut.clicked.connect(partial(self.showjiejue)) hbj2.addStretch(1) hbj2.addWidget(self.weijiejuebut) hbj2.addStretch(2) hbj2.addWidget(self.jiejuebut) hbj2.addStretch(1) vbj.addStretch(1) vbj.addWidget(self.paichatishi) vbj.addStretch(2) vbj.addLayout(self.hbj1) vbj.addStretch(2) vbj.addLayout(hbj2) vbj.addStretch(1) self.setLayout(vbj) def tonext(self): for i in reversed (range(self.hbj1.count())): self.hbj1.itemAt(i).widget().close() self.hbj1.takeAt(i) changdu=len(self.list1) self.i1=self.i1+1 if self.i1+1<changdu: self.paichatishi.setText(self.list1[self.i1]) if self.i1+1==changdu: self.paichatishi.setText(self.list1[self.i1]) self.weijiejuebut.setText("已经是最后一条") self.weijiejuebut.setEnabled(False) db = pymysql.connect("localhost", "root", "123456", "expertsy", charset='utf8') cur = db.cursor() sql = 'SELECT 参考资料 FROM 问题关联 WHERE 问题="%s"' % self.list1[self.i1] cur.execute(sql) string = cur.fetchone() string0 = string[0] if not string0 is None: print("assa") self.ckzl = string0.split(",") for fuzu in self.ckzl: self.title1= QPushButton(fuzu) self.title1.setStyleSheet(''' QPushButton{ border:none; color:blue; font-size:15px; height:30px; padding-left:5px; padding-right:5px; text-align:center; } QPushButton:hover{ color:black; border:1px solid #F3F3F5; border-radius:10px; background:LightGray; } ''') self.title1.clicked.connect(partial(self.lianjie)) #title1.clicked.connect(lambda :self.lianjie(file_path)) self.hbj1.addWidget(self.title1) def showjiejue(self): self.w3=Jiejue() self.w3.show() def lianjie(self): sender=self.sender() os.startfile(sender.text())
class LibraryWidget(QWidget): def __init__(self, parent, item, link, list_widget, show_new=False): super(LibraryWidget, self).__init__(None) self.parent = parent self.item = item self.link = link self.list_widget = list_widget self.show_new = show_new self.observer = None self.build_info = None self.destroyed.connect(lambda: self._destroyed()) self.setEnabled(False) self.layout = QHBoxLayout() self.layout.setContentsMargins(2, 2, 2, 2) self.setLayout(self.layout) self.infoLabel = QLabel("Loading build information...") self.launchButton = QPushButton("Launch") self.launchButton.setMinimumWidth(75) self.launchButton.setProperty("CancelButton", True) self.layout.addWidget(self.launchButton) self.layout.addWidget(self.infoLabel, stretch=1) self.thread = BuildInfoReader(link) self.thread.finished.connect(self.draw) self.thread.start() self.item.setSizeHint(self.sizeHint()) def draw(self, build_info): if build_info is None: self.infoLabel.setText( ("Build *{0}* is damaged!").format(Path(self.link).name)) self.launchButton.setText("Delete") self.launchButton.clicked.connect(self.ask_remove_from_drive) self.setEnabled(True) return for i in reversed(range(self.layout.count())): self.layout.itemAt(i).widget().setParent(None) self.build_info = build_info self.branch = self.build_info.branch self.item.date = build_info.commit_time self.icon_favorite = QIcon(":resources/icons/favorite.svg") self.icon_fake = QIcon(":resources/icons/fake.svg") self.icon_delete = QIcon(":resources/icons/delete.svg") self.launchButton = QPushButton("Launch") self.launchButton.setMinimumWidth(75) self.launchButton.setProperty("LaunchButton", True) self.subversionLabel = QLabel() self.branchLabel = QLabel() self.commitTimeLabel = QLabel() self.buildHashLabel = QLabel() self.countButton = QPushButton("0") self.countButton.setEnabled(False) self.countButton.setProperty("Count", True) self.countButton.hide() self.countButton.setFixedSize(24, 24) self.widgetFavorite = QPushButton() self.widgetFavorite.setEnabled(False) self.widgetFavorite.setFixedSize(24, 24) self.widgetFavorite.setIcon(self.icon_fake) self.widgetFavorite.setProperty("Icon", True) self.layout.addWidget(self.launchButton) self.layout.addWidget(self.subversionLabel) self.layout.addWidget(self.branchLabel) self.layout.addWidget(self.commitTimeLabel) self.layout.addWidget(self.buildHashLabel) self.layout.addStretch() self.layout.addWidget(self.countButton) self.layout.addWidget(self.widgetFavorite) self.launchButton.clicked.connect(self.launch) self.subversionLabel.setText(self.build_info.subversion) if self.branch == 'lts': branch_name = "LTS" else: branch_name = self.branch.replace('-', ' ').title() self.branchLabel.setText(branch_name) self.commitTimeLabel.setText(self.build_info.commit_time) self.buildHashLabel.setText(self.build_info.build_hash) # Context menu self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.context_menu) self.menu = QMenu() self.menu.setFont(self.parent.font) self.menu_extended = QMenu() self.menu_extended.setFont(self.parent.font) self.deleteAction = QAction("Delete From Drive", self) self.deleteAction.setIcon(self.icon_delete) self.deleteAction.triggered.connect(self.ask_remove_from_drive) self.setAsFavoriteAction = QAction("Mark As Favorite", self) self.setAsFavoriteAction.setIcon(self.icon_favorite) self.setAsFavoriteAction.triggered.connect(self.set_favorite) self.registerExtentionAction = QAction("Register Extension") self.registerExtentionAction.triggered.connect(self.register_extension) self.createShortcutAction = QAction("Create Shortcut") self.createShortcutAction.triggered.connect(self.create_shortcut) self.showFolderAction = QAction("Show Folder") self.showFolderAction.triggered.connect(self.show_folder) self.createSymlinkAction = QAction("Create Symlink") self.createSymlinkAction.triggered.connect(self.create_symlink) self.menu.addAction(self.setAsFavoriteAction) if get_platform() == 'Windows': self.menu.addAction(self.registerExtentionAction) self.menu.addAction(self.createShortcutAction) self.menu.addAction(self.createSymlinkAction) self.menu.addAction(self.showFolderAction) self.menu.addAction(self.deleteAction) self.menu_extended.addAction(self.deleteAction) if self.show_new: self.NewItemLabel = QLabel("New") self.NewItemLabel.setAlignment(Qt.AlignRight | Qt.AlignCenter) self.NewItemLabel.setIndent(6) self.layout.addWidget(self.NewItemLabel) if get_mark_as_favorite() == 0: pass elif (get_mark_as_favorite() == 1 and self.branch == "stable"): self.set_favorite() elif (get_mark_as_favorite() == 2 and self.branch == "daily"): self.set_favorite() elif get_mark_as_favorite() == 3: self.set_favorite() elif get_favorite_path() == self.link: self.set_favorite() self.setEnabled(True) self.list_widget.sortItems() self.list_widget.resize_labels( ('subversionLabel', 'branchLabel', 'commitTimeLabel', 'buildHashLabel')) def context_menu(self): if len(self.list_widget.selectedItems()) > 1: self.menu_extended.exec_(QCursor.pos()) return link_path = Path(get_library_folder()) / "bl_symlink" link = link_path.as_posix() if os.path.exists(link): if (os.path.isdir(link) or os.path.islink(link)): if link_path.resolve() == self.link: self.createSymlinkAction.setEnabled(False) self.menu.exec_(QCursor.pos()) return self.createSymlinkAction.setEnabled(True) self.menu.exec_(QCursor.pos()) def mouseDoubleClickEvent(self, event): if self.build_info is not None: self.launch() def mouseReleaseEvent(self, event): if event.button == Qt.LeftButton: if hasattr(self, "NewItemLabel"): self.NewItemLabel.hide() mod = QApplication.keyboardModifiers() if not (mod == Qt.ShiftModifier or mod == Qt.ControlModifier): self.list_widget.clearSelection() self.item.setSelected(True) event.accept() event.ignore() @QtCore.pyqtSlot() def launch(self): self.item.setSelected(True) if hasattr(self, "NewItemLabel"): self.NewItemLabel.hide() platform = get_platform() library_folder = Path(get_library_folder()) if platform == 'Windows': b3d_exe = library_folder / self.link / "blender.exe" proc = _popen(b3d_exe.as_posix()) elif platform == 'Linux': b3d_exe = library_folder / self.link / "blender" proc = _popen('nohup "' + b3d_exe.as_posix() + '"') if self.observer is None: self.observer = Observer(self) self.observer.count_changed.connect(self.proc_count_changed) self.observer.started.connect(self.observer_started) self.observer.finished.connect(self.observer_finished) self.observer.start() self.observer.append_proc(proc) def proc_count_changed(self, count): self.countButton.setText(str(count)) def observer_started(self): self.countButton.show() self.deleteAction.setEnabled(False) def observer_finished(self): self.observer = None self.countButton.hide() self.deleteAction.setEnabled(True) @QtCore.pyqtSlot() def ask_remove_from_drive(self): self.item.setSelected(True) self.dlg = DialogWindow( self.parent, title="Warning", text="Are you sure you want to<br>delete selected builds?", accept_text="Yes", cancel_text="No", icon=DialogIcon.WARNING) if len(self.list_widget.selectedItems()) > 1: self.dlg.accepted.connect(self.remove_from_drive_extended) else: self.dlg.accepted.connect(self.remove_from_drive) @QtCore.pyqtSlot() def remove_from_drive_extended(self): for item in self.list_widget.selectedItems(): self.list_widget.itemWidget(item).remove_from_drive() @QtCore.pyqtSlot() def remove_from_drive(self): self.launchButton.setText("Deleting") self.setEnabled(False) self.item.setFlags(self.item.flags() & ~Qt.ItemIsSelectable) path = Path(get_library_folder()) / self.link self.remover = Remover(path) self.remover.finished.connect(self.remover_finished) self.remover.start() def remover_finished(self, code): if code == 0: self.parent.draw_from_cashed(self.build_info) self.list_widget.remove_item(self.item) return else: self.launchButton.setText("Launch") self.setEnabled(True) return @QtCore.pyqtSlot() def set_favorite(self): set_favorite_path(self.link) if self.parent.favorite is not None: self.parent.favorite.widgetFavorite.setIcon(self.icon_fake) self.parent.favorite.setAsFavoriteAction.setVisible(True) self.parent.favorite = self self.widgetFavorite.setIcon(self.icon_favorite) self.setAsFavoriteAction.setVisible(False) @QtCore.pyqtSlot() def register_extension(self): path = Path(get_library_folder()) / self.link self.register = Register(path) self.register.start() @QtCore.pyqtSlot() def create_shortcut(self): name = "Blender {0} {1}".format( self.build_info.subversion.replace('(', '').replace(')', ''), self.build_info.branch.replace('-', ' ').title()) create_shortcut(self.link, name) @QtCore.pyqtSlot() def create_symlink(self): target = self.link.as_posix() link = (Path(get_library_folder()) / "bl_symlink").as_posix() platform = get_platform() if platform == 'Windows': if os.path.exists(link): if os.path.isdir(link): os.rmdir(link) _check_call('mklink /J "{0}" "{1}"'.format(link, target)) elif platform == 'Linux': if os.path.exists(link): if os.path.islink(link): os.unlink(link) os.symlink(target, link) @QtCore.pyqtSlot() def show_folder(self): platform = get_platform() library_folder = Path(get_library_folder()) folder = library_folder / self.link if platform == 'Windows': os.startfile(folder.as_posix()) elif platform == 'Linux': subprocess.call(["xdg-open", folder.as_posix()]) def _destroyed(self): if self.parent.favorite == self: self.parent.favorite = None
class Calendar(QWidget): def __init__(self, parent=None, year=int(time.strftime('%Y', time.localtime(time.time()))), month=int(time.strftime('%m', time.localtime(time.time())))): super().__init__(parent) # Set Schedule Layout Components =============== self.scheduleLayout = QVBoxLayout() # ------------------------------- self.titleBox = QHBoxLayout() self.titleLabel = QLabel("title: ") self.titleLineEdit = QLineEdit() # ------------------------------- self.placeBox = QHBoxLayout() self.placeLabel = QLabel("place: ") self.placeLineEdit = QLineEdit() # ------------------------------- self.dateBox = QHBoxLayout() self.dateLabel = QLabel("time:") self.fromHour = QSpinBox() self.fromMin = QSpinBox() self.toHour = QSpinBox() self.toMin = QSpinBox() # ------------------------------- self.discription = QHBoxLayout() self.contentLabel = QLabel("content: ") self.content = QTextEdit() # ------------------------------- self.modifyBtn = Button("Modifying", self.modifying) # ============================================== self.displayCalendar = MyCalendar() self.startDay = 0 self.maxDay = 0 self.currentYear = year self.currentMonth = month self.currentDay = 0 self.firstClick = True self.displayCalendar.loadHoliday() self.today = time.localtime() if os.name == 'nt': self.fileRoot = ".\schedules\schedules.txt" else: self.fileRoot = "./schedules/schedules.txt" try: scheduleFile = open(self.fileRoot, "rb") self.displayCalendar.schedule = pickle.load(scheduleFile) print(self.displayCalendar.schedule) except EOFError: pass # main layout self.mainLayout = QHBoxLayout() # Left side Layout ================================ self.leftLayout = QVBoxLayout() # Stacked Widget Part ----------------------------- # Setting Stacked Widget(like a switching Tabs) self.setSchedule = QWidget() self.lunaDate = QWidget() # Design And Setting Actions each Tab. if want to Append any action, plz input the action in here. self.setScheduleUI() self.lunaDateUI() # Appending tabs in Stack self.Stack = QStackedWidget() self.Stack.addWidget(self.setSchedule) self.Stack.addWidget(self.lunaDate) # Switching Button layout Design And binding button with action. self.tabLayout = QHBoxLayout() self.tabLayout.addWidget(Button("스케쥴러", lambda: self.display(0))) self.tabLayout.addWidget(Button("음력", lambda: self.display(1))) for i in range(self.tabLayout.count()): self.tabLayout.itemAt(i).widget().setStyleSheet('font-size: 8pt') self.leftLayout.addLayout(self.tabLayout) # ------------------------------------------------- # handling Year & month ---------------------------------- self.moveMonth = QHBoxLayout() self.previousBtn = Button("<", self.previousMonth) # showing Year and month using Combobox(Year range: 1980 ~ 2040, Month range: 1, 12) self.yearCombo = QComboBox() self.yearCombo.addItems([str(x) for x in range(1980, 2041)]) self.yearCombo.setCurrentText(str(self.currentYear)) self.monthCombo = QComboBox() self.monthCombo.addItems([str(x) for x in range(1, 13)]) self.monthCombo.setCurrentText(str(self.currentMonth)) self.nextBtn = Button(">", self.nextMonth) self.moveMonth.addStretch() self.moveMonth.addWidget(self.previousBtn) self.moveMonth.addWidget(self.yearCombo) self.moveMonth.addWidget(self.monthCombo) self.moveMonth.addWidget(self.nextBtn) self.moveMonth.addStretch() self.leftLayout.addLayout(self.moveMonth) self.leftLayout.addStretch() # ------------------------------------------------- # Set Day of Week --------------------------------- self.weekDayLayout = QHBoxLayout() enumDays = ["일", "월", "화", "수", "목", "금", "토"] for i in enumDays: label = QLabel(i) label.setAlignment(Qt.AlignCenter) self.weekDayLayout.addWidget(label) self.leftLayout.addLayout(self.weekDayLayout) # ------------------------------------------------- # grid layout to appending date Buttons self.calendarGrid = QGridLayout() self.calendarGrid.setSizeConstraint(QLayout.SetFixedSize) self.leftLayout.addLayout(self.calendarGrid) self.leftLayout.addStretch(7) # showing status self.statusLabel = QLabel("btn Status") self.leftLayout.addWidget(self.statusLabel) # ================================================== # Set grid self.displayCalendar.setCalander(self.currentYear, self.currentMonth) self.renderDate(self.displayCalendar.getCalander()) # Set ComboBox Changing Event self.yearCombo.currentTextChanged.connect( lambda: self.selectionChanged()) self.monthCombo.currentTextChanged.connect( lambda: self.selectionChanged()) self.mainLayout.addLayout(self.leftLayout) self.mainLayout.addWidget(self.Stack) self.Stack.setCurrentIndex(0) # default Tab -> set calendar self.setLayout(self.mainLayout) self.setWindowTitle("Calendar") def renderDate(self, newCalendar): # =========== Append Day Buttons =============== self.clearLayout(self.calendarGrid) todayYear = self.today.tm_year todayMonth = self.today.tm_mon todayDay = self.today.tm_mday toggle = True for i in newCalendar: print(i) # Enroll button for row, column in enumerate(newCalendar): for col, day in enumerate(column): btn = Button(str(day), self.btnEvent) # deactivate button condition if toggle: if day != 1: btn.setEnabled(False) else: toggle = False else: if (row == len(newCalendar) - 1) and (day // 10 == 0): btn.setEnabled(False) # set today button color if (self.currentYear, self.currentMonth, day) == (todayYear, todayMonth, todayDay): btn.setStyleSheet('font-style: italic;') # if this day have any event represent event key = '-'.join( [str(self.currentYear), str(self.currentMonth), str(day)]) if key in self.displayCalendar.schedule.keys( ) and btn.isEnabled(): btn.setStyleSheet('color: blue;') btn.setStyleSheet('background-color: skyblue;') btn.setToolTip( self.displayCalendar.schedule[key].getTitle()) for restMonth, restDay, title in self.displayCalendar.holidays: if restMonth == self.currentMonth and restDay == day and btn.isEnabled( ): if key in self.displayCalendar.schedule.keys( ) and btn.isEnabled(): btn.setStyleSheet( 'background-color: skyblue; color: red;') btn.setToolTip(title) else: btn.setStyleSheet('color: red;') btn.setToolTip(title) break # 공휴일은 빨간색으로 설정해준다. if col == 0 and btn.isEnabled(): btn.setStyleSheet('color: red;') self.calendarGrid.addWidget(btn, row, col) # =============================================== self.displayCalendar.enrollHoliday(self.currentYear) self.displayCalendar.loadHoliday() def btnEvent(self): # self.showingWidget(self.scheduleLayout) self.setFixedSize(self.mainLayout.sizeHint()) btn = self.sender() self.statusLabel.setText("Day: " + btn.text() + " is Clicked.") self.currentDay = btn.text() target = "-".join([ str(self.currentYear), str(self.currentMonth), str(self.currentDay) ]) targetEvent = self.displayCalendar.schedule.get(target) if not targetEvent: self.titleLineEdit.setText("None") self.placeLineEdit.clear() self.fromHour.setValue(0) self.fromMin.setValue(0) self.toHour.setValue(0) self.toMin.setValue(0) self.content.clear() else: self.titleLineEdit.setText(targetEvent.getTitle()) self.placeLineEdit.setText(targetEvent.getPlace()) timeSet = targetEvent.getDate().split(",") self.fromHour.setValue(int(timeSet[0])) self.fromMin.setValue(int(timeSet[1])) self.toHour.setValue(int(timeSet[2])) self.toMin.setValue(int(timeSet[3])) self.content.setText(targetEvent.getDescription()) def modifying(self): newEvent = MyEvent() eventList = [ self.titleLineEdit.text(), self.placeLineEdit.text(), ",".join([ str(self.fromHour.value()), str(self.fromMin.value()), str(self.toHour.value()), str(self.toMin.value()) ]), self.content.toPlainText(), ] newEvent.setEvent(*eventList) target = "-".join([ str(self.currentYear), str(self.currentMonth), str(self.currentDay) ]) self.displayCalendar.schedule[target] = newEvent self.statusLabel.setText("modified") # rendering previous month calendar def previousMonth(self): if self.currentMonth is 1: self.currentYear -= 1 self.yearCombo.setCurrentText(str(self.currentYear)) self.currentMonth = 12 self.monthCombo.setCurrentText(str(self.currentMonth)) else: self.currentMonth -= 1 self.monthCombo.setCurrentText(str(self.currentMonth)) # rendering next month calendar def nextMonth(self): if self.currentMonth is 12: self.currentYear += 1 self.yearCombo.setCurrentText(str(self.currentYear)) self.currentMonth = 1 self.monthCombo.setCurrentText(str(self.currentMonth)) else: self.currentMonth += 1 self.monthCombo.setCurrentText(str(self.currentMonth)) def selectionChanged(self): self.currentYear = int(self.yearCombo.currentText()) self.currentMonth = int(self.monthCombo.currentText()) self.displayCalendar.setYear(self.currentYear) self.displayCalendar.setMonth(self.currentMonth) self.displayCalendar.setCalander(self.currentYear, self.currentMonth) self.renderDate(self.displayCalendar.getCalander()) def clearLayout(self, layout): while layout.count(): child = layout.takeAt(0) if child.widget(): child.widget().deleteLater() def closeEvent(self, event): keys = [] myEvent = self.displayCalendar.schedule for target in myEvent.keys(): title = myEvent[target].title place = myEvent[target].place description = myEvent[target].description if (title, place, description) == ('', '', ''): keys.append(target) for target in keys: del self.displayCalendar.schedule[target] with open(self.fileRoot, "wb") as file: pickle.dump(self.displayCalendar.schedule, file) def setScheduleUI(self): # Schedules layout ================================== self.titleBox.addWidget(self.titleLabel) self.titleBox.addWidget(self.titleLineEdit) self.placeBox.addWidget(self.placeLabel) self.placeBox.addWidget(self.placeLineEdit) self.fromHour.setRange(0, 24) self.toHour.setRange(0, 24) self.fromMin.setRange(0, 59) self.toMin.setRange(0, 59) self.fromHour.valueChanged.connect( lambda: self.toHour.setRange(self.fromHour.value(), 24)) # self.toHour.valueChanged.connect(lambda: self.fromHour.setRange(0, self.toHour.value())) self.fromMin.valueChanged.connect( lambda: self.toMin.setRange(self.fromMin.value(), 59)) # self.toMin.valueChanged.connect(lambda: self.fromMin.setRange(0, self.toMin.value())) self.dateBox.addWidget(self.dateLabel) self.dateBox.addWidget(self.fromHour) self.dateBox.addWidget(self.fromMin) self.dateBox.addWidget(QLabel(" ~ ")) self.dateBox.addWidget(self.toHour) self.dateBox.addWidget(self.toMin) self.contentLabel.setAlignment(Qt.AlignTop) self.discription.addWidget(self.contentLabel) self.discription.addWidget(self.content) self.scheduleLayout.addLayout(self.titleBox) self.scheduleLayout.addLayout(self.placeBox) self.scheduleLayout.addLayout(self.dateBox) self.scheduleLayout.addLayout(self.discription) # modifying schedule Button self.scheduleLayout.addWidget(self.modifyBtn) self.setSchedule.setLayout(self.scheduleLayout) def lunaDateUI(self): month_31 = [1, 3, 5, 7, 8, 10, 12] layout = QVBoxLayout() #layout.addWidget(QLabel("Luna Date")) topLayout = QHBoxLayout() self.yearSpinner = QSpinBox() self.yearSpinner.setRange(1980, 2040) self.monthSpinner = QSpinBox() self.monthSpinner.setRange(1, 12) self.daySpinner = QSpinBox() self.yearSpinner.setValue(self.today.tm_year) self.monthSpinner.setValue(self.today.tm_mon) self.daySpinner.setValue(self.today.tm_mday) self.monthSpinner.valueChanged.connect( lambda: self.daySpinner.setRange( 1, self.displayCalendar.getMaxday(self.yearSpinner.value(), self.monthSpinner.value()))) self.modeComboBox = QComboBox() self.modeComboBox.addItems(["양력 -> 음력", "음력 -> 양력"]) convertBtn = Button("convert", self.lunarBtnEvent) resetBtn = Button("reset", self.lunarBtnEvent) bottomLayout = QVBoxLayout() titleBox = QHBoxLayout() solarBox = QHBoxLayout() lunarBox = QHBoxLayout() self.todayLabel = QLabel("오늘의 날짜정보") self.todayLabel.setStyleSheet('color: red; font-size: 18px;') solarLabel = QLabel("양력날짜") solarLabel.setStyleSheet('color: gray;') todaySolarDay = "%04d-%02d-%02d" % ( self.today.tm_year, self.today.tm_mon, self.today.tm_mday) self.solarDateLabel = QLabel(todaySolarDay) lunarLabel = QLabel("음력날짜") lunarLabel.setStyleSheet('color: gray;') self.lunarDateLabel = QLabel( self.displayCalendar.calculator.getToLunarDate( self.today.tm_year, self.today.tm_mon, self.today.tm_mday)) titleBox.addWidget(self.todayLabel) solarBox.addWidget(solarLabel) solarBox.addWidget(self.solarDateLabel) lunarBox.addWidget(lunarLabel) lunarBox.addWidget(self.lunarDateLabel) bottomLayout.addLayout(titleBox) bottomLayout.addLayout(solarBox) bottomLayout.addLayout(lunarBox) topLayout.addWidget(self.yearSpinner) topLayout.addWidget(self.monthSpinner) topLayout.addWidget(self.daySpinner) topLayout.addWidget(self.modeComboBox) topLayout.addWidget(convertBtn) topLayout.addWidget(resetBtn) layout.addStretch() layout.addLayout(bottomLayout) layout.addLayout(topLayout) layout.addStretch() self.lunaDate.setLayout(layout) def display(self, i): self.Stack.setCurrentIndex(i) def hidingWidget(self, layout): for i in range(layout.count()): item = layout.itemAt(i) if item.widget() is not None: layout.itemAt(i).widget().hide() elif item.layout() is not None: self.hidingWidget(layout.itemAt(i).layout()) def showingWidget(self, layout): for i in range(layout.count()): item = layout.itemAt(i) if item.widget() is not None: layout.itemAt(i).widget().show() elif item.layout() is not None: self.showingWidget(layout.itemAt(i).layout()) def lunarBtnEvent(self): btn = self.sender() key = btn.text() if key == 'reset': self.todayLabel.setText('오늘의 날짜정보') self.todayLabel.setStyleSheet('color: red; font-size: 18px;') elif key == 'convert': if self.modeComboBox.currentIndex() is 0: self.todayLabel.setText("양력 {}년 {}월 {}일".format( self.yearSpinner.value(), self.monthSpinner.value(), self.daySpinner.value())) self.todayLabel.setStyleSheet( 'font-weight: bold; color: black; font-size: 12px;') lunarDate = self.displayCalendar.calculator.getToLunarDate( self.yearSpinner.value(), self.monthSpinner.value(), self.daySpinner.value()) self.solarDateLabel.setText( str(self.yearSpinner.value()) + "-" + str(self.monthSpinner.value()) + "-" + str(self.daySpinner.value())) self.lunarDateLabel.setText(lunarDate) else: self.todayLabel.setText("음력 {}년 {}월 {}일".format( self.yearSpinner.value(), self.monthSpinner.value(), self.daySpinner.value())) self.todayLabel.setStyleSheet( 'font-weight: bold; color: black; font-size: 12px;') solarDate = self.displayCalendar.calculator.toSolarDate( self.yearSpinner.value(), self.monthSpinner.value(), self.daySpinner.value()) self.solarDateLabel.setText( str(solarDate[0]) + "-" + str(solarDate[1]) + "-" + str(solarDate[2])) self.lunarDateLabel.setText( str(self.yearSpinner.value()) + "-" + str(self.monthSpinner.value()) + "-" + str(self.daySpinner.value()))
class Ui_Widget(object): """ Klasa definiująca GUI """ def setupUi(self, Widget): # widgety rysujące kształty, instancje klasy Ksztalt self.ksztalt1 = Ksztalt(self, Ksztalty.Polygon) self.ksztalt2 = Ksztalt(self, Ksztalty.Ellipse) self.ksztaltAktywny = self.ksztalt1 # przyciski CheckBox ### uklad = QVBoxLayout() # układ pionowy self.grupaChk = QButtonGroup() for i, v in enumerate(('Kwadrat', 'Koło', 'Trójkąt', 'Linia')): self.chk = QCheckBox(v) self.grupaChk.addButton(self.chk, i) uklad.addWidget(self.chk) self.grupaChk.buttons()[self.ksztaltAktywny.ksztalt].setChecked(True) # CheckBox do wyboru aktywnego kształtu self.ksztaltChk = QCheckBox('<=') self.ksztaltChk.setChecked(True) uklad.addWidget(self.ksztaltChk) # układ poziomy dla kształtów oraz przycisków CheckBox ukladH1 = QHBoxLayout() ukladH1.addWidget(self.ksztalt1) ukladH1.addLayout(uklad) ukladH1.addWidget(self.ksztalt2) # koniec CheckBox ### # Slider i LCDNumber ### self.suwak = QSlider(Qt.Horizontal) self.suwak.setMinimum(0) self.suwak.setMaximum(255) self.lcd = QLCDNumber() self.lcd.setSegmentStyle(QLCDNumber.Flat) # układ poziomy (splitter) dla slajdera i lcd ukladH2 = QSplitter(Qt.Horizontal, self) ukladH2.addWidget(self.suwak) ukladH2.addWidget(self.lcd) ukladH2.setSizes((125, 75)) # przyciski RadioButton ### self.ukladR = QHBoxLayout() for v in ('R', 'G', 'B'): self.radio = QRadioButton(v) self.ukladR.addWidget(self.radio) self.ukladR.itemAt(0).widget().setChecked(True) # grupujemy przyciski self.grupaRBtn = QGroupBox('Opcje RGB') self.grupaRBtn.setLayout(self.ukladR) self.grupaRBtn.setObjectName('Radio') self.grupaRBtn.setCheckable(True) # układ poziomy dla grupy Radio ukladH3 = QHBoxLayout() ukladH3.addWidget(self.grupaRBtn) # koniec RadioButton ### # Lista ComboBox i SpinBox ### self.listaRGB = QComboBox(self) for v in ('R', 'G', 'B'): self.listaRGB.addItem(v) self.listaRGB.setEnabled(False) # SpinBox self.spinRGB = QSpinBox() self.spinRGB.setMinimum(0) self.spinRGB.setMaximum(255) self.spinRGB.setEnabled(False) # układ pionowy dla ComboBox i SpinBox uklad = QVBoxLayout() uklad.addWidget(self.listaRGB) uklad.addWidget(self.spinRGB) # do układu poziomego grupy Radio dodajemy układ ComboBox i SpinBox ukladH3.insertSpacing(1, 25) ukladH3.addLayout(uklad) # koniec ComboBox i SpinBox ### # przyciski PushButton ### uklad = QHBoxLayout() self.grupaP = QButtonGroup() self.grupaP.setExclusive(False) for v in ('R', 'G', 'B'): self.btn = QPushButton(v) self.btn.setCheckable(True) self.grupaP.addButton(self.btn) uklad.addWidget(self.btn) # grupujemy przyciski self.grupaPBtn = QGroupBox('Przyciski RGB') self.grupaPBtn.setLayout(uklad) self.grupaPBtn.setObjectName('Push') self.grupaPBtn.setCheckable(True) self.grupaPBtn.setChecked(False) # koniec PushButton ### # etykiety QLabel i pola QLineEdit ### ukladH4 = QHBoxLayout() self.labelR = QLabel('R') self.labelG = QLabel('G') self.labelB = QLabel('B') self.kolorR = QLineEdit('0') self.kolorG = QLineEdit('0') self.kolorB = QLineEdit('0') for v in ('R', 'G', 'B'): label = getattr(self, 'label' + v) kolor = getattr(self, 'kolor' + v) ukladH4.addWidget(label) ukladH4.addWidget(kolor) kolor.setMaxLength(3) # koniec QLabel i QLineEdit ### # główny układ okna, wertykalny ### ukladOkna = QVBoxLayout() ukladOkna.addLayout(ukladH1) ukladOkna.addWidget(ukladH2) ukladOkna.addLayout(ukladH3) ukladOkna.addWidget(self.grupaPBtn) ukladOkna.addLayout(ukladH4) self.setLayout(ukladOkna) # przypisanie układu do okna głównego self.setWindowTitle('Widżety') self.resize(200, 250)
class CPinUI(QWidget): def __init__(self, pinID, parent=None): super(CPinUI, self).__init__(parent) self.m_PinID = pinID self.m_NodeID = interface.GetNodeIDByPinID(pinID) self.m_GraphicID = interface.GetGraphicIDByNodeID(self.m_NodeID) self.m_Btn = None self.m_Label = None self.m_HLayout = None self.m_DefaultWidget = None # 默认值控件 self._InitUI() self.SetIcon() self.SetText() self.ShowDefaultWidget() GetUIMgr().AddPinUI(pinID, self) def __del__(self): GetUIMgr().DelPinUI(self.m_PinID) def _InitUI(self): hBox = QHBoxLayout(self) hBox.setContentsMargins(0, 0, 0, 0) hBox.setSpacing(6) self.m_Btn = CTypeButton(self.m_PinID, self) self.m_Label = QLabel(self) self.m_HLayout = QHBoxLayout() self.m_HLayout.setContentsMargins(0, 0, 0, 0) self.m_HLayout.setSpacing(6) hBox.addWidget(self.m_Btn) hBox.addWidget(self.m_Label) hBox.addLayout(self.m_HLayout) def contextMenuEvent(self, event): super(CPinUI, self).contextMenuEvent(event) lstLineID = interface.GetAllLineByPin(self.m_PinID) menu = QMenu() for lineID in lstLineID: oPinID = interface.GetLineOtherPin(lineID, self.m_PinID) sPinDisplayName = interface.GetPinAttr(oPinID, bddefine.PinAttrName.DISPLAYNAME) nodeID = interface.GetNodeIDByPinID(oPinID) sNodeDisplayName = interface.GetNodeAttr(nodeID, bddefine.NodeAttrName.DISPLAYNAME) sMsg = "删除与\"%s\"-\"%s\"的连线" % (sNodeDisplayName, sPinDisplayName) func = functor.Functor(interface.DelLine, lineID) menu.addAction(sMsg, func) menu.exec_(QCursor.pos()) event.accept() def SetIcon(self, iDataType=None): if iDataType is None: iPinType = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.PIN_TYPE) if bddefine.PinIsFlow(iPinType): iDataType = -1 else: iDataType = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.DATA_TYPE) icon = QIcon() pix = ":/icon/btn_%s.png" % iDataType icon.addPixmap(QPixmap(pix), QIcon.Normal, QIcon.Off) self.m_Btn.setIcon(icon) def SetText(self, sText=None): if sText is None: sText = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.DISPLAYNAME) self.m_Label.setText(sText) def ShowDefaultWidget(self): iPinType = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.PIN_TYPE) if iPinType != bddefine.PIN_INPUT_DATA_TYPE: return lstLine = interface.GetAllLineByPin(self.m_PinID) if lstLine: return oWidget = None iDataTye = interface.GetPinAttr(self.m_PinID, bddefine.PinAttrName.DATA_TYPE) if iDataTye in (bddefine.Type.INT, bddefine.Type.FLOAT, bddefine.Type.STR): oWidget = subpinui.CValidatorLineEdit(self.m_PinID, iDataTye) elif iDataTye == bddefine.Type.BOOL: oWidget = subpinui.CCheckBox(self.m_PinID) elif iDataTye == bddefine.Type.ENUM: oWidget = subpinui.CEnum(self.m_PinID) elif iDataTye == bddefine.Type.VECTOR3: oWidget = subpinui.CVector3(self.m_PinID) elif iDataTye == bddefine.Type.CHECKBOX: oWidget = subpinui.CComCheckBox(self.m_PinID) if oWidget: self.m_HLayout.addWidget(oWidget) self.m_DefaultWidget = oWidget self.adjustSize() def HideDefaultWidget(self): if not self.m_DefaultWidget: return self.m_DefaultWidget.setParent(None) index = self.m_HLayout.indexOf(self.m_DefaultWidget) item = self.m_HLayout.itemAt(index) self.m_HLayout.removeWidget(self.m_DefaultWidget) self.m_HLayout.removeItem(item) self.m_DefaultWidget = None self.adjustSize() def enterEvent(self, event): super(CPinUI, self).enterEvent(event) GetSignal().UI_LINE_CONNECT.emit(self.m_GraphicID, self.m_PinID) event.accept()
class SimMoveDemo(QWidget): menuSignal = pyqtSignal(int) def __init__(self, parent): super().__init__(parent) self.parent = parent self.menuSignal.connect(self.addPlayers) self.currentAmp = AMPLITUDE self.startingBallSize = MINBALLSIZE * 2 + 1 self.setGeometry(600, 200, WINDOWWIDTH, WINDOWHEIGHT) self.players = [] self.bonuses = [] self.cupPlayers = [] self.cupMode = False self.finalGame = False self.balls = [Ball(self, self.startingBallSize)] self.key_notifier = KeyNotifier() self.key_notifier.key_signal.connect(self.__update_position__) self.key_notifier.start() self.stopOnStart = True self.finishCup = False self.playerLen = None self.previousBalls = len(self.balls) self.currentLevel = 1 self.currentBall = 0 self.semiFinalEnd = False self.weaponObj = None self.weaponObj2 = None self.deadPoints = [] self.finalist1points = 0 self.finalist2points = 0 self.finalist1 = '' self.finalist2 = '' def addPlayers(self, option): if option == 1: self.players = [Player(self, 'player1', 1)] elif option == 2: self.players = [ Player(self, 'player1', 2), Player(self, 'player2', 2) ] elif option == 4: self.players = [ Player(self, 'player1', 2), Player(self, 'player2', 2) ] self.cupMode = True self.__init_ui__() self.timer = QBasicTimer() self.timer.start(20, self) def initPlayersAndBalls(self): for player in self.players: player.player.setPixmap(player.PixMap) player.player.setGeometry(player.PositionX, player.PositionY, player.Width, player.Heigth) player.weapon.weapon.setPixmap(player.weapon.PixMap) player.weapon.weapon.setGeometry(0, WINDOWHEIGHT - 87, WINDOWWIDTH, 0) player.livesSignal.connect(self.updateLives) player.pointsSignal.connect(self.updatePoints) if self.cupMode: self.weaponObj = self.players[0].weapon self.weaponObj2 = self.players[1].weapon for ball in self.balls: ball.ball.setPixmap(ball.pixMapScaled) ball.ball.setGeometry(ball.x, ball.y, ball.size, ball.size) for p in self.players: p.show() def __init_ui__(self): self.initPlayersAndBalls() self.setWindowTitle('Bubble Trouble') self.stopOnStart = True # BACKGROUND oImage = QImage(IMAGES_DIR + 'background.png') sImage = oImage.scaled(QSize(WINDOWWIDTH, WINDOWHEIGHT)) palette = QPalette() palette.setBrush(10, QBrush(sImage)) self.setFocus() self.parent.setPalette(palette) self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint) # elements self.livesPic1 = QPixmap(IMAGES_DIR + 'player1.png').scaled(20, 30) self.livesPic2 = QPixmap(IMAGES_DIR + 'player2.png').scaled(20, 30) verticalPlayerInf = QVBoxLayout() self.horizontalBox = QHBoxLayout() self.labelLives = [] for player in self.players: self.labelLives.append( self.initPlayerLives( QPixmap(IMAGES_DIR + player.playerId + '.png').scaled( 20, 30), player.lifes)) for label in self.labelLives[0]: self.horizontalBox.addWidget(label, 1, Qt.AlignLeft | Qt.AlignTop) if len(self.players) > 1: self.horizontalBox.addSpacing(WINDOWWIDTH - 2 * 80 - 75) for label in self.labelLives[1]: self.horizontalBox.addWidget(label, 1, Qt.AlignRight | Qt.AlignTop) else: self.horizontalBox.addSpacing(WINDOWWIDTH - 150) self.initGuiElements(self.horizontalBox, verticalPlayerInf) self.setLayout(verticalPlayerInf) def initPlayerLives(self, pixMap, currentLives): labelLives = [] for i in range(currentLives): labelLives.append(QLabel()) labelLives[i].setPixmap(pixMap) return labelLives def updatePlayerPixMapLives(self, pixMap, currentLives, playerUpdated): if playerUpdated.playerId == 'player1': self.labelLives[0][currentLives].clear() elif playerUpdated.playerId == 'player2': self.labelLives[1][-currentLives - 1].clear() def resetPlayerPixMapLives(self, initLives): for x in range(2 * initLives + 1): if x != initLives: widget = self.horizontalBox.itemAt(x).widget() if x < initLives: widget.setPixmap( QPixmap(IMAGES_DIR + 'player1.png').scaled(20, 30)) elif x > initLives: widget.setPixmap( QPixmap(IMAGES_DIR + 'player2.png').scaled(20, 30)) def initGuiElements(self, horizontalBox, verticalPlayerInf): self.getReadyLabel = QLabel() self.getReadyLabel.setText('Get Ready!') self.getReadyLabel.setFont( QFont('Denne Kitten Heels', 30, QFont.ExtraBold)) self.getReadyLabel.setAlignment(Qt.AlignTop) self.getReadyLabel.setFrameStyle(1) self.getReadyLabel.setStyleSheet( "QLabel{ background-color:rgba(81, 109, 131, 0.4) ;color:#D9C91B ;border-width:1px; border-style:solid;}" ) self.player11LabelTxt = 'PLAYER 1' self.player1Tag = QLabel() self.player1Tag.setText(self.player11LabelTxt) self.player1Tag.setFont( QFont('Denne Kitten Heels', 18, QFont.ExtraBold)) self.player1Tag.setAlignment(Qt.AlignLeft) self.player1Tag.setFrameStyle(33) self.player1Tag.setMidLineWidth(1) self.player1Tag.setStyleSheet( "QLabel{background-color: #CECECE; color:#E20000;}") self.player1Tag.setFixedSize(QSize(130, 31)) self.player2LabelTxt = 'PLAYER 2' self.player2Tag = QLabel() self.player2Tag.setText(self.player2LabelTxt) self.player2Tag.setFont( QFont('Denne Kitten Heels', 18, QFont.ExtraBold)) self.player2Tag.setAlignment(Qt.AlignLeft) self.player2Tag.setFrameStyle(33) self.player2Tag.setMidLineWidth(1) self.player2Tag.setStyleSheet( "QLabel{background-color: #CECECE; color:#265EBB;}") self.player2Tag.setFixedSize(QSize(130, 31)) player1Points = '0' self.player1PointsTag = QLabel() self.player1PointsTag.setText(player1Points) self.player1PointsTag.setFont(QFont('kristen itc', 17, QFont.ExtraBold)) self.player1PointsTag.setAlignment(Qt.AlignRight) self.player1PointsTag.setFrameStyle(33) self.player1PointsTag.setMidLineWidth(1) self.player1PointsTag.setStyleSheet( "QLabel{background-color: #CECECE; color:#676769;}") self.player1PointsTag.setFixedSize(QSize(100, 31)) player2Points = '0' self.player2PointsTag = QLabel() self.player2PointsTag.setText(player2Points) self.player2PointsTag.setFont(QFont('kristen itc', 17, QFont.ExtraBold)) self.player2PointsTag.setAlignment(Qt.AlignRight) self.player2PointsTag.setFrameStyle(33) self.player2PointsTag.setMidLineWidth(1) self.player2PointsTag.setStyleSheet( "QLabel{background-color: #CECECE; color:#676769;}") self.player2PointsTag.setFixedSize(QSize(100, 31)) levelText = 'Level' levelTag = QLabel() levelTag.setText(levelText) levelTag.setFont(QFont('denne kitten heels', 17, QFont.ExtraBold)) levelTag.setAlignment(Qt.AlignCenter) levelTag.setFrameStyle(33) levelTag.setMidLineWidth(1) levelTag.setStyleSheet( "QLabel{background-color: #CECECE; color:#C7820D;}") levelTag.setFixedSize(QSize(100, 31)) self.levelNum = str(self.currentLevel) self.levelNumTag = QLabel() self.levelNumTag.setText(self.levelNum) self.levelNumTag.setFont( QFont('denne kitten heels', 17, QFont.ExtraBold)) self.levelNumTag.setAlignment(Qt.AlignCenter) self.levelNumTag.setStyleSheet( "QLabel{background-color: #CECECE; color:#E20000;}") self.levelNumTag.setFixedSize(QSize(50, 31)) horizontalBox.setContentsMargins(20, 0, 20, 0) verticalLevel = QVBoxLayout() verticalLevel.addWidget(levelTag) verticalLevel.addSpacing(-9) verticalLevel.addWidget(self.levelNumTag, 0, Qt.AlignCenter) horizontalPlayerInf = QHBoxLayout() horizontalPlayerInf.addWidget(self.player1Tag) horizontalPlayerInf.addWidget(self.player1PointsTag) horizontalPlayerInf.addSpacing(90) horizontalPlayerInf.addLayout(verticalLevel) horizontalPlayerInf.addSpacing(82) horizontalPlayerInf.addWidget(self.player2PointsTag) horizontalPlayerInf.addWidget(self.player2Tag) horizontalPlayerInf.setAlignment(Qt.AlignBottom) horizontalPlayerInf.setContentsMargins(10, 0, 10, 0) verticalPlayerInf.addLayout(horizontalBox) verticalPlayerInf.addWidget(self.getReadyLabel, 1, Qt.AlignCenter | Qt.AlignTop) verticalPlayerInf.addLayout(horizontalPlayerInf) def keyPressEvent(self, event): self.key_notifier.add_key(event.key()) def keyReleaseEvent(self, event): self.key_notifier.rem_key(event.key()) if not event.isAutoRepeat(): for player in self.players: player.drawPlayer('normal') def __update_position__(self, key): for player in self.players: player.update(key) def closeEvent(self, event): self.key_notifier.die() def timerEvent(self, event): for ball in self.balls: if self.stopOnStart: time.sleep(2) self.getReadyLabel.close() ball.start() self.stopOnStart = False for bonus in self.bonuses: bonus.update() bonus.bonus.setPixmap(bonus.pixMapScaled) bonus.bonus.setGeometry(bonus.posX, bonus.posY, 30, 30) bonus.bonus.show() self.checkCollisionWeapon() self.checkCollisionPlayer() def splitBall(self, size, x, y): if size / 2 <= MINBALLSIZE: if len(self.balls) == 0: self.timer.stop() time.sleep(1) self.loadNextLevel() else: ball1 = Ball(self, size / 2) ball2 = Ball(self, size / 2) self.setBallProperties(ball1, x, y, True) self.setBallProperties(ball2, x, y, False) self.balls.append(ball1) self.balls.append(ball2) if random.randrange(BONUS_RANGE) == 0: bonus_type = random.choice(bonus_types) bonus = Bonus(self, bonus_type, x, y) bonus.isActive = True self.bonuses.append(bonus) ball1.splitedLeft = True ball2.splitedRight = True ball1.splitedCounter = 42 ball2.splitedCounter = 42 ball1.y = ball1.dy ball2.y = ball2.dy ball1.ball.show() ball2.ball.show() def setBallProperties(self, ball, x, y, isForward): ball.counter = x ball.dy = y ball.forward = isForward ball.ball.setPixmap(ball.pixMapScaled) ball.ball.setGeometry(ball.counter, ball.dy, ball.size, ball.size) def checkCollisionWeapon(self): for player in self.players: if player.weapon.isActive: for ball in self.balls: if ball.counter <= player.weapon.posX and ball.counter + ball.size >= player.weapon.posX: if ball.dy + ball.size >= player.weapon.posY: player.weapon.isActive = False size = ball.size x = ball.counter y = ball.dy self.balls.remove(ball) ball.ball.hide() del ball self.splitBall(size, x, y) player.pointsSignal.emit(50) break # unisti samo jednu lopticu i izadji (pravi bag ako se izostavi -> unistava # novonastale lopte) def checkCollisionPlayer(self): for player in self.players: for ball in self.balls: if player.PositionY <= ball.dy + ball.size - 20: if(ball.counter <= player.PositionX and player.PositionX <= ball.counter + ball.size) or \ (ball.counter <= player.PositionX + 25 and player.PositionX + 25 <= ball.counter + ball.size) or \ (ball.counter <= player.PositionX and ball.counter + ball.size >= player.PositionX + 28) or \ (ball.counter >= player.PositionX and ball.counter + ball.size <= player.PositionX + 40): self.timer.stop() ball.ball.hide() self.balls.remove(ball) self.resetLevel() player.livesSignal.emit() for bonus in self.bonuses: if (player.PositionX + player.Width >= bonus.posX and player.PositionX <= bonus.posX \ and bonus.posY + bonus.height >= player.PositionY) or \ (player.PositionX <= bonus.posX + bonus.width and player.PositionX >= bonus.posX and bonus.posY + bonus.height >= player.PositionY): if bonus.bonusType == BONUS_COINS: player.pointsSignal.emit(375) elif bonus.bonusType == BONUS_NO_WEAPON: player.weapon.isActive = False player.bonusNoWeapon = True bonus.bonus.hide() self.bonuses.remove(bonus) def loadNextLevel(self): self.key_notifier.keys.clear() self.currentLevel += 1 nextLevelType = random.choice([0, 1]) for bonus in self.bonuses: bonus.bonus.hide() self.bonuses.clear() if nextLevelType == 0: if self.startingBallSize * 2 <= MAXBALLSIZE: self.startingBallSize = self.startingBallSize * 2 self.balls.append(Ball(self, self.startingBallSize)) self.balls[0].ball.setPixmap(self.balls[0].pixMapScaled) self.balls[0].ball.setGeometry(self.balls[0].x, self.balls[0].y, self.balls[0].size, self.balls[0].size) self.balls[0].ball.show() # self.currentAmp = AMPLITUDE + 46 else: nextLevelType = 1 if nextLevelType == 1: self.previousBalls = self.previousBalls + 1 temp = self.previousBalls for x in range(self.previousBalls): self.balls.append(Ball(self, self.startingBallSize)) for b in self.balls: b.ball.setPixmap(b.pixMapScaled) if self.currentBall % 2 == 0: b.x = b.x - 35 * temp temp += 1 b.counter = b.x b.ball.setGeometry(b.x, b.y, b.size, b.size) b.forward = False elif self.currentBall % 2 == 1: b.x = b.x + 35 * temp temp += 1 b.counter = b.x b.ball.setGeometry(b.x, b.y, b.size, b.size) b.ball.show() self.currentBall += 1 self.stopOnStart = True for player in self.players: player.PositionX = player.initialPositionX player.update(Qt.Key_Minus) player.bonusNoWeapon = False if player.weapon.isActive: player.weapon.isActive = False player.weapon.update() self.getReadyLabel.setText('Get ready!') self.getReadyLabel.show() self.getReadyLabel.raise_() self.levelNumTag.setText(str(self.currentLevel)) self.timer.start(20, self) def resetLevel(self): for ball in self.balls: ball.ball.hide() self.balls.clear() for bonus in self.bonuses: bonus.bonus.hide() self.bonuses.clear() for x in range(self.previousBalls): temp = x + 2 self.balls.append(Ball(self, self.startingBallSize)) self.balls[x].ball.setPixmap(self.balls[x].pixMapScaled) if x % 2 == 0: if len(self.balls) > 1: self.balls[x].forward = False self.balls[x].x = self.balls[x].x - 35 * temp self.balls[x].counter = self.balls[x].x self.balls[x].ball.setGeometry(self.balls[x].x, self.balls[x].y, self.balls[x].size, self.balls[x].size) elif x % 2 == 1: self.balls[x].x = self.balls[x].x + 35 * temp self.balls[x].counter = self.balls[x].x self.balls[x].ball.setGeometry(self.balls[x].x, self.balls[x].y, self.balls[x].size, self.balls[x].size) self.balls[x].ball.show() for player in self.players: player.PositionX = player.initialPositionX self.key_notifier.keys.clear() player.update(Qt.Key_Minus) player.bonusNoWeapon = False if player.weapon.isActive: player.weapon.isActive = False player.weapon.update() time.sleep(1) self.currentAmp = AMPLITUDE self.stopOnStart = True if not self.semiFinalEnd: self.getReadyLabel.setText('Get ready!') if not self.finishCup: self.timer.start(20, self) else: # gotov turnir, ispisi rezultate self.cupScores() self.getReadyLabel.show() self.getReadyLabel.raise_() self.semiFinalEnd = False def getPlayersFromSemifinal1(self, ind): points = self.deadPoints[ind].split('_')[0] playerName = self.deadPoints[ind].split('_')[1] semifinal1 = playerName + ' ' + points + '-' + self.deadPoints[ind+1].split('_')[0] + ' ' + \ self.deadPoints[ind+1].split('_')[1] return semifinal1 def cupScores(self): # stringovi za ispis rezultata polufinala semifinal1 = self.getPlayersFromSemifinal1(0) semifinal2 = self.getPlayersFromSemifinal1(2) f1points = self.deadPoints[4].split('_')[ 0] # finalist 1 points from final f1name = self.deadPoints[4].split('_')[1] # finalist 1 name f2points = self.deadPoints[5].split('_')[ 0] # finalist 2 points from final f2name = self.deadPoints[5].split('_')[1] # finalist 2 name # string za ispis rezultata finala final = f1name + ' ' + f1points + '-' + f2points + ' ' + f2name # ime pobjednika je u winner-u winner = '' if int(f1points) > int(f2points): winner = f1name elif int(f1points) == int( f2points ): # ako imaju isti broj poena u finalu neka pobijedi onaj koji je imao # vise u polufinalu, a ako opet imaju isto neka pobijedi domacin if int(self.finalist1points) > int( self.finalist2points ): # prvi finalista je imao vise u polufinalu winner = self.finalist1.upper() elif int(self.finalist1points) < int( self.finalist2points ): # drugi finalista je imao vise u polufinalu winner = self.finalist2.upper() else: # imali su isto poena i u polufinalu if int(f1name[-1]) < int(f2name[-1]): winner = f1name else: winner = f2name else: winner = f2name self.getReadyLabel.setText('SF 1: ' + semifinal1 + '\nSF 2: ' + semifinal2 + '\nFINAL: ' + final + '\nWINNER: ' + winner) def updateLives(self): sender = self.sender() livesPic = None lives = sender.lifes if sender.playerId == 'player1': livesPic = self.livesPic1 elif sender.playerId == 'player2': livesPic = self.livesPic2 queueCalcLives.put(str(lives)) res = str(queueResLives.get()) sender.lifes = int(res) self.updatePlayerPixMapLives(livesPic, sender.lifes, sender) if sender.lifes == 0: sender.isDead = True if sender.isDead: if sender.playerId == 'player1': self.deadPoints.append(self.player1PointsTag.text() + '_' + self.player1Tag.text()) elif sender.playerId == 'player2': self.deadPoints.append(self.player2PointsTag.text() + '_' + self.player2Tag.text()) sender.player.hide() self.players.remove(sender) if len(self.players) == 0: if self.finalGame: self.finishCup = True p1points = int(self.player1PointsTag.text()) p2points = int(self.player2PointsTag.text()) if len(self.cupPlayers) == 0: if p1points >= p2points: self.cupPlayers.append('player 1,' + str(p1points)) else: self.cupPlayers.append('player 2,' + str(p2points)) else: if p1points >= p2points: self.cupPlayers.append('player 3,' + str(p1points)) else: self.cupPlayers.append('player 4,' + str(p2points)) self.gameOver() def updatePoints(self, num): sender = self.sender() playerLabel = None previous = None if sender.playerId == 'player1': previous = self.player1PointsTag.text() playerLabel = self.player1PointsTag elif sender.playerId == 'player2': previous = self.player2PointsTag.text() playerLabel = self.player2PointsTag queueForCalcs.put(sender.playerId + ',' + str(previous) + ',' + str(num)) points = str(queueForResults.get()) playerLabel.setText(points) def gameOver(self): if not self.cupMode: self.getReadyLabel.setText("Game over") self.getReadyLabel.show() self.getReadyLabel.raise_() self.timer.stop() if self.cupMode: self.playerWon = self.cupPlayers[len(self.cupPlayers) - 1] self.getReadyLabel.setText( self.playerWon.split(',')[0].upper() + " WON!") self.cupModeLogic() def cupModeLogic(self): self.players = [Player(self, 'player1', 2), Player(self, 'player2', 2)] self.initStartingLevel() self.initCupPlayers() self.resetPlayerPixMapLives(self.players[0].lifes) if len(self.cupPlayers) == 1: # pocelo drugo polufinale self.getReadyLabel.setText( self.playerWon.split(',')[0].upper() + " WON!") self.player1Tag.setText('PLAYER 3') self.player2Tag.setText('PLAYER 4') else: # pocelo finale self.finalist1 = self.cupPlayers[0].split(',')[0] self.finalist1points = self.cupPlayers[0].split(',')[1] self.finalist2 = self.cupPlayers[1].split(',')[0] self.finalist2points = self.cupPlayers[1].split(',')[1] self.player1Tag.setText(self.finalist1.upper()) self.player2Tag.setText(self.finalist2.upper()) self.finalGame = True self.resetLevel() def initStartingLevel( self): # vrati poene na 0, loptu na inicijalnu, level na 1 self.player1PointsTag.setText('0') self.player2PointsTag.setText('0') self.semiFinalEnd = True self.currentLevel = 1 self.levelNumTag.setText(str(self.currentLevel)) self.previousBalls = 1 self.currentAmp = AMPLITUDE self.startingBallSize = MINBALLSIZE * 2 + 1 self.semiFinalEnd = True def initCupPlayers(self): self.players[0].weapon.weapon = self.weaponObj.weapon self.players[1].weapon.weapon = self.weaponObj2.weapon for p in self.players: p.player.setPixmap(p.PixMap) p.weapon.weapon.show() p.livesSignal.connect(self.updateLives) p.pointsSignal.connect(self.updatePoints) p.player.show()