def show_info(self): info_dialog = QDialog(self) uic.loadUi(resource_path("vi/ui/Info.ui"), info_dialog) info_dialog.version_label.setText(u"Version: {0}".format(VERSION)) info_dialog.logo_label.setPixmap( QtGui.QPixmap(resource_path("vi/ui/res/logo.png"))) info_dialog.close_button.clicked.connect(info_dialog.accept) info_dialog.show()
def __init__(self, parent, url): QDialog.__init__(self, parent) uic.loadUi(resource_path("vi/ui/JumpbridgeChooser.ui"), self) self.save_button.clicked.connect(self.save_path) self.cancel_button.clicked.connect(self.accept) self.url_field.setText(url) # loading format explanation from textfile with open(resource_path("docs/jumpbridgeformat.txt")) as f: self.format_info_field.setPlainText(f.read())
def __init__(self, message): QWidget.__init__(self) uic.loadUi(resource_path("vi/ui/ChatEntry.ui"), self) self.avatar_label.setPixmap( QtGui.QPixmap(resource_path("vi/ui/res/qmark.png"))) self.message = message self.update_text() self.text_label.linkActivated.connect(self.link_clicked) self.change_fontsize(self.TEXTSIZE) if not ChatEntry.SHOW_AVATAR: self.avatar_label.setVisible(False)
def show_kos_result(self, state, text, request_type, has_kos): if has_kos: sound.play_sound("beep") self.trayicon.setIcon( QtGui.QIcon(resource_path("vi/ui/res/logo_small.png"))) if state == "ok": if request_type == "xxx": # a xxx request out of the chat self.trayicon.showMessage("A xxx KOS-Check", text, 1) elif request_type == "clipboard": # request from clipboard-change if len(text) <= 0: text = "Noone KOS" self.trayicon.showMessage("Your KOS-Check", text, 1) text = text.replace("\n\n", "<br>") message = chatparser.chatparser.Message("Vintel KOS-Check", text, evegate.current_eve_time(), "VINTEL", [], states.NOT_CHANGE, text.upper(), text) self.add_message_to_intelchat(message) elif state == "error": self.trayicon.showMessage("KOS Failure", text, 3)
def __init__(self, parent, chat_type, selector, chatentries, known_playernames): QDialog.__init__(self, parent) uic.loadUi(resource_path("vi/ui/SystemChat.ui"), self) self.parent = parent self.chat_type = 0 self.selector = selector self.chatentries = [] for entry in chatentries: self.add_chatentry(entry) titlename = "" if self.chat_type == SystemChat.SYSTEM: titlename = self.selector.name self.system = selector self.setWindowTitle("Chat for {0}".format(titlename)) for name in known_playernames: self.playernames_box.addItem(name) self.close_button.clicked.connect(self.close_dialog) self.alarm_button.clicked.connect(self.set_system_alarm) self.clear_button.clicked.connect(self.set_system_clear) self.location_button.clicked.connect(self.location_set)
def show_sound_setup(self): dialog = QDialog(self) uic.loadUi(resource_path("vi/ui/SoundSetup.ui"), dialog) dialog.volumeSlider.setValue(self.sound_volume) dialog.volumeSlider.valueChanged.connect(self.set_sound_volume) dialog.testsound_button.clicked.connect(sound.play_sound) dialog.close_button.clicked.connect(dialog.accept) dialog.show()
def __init__(self, app): self.icon = QtGui.QIcon(resource_path("vi/ui/res/logo_small.png")) QtWidgets.QSystemTrayIcon.__init__(self, self.icon, app) self.setToolTip("Your Vintel-Information-Service! :)") self.last_notifications = {} self.setContextMenu(TrayContextMenu(self)) self.show_alarm = True self.show_request = True self.alarm_distance_value = 0
def __init__(self, parent): QDialog.__init__(self, parent) uic.loadUi(resource_path("vi/ui/ChatroomsChooser.ui"), self) self.default_button.clicked.connect(self.set_defaults) self.cancel_button.clicked.connect(self.accept) self.save_button.clicked.connect(self.save_clicked) cache = Cache() roomnames = cache.get_from_cache("roomnames") if not roomnames: roomnames = u"TheCitadel, North Provi Intel" self.roomnames_field.setPlainText(roomnames)
def __init__(self, parent): QDialog.__init__(self, parent) uic.loadUi(resource_path("vi/ui/RegionChooser.ui"), self) self.default_button.clicked.connect(self.set_defaults) self.cancel_button.clicked.connect(self.accept) self.save_button.clicked.connect(self.save_clicked) cache = Cache() regionname = cache.get_from_cache("regionname") if not regionname: regionname = u"Providence" self.regionname_field.setPlainText(regionname)
def __client_script(scriptname): log.debug('loading script {0}.js'.format(scriptname)) script = QWebEngineScript() with open(resource_path( 'vi/ui/res/{0}.js'.format(scriptname))) as src_file: script_content = src_file.read() script.setSourceCode(script_content) script.setName(scriptname) script.setWorldId(QWebEngineScript.MainWorld) script.setInjectionPoint(QWebEngineScript.DocumentReady) script.setRunsOnSubFrames(True) return script
def play_sound(name="alarm"): if SOUND_AVAILABLE and sound_active: if name == False: name = "alarm" if name not in SOUNDS: raise ValueError("Sound '{0}' is not available".format(name)) if name not in soundcache: path = resource_path("vi/ui/res/{0}".format(SOUNDS[name])) soundcache[name] = pygame.mixer.Sound(path) # soundcache[name].set_volume(sound_volume) soundcache[name].play()
def logfile_changed(self, path, roomname): messages = self.chatparser.file_modified(path, roomname) for message in messages: # if players location changed if message.status == states.LOCATION: self.known_playernames.add(message.user) self.set_location(message.user, message.systems[0]) # soundtest special elif message.status == states.SOUNDTEST and message.user in self.known_playernames: words = message.message.split() if len(words) > 1: sound.play_sound(words[1]) # KOS request elif message.status == states.KOS_STATUS_REQUEST: text = message.message[4:] text = text.replace(" ", ",") parts = (name.strip() for name in text.split(",")) self.trayicon.setIcon( QtGui.QIcon( resource_path("vi/ui/res/logo_small_green.png"))) self.kos_request_thread.add_request(parts, "xxx", False) # if it is a 'normal' chat message elif message.user not in ("EVE-System", "EVE System" ) and message.status != states.IGNORE: self.add_message_to_intelchat(message) if message.systems: for system in message.systems: systemname = system.name # self.dotlan.set_system_status(systemname, message.status) self.map.page().set_system_status(system, message) if message.status in (states.REQUEST, states.ALARM) \ and message.user not in self.known_playernames: if message.status == states.ALARM: alarm_distance = self.alarm_distance else: alarm_distance = 0 for nsystem, data in system.get_neighbours( alarm_distance).items(): distance = data["distance"] chars = nsystem.get_located_characters() if len(chars ) > 0 and message.user not in chars: self.trayicon.show_notification( message, system.name, ", ".join(chars), distance)
def run(self): cache = Cache() last_call = 0 wait = 300 # time between 2 requests in ms while True: try: chatentry = self.q.get() charname = chatentry.message.user avatar = None logging.debug('loading avatar for {0}'.format(charname)) if charname == "VINTEL": logging.debug('fetching VINTEL avatar') with open(resource_path("vi/ui/res/logo_small.png"), "rb") as f: avatar = f.read() if not avatar: logging.debug('getting avatar from cache') avatar = cache.get_avatar(charname) if not avatar: diff_last_call = time.time() - last_call if diff_last_call < wait: time.sleep((wait - diff_last_call) / 1000.0) logging.debug('getting avatar from evegate') avatar = evegate.get_avatar_for_player(charname) last_call = time.time() if avatar: logging.debug('saving avatar from evegate to cache') cache.put_avatar(charname, avatar) if avatar: if isinstance(avatar, str): self.avatar_update.emit(chatentry, eval(avatar)) elif isinstance(avatar, bytes): self.avatar_update.emit(chatentry, avatar) else: logging.warning('unknown avatar object type {0}'.format(type(avatar))) except Exception as e: print("An error in the avatar-find-thread:", str(e))
def clipboard_changed(self, mode): if mode == 0 and self.action_kos_clipboard_active.isChecked(): content = str(self.clipboard.text()) last_modified, old_content = self.old_clipboard_content if content == old_content and time.time() - last_modified < 3: parts = content.split("\n") for part in parts: if part in self.known_playernames: self.trayicon.setIcon( QtGui.QIcon( resource_path( "vi/ui/res/logo_small_green.png"))) self.kos_request_thread.add_request( parts, "clipboard", True) self.old_clipboard_content = (0, "") break else: self.old_clipboard_content = (time.time(), content)
def save_clicked(self): text = str(self.regionname_field.toPlainText()) text = dotlan.convert_regionname(text) self.regionname_field.setPlainText(text) correct = False try: url = dotlan.Map.DOTLAN_BASIC_URL.format(text) content = requests.get(url).text # request = urllib.request.urlopen(url) # content = request.read() if u"not found" in content: correct = False # Fallback -> ships vintel with this map? try: with open( resource_path("vi/ui/res/mapdata/{0}.svg".format( text))) as _: correct = True except Exception as e: print(str(e)) correct = False if not correct: QMessageBox.warning( None, u"No such region!", u"I can't find a region called '{0}'".format(text), QMessageBox.Ok) else: correct = True except Exception as e: QMessageBox.critical( None, u"Something went wrong!", u"Error while testing existing '{0}'".format(str(e)), QMessageBox.Ok) correct = False if correct: c = Cache() c.put_into_cache("regionname", text, 60 * 60 * 24 * 365) QMessageBox.information( None, u"VINTEL needs restart", u"Region was changed, you need to restart VINTEL!", QMessageBox.Ok) self.accept()
def __init__(self): super(MainWindowPage, self).__init__() self.m_pView = QWebEngineView() self.m_pView.setPage(self) self.channel = QtWebChannel.QWebChannel(self) self.bridge = Bridge() self.bridge.sig_message.connect(self.page_event) self.m_pView.page().setWebChannel(self.channel) self.m_pView.page().profile().scripts().insert( self.__client_script('jquery-3.1.1.min')) self.m_pView.page().profile().scripts().insert( self.__client_script('clientscript')) # self.m_pView.page().profile().scripts().insert(self.__client_script('firebug-lite')) self.m_pView.page().setHtml(self.__client_html()) self.channel.registerObject('VIntelAPI', self.bridge) self.styles = {} for stype in 'dark', 'light': with open(resource_path( 'vi/ui/res/style-{0}.css'.format(stype))) as src_file: self.styles['style_' + stype] = src_file.read() self.set_style('light')
def main(): FORMAT = '%(asctime)-15s %(filename)s L%(lineno)d %(funcName)s: %(message)s' logging.basicConfig(level=logging.FATAL, format=FORMAT, datefmt='%d.%m.%Y %H:%M:%S') global error_file splash = QtWidgets.QSplashScreen( QtGui.QPixmap(resource_path("vi/ui/res/logo.png"))) splash.show() app.processEvents() PATH_TO_LOGS = None # did we have a manuel path to the logs as an argument at start? if len(sys.argv) > 1: PATH_TO_LOGS = sys.argv[1] print("Try to find Logdir @:", PATH_TO_LOGS) # Path to Chatlogs on Linux System using wine if not PATH_TO_LOGS or not os.path.exists(PATH_TO_LOGS): print("Going on find logdir...") PATH_TO_LOGS = os.path.join(os.path.expanduser("~"), "EVE", "logs", "Chatlogs") print("Try to find Logdir @:", PATH_TO_LOGS) # Path to Chatlogs on MacOS if not os.path.exists(PATH_TO_LOGS): print("No logdir @:", PATH_TO_LOGS) PATH_TO_LOGS = os.path.join(os.path.expanduser("~"), "Library", "Application Support", "Eve Online", "p_drive", "User", "My Documents", "EVE", "logs", "Chatlogs") print("Try to find Logdir @:", PATH_TO_LOGS) # Path to chatlogs on windows if not os.path.exists(PATH_TO_LOGS): print("No logdir @: ", PATH_TO_LOGS) CSIDL_PERSONAL = 5 SHGFP_TYPE_CURRENT = 0 buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) ctypes.windll.shell32.SHGetFolderPathW(0, CSIDL_PERSONAL, 0, SHGFP_TYPE_CURRENT, buf) documents_path = buf.value print("Documents path? :", documents_path) PATH_TO_LOGS = os.path.join(documents_path, "EVE", "logs", "Chatlogs") # None of the pathes for logs exists? So we can not work, sorry if not os.path.exists(PATH_TO_LOGS): QtWidgets.QMessageBox.critical( None, "No path to Logs", "Vintel could not find the directory where the EvE chatlogs are stored. Sorry.", QtWidgets.QMessageBox.Close) sys.exit(1) print("I expect logs @:", PATH_TO_LOGS) # setting local working directory for cache, etc. # datadir = os.path.join(os.path.expanduser("~"), "EVE", "vintel") datadir = os.path.join(os.path.dirname(os.path.dirname(PATH_TO_LOGS)), "vintel") if not os.path.exists(datadir): os.mkdir(datadir) print("Vintel writes data in :", datadir) cache.Cache.PATH_TO_CACHE = os.path.join(datadir, "cache.sqlite3") error_file = os.path.join(datadir, "error.log") trayicon = systemtray.TrayIcon(app) trayicon.setContextMenu(systemtray.TrayContextMenu(trayicon)) trayicon.show() mw = viui.MainWindow(PATH_TO_LOGS, trayicon) mw.show() splash.finish(mw) app.exec() app.quit()
def __init__(self, path_to_logs, trayicon): """ systems = list of system-objects creted by dotlan.py """ QMainWindow.__init__(self) uic.loadUi(resource_path('vi/ui/MainWindow.ui'), self) self.setWindowTitle("Vintel " + VERSION) self.setWindowIcon( QtGui.QIcon(resource_path("vi/ui/res/logo_small.png"))) self.path_to_logs = path_to_logs self.trayicon = trayicon self.trayicon.activated.connect(self.systray_activated) c = Cache() regionname = c.get_from_cache("regionname") if not regionname: regionname = "Providence" # is it a local map? svg = None try: with open( resource_path("vi/ui/res/mapdata/{0}.svg".format( regionname))) as svg_file: svg = svg_file.read() except Exception as e: pass try: self.dotlan = dotlan.Map(regionname, svg) except dotlan.DotlanException as e: QMessageBox.critical(None, "Error getting map", str(e), QMessageBox.Close) sys.exit(1) if self.dotlan.outdated_cache_error: e = self.dotlan.outdated_cache_error diatext = "I tried to get and process the data for the map "\ "but something went wrong. To proceed I use the data I "\ "have in my cache. This could be outdated.\nIf this problem "\ "is permanent, there might be a change in the dotlan data "\ "and VINTEL must be modified. Check for a newer version "\ "and inform the maintainer.\n\nWhat went wrong: {0} {1}"\ .format(type(e), str(e)) QMessageBox.warning(None, "Using map from my cache", diatext, QMessageBox.Ok) jumpbridge_url = c.get_from_cache("jumpbridge_url") self.set_jumpbridges(jumpbridge_url) self.init_map_position = None # we read this after first rendering # self.systems = self.dotlan.systems self.chatentries = [] self.kos_request_thread = KOSCheckerThread() self.kos_request_thread.kos_result.connect(self.show_kos_result) self.kos_request_thread.start() self.avatar_find_thread = AvatarFindThread() self.avatar_find_thread.avatar_update.connect( self.update_avatar_on_chatentry) self.avatar_find_thread.start() self.clipboard = QApplication.clipboard() self.clipboard.clear(mode=self.clipboard.Clipboard) self.old_clipboard_content = (0, "") self.clipboard.changed.connect(self.clipboard_changed) self.zoomin.clicked.connect(self.zoomMapIn) self.zoomout.clicked.connect(self.zoomMapOut) self.actionStatistics.clicked.connect( self.dotlan.change_statistics_visibility) self.chat_large.clicked.connect(self.chat_larger) self.chat_small.clicked.connect(self.chat_smaller) self.jumpBridgesButton.clicked.connect(self.change_jumpbridge_view) self.sound_button.clicked.connect(self.show_sound_setup) self.actionInfo.triggered.connect(self.show_info) self.actionShow_Chat_Avatars.triggered.connect( self.change_show_avatars) self.actionAlways_on_top.triggered.connect(self.change_always_on_top) self.choose_chatrooms_button.triggered.connect( self.show_chatroom_chooser) self.choose_region_button.triggered.connect(self.show_region_chooser) self.action_show_chat.triggered.connect(self.change_chat_visibility) self.actionSound_Setup.triggered.connect(self.show_sound_setup) self.opacity_group = QActionGroup(self.menu) for i in (100, 80, 60, 40, 20): action = QAction("Opacity {0}%".format(i), None, checkable=True) if i == 100: action.setChecked(True) action.opacity = i / 100.0 action.triggered.connect(self.change_opacity) self.opacity_group.addAction(action) self.menuTransparency.addAction(action) # map with menu ======================================================= self.custom_content_page = MainWindowPage() self.custom_content_page.sig_link_clicked.connect( self.map_link_clicked) self.map.setPage(self.custom_content_page) self.map.page().set_svg(self.dotlan.svg_clean) self.map.contextmenu = TrayContextMenu(self.trayicon) def map_contextmenu_event(event): self.map.contextmenu.exec_( self.mapToGlobal(QPoint(event.x(), event.y()))) self.map.contextMenuEvent = map_contextmenu_event # self.map.connect(self.map, Qt.SIGNAL("linkClicked(const QUrl&)"), self.map_link_clicked) # self.map.page().linkClicked.connect(self.map_link_clicked) # http://stackoverflow.com/questions/40747827/qwebenginepage-disable-links # end map ============================================================= self.filewatcher_thread = filewatcher.FileWatcher( self.path_to_logs, 60 * 60 * 24) # self.connect(self.filewatcher_thread, QtCore.SIGNAL("fchange"), self.logfile_changed) self.filewatcher_thread.fchange.connect(self.logfile_changed) self.filewatcher_thread.start() if False: self.last_statistics_update = 0 self.maptimer = QtCore.QTimer(self) # self.connect(self.maptimer, QtCore.SIGNAL("timeout()"), self.update_map) self.maptimer.timeout.connect(self.update_map) self.maptimer.start(1000) self.evetimer = QtCore.QTimer(self) # self.connect(self.maptimer, QtCore.SIGNAL("timeout()"), self.update_map) self.evetimer.timeout.connect(self.update_evetime) self.evetimer.start(1000) self.trayicon.sig_alarm_distance.connect(self.change_alarm_distance) self.trayicon.sig_change_frameless.connect(self.change_frameless) self.frameButton.clicked.connect(self.change_frameless) self.frameButton.setVisible(False) self.btn_night_mode.clicked.connect(self.toggle_nightmode) self.btn_night_mode.setCheckable(True) # self.btn_night_mode.setChecked(True) self.actionFrameless_Window.triggered.connect(self.change_frameless) self.is_frameless = None # we need this because 2 places to change self.alarm_distance = 0 self.actionActivate_Sound.triggered.connect(self.change_sound) if not sound.SOUND_AVAILABLE: self.change_sound(disable=True) else: self.change_sound() self.jumpbridgedata_button.triggered.connect( self.show_jumbridge_chooser) # load something from cache ===================================== self.known_playernames = c.get_from_cache("known_playernames") if self.known_playernames: self.known_playernames = set(self.known_playernames.split(",")) else: self.known_playernames = set() roomnames = c.get_from_cache("roomnames") if roomnames: roomnames = roomnames.split(",") else: roomnames = ("TheCitadel", "North Provi Intel") c.put_into_cache("roomnames", ",".join(roomnames), 60 * 60 * 24 * 365 * 5) self.set_sound_volume( 75) # default - maybe overwritten by the settings try: settings = c.get_from_cache("settings") if settings: settings = pickle.loads(base64.b64decode(settings)) for setting in settings: try: if not setting[0]: obj = self else: obj = getattr(self, setting[0]) getattr(obj, setting[1])(setting[2]) except Exception as e: log.error(str(e)) except Exception as e: self.trayicon.showMessage( "Can't remember", "Something went wrong when I load my last state:\n{0}".format( str(e)), 1) # load cache ends =============================================== self.actionQuit.triggered.connect(self.close) self.trayicon.sig_quit.connect(self.close) self.chatparser = ChatParser(self.path_to_logs, roomnames, self.dotlan.systems) version_check_thread = drachenjaeger.NotifyNewVersionThread() version_check_thread.newer_version.connect(self.notify_newer_version) version_check_thread.run()