def __init__(self, user_id, skill, position, parent=None): QWidget.__init__(self, parent=parent) self.skill = skill self.position = position self.user_id = user_id self.dbHandler = DatabaseHandler() self.staticData = self.dbHandler.getStaticSkillData( self.skill.skill_id) self.skillQueueItem = None # ToDo: If this skill is in this User's skillQueue activate updateTimer and update labels self.setBackgroundColor() self.createLayout() self.checkSkillQueue() if self.staticData is None: print("Completed Skill Item Widget got a None Skill Static Data") else: # Int Values of the Characters primary and secondary Attributes, used for calculation charAttributes = self.dbHandler.getCharacterAttributes( self.user_id) charPrimaryAtt = tools.getCharPrimaryValue(charAttributes, self.staticData) charSecondaryAtt = tools.getCharSecondaryValue( charAttributes, self.staticData) self.spPerMinute = tools.spPerMinute(charPrimaryAtt, charSecondaryAtt) # Fill the Labels with Data, and update it every second for the 1st Skill in the Queue self.updateLabels()
def __init__(self): super().__init__() self.dbHandler = DatabaseHandler() self.selected_character = None self.init_MainWindow() self.gui_queue = queue.Queue() self.startUpdateTimer()
def __init__(self, plan_id, parent=None): super(SkillPlannerWindow, self).__init__(parent) self.dbHandler = DatabaseHandler() self.plan = None self.loadPlan(plan_id) if self.plan is not None: self.user_id = self.plan.owner_id self.character_name = self.dbHandler.getCharacter(self.user_id).name self.set_main_window() self.initLayout()
def __init__(self, user, parent=None): QWidget.__init__(self, parent=parent) self.user = user self.dbHandler = DatabaseHandler() self.initiateLayout() self.createGroupList() #self.tabLayout.setContentsMargins(0,0,0,0) #self.tabLayout.setSpacing(0) self.setBackgroundColor()
def __init__(self, gui_queue, user_id, parent=None): super(NewPlanWindow, self).__init__(parent) self.parent = parent self.dbHandler = DatabaseHandler() self.gui_queue = gui_queue self.user_id = user_id if self.user_id is None: self.close() self.set_main_window() self.createLayout()
def __init__(self, parent=None): super(MainTabWidget, self).__init__(parent) self.parent = parent self.dbHandler = DatabaseHandler( ) # ToDo: Dangerous to start an own instance of dbHandler? self.initiateLayout() try: userList = self.dbHandler.getAllUser() # Overview Tab self.createOverviewTab(userList) self.createCharacterTabs(userList) except Exception as e: print("Exception in MainTabWidget init: " + str(e))
class KnownSkillsWidget(QWidget): def __init__(self, user, parent=None): QWidget.__init__(self, parent=parent) self.user = user self.dbHandler = DatabaseHandler() self.initiateLayout() self.createGroupList() #self.tabLayout.setContentsMargins(0,0,0,0) #self.tabLayout.setSpacing(0) self.setBackgroundColor() def initiateLayout(self): ''' box is a Layout needed to Stretch the scrollArea scrollArea is needed to add the Scrollbar scrollContent is needed to display the scrollable Items inside the scrollArea scrollLayout is needed to stretch the Items inside scrollContent ''' box = QVBoxLayout(self) box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) self.setLayout(box) self.scrollArea = QScrollArea(self) box.addWidget(self.scrollArea) self.scrollArea.setWidgetResizable(True) self.scrollContent = QWidget(self.scrollArea) self.scrollLayout = QVBoxLayout(self.scrollContent) self.scrollLayout.setContentsMargins(0, 0, 0, 0) self.scrollLayout.setSpacing(1) self.scrollLayout.setAlignment(QtCore.Qt.AlignTop) self.scrollContent.setLayout(self.scrollLayout) def createGroupList(self): groups = self.dbHandler.getStaticSkillGroups() if groups is not None: for grp in groups: if grp.name == "Fake Skills": continue grpWidget = SkillGroupWidget(self.user.id, grp) self.scrollLayout.addWidget(grpWidget) for skillWidget in grpWidget.getChildWidgets(): self.scrollLayout.addWidget(skillWidget) self.scrollArea.setWidget(self.scrollContent) # Never forget this!! def setBackgroundColor(self): self.setAutoFillBackground(True) # Background Color pal = QPalette() pal.setColor(self.backgroundRole(), QtCore.Qt.lightGray) self.setPalette(pal)
def __init__(self, parent=None): super(UpdateHandler, self).__init__() esiapp = App.create(config.ESI_SWAGGER_JSON) self.clientStartTime = datetime.datetime.now() # init the security object self.esisecurity = EsiSecurity( app=esiapp, redirect_uri=config.ESI_CALLBACK, client_id=config.ESI_CLIENT_ID, secret_key=config.ESI_SECRET_KEY, ) self.dbHandler = DatabaseHandler()
def __init__(self, user, parent=None): super(FunctionTabWidget, self).__init__(parent) self.user = user self.dbHandler = DatabaseHandler() self.setBackgroundColor() self.createCompletedSkills(user) self.createSkillQueue(user)
def __init__(self, character_id, gui_queue, parent=None): super(DeleteWindow, self).__init__(parent) self.dbHandler = DatabaseHandler() self.user = self.dbHandler.getUser(character_id) self.gui_queue = gui_queue self.set_main_window() self.centralwidget = QWidget(self) self.layout = QVBoxLayout(self.centralwidget) if self.user.id is None: self.layout.addWidget(QLabel("No User selected")) self.layout.addStretch(1) hBox = QHBoxLayout() hBox.addStretch(1) button = QPushButton("OK") button.clicked.connect(self.close) hBox.addWidget(button) self.layout.addLayout(hBox) else: self.layout.addWidget( QLabel("You are about to delete the Character: " + self.user.CharacterName)) self.layout.addWidget( QLabel("All Data will be lost! Are you sure?")) self.layout.addStretch(1) hBox = QHBoxLayout() deleteButton = QPushButton("Delete") deleteButton.clicked.connect(self.deleteUser) cancelButton = QPushButton("Cancel") cancelButton.clicked.connect(self.close) hBox.addStretch(1) hBox.addWidget(deleteButton) hBox.addWidget(cancelButton) self.layout.addLayout(hBox) self.setCentralWidget(self.centralwidget) self.show()
def __init__(self, user, parent=None): super(CharacterTabWidget, self).__init__(parent) self.parent = parent self.user = user self.dbHandler = DatabaseHandler() try: self.character = self.dbHandler.getCharacter(user.get_id()) self.attributes = self.dbHandler.getCharacterAttributes(user.get_id()) except Exception as e: print("Exception in CharacterTab: " + str(e)) if self.character is None: print("Character Tab has a None Character") else: self.layout = self.createLayout() self.layout.setSpacing(0) self.setLayout(self.layout) self.startUpdateTimer()
def __init__(self, queue): """ A note on login/logout events: the character login events happen whenever a characters is logged into via the SSO, regardless of mod. However, the mode should be send as an argument. Similarily, the Logout even happens whenever the character is deleted for either mode. The mode is sent as an argument, as well as the umber of characters still in the cache (if USER mode) """ # self.settings = CRESTSettings.getInstance() self.dbHandler = DatabaseHandler() # ToDo: Dangerous to start an own instance of dbHandler self.updateHandler = UpdateHandler() # ToDo: Dangerous to start an own instance of updateHandler self.gui_queue = queue # these will be set when needed self.httpd = None self.state = None self.ssoTimer = None self.login()
def __init__(self, gui_queue, parent=None): super(CharManagerWindow, self).__init__(parent) self.dbHandler = DatabaseHandler() self.gui_queue = gui_queue self.set_main_window() self.centralwidget = QWidget(self) self.layout = QVBoxLayout(self.centralwidget) self.layout.setContentsMargins(20, 20, 20, 20) self.layout.setSpacing(0) self.setCentralWidget(self.centralwidget) #Heading Label self.headingLabel = QLabel("Characters") self.headingLabel.setFont(QFont("Arial", 18, QFont.Bold)) self.layout.addWidget(self.headingLabel) self.layout.addSpacing(10) #Buttons hBox = QHBoxLayout() deleteButton = QPushButton("Delete") importButton = QPushButton("Import") exportButton = QPushButton("Export") deleteButton.clicked.connect(self.deleteTriggered) importButton.clicked.connect(self.importTriggered) exportButton.clicked.connect(self.exportTriggered) hBox.addWidget(deleteButton) hBox.addWidget(importButton) hBox.addWidget(exportButton) self.layout.addLayout(hBox) self.createTable() self.show()
class CharManagerWindow(QMainWindow): def __init__(self, gui_queue, parent=None): super(CharManagerWindow, self).__init__(parent) self.dbHandler = DatabaseHandler() self.gui_queue = gui_queue self.set_main_window() self.centralwidget = QWidget(self) self.layout = QVBoxLayout(self.centralwidget) self.layout.setContentsMargins(20, 20, 20, 20) self.layout.setSpacing(0) self.setCentralWidget(self.centralwidget) #Heading Label self.headingLabel = QLabel("Characters") self.headingLabel.setFont(QFont("Arial", 18, QFont.Bold)) self.layout.addWidget(self.headingLabel) self.layout.addSpacing(10) #Buttons hBox = QHBoxLayout() deleteButton = QPushButton("Delete") importButton = QPushButton("Import") exportButton = QPushButton("Export") deleteButton.clicked.connect(self.deleteTriggered) importButton.clicked.connect(self.importTriggered) exportButton.clicked.connect(self.exportTriggered) hBox.addWidget(deleteButton) hBox.addWidget(importButton) hBox.addWidget(exportButton) self.layout.addLayout(hBox) self.createTable() self.show() def createTable(self): self.characterTable = MyTable(0, 4) self.layout.addWidget(self.characterTable) self.setTableHeader() self.setTableContent() def setTableHeader(self): header = ("", "ID", "Name", "Authentication Status") self.characterTable.setHorizontalHeaderLabels(header) self.characterTable.verticalHeader().setVisible(False) # set each column width, for now ResizeToContents for x in range(0, len(header) - 1): self.characterTable.horizontalHeader().setSectionResizeMode( x, QHeaderView.ResizeToContents) self.characterTable.horizontalHeader().setStretchLastSection(True) self.characterTable.horizontalHeader().setDefaultAlignment( Qt.AlignLeft) def setTableContent(self): # self.characterTable.add_row(["test", "test2"]) # Ask the Database for a List of all saved Characters userList = self.dbHandler.getAllUser() # If there are any users saved get the needed elements for our table for user in userList: data = [] data.append(str(user.id)) data.append(str(user.CharacterID)) data.append(user.CharacterName) data.append(self.getUserAuthStatus(user)) self.characterTable.add_row(data) def set_main_window(self): # Standard Values for this Window standard_width = 544 standard_height = 480 minimum_width = 544 minimum_height = 300 """Sets the size policies of the main window""" self.resize(standard_width, standard_height) size_policy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(size_policy) self.setMinimumSize(QSize(minimum_width, minimum_height)) # main window icon self.setWindowIcon(QIcon(config.APP_ICON)) self.setWindowTitle(config.APP_NAME + " Character Manager") def getSelectedUser(self): #print(self.characterTable.selectedItems()) selection = self.characterTable.selectedItems() if selection is None or len(selection) == 0: return None else: return int(self.characterTable.selectedItems()[1].text()) def getUserAuthStatus(self, user): status = "" now = datetime.datetime.utcnow() if user.RefreshToken is None or user.AccessToken is None: status = "No Authentication" elif now < user.AccessTokenExpire: status = "Valid Access Token" elif now > user.AccessTokenExpire: status = "Valid Refresh Token" return status def deleteTriggered(self): character_id = self.getSelectedUser() #print(str(character_id)) self.deleteWindow = DeleteWindow(character_id, self.gui_queue, self) self.deleteWindow.show() def importTriggered(self): print("import") def exportTriggered(self): print("export")
class CharacterTabWidget(QWidget): def __init__(self, user, parent=None): super(CharacterTabWidget, self).__init__(parent) self.parent = parent self.user = user self.dbHandler = DatabaseHandler() try: self.character = self.dbHandler.getCharacter(user.get_id()) self.attributes = self.dbHandler.getCharacterAttributes(user.get_id()) except Exception as e: print("Exception in CharacterTab: " + str(e)) if self.character is None: print("Character Tab has a None Character") else: self.layout = self.createLayout() self.layout.setSpacing(0) self.setLayout(self.layout) self.startUpdateTimer() def getUser(self): # returns the user_id for this character_tab return self.user.id def startUpdateTimer(self): self.timer = QtCore.QTimer() self.timer.timeout.connect(self.updateLabels) self.timer.setSingleShot(False) self.timer.start(1000) def updateLabels(self): self.layout.update() def createLayout(self): vBox = QVBoxLayout() vBox.addLayout(self.horizontalTop()) vBox.addSpacing(5) vBox.addLayout(self.horizontalMiddle()) self.functionTab = FunctionTabWidget(self.user) vBox.addWidget(self.functionTab) #vBox.addStretch(1) return vBox def horizontalTop(self): # Character Image characterImage = QLabel() pixmap = QPixmap(self.getCharacterPortrait()) if pixmap is None: pixmap = QPixmap('portrait.png') characterImage.setPixmap(pixmap.scaled(150, 150)) characterImage.resize(150, 150) hBox = QHBoxLayout() hBox.setAlignment(QtCore.Qt.AlignTop) hBox.addWidget(characterImage) hBox.addSpacing(5) # Character General Information vBox = QVBoxLayout() #vBox.setAlignment(QtCore.Qt.AlignLeft) vBox.setAlignment(QtCore.Qt.AlignTop) vBox.setSpacing(0) vBox.setContentsMargins(0,0,0,0) nameLabel = QLabel(self.character.name) nameLabel.setFont(QFont("Arial", 14, QFont.Bold)) balanceLabel = QLabel("Balance: " + format(self.character.balance) + " ISK") corpLabel = QLabel("Corporation: ") allyLabel = QLabel("Alliance: ") secLabel = QLabel("Security Status: " + str(round(self.character.security_status, 2))) fatigueLabel = QLabel("Jump Fatigue: ") shipLabel = QLabel("Active Ship: ") locationLabel = QLabel("Located in: ") dockedLabel = QLabel("Docked at: ") vBox.addWidget(nameLabel) vBox.addWidget(balanceLabel) vBox.addWidget(corpLabel) vBox.addWidget(allyLabel) vBox.addWidget(secLabel) vBox.addWidget(fatigueLabel) vBox.addWidget(shipLabel) vBox.addWidget(locationLabel) vBox.addWidget(dockedLabel) #vBox.addStretch(1) hBox.addLayout(vBox) hBox.addStretch(1) #ToDo: Update Timer + Force update button (When will the next update occur) return hBox def horizontalMiddle(self): # Account Subscription Status vBox1 = QVBoxLayout() vBox1.setAlignment(QtCore.Qt.AlignTop) subscriptionStatusLabel = QLabel("Account Status: " + "Unknown") #subsriptionTimeLabel = QLabel("Remaining Time") subscriptionStatusLabel.setFixedWidth(155) # To indent the Middle hBox. size: pixmap + spacing vBox1.addWidget(subscriptionStatusLabel) #vBox1.addWidget(subsriptionTimeLabel) #vBox1.addStretch(1) # Character Stats vBox2 = QVBoxLayout() vBox2.setAlignment(QtCore.Qt.AlignTop) intelligenceLabel = QLabel("Intelligence: " + offset(8) + str(self.attributes.intelligence)) # 12 perceptionLabel = QLabel("Perception: " + offset(9) + str(self.attributes.perception)) # 10 charismaLabel = QLabel("Charisma: " + offset(11) + str(self.attributes.charisma)) # 8 willpowerLabel = QLabel("Willpower: " + offset(11) + str(self.attributes.willpower)) # 9 memoryLabel = QLabel("Memory: " + offset(13) + str(self.attributes.memory)) # 6 intelligenceLabel.setFixedWidth(120) vBox2.addWidget(intelligenceLabel) vBox2.addWidget(perceptionLabel) vBox2.addWidget(charismaLabel) vBox2.addWidget(willpowerLabel) vBox2.addWidget(memoryLabel) #vBox2.addStretch(1) #Clone Jump Status vBox3 = QVBoxLayout() vBox3.setAlignment(QtCore.Qt.AlignTop) bonusRemapLabel = QLabel("Bonus Remap: " + str(self.attributes.bonus_remaps)) neuralRemapLabel = QLabel("Next Neural Remap: " + remapTime(self.attributes.accrued_remap_cooldown_date)) cloneJumpLabel = QLabel("Next Clone Jump: ") vBox3.addWidget(bonusRemapLabel) vBox3.addWidget(neuralRemapLabel) vBox3.addWidget(cloneJumpLabel) #vBox3.addStretch(1) # Skills Statistics vBox4 = QVBoxLayout() vBox4.setAlignment(QtCore.Qt.AlignTop) # ToDo: Include the completed Skills in SkillQueue knownSkillsLabel = QLabel("Known Skills: " + str(self.dbHandler.getKnownSkillsCount(self.user))) skillsAt5Label = QLabel("Skills at Level V: " + str(self.dbHandler.getSkillsAtV(self.user))) totalSPLabel = QLabel("Total SP: " + format(self.character.total_sp)) if self.character.unallocated_sp is None: tmp = 0 else: tmp = self.character.unallocated_sp unallocatedSP = QLabel("Unallocated SP: " + format(tmp)) vBox4.addWidget(knownSkillsLabel) vBox4.addWidget(skillsAt5Label) vBox4.addWidget(totalSPLabel) vBox4.addWidget(unallocatedSP) #vBox4.addStretch(1) # Complete horizontal Middle hBox = QHBoxLayout() hBox.addLayout(vBox1) hBox.addLayout(vBox2) hBox.addSpacing(20) hBox.addLayout(vBox3) hBox.addStretch(1) hBox.addLayout(vBox4) return hBox def getCharacterPortrait(self): # Gets url to the character Portrait from db and sets the shown image to it # ToDo: Needs to be changed, so that the image is be save on the harddrive pixmap = QPixmap() try: portraitUrl = self.dbHandler.getCharacterPortrait(self.user.get_id()) if portraitUrl is not None: data = request.urlopen(portraitUrl.px256x256).read() pixmap.loadFromData(data) else: print("No portrait URL for " + self.user.CharacterName + " in the Database") except Exception as e: print("Exception in CharacterTabWidget.getCharacterPortrait: " + str(e)) return pixmap
class DeleteWindow(QMainWindow): def __init__(self, character_id, gui_queue, parent=None): super(DeleteWindow, self).__init__(parent) self.dbHandler = DatabaseHandler() self.user = self.dbHandler.getUser(character_id) self.gui_queue = gui_queue self.set_main_window() self.centralwidget = QWidget(self) self.layout = QVBoxLayout(self.centralwidget) if self.user.id is None: self.layout.addWidget(QLabel("No User selected")) self.layout.addStretch(1) hBox = QHBoxLayout() hBox.addStretch(1) button = QPushButton("OK") button.clicked.connect(self.close) hBox.addWidget(button) self.layout.addLayout(hBox) else: self.layout.addWidget( QLabel("You are about to delete the Character: " + self.user.CharacterName)) self.layout.addWidget( QLabel("All Data will be lost! Are you sure?")) self.layout.addStretch(1) hBox = QHBoxLayout() deleteButton = QPushButton("Delete") deleteButton.clicked.connect(self.deleteUser) cancelButton = QPushButton("Cancel") cancelButton.clicked.connect(self.close) hBox.addStretch(1) hBox.addWidget(deleteButton) hBox.addWidget(cancelButton) self.layout.addLayout(hBox) self.setCentralWidget(self.centralwidget) self.show() def deleteUser(self): self.dbHandler.deleteUser(self.user.id) self.gui_queue.put("Reprint MainWindow") self.close() def set_main_window(self): # Standard Values for this Window standard_width = 400 standard_height = 180 """Sets the size policies of the main window""" self.resize(standard_width, standard_height) size_policy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(size_policy) self.setMinimumSize(QSize(standard_width, standard_height)) self.setMaximumSize(QSize(standard_width, standard_height)) # main window icon self.setWindowIcon(QIcon(config.APP_ICON)) self.setWindowTitle("Delete Character")
class CharacterOverviewWidget(QPushButton): def __init__(self, user, parent=None): super(CharacterOverviewWidget, self).__init__(parent) self.setAutoFillBackground(True) # self.installEventFilter() self.user = user self.dbHandler = DatabaseHandler() try: self.character = self.dbHandler.getCharacter(user.get_id()) except Exception as e: print("Exception in Character Overview Widget: " + str(e)) if self.character is None: print("Character Overview has a None Character") # Background Color #pal = QPalette() #pal.setColor(self.backgroundRole(), QtCore.Qt.red) #self.setPalette(pal) # Character Image self.characterImage = QLabel() self.pixmap = QPixmap('portrait.png') self.characterImage.setPixmap(self.pixmap.scaled(120, 120)) self.characterImage.resize(120, 120) # Labels self.characterNameLabel = QLabel("Name") self.characterBalanceLabel = QLabel("Balance") self.characterSkillpointsLabel = QLabel("Skillpoints") self.characterSkillRemainingTimeLabel = QLabel("Skill Remaining Time") self.characterSkillNameLabel = QLabel("Skillname") self.characterSkillEndDateLabel = QLabel("Skill End Date") self.characterQueueRemainingTimeLabel = QLabel("Queue Remaining Time") self.setLabels() self.setCharacterPortrait() self.setLabelFonts() vbox = QVBoxLayout() vbox.setSpacing(1) vbox.setAlignment(QtCore.Qt.AlignTop) vbox.addWidget(self.characterNameLabel) vbox.addWidget(self.characterBalanceLabel) vbox.addWidget(self.characterSkillpointsLabel) vbox.addSpacing(10) vbox.addWidget(self.characterSkillRemainingTimeLabel) vbox.addSpacing(5) vbox.addWidget(self.characterSkillNameLabel) vbox.addWidget(self.characterSkillEndDateLabel) vbox.addWidget(self.characterQueueRemainingTimeLabel) hbox = QHBoxLayout() hbox.addWidget(self.characterImage) hbox.addSpacing(10) hbox.addLayout(vbox) hbox.addStretch(1) self.setLayout(hbox) self.set_size_policy() self.startUpdateTimer() def initLayout(self): print("") def setLabels(self): if self.character is not None: self.characterNameLabel.setText(self.character.name) self.characterBalanceLabel.setText( format(self.character.balance, ",") + " ISK") self.characterSkillpointsLabel.setText( format(self.character.total_sp, ",") + " SP") lastSkill = self.dbHandler.getSkillQueueLast(self.user.get_id()) #firstSkill = self.dbHandler.getSkillQueueFirst(self.user.get_id()) #dbThread = threading.Thread(target=self.dbHandler.getQueueFirst, args=(self.user.get_id(),)) #dbThread.daemon = True #dbThread.start() firstSkill = self.dbHandler.getQueueFirst(self.user.get_id()) #print(realFirst) if firstSkill is None: # ToDo: Check for different approach # Character has no SkillQueue #print(self.character.name + " has an empty SkillQueue") SkillRemainingTime = "" SkillName = "" SkillEndDate = "" QueueRemainingTime = "" elif firstSkill.finish_date is None: # Character has an inactive SkillQueue # print(self.character.name + " has an inactive SkillQueue") SkillRemainingTime = "Paused" SkillName = self.dbHandler.getStaticSkillData( firstSkill.skill_id).name + " " + str( firstSkill.finished_level) SkillEndDate = "" QueueRemainingTime = "" else: # Character has an active SkillQueue #print(self.character.name + " has an active SkillQueue") SkillRemainingTime = service.tools.getSkillRemainingTime( firstSkill) SkillName = self.dbHandler.getStaticSkillData( firstSkill.skill_id).name + " " + str( firstSkill.finished_level) SkillEndDate = service.tools.formatDateTime( firstSkill.finish_date + config.TIME_DIFFERENCE) QueueRemainingTime = "Queue ends in " + service.tools.getSkillRemainingTime( lastSkill) self.characterSkillRemainingTimeLabel.setText(SkillRemainingTime) self.characterSkillNameLabel.setText(SkillName) self.characterSkillEndDateLabel.setText(SkillEndDate) self.characterQueueRemainingTimeLabel.setText(QueueRemainingTime) def setCharacterPortrait(self): # Gets url to the character Portrait from db and sets the shown image to it # ToDo: Needs to be changed, so that the image is be save on the harddrive try: portraitUrl = self.dbHandler.getCharacterPortrait( self.user.get_id()) if portraitUrl is not None: data = request.urlopen(portraitUrl.px128x128).read() self.pixmap.loadFromData(data) self.characterImage.setPixmap(self.pixmap.scaled(120, 120)) else: print("No portrait URL for " + self.user.CharacterName + " in the Database") #data = request.urlopen("https://pixabay.com/de/pinguin-vogel-tier-tierwelt-k%C3%A4lte-42936/").read() except Exception as e: print("Exception in CharacterOverview Widget: " + str(e)) def eventFilter(self, object, event): if event.type() == QtCore.QEvent.HoverMove: print("Mouseover") def set_size_policy(self): self.setMaximumSize(350, 150) self.setMinimumSize(350, 150) def setLabelFonts(self): self.characterNameLabel.setFont(QFont("Arial", 14, QFont.Bold)) self.characterBalanceLabel.setFont(QFont("Arial", 12, QFont.Bold)) self.characterSkillpointsLabel.setFont(QFont("Arial", 10)) self.characterSkillRemainingTimeLabel.setFont(QFont("Arial", 10)) def startUpdateTimer(self): self.timer = QtCore.QTimer() self.timer.timeout.connect(self.setLabels) self.timer.setSingleShot(False) self.timer.start(1000) def updateLabel(self): self.characterBalanceLabel.update() self.characterSkillpointsLabel.update() self.characterSkillRemainingTimeLabel.update() self.characterSkillNameLabel.update() self.characterSkillEndDateLabel.update() self.characterQueueRemainingTimeLabel.update() def enterEvent(self, QEvent): # here the code for mouse hover pass def leaveEvent(self, QEvent): # here the code for mouse leave pass
class Esi(): def __init__(self, queue): """ A note on login/logout events: the character login events happen whenever a characters is logged into via the SSO, regardless of mod. However, the mode should be send as an argument. Similarily, the Logout even happens whenever the character is deleted for either mode. The mode is sent as an argument, as well as the umber of characters still in the cache (if USER mode) """ # self.settings = CRESTSettings.getInstance() self.dbHandler = DatabaseHandler() # ToDo: Dangerous to start an own instance of dbHandler self.updateHandler = UpdateHandler() # ToDo: Dangerous to start an own instance of updateHandler self.gui_queue = queue # these will be set when needed self.httpd = None self.state = None self.ssoTimer = None self.login() def login(self): """ this redirects the user to the EVE SSO login """ # token = generate_token() # requests.session['token'] = token self.startServer() return webbrowser.open(esisecurity.get_auth_uri(scopes=config.ESI_SCOPES)) def logout(self): """Logout of implicit character""" print("Character logout") self.implicitCharacter = None def stopServer(self): print("Stopping Server") self.httpd.stop() self.httpd = None def startServer(self): print("Starting server") if self.httpd: self.stopServer() time.sleep(1) # we need this to ensure that the previous get_request finishes, and then the socket will close self.httpd = StoppableHTTPServer((config.HOST, config.PORT), AuthHandler) self.serverThread = threading.Thread(target=self.httpd.serve, args=(self.callback,)) self.serverThread.name = "ESIServer" self.serverThread.daemon = True self.serverThread.start() return def callback(self, parts): """ This is where the user comes after he logged in SSO """ # get the code from the login process code = str(parts['code'][0]) # token = str(parts['code'][0]) # compare the state with the saved token for CSRF check # now we try to get tokens try: auth_response = esisecurity.auth(code) except APIException as e: return print('Login EVE Online SSO failed: %s' % e) # we get the character informations cdata = esisecurity.verify() # if the user is already authed, we log him out #if current_user.is_authenticated: # logout_user() # now we check in database, if the user exists # actually we'd have to also check with character_owner_hash, to be # sure the owner is still the same, but that's an example only... user = User() user.CharacterID = cdata['CharacterID'] user.CharacterOwnerHash = cdata['CharacterOwnerHash'] user.CharacterName = cdata['CharacterName'] user.update_token(auth_response) ''' try: user.id = self.dbHandler.saveUser(user) except Exception as e: print("Exception in Esi.callback1: " + str(e)) try: if user.id is not None: # We don't want DB Entrys without owner self.updateHandler.updateUser(user) self.writeToQueue() except Exception as e: print("Exception in Esi.callback2: " + str(e)) ''' try: u = self.dbHandler.saveUser(user) user = self.dbHandler.getUser(u.CharacterID) if user is not None and user.id is not None: print("") self.updateHandler.updateUser(user) self.writeToQueue() except Exception as e: print("Exception in Esi.callback: " + str(e)) def writeToQueue(self): self.gui_queue.put("Reprint MainWindow")
def __init__(self, user, parent=None): super(CharacterOverviewWidget, self).__init__(parent) self.setAutoFillBackground(True) # self.installEventFilter() self.user = user self.dbHandler = DatabaseHandler() try: self.character = self.dbHandler.getCharacter(user.get_id()) except Exception as e: print("Exception in Character Overview Widget: " + str(e)) if self.character is None: print("Character Overview has a None Character") # Background Color #pal = QPalette() #pal.setColor(self.backgroundRole(), QtCore.Qt.red) #self.setPalette(pal) # Character Image self.characterImage = QLabel() self.pixmap = QPixmap('portrait.png') self.characterImage.setPixmap(self.pixmap.scaled(120, 120)) self.characterImage.resize(120, 120) # Labels self.characterNameLabel = QLabel("Name") self.characterBalanceLabel = QLabel("Balance") self.characterSkillpointsLabel = QLabel("Skillpoints") self.characterSkillRemainingTimeLabel = QLabel("Skill Remaining Time") self.characterSkillNameLabel = QLabel("Skillname") self.characterSkillEndDateLabel = QLabel("Skill End Date") self.characterQueueRemainingTimeLabel = QLabel("Queue Remaining Time") self.setLabels() self.setCharacterPortrait() self.setLabelFonts() vbox = QVBoxLayout() vbox.setSpacing(1) vbox.setAlignment(QtCore.Qt.AlignTop) vbox.addWidget(self.characterNameLabel) vbox.addWidget(self.characterBalanceLabel) vbox.addWidget(self.characterSkillpointsLabel) vbox.addSpacing(10) vbox.addWidget(self.characterSkillRemainingTimeLabel) vbox.addSpacing(5) vbox.addWidget(self.characterSkillNameLabel) vbox.addWidget(self.characterSkillEndDateLabel) vbox.addWidget(self.characterQueueRemainingTimeLabel) hbox = QHBoxLayout() hbox.addWidget(self.characterImage) hbox.addSpacing(10) hbox.addLayout(vbox) hbox.addStretch(1) self.setLayout(hbox) self.set_size_policy() self.startUpdateTimer()
class MainTabWidget(QTabWidget): def __init__(self, parent=None): super(MainTabWidget, self).__init__(parent) self.parent = parent self.dbHandler = DatabaseHandler( ) # ToDo: Dangerous to start an own instance of dbHandler? self.initiateLayout() try: userList = self.dbHandler.getAllUser() # Overview Tab self.createOverviewTab(userList) self.createCharacterTabs(userList) except Exception as e: print("Exception in MainTabWidget init: " + str(e)) def initiateLayout(self): ''' box is a Layout needed to Stretch the scrollArea scrollArea is needed to add the Scrollbar scrollContent is needed to display the scrollable Items inside the scrollArea scrollLayout is needed to stretch the Items inside scrollContent ''' box = QVBoxLayout(self) box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) self.setLayout(box) self.scrollArea = QScrollArea(self) box.addWidget(self.scrollArea) self.scrollArea.setWidgetResizable(True) self.scrollContent = QWidget(self.scrollArea) self.scrollLayout = QGridLayout(self.scrollContent) self.scrollLayout.setContentsMargins(2, 2, 2, 2) self.scrollLayout.setSpacing(4) #self.scrollLayout.setAlignment(QtCore.Qt.AlignTop) self.scrollContent.setLayout(self.scrollLayout) def createOverviewTab(self, userList): self.overviewTab = QWidget() x = 0 y = 0 self.widgetList = [] for user in userList: newWidget = CharacterOverviewWidget(user) self.widgetList.append(newWidget) self.scrollLayout.addWidget(newWidget, x, y) # ToDo: Find a proper Way to print these widgets relative to mainwindow size # after adding a widget we need to prepare the next coordinates if (y == 0): y = y + 1 elif (y == 1): x = x + 1 y = y - 1 elif (y > 1): y = 0 self.addTab(self.scrollArea, "Overview") self.scrollArea.setWidget(self.scrollContent) # Never forget this! #self.overviewTab.setLayout(grid) def repaintOverviewTab(self): self.createOverviewTab() def getSelection(self): # Returns the selected User, if any if self.currentWidget() == self.overviewTab: return None elif self.currentWidget() == self.scrollArea: return None else: return self.currentWidget().getUser() def createCharacterTabs(self, userList): for user in userList: characterTab = CharacterTabWidget(user) self.addTab(characterTab, user.CharacterName)
class SkillPlannerWindow(QMainWindow): def __init__(self, plan_id, parent=None): super(SkillPlannerWindow, self).__init__(parent) self.dbHandler = DatabaseHandler() self.plan = None self.loadPlan(plan_id) if self.plan is not None: self.user_id = self.plan.owner_id self.character_name = self.dbHandler.getCharacter(self.user_id).name self.set_main_window() self.initLayout() def set_main_window(self): # Standard Values for this Window standard_width = 860 standard_height = 600 minimum_width = 544 minimum_height = 300 """Sets the size policies of the main window""" self.resize(standard_width, standard_height) size_policy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(size_policy) self.setMinimumSize(QSize(minimum_width, minimum_height)) # self.setMaximumSize(QSize(standard_width, standard_height)) # main window icon self.setWindowIcon(QIcon(config.APP_ICON)) #self.setWindowTitle(self.character_name + self.plan.name + config.APP_NAME + " Skill Planner") # ToDo: Add plan owner and plan name def initLayout(self): self.centralwidget = QWidget(self) self.layout = QVBoxLayout(self.centralwidget) self.layout.setContentsMargins(20, 20, 20, 20) self.layout.setSpacing(5) self.setCentralWidget(self.centralwidget) self.plansCombo = QComboBox(self) self.plansCombo.addItem("Select Plan") self.plansCombo.addItem("New Plan") self.plansCombo.addItem("Create Plan from Skill Queue") self.plansCombo.activated.connect(self.handlePlansCombo) self.fillPlansCombo() self.layout.addLayout(self.firstLineOptions()) def firstLineOptions(self): ''' First Line Options: Select Plan Export Plan to Delete Plan Print Plan (drucken) Copy to clipboard Implant calculator atrribute optimizer :return: ''' hbox = QHBoxLayout() hbox.addWidget(self.plansCombo) hbox.addStretch(1) return hbox def skillPlannerTabs(self): print("") def handlePlansCombo(self, index): itemData = self.plansCombo.itemData(index) itemText = self.plansCombo.itemText(index) if itemData is not None: print(self.plansCombo.itemData(index)) def fillPlansCombo(self): plan_list = self.dbHandler.getCharacterPlans(self.user_id) for plan in plan_list: self.plansCombo.addItem(plan.name, plan.id) self.layout.update() def loadPlan(self, plan_id): if plan_id is not None: self.plan = self.dbHandler.getPlan(plan_id)
class NewPlanWindow(QMainWindow): def __init__(self, gui_queue, user_id, parent=None): super(NewPlanWindow, self).__init__(parent) self.parent = parent self.dbHandler = DatabaseHandler() self.gui_queue = gui_queue self.user_id = user_id if self.user_id is None: self.close() self.set_main_window() self.createLayout() def createLayout(self): self.centralwidget = QWidget(self) self.layout = QVBoxLayout(self.centralwidget) self.layout.setContentsMargins(20, 20, 20, 20) self.layout.setSpacing(5) self.setCentralWidget(self.centralwidget) self.layout.addWidget(QLabel("Enter a name for this plan:")) self.name_dialog = QLineEdit(self) self.name_dialog.textChanged.connect(self.nameChanged) self.description_dialog = QTextEdit(self) self.layout.addWidget(self.name_dialog) self.layout.addSpacing(2) self.layout.addWidget( QLabel("Enter a description for this plan (optional):")) self.layout.addWidget(self.description_dialog) #self.layout.addStretch(1) self.ok_button = QPushButton("OK") self.ok_button.setDisabled(True) self.ok_button.clicked.connect(self.addPlan) self.cancel_button = QPushButton("Cancel") self.cancel_button.clicked.connect(self.close) hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(self.ok_button) hbox.addWidget(self.cancel_button) self.layout.addLayout(hbox) #self.setLayout(self.layout) def nameChanged(self, text): if self.name_dialog.text() == "": self.ok_button.setDisabled(True) else: self.ok_button.setDisabled(False) def addPlan(self): name = self.name_dialog.text() description = self.description_dialog.toPlainText() newPlan = SkillPlan().create(name, description, self.user_id) self.dbHandler.addPlan(newPlan) self.openSkillPlanner(newPlan.id) self.close() def openSkillPlanner(self, plan_id): skillPlanner = SkillPlannerWindow(plan_id) skillPlanner.show() def set_main_window(self): # Standard Values for this Window standard_width = 300 standard_height = 200 """Sets the size policies of the main window""" self.resize(standard_width, standard_height) size_policy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(size_policy) self.setMinimumSize(QSize(standard_width, standard_height)) self.setMaximumSize(QSize(standard_width, standard_height)) # main window icon self.setWindowIcon(QIcon(config.APP_ICON)) self.setWindowTitle(" New Plan")
class UpdateHandler(): def __init__(self, parent=None): super(UpdateHandler, self).__init__() esiapp = App.create(config.ESI_SWAGGER_JSON) self.clientStartTime = datetime.datetime.now() # init the security object self.esisecurity = EsiSecurity( app=esiapp, redirect_uri=config.ESI_CALLBACK, client_id=config.ESI_CLIENT_ID, secret_key=config.ESI_SECRET_KEY, ) self.dbHandler = DatabaseHandler() #self.dbHandler.initSession() def calculateTimeDifference(self): config.TIME_DIFFERENCE = 0 def setApiDetails(self, api, user): api.api_client.set_default_header(config.ESI_USER_AGENT, config.ESI_AGENT_DESCRIPTION) api.api_client.host = config.ESI_ESI_URL api.api_client.configuration.access_token = user.AccessToken return api def updateAll(self, gui_queue): """ Method to update Data for all stored Users. """ self.updateServerStatus() # If we have'nt yet, we get the Static Informations for Skills/Ships etc from Eve # ToDo: Get Ship Dump and implement a real update function if self.dbHandler.staticDumpPresent() == False: print("No Skill Dump present ... ") #dumpThread = threading.Thread(target=self.getSkilldump) #dumpThread.daemon = True #dumpThread.start() try: self.userList = self.dbHandler.getAllUser() for user in self.userList: self.updateUser(user) except Exception as e: print("Exception in updateHandler.updateAll: %s\n" % e) finally: gui_queue.put("Reprint MainWindow") self.updateLoop() def updateLoop(self): while True: self.frequentlyUpdate() time.sleep(1) def frequentlyUpdate(self): # Get a new Server Status every Minute now = datetime.datetime.now() clientRunTime = int((now - self.clientStartTime).total_seconds()) if (clientRunTime % 60) == 0: # minutely Update # Server Status self.updateServerStatus() if (clientRunTime % 300) == 0: # 5 minutely Update print("5 Min Update now") # Jump Fatigue # Balance # Notifications for user in self.userList: self.refreshUserAuth(user) self.updateBalance(user) self.updateCharacterNotifications(user) if (clientRunTime % 900) == 0: # 15 minutely Update print("15 Min Update now") if (clientRunTime % 1800) == 0: # 30 minutely Update print("30 Min Update now") # Skill Queue # Completed Skills # Attributes for user in self.userList: self.refreshUserAuth(user) self.updateSkillQueue(user) self.updateCompletedSkills(user) self.updateCharacterAttributes(user) if (clientRunTime % 3600) == 0: # 60 minutely Update print("60 Min Update now") # Skill Points # Corp History def getSkilldump(self): #skilldump.SkillDump() skilldump.ShipDump() def updateUser(self, user): """ Method to update Data for one stored User. 1. refresh the Authentication 2. ask EvE API for new Data """ #if self.getServerStatus() is not None: self.refreshUserAuth(user) self.updateCharacter(user) self.updateBalance(user) self.updatePortrait(user) self.updateSkillQueue(user) self.updateCompletedSkills(user) self.updateCharacterAttributes(user) self.updateCharacterNotifications(user) #self.getStructureDetails(user) def refreshUserAuth(self, user): """ Get a new Access Token based on Refresh Token. Feeding the esipy with Datas from the Database and ask if AcessToken is expired. If so, we refresh the Auth, store the New Tokens in user Class and write them to the Database :param user: Stored User Class from Database """ try: self.esisecurity.set_token(user.AccessToken, user.RefreshToken, user.AccessTokenExpire) if self.esisecurity.is_token_expired() is True: user.update_token(self.esisecurity.refresh()) self.dbHandler.saveUser(user) else: print("Access Token valid, nothing to do") except Exception as e: print("Exception in updateHandler.refreshUserAuth: %s\n" % e) def updateServerStatus(self): api = swagger_client.StatusApi() api.api_client.set_default_header(config.ESI_USER_AGENT, config.ESI_AGENT_DESCRIPTION) api.api_client.host = config.ESI_ESI_URL status = None try: response = api.get_status() now = datetime.datetime.utcnow() status = ServerStatus().setStatus(response, now) # ToDo: Handle 502 Exception differently as is only means that server is offline except Exception as e: print(datetime.datetime.now().strftime("%H:%M:%S")) print("Exception in updateHandler.getServerStatus: %s\n" % e) status = ServerStatus().setStatus(None, None) finally: self.dbHandler.saveServerStatus(status) def updateCharacter(self, user): api = swagger_client.CharacterApi() api = self.setApiDetails(api, user) try: response = api.get_characters_character_id(user.CharacterID) char = Character().setCharacter(response, user.get_id()) # create an databaseTables Object of Character self.dbHandler.saveCharacter(char) #self.updateAllianceName(char) #self.updateCorporationName(char) except Exception as e: print("Exception in updateHandler.updateCharacter(): %s\n" % e) def updateBalance(self, user): api = swagger_client.WalletApi() api = self.setApiDetails(api, user) try: response = api.get_characters_character_id_wallet(user.CharacterID) self.dbHandler.saveCharacterBalance(response, user.get_id()) except Exception as e: print("Exception in updateHandler.updateBalance(): %s\n" % e) def updatePortrait(self, user): api = swagger_client.CharacterApi() api = self.setApiDetails(api, user) try: response = api.get_characters_character_id_portrait(user.CharacterID) portrait = CharacterPortrait().setCharacterPortrait(response, user.get_id()) self.dbHandler.saveCharacterPortrait(portrait) except Exception as e: print("Exception in updateHandler.updatePortrait(): %s\n" % e) def downloadPortraits(self, user): #ToDo: finalize this netwManager = QNetworkAccessManager() url = QUrl() def updateSkillQueue(self, user): api = swagger_client.SkillsApi() api = self.setApiDetails(api, user) try: response = api.get_characters_character_id_skillqueue(user.CharacterID) if len(response) > 0: # Create a SkillQueue Object, containing list of Skills and the owner ID skillQueue = SkillQueue().createSkillQueue(response, user.get_id()) # Saving the Skill Queue self.dbHandler.saveSkillQueue(skillQueue) else: print(user.CharacterName + " has an Empty Skillqueue") except Exception as e: print("Exception in updateHandler.updateSkillqueue(): %s\n" % e) def updateCompletedSkills(self, user): """ Update the completed Skills Since we get a List of completed Skills and the Skillpoint values, we need to split where we save them The Skills go in the CompletedSkillItems DB. The Skillpoint values will be added to the character Table :param user: Stored User Class from Database """ api = swagger_client.SkillsApi() api = self.setApiDetails(api, user) try: response = api.get_characters_character_id_skills(user.CharacterID) skillList = CompletedSkillList().createCSL(response, user.get_id()) self.dbHandler.saveKnownSkills(skillList) self.dbHandler.saveCharacterSP(user.get_id(), response.total_sp, response.unallocated_sp) except Exception as e: print("Exception in updateHandler.updateCompletedSkills: %s\n" % e) def updateCharacterAttributes(self, user): api = swagger_client.SkillsApi() api = self.setApiDetails(api, user) try: response = api.get_characters_character_id_attributes(user.CharacterID) charAttributes = CharacterAttributes().create(response, user.get_id()) self.dbHandler.saveCharacterAttributes(charAttributes) except Exception as e: print("Exception in updateHandler.updateCharacterAttributes(): %s\n" % e) def updateAllianceName(self, char): api = swagger_client.AllianceApi() api = self.setApiDetails(api) try: response = api.get_alliances_alliance_id(char.alliance_id) print(response) except Exception as e: print("Exception in UpdateHandler.updateAllianceName: " + str(e)) def updateCorporationName(self, char): api = swagger_client.CorporationApi() api = self.setApiDetails(api) try: response = api.get_alliances_alliance_id(char.corporation_id) print(response) except Exception as e: print("Exception in UpdateHandler.updateCorporationName: " + str(e)) def updateCharacterNotifications(self, user): api = swagger_client.CharacterApi() api = self.setApiDetails(api, user) try: response = api.get_characters_character_id_notifications(user.CharacterID) notifications = [] for item in response: new = CharacterNotifications().create(item, user.id) notifications.append(new) self.dbHandler.saveCharacterNotification(new) except Exception as e: print("Exception in updateHandler.getCharacterNotifications: %s\n" % e) def getStructureDetails(self, user): # Test Function for getting Corp Structures, specially remaining structure fuel/time api = swagger_client.CorporationApi() api = self.setApiDetails(api, user) try: response = api.get_corporations_corporation_id_structures(573400667) print(response) print(response.data) except Exception as e: print("Exception in updateHandler.getStructureDetails: %s\n" % e)
class SkillQueueWidget(QWidget): def __init__(self, user, parent=None): QWidget.__init__(self, parent=parent) self.user = user self.dbHandler = DatabaseHandler() self.initiateLayout() self.createSkillQueue() #self.tabLayout.setContentsMargins(0,0,0,0) #self.tabLayout.setSpacing(0) self.setBackgroundColor() def initiateLayout(self): ''' box is a Layout needed to Stretch the scrollArea scrollArea is needed to add the Scrollbar scrollContent is needed to display the scrollable Items inside the scrollArea scrollLayout is needed to stretch the Items inside scrollContent ''' box = QVBoxLayout(self) box.setContentsMargins(0,0,0,0) box.setSpacing(0) self.setLayout(box) self.scrollArea = QScrollArea(self) box.addWidget(self.scrollArea) self.scrollArea.setWidgetResizable(True) self.scrollContent = QWidget(self.scrollArea) self.scrollLayout = QVBoxLayout(self.scrollContent) self.scrollLayout.setContentsMargins(2,2,2,2) self.scrollLayout.setSpacing(4) self.scrollLayout.setAlignment(QtCore.Qt.AlignTop) self.scrollContent.setLayout(self.scrollLayout) def setBackgroundColor(self): self.setAutoFillBackground(True) # Background Color pal = QPalette() pal.setColor(self.backgroundRole(), QtCore.Qt.white) self.setPalette(pal) def createSkillQueue(self): skillQueue = self.dbHandler.getSkillQueue(self.user.get_id()) now = datetime.datetime.utcnow() # ToDo: Optimize with pythontricks if skillQueue is not None: queue_position = 1 for skill in skillQueue: if (skill.finish_date is None) or (skill.finish_date > now): # Skip completed Skills widget = QueueItem(self.user.id, skill, queue_position) self.scrollLayout.addWidget(widget) queue_position += 1 self.scrollArea.setWidget(self.scrollContent) # Never forget this!
class QueueItem(QWidget): def __init__(self, user_id, skill, queue_position, parent=None): QWidget.__init__(self, parent=parent) self.skill = skill self.user_id = user_id self.queue_position = queue_position self.setBackgroundColor() self.dbHandler = DatabaseHandler() self.staticData = self.dbHandler.getStaticSkillData(self.skill.skill_id) self.createLayout() if self.staticData is None: print("Queue Item Widget got a None Skill Static Data") else: # Int Values of the Characters primary and secondary Attributes, used for calculation charAttributes = self.dbHandler.getCharacterAttributes(self.user_id) charPrimaryAtt = tools.getCharPrimaryValue(charAttributes, self.staticData) charSecondaryAtt = tools.getCharSecondaryValue(charAttributes, self.staticData) self.spPerMinute = tools.spPerMinute(charPrimaryAtt, charSecondaryAtt) # Fill the Labels with Data, and update it every second for the 1st Skill in the Queue self.updateLabels() if self.queue_position == 1: self.startUpdateTimer() def createLayout(self): self.layout = QVBoxLayout() self.layout.addLayout(self.firstLine()) self.layout.addLayout(self.secondLine()) self.setLayout(self.layout) self.set_size_policy() def firstLine(self): hbox = QHBoxLayout() self.titleLabel = QLabel("x. Skill Name") self.rankLabel = QLabel("Rank x") self.levelLabel = QLabel("Level X") self.titleLabel.setFont(QFont("Arial", 8, QFont.Bold)) hbox.addWidget(self.titleLabel) hbox.addSpacing(5) hbox.addWidget(self.rankLabel) hbox.addStretch(1) hbox.addWidget(self.levelLabel) return hbox def secondLine(self): hbox = QHBoxLayout() self.spLabel = QLabel("SP: ") self.spPerHourLabel = QLabel("SP/Hour: ") self.trainingTimeLabel = QLabel("Training Time: ") self.progressLabel = QLabel(" % Done") hbox.addWidget(self.spLabel) hbox.addSpacing(5) hbox.addWidget(self.spPerHourLabel) hbox.addSpacing(5) hbox.addWidget(self.trainingTimeLabel) hbox.addStretch(1) hbox.addWidget(self.progressLabel) return hbox def updateLabels(self): #First Line ToDo: Optimize pos = str(self.queue_position) name = self.staticData.name self.titleLabel.setText(pos + ". " + name) self.rankLabel.setText("(Rank " + str(self.staticData.rank) + ")") self.levelLabel.setText("Level " + str(self.skill.finished_level)) if self.skill.finish_date is not None: self.trainingTimeLabel.setText("Training Time: " + tools.getSkillTrainingTime(self.skill)) # - # Second Line skillTrainingProgress = tools.getSkillTrainingProgress(self.skill, self.spPerMinute) # + self.spLabel.setText("SP: " + format(self.skill.level_start_sp + skillTrainingProgress) + "/" # + + format(self.skill.level_end_sp)) self.spPerHourLabel.setText("SP/Hour: " + str(int(60*self.spPerMinute))) # - self.progressLabel.setText(str(round(skillTrainingProgress / (self.skill.level_end_sp - self.skill.level_start_sp) * 100, 1)) + " % Done") # + self.layout.update() def setBackgroundColor(self): self.setAutoFillBackground(True) # Background Color pal = QPalette() mod = self.skill.queue_position % 2 if mod == 0: pal.setColor(self.backgroundRole(), QtCore.Qt.lightGray) else: pal.setColor(self.backgroundRole(), QtCore.Qt.white) self.setPalette(pal) def set_size_policy(self): self.layout.setContentsMargins(1, 1, 1, 1) self.layout.setSpacing(1) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) def startUpdateTimer(self): self.timer = QtCore.QTimer() self.timer.timeout.connect(self.updateLabels) self.timer.setSingleShot(False) self.timer.start(1000)
class KnownSkillsItem(QWidget): def __init__(self, user_id, skill, position, parent=None): QWidget.__init__(self, parent=parent) self.skill = skill self.position = position self.user_id = user_id self.dbHandler = DatabaseHandler() self.staticData = self.dbHandler.getStaticSkillData( self.skill.skill_id) self.skillQueueItem = None # ToDo: If this skill is in this User's skillQueue activate updateTimer and update labels self.setBackgroundColor() self.createLayout() self.checkSkillQueue() if self.staticData is None: print("Completed Skill Item Widget got a None Skill Static Data") else: # Int Values of the Characters primary and secondary Attributes, used for calculation charAttributes = self.dbHandler.getCharacterAttributes( self.user_id) charPrimaryAtt = tools.getCharPrimaryValue(charAttributes, self.staticData) charSecondaryAtt = tools.getCharSecondaryValue( charAttributes, self.staticData) self.spPerMinute = tools.spPerMinute(charPrimaryAtt, charSecondaryAtt) # Fill the Labels with Data, and update it every second for the 1st Skill in the Queue self.updateLabels() def createLayout(self): self.layout = QVBoxLayout() self.layout.addLayout(self.firstLine()) self.layout.addLayout(self.secondLine()) self.setLayout(self.layout) self.set_size_policy() def firstLine(self): hbox = QHBoxLayout() self.titleLabel = QLabel("x. Skill Name") self.rankLabel = QLabel("Rank x") self.levelLabel = QLabel("Level X") self.titleLabel.setFont(QFont("Arial", 8, QFont.Bold)) hbox.addWidget(self.titleLabel) hbox.addSpacing(5) hbox.addWidget(self.rankLabel) hbox.addStretch(1) hbox.addWidget(self.levelLabel) return hbox def secondLine(self): hbox = QHBoxLayout() self.spLabel = QLabel("SP: ") self.progressLabel = QLabel(" % Done") hbox.addWidget(self.spLabel) hbox.addStretch(1) hbox.addWidget(self.progressLabel) return hbox def updateLabels(self): #First Line ToDo: Optimize #pos = str(self.queue_position) name = self.staticData.name self.titleLabel.setText(name) self.rankLabel.setText("(Rank " + str(self.staticData.rank) + ")") self.levelLabel.setText("Level " + str(self.skill.trained_skill_level)) # Second Line if self.skill.trained_skill_level == 5: modifier = 4 else: modifier = self.skill.trained_skill_level # Eve training multiplier formula: SP = 250 * multiplier * sqrt(32)^(level-1) skill_level_end_sp = 250 * self.staticData.rank * math.sqrt( 32)**modifier if self.skillQueueItem is None: skillTrainingProgress = 0 else: skillTrainingProgress = tools.getSkillTrainingProgress( self.skillQueueItem, self.spPerMinute) self.spLabel.setText("SP: " + format(self.skill.skillpoints_in_skill + skillTrainingProgress) + "/" + format(round(skill_level_end_sp))) self.progressLabel.setText( str( round( skillTrainingProgress / (skill_level_end_sp - self.skill.skillpoints_in_skill) * 100, 1)) + " % Done") # + self.layout.update() def checkSkillQueue(self): # ToDO: Might need improvement check if skill is already completed # we want to know if this skill is in this users skill queue self.skillQueueItem = dbHandler.getSkillQueueItem( self.user_id, self.skill.skill_id) if self.skillQueueItem is not None: self.startUpdateTimer() def setBackgroundColor(self): self.setAutoFillBackground(True) # Background Color pal = QPalette() mod = self.position % 2 if mod == 0: pal.setColor(self.backgroundRole(), QtCore.Qt.lightGray) else: pal.setColor(self.backgroundRole(), QtCore.Qt.white) self.setPalette(pal) def set_size_policy(self): self.layout.setContentsMargins(1, 1, 1, 1) self.layout.setSpacing(1) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) def startUpdateTimer(self): self.timer = QtCore.QTimer() self.timer.timeout.connect(self.updateLabels) self.timer.setSingleShot(False) self.timer.start(1000)
class GeneralMainDesign(QMainWindow): """General design of the main window""" def __init__(self): super().__init__() self.dbHandler = DatabaseHandler() self.selected_character = None self.init_MainWindow() self.gui_queue = queue.Queue() self.startUpdateTimer() def init_MainWindow(self): self.set_main_window() self.setBackgroundColor() self.createLayout() self.setWindowIcon(QIcon(config.APP_ICON)) # query frame # self.frame_query = QueryFrame() # self._set_frame() # layout.addWidget(self.frame_query) # status bar self.statusbar = QStatusBar(self) self.set_status_bar() self.setStatusBar(self.statusbar) # MainMenuBar self.menubar = self.menuBar() self.set_main_menubar() # Tab Widget self.createTabwidget() #self.resizeEvent. self.show() # self.progress_bar = ProgressBar(self) # self.statusbar.addPermanentWidget(self.progress_bar) # self.progress_bar.setVisible(True) # self.dw_top = DockWidget(460, 90, 20000, 50) # self.dw_top.setTitleBarWidget(QWidget()) # self.dwc_top = DockWidgetContentsTop() # .dw_top.setWidget(self.dwc_top) # self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.dw_top) # dockwidget collection (left side) # self.dw_collections = DockWidget(350, 620, 700, 20000) # self.dw_collections.setTitleBarWidget(QWidget()) # self.dwc_left = DockWidgetContentsLeft(self) # self.dw_collections.setWidget(self.dwc_left) # self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dw_collections) QMetaObject.connectSlotsByName(self) def set_main_window(self): # Standard Values for this Window standard_width = 960 standard_height = 720 minimum_width = 544 minimum_height = 480 """Sets the size policies of the main window""" self.resize(standard_width, standard_height) size_policy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(size_policy) self.setMinimumSize(QSize(minimum_width, minimum_height)) # main window icon self.setWindowIcon(QIcon("")) self.setWindowTitle(config.APP_NAME) def setBackgroundColor(self): self.setAutoFillBackground(True) # Background Color pal = QPalette() pal.setColor(self.backgroundRole(), Qt.white) self.setPalette(pal) def set_main_menubar(self): # Create Menu Bar with Actions # .menubar.setGeometry(QRect(0, 0, 908, 21)) self.menubar.clear() # delete all actions self.menubar.setObjectName("menubar") # File Menu self.fileMenu = self.menubar.addMenu('&File') #File Menu Actions addCharAction = QAction("&Add Character", self) manageCharAction = QAction("&Manage Character", self) exitAction = QAction("&Exit", self) #File Menu Action Triggers addCharAction.triggered.connect(self.addCharacterTriggered) manageCharAction.triggered.connect(self.manageCharacterTriggered) exitAction.triggered.connect(self.exitTriggered) self.fileMenu.addAction(addCharAction) self.fileMenu.addAction(manageCharAction) self.fileMenu.addSeparator() self.fileMenu.addAction(exitAction) # Plans Menu ------------------------------------------------------------------- self.plansMenu = self.menubar.addMenu('&Plans') self.addPlanAction = QAction("&Add Plan", self) self.createSkillQueuePlanAction = QAction( "&Create Plan from Skillqueue", self) self.importPlanfromFileAction = QAction("&Import Plan from File", self) self.managePlanPlanAction = QAction("&Manage Plans", self) self.addPlanAction.triggered.connect(self.addPlan) self.plansMenu.addAction(self.addPlanAction) self.plansMenu.addAction(self.createSkillQueuePlanAction) self.plansMenu.addAction(self.importPlanfromFileAction) self.plansMenu.addAction(self.managePlanPlanAction) self.plansMenu.addSeparator() # Initially disable Plan Buttons self.addPlanAction.setDisabled(True) self.createSkillQueuePlanAction.setDisabled(True) self.importPlanfromFileAction.setDisabled(True) self.managePlanPlanAction.setDisabled(True) if self.selected_character is not None: self.addCharacterPlansToMenu() # Tools Menu -------------------------------------------------------------------- self.toolsMenu = self.menubar.addMenu('&Tools') manageNotificationsAction = QAction("&Manage Notifications", self) #reloadUI = QAction("&Reload UI", self) optionsAction = QAction("&Options", self) #reloadUI.triggered.connect(self.writeToQueue) self.toolsMenu.addAction(manageNotificationsAction) #self.toolsMenu.addAction(reloadUI) self.toolsMenu.addSeparator() self.toolsMenu.addAction(optionsAction) #Help Menu self.helpMenu = self.menubar.addMenu('&Help') helpAction = QAction("&Help", self) aboutAction = QAction("&About", self) self.helpMenu.addAction(helpAction) self.helpMenu.addSeparator() self.helpMenu.addAction(aboutAction) def set_frame(self): self.frame_query.setFrameShape(QFrame.StyledPanel) self.frame_query.setFrameShadow(QFrame.Raised) def set_status_bar(self): self.statusbar.setMinimumSize(QSize(0, 18)) font = QFont() font.setPointSize(9) self.statusbar.setFont(font) self.updateStatusbar() def updateStatusbar(self): #now = datetime.datetime.utcnow() #now = pytz.UTC time = datetime.datetime.utcnow().strftime("%H:%M") data = self.dbHandler.getServerStatus() if data is None: self.statusbar.showMessage("EVE Time " + time + " | Tranquility Server Offline") elif data.start_time is None: self.statusbar.showMessage("EVE Time " + time + " | Tranquility Server Offline") else: playerCount = data.players self.statusbar.showMessage("EVE Time " + time + " | Tranquility Server Online (" + tools.format(playerCount) + " Pilots)") def windowResized(self): print("X") ################ # # Menubar Action trigger Functions # ################ def addCharacterPlansToMenu(self): plan_list = self.dbHandler.getCharacterPlans(self.selected_character) for plan in plan_list: action = QAction(plan.name, self) action.triggered.connect( functools.partial(self.openSkillPlanner, plan.id)) self.plansMenu.addAction(action) def exitTriggered(self): # Close the Application self.close() def addCharacterTriggered(self): # self.startUpdateTimer() Esi(self.gui_queue) def addPlan(self): self.newPlanWindow = NewPlanWindow(self.gui_queue, self.selected_character, self) self.newPlanWindow.show() def manageCharacterTriggered(self): # Open New Window Character Manager self.charManager = CharManagerWindow(self.gui_queue, self) self.charManager.show() def deleteLayout(self): print("Deleting Layout..") while self.layout.count() > 0: item = self.layout.takeAt(0) if not item: continue w = item.widget() if w: w.deleteLater() print("Layout deleted.") def createLayout(self): print("creating Layout...") self.centralwidget = QWidget(self) self.layout = QVBoxLayout(self.centralwidget) self.layout.setContentsMargins(0, 0, 2, 0) self.layout.setSpacing(0) self.setCentralWidget(self.centralwidget) print("Layout created.") def createTabwidget(self): print("creating Tabwidget ...") self.tab_widget = MainTabWidget(self) self.tab_widget.currentChanged.connect(self.updateSelection) self.layout.addWidget(self.tab_widget) print("Tabwidget created.") def updateSelection(self): # we wan't to know wich tab is selected # selected_character = None for Overview, user_id for every characterTab # then update Button Activation and menubar self.selected_character = self.tab_widget.getSelection() self.set_main_menubar() self.updateButtonActivation() def updateButtonActivation(self): if self.selected_character is None: # Plans Menu self.addPlanAction.setDisabled(True) self.createSkillQueuePlanAction.setDisabled(True) self.importPlanfromFileAction.setDisabled(True) self.managePlanPlanAction.setDisabled(True) else: # Plans Menu self.addPlanAction.setDisabled(False) self.createSkillQueuePlanAction.setDisabled(False) self.importPlanfromFileAction.setDisabled(False) self.managePlanPlanAction.setDisabled(False) def reprintUI(self): # repaint Function: delete old layout and children, then paint a new one # should only be neccessary after adding a new Character try: self.deleteLayout() self.createLayout() self.createTabwidget() except Exception as e: print("Exception in mainwindow.reprintUI: " + str(e)) def hearAtQueue(self): now = datetime.datetime.utcnow() if (now.second % 60) == 0: self.updateStatusbar() if self.gui_queue.empty() is False: msg = self.gui_queue.get() if msg == "Reprint MainWindow": self.reprintUI() #self.timer.stop() def openSkillPlanner(self, plan_id): self.skillPlanner = SkillPlannerWindow(plan_id, self) self.skillPlanner.show() def startUpdateTimer(self): self.timer = QTimer() self.timer.timeout.connect(self.hearAtQueue) self.timer.setSingleShot(False) self.timer.start(1000)
from PyQt5.QtWidgets import QWidget, QSizePolicy, QLabel, QGridLayout, QVBoxLayout, QHBoxLayout, QMainWindow, QApplication, \ QGridLayout, QPushButton, QScrollArea, QFrame from PyQt5 import QtCore from PyQt5.QtGui import QPalette, QPixmap, QFont import sys import math from db.databaseHandler import DatabaseHandler from db.databaseTables import CompletedSkillList, CompletedSkillItem, User, StaticSkills, StaticSkillGroups from service import tools from service.tools import format #hyper Parameter dbHandler = DatabaseHandler() # ToDo Mouse Over and click Event/Action class KnownSkillsWidget(QWidget): def __init__(self, user, parent=None): QWidget.__init__(self, parent=parent) self.user = user self.dbHandler = DatabaseHandler() self.initiateLayout() self.createGroupList() #self.tabLayout.setContentsMargins(0,0,0,0) #self.tabLayout.setSpacing(0) self.setBackgroundColor()