def createTrayIcon(self): if platform.linux_distribution()[0] == "Ubuntu": if not os.path.exists('/usr/share/icons/ubuntu-mono-light/status/24/lunchinator.svg') or \ not os.path.exists('/usr/share/icons/ubuntu-mono-dark/status/24/lunchinator.svg'): result = QMessageBox.question(self.mainWindow, "Install Icons", "Do you want to install the Lunchinator icons into the Ubuntu theme folders? You will have to enter your sudo password.", buttons=QMessageBox.Yes | QMessageBox.No, defaultButton=QMessageBox.Yes) if result == QMessageBox.Yes: if subprocess.call(['gksu', get_settings().get_resource('bin', 'install-lunch-icons.sh') + ' lunchinator']) == 0: getCoreLogger().info("restarting after icons were installed") restart(getCoreLogger()) return False else: QMessageBox.critical(self.mainWindow, "Error installing icons", "The icons were not installed, there was an error.", buttons=QMessageBox.Ok, defaultButton=QMessageBox.Ok) getCoreLogger().info("icons were not installed because of an error") # initialize tray icon self.statusicon = QSystemTrayIcon(self.mainWindow) # _highlightIcon sets the default icon self._highlightIcon() contextMenu = self.init_menu(self.mainWindow) self.statusicon.activated.connect(self.trayActivated) self.statusicon.setContextMenu(contextMenu) self.statusicon.show() return True
def run(self): try: get_server().start_server() except: from lunchinator.log import getCoreLogger getCoreLogger().exception("Exception in Lunch Server") get_server().running = False
def changeNextLunchTime(self, begin = None, end = None): if begin == None: if self.mainWindow == None: getCoreLogger().error("mainWindow is not initialized") return from lunchinator.timespan_input_dialog import TimespanInputDialog dialog = TimespanInputDialog(self.mainWindow, "Change Lunch Time", "When are you free for lunch today?", get_settings().get_next_lunch_begin(), get_settings().get_next_lunch_end()) dialog.exec_() if dialog.result() == QDialog.Accepted: get_settings().set_next_lunch_time(dialog.getBeginTimeString(), dialog.getEndTimeString()) else: return else: get_settings().set_next_lunch_time(begin, end) if self.resetNextLunchTimeTimer != None: self.resetNextLunchTimeTimer.stop() self.resetNextLunchTimeTimer.deleteLater() td = get_settings().get_next_lunch_reset_time() if td > 0: self.resetNextLunchTimeTimer = QTimer(getValidQtParent()) self.resetNextLunchTimeTimer.timeout.connect(self._resetNextLunchTime) self.resetNextLunchTimeTimer.setSingleShot(True) self.resetNextLunchTimeTimer.start(abs(td) + 1000) get_server().call_info()
def _compress(self, value): import zlib compressedMsg = zlib.compress(value) self._statusByte = 0b00010000 | self._statusByte getCoreLogger().debug("Compression: %d -> %d"%(len(value), len(compressedMsg))) return compressedMsg
def activatePlugin(self, pluginInfo, save_state=True, checkDependencies=True): from lunchinator.utilities import handleMissingDependencies from lunchinator import get_server if checkDependencies: missing = self.checkActivation([pluginInfo]) result = handleMissingDependencies(missing) if result == INSTALL_FAIL: # maybe there were dependencies installed, better re-check missing = self.checkActivation([pluginInfo]) if missing: self._logCannotLoad(pluginInfo, missing) get_notification_center().emitPluginDeactivated(pluginInfo.name, pluginInfo.category) return elif result == INSTALL_CANCEL: # user chose not to install -> deactivate get_notification_center().emitPluginDeactivated(pluginInfo.name, pluginInfo.category) self._deactivateMissing(missing) return elif result in (INSTALL_SUCCESS, INSTALL_IGNORE): missing = {} elif result == INSTALL_RESTART: # store that the plugin is activated now self.__addPluginToConfig(pluginInfo.category, pluginInfo.name) return getCoreLogger().info("Activating plugin '%s' of type '%s'", pluginInfo.name, pluginInfo.category) try: pluginInfo.plugin_object.setPluginName(pluginInfo.name) result = ConfigurablePluginManager.activatePluginByName(self, pluginInfo.name, category_name=pluginInfo.category, save_state=save_state) if self._emitSignals and result != None: get_notification_center().emitPluginActivated(pluginInfo.name, pluginInfo.category) except: getCoreLogger().exception("Error activating plugin '%s' of type '%s'", pluginInfo.name, pluginInfo.category)
def _checkLogMessage(self, record): try: if self._notAgain.checkState() == Qt.Checked: return if record.levelno >= logging.ERROR: recMsg = record.msg if not isinstance(recMsg, basestring): recMsg = unicode(recMsg) err = convert_string(recMsg) % record.args component = record.name if component.startswith("lunchinator."): component = component[12:] msg = u"%s - In component %s (%s:%d):\n%s" % (strftime("%H:%M:%S", localtime(record.created)), component, record.pathname, record.lineno, err) if record.exc_info: out = StringIO() traceback.print_tb(record.exc_info[2], file=out) msg += u"\nStack trace:\n" + out.getvalue() + formatException(record.exc_info) + u"\n" self._errorLog.append(msg) self._empty = False if not self.isVisible(): self.showNormal() self.raise_() self.activateWindow() except: from lunchinator.log import getCoreLogger getCoreLogger().info(formatException())
def _build_info_string(self): from lunchinator.utilities import getPlatform, PLATFORM_LINUX, PLATFORM_MAC, PLATFORM_WINDOWS info_d = {u"avatar": get_settings().get_avatar_file(), u"name": get_settings().get_user_name(), u"group": get_settings().get_group(), u"ID": get_settings().get_ID(), u"next_lunch_begin":get_settings().get_default_lunch_begin(), u"next_lunch_end":get_settings().get_default_lunch_end(), u"version":get_settings().get_version(), u"version_commit_count":get_settings().get_commit_count(), u"platform": sys.platform} try: if getPlatform() == PLATFORM_LINUX: info_d[u"os"] = u" ".join(aString if type(aString) in (str, unicode) else "[%s]" % " ".join(aString) for aString in platform.linux_distribution()) elif getPlatform() == PLATFORM_WINDOWS: info_d[u"os"] = u" ".join(aString if type(aString) in (str, unicode) else "[%s]" % " ".join(aString) for aString in platform.win32_ver()) elif getPlatform() == PLATFORM_MAC: info_d[u"os"] = u" ".join(aString if type(aString) in (str, unicode) else "[%s]" % " ".join(aString) for aString in platform.mac_ver()) except: getCoreLogger().exception("Error generating OS version string") if get_settings().get_next_lunch_begin(): info_d[u"next_lunch_begin"] = get_settings().get_next_lunch_begin() if get_settings().get_next_lunch_end(): info_d[u"next_lunch_end"] = get_settings().get_next_lunch_end() self.controller.extendMemberInfo(info_d) return json.dumps(info_d)
def openWindowClicked(self, _=None): if self.mainWindow == None: getCoreLogger().error("mainWindow is not initialized") return self.mainWindow.showNormal() self.mainWindow.raise_() self.mainWindow.activateWindow()
def __init__(self): QObject.__init__(self) LunchServerController.__init__(self) getCoreLogger().info("Your PyQt version is %s, based on Qt %s", QtCore.PYQT_VERSION_STR, QtCore.QT_VERSION_STR) self._shuttingDown = False self.resetNextLunchTimeTimer = None self._updateAvailable = False self._repoUpdates = 0 self._installUpdatesAction = None self._appUpdateStatusAction = None self._repoUpdateStatusAction = None self._restartAction = None self._restartStatusAction = None self._restartReason = u"" self._highlightNewMessage = False self._highlightPeersReady = False self.exitCode = 0 self.serverThread = None self.running = True get_server().initialize(self) self.pluginNameToMenuAction = {} # initialize main window self.mainWindow = LunchinatorWindow(self) self.settingsWindow = None self.errorDialog = ErrorLogDialog(self.mainWindow) self.setParent(self.mainWindow) if not self.createTrayIcon(): return self.mainWindow.createMenuBar(self.pluginActions) # connect private signals self._initDone.connect(self.initDoneSlot) self._performCall.connect(self.performCallSlot) self._receiveFile.connect(self.receiveFileSlot) self._sendFile.connect(self.sendFileSlot) self._processEvent.connect(self.processEventSlot) self._processMessage.connect(self.processMessageSlot) self._updateRequested.connect(self.updateRequested) self._openWindow.connect(self.openWindowClicked) get_notification_center().connectApplicationUpdate(self._appUpdateAvailable) get_notification_center().connectOutdatedRepositoriesChanged(self._outdatedReposChanged) get_notification_center().connectUpdatesDisabled(self._updatesDisabled) get_notification_center().connectMessagePrepended(self._newMessage) get_notification_center().connectRestartRequired(self._restartRequired) get_notification_center().connectPluginActivated(self._pluginActivated) get_notification_center().connectPluginDeactivated(self._pluginDeactivated) self.serverThread = LunchServerThread(self) self.serverThread.finished.connect(self.serverFinishedUnexpectedly) self.serverThread.finished.connect(self.serverThread.deleteLater) self.serverThread.start()
def set_group(self, value, init=False): from lunchinator import get_server oldGroup = self._group self._group = value if not init: getCoreLogger().info("Changing Group: '%s' -> '%s'", oldGroup, self._group) get_server().changeGroup(unicode(value)) get_notification_center().emitGroupChanged(oldGroup, self._group)
def _process_queued_messages(self, ip): with self.message_queues_lock: if ip in self._message_queues: if len(self._message_queues[ip][1]) > 0: getCoreLogger().debug("Processing enqueued messages of IP %s", ip) for eventTime, xmsg in self._message_queues[ip][1]: self._handle_event(xmsg, ip, eventTime, newPeer=False, fromQueue=True) del self._message_queues[ip]
def _deactivateMissing(self, missing): for component in missing.keys(): pluginName, category = component pluginInfo = self._component.getPluginByName(pluginName, category) try: self.__removePluginFromConfig(pluginInfo.category, pluginInfo.name) except: getCoreLogger().exception("Error removing plugin %s (%s) from list of plugins to load", pluginInfo.name, pluginInfo.category)
def getOptionCategories(self): try: if get_settings().get_plugins_enabled(): for pluginInfo in get_plugin_manager().getAllPlugins(): if pluginInfo.plugin_object.is_activated: if pluginInfo.plugin_object.has_options(): yield (pluginInfo.name, pluginInfo.description) except: getCoreLogger().exception("while collecting option categories")
def showPeerActionsPopup(peerID, filterFunc, parent): from PyQt4.QtGui import QMenu, QCursor if get_peers() == None: getCoreLogger().warning("no lunch_peers instance available, cannot show peer actions") return if peerID: popupMenu = _fillPeerActionsMenu(QMenu(parent), peerID, filterFunc, parent) popupMenu.exec_(QCursor.pos()) popupMenu.deleteLater()
def initializePeerActionsMenu(menu, peerID, filterFunc, parentWidget): menu.clear() if get_peers() == None: getCoreLogger().warning("no lunch_peers instance available, cannot show peer actions") return menu if peerID: _fillPeerActionsMenu(menu, peerID, filterFunc, parentWidget) return menu
def getCoreDependencies(): try: req_file = get_settings().get_resource("requirements.txt") with open(req_file, "r") as f: requirements = f.readlines() except IOError: getCoreLogger().warning("requirements.txt does not exist") requirements = [] return requirements
def get_option(self, o): """Get an option by its name.""" methodname = "get_" + o if hasattr(self, methodname): _member = getattr(self, methodname) return _member() else: getCoreLogger().warning("settings has no attribute called '%s'", o) return None
def _pluginActivated(self, pName, pCat): pName = convert_string(pName) pCat = convert_string(pCat) if pCat == "gui": try: pluginInfo = get_plugin_manager().getPluginByName(pName, u"gui") self.addPluginWidget(pluginInfo.plugin_object, pName) except: getCoreLogger().exception("while including plugins %s", str(sys.exc_info()))
def handleMissingDependencies(missing, optionalCallback=lambda _req : True): """If there are missing dependencies, asks and installs them. Returns a list of components whose requirements were not fully installed. missing -- dictionary returned by checkRequirements(...) optionalCallbacl -- function that takes a requirement string and returns True if the requirement is optional and False otherwise. """ if missing: if isPyinstallerBuild(): canInstall = False text = u"There are missing dependencies in your PyInstaller build. " +\ u"Unfortunately, you cannot install additional packages for a PyInstaller build." getCoreLogger().warning(text + u"\n The missing dependencies are: \n" + unicode(str(missing))) else: canInstall = True text = None if lunchinator_has_gui(): from lunchinator.req_error_dialog import RequirementsErrorDialog from PyQt4.QtGui import QMessageBox requirements = [] for _component, missingList in missing.iteritems(): for dispName, req, reason, info in missingList: if reason == REASON_PACKAGE_MISSING: reasonStr = u"Not installed" elif reason == REASON_VERSION_CONFLICT: reasonStr = u"Wrong version (installed: %s)" % info.version else: reasonStr = u"Unknown" requirements.append((req, dispName, reasonStr, optionalCallback(req))) f = RequirementsErrorDialog(requirements, None, canInstall, text) res = f.exec_() if res == RequirementsErrorDialog.Accepted: if not canInstall: return INSTALL_NOT_POSSIBLE installRes = installDependencies(f.getSelectedRequirements()) if installRes == INSTALL_FAIL: QMessageBox.critical(None, "Install Failed", "Some dependencies could not be installed.") elif installRes == INSTALL_SUCCESS: QMessageBox.information(None, "Install Succeeded", "Dependencies were successfully installed.") elif installRes == INSTALL_RESTART: QMessageBox.information(None, "Install Finished", "Lunchinator needs to be restarted to complete the installation.") return installRes elif res == RequirementsErrorDialog.IGNORED: return INSTALL_IGNORE else: return INSTALL_CANCEL return INSTALL_FAIL return INSTALL_NOT_POSSIBLE
def performAction(self, peerID, _peerInfo, _parent): try: from PyQt4.QtGui import QInputDialog oldName = get_peers().getDisplayedPeerName(pID=peerID) customName, ok = QInputDialog.getText(None, u"Custom Peer Name", u"Enter the displayed peer name:", text=oldName) if ok: customName = convert_string(customName) get_peers().setCustomPeerName(peerID, customName) except: getCoreLogger().exception("Error changing displayed peer name.")
def extendMemberInfo(self, infoDict): """Add some specific information to the info dictionary""" if not get_settings().get_plugins_enabled(): return for pluginInfo in get_plugin_manager().getAllPlugins(): if pluginInfo.plugin_object.is_activated and pluginInfo.plugin_object.extendsInfoDict(): try: pluginInfo.plugin_object.extendInfoDict(infoDict) except: getCoreLogger().exception(u"plugin error in %s while extending member info" % pluginInfo.name)
def _pluginWillBeDeactivated(self, pName, pCat): pName = convert_string(pName) pCat = convert_string(pCat) if pCat == "gui": pluginInfo = get_plugin_manager().getPluginByName(pName, pCat) try: pluginInfo.plugin_object.destroy_widget() except: getCoreLogger().exception("Error destroying plugin widget for plugin %s", pName) self.removePluginWidget(pName)
def sendFileSlot(self, addr, fileToSend, other_tcp_port, isData): addr = convert_string(addr) if isData: fileToSend = str(fileToSend) ds = DataSenderThread.sendData(addr, other_tcp_port, fileToSend, getCoreLogger(), parent=self) else: fileToSend = str(fileToSend).decode("utf-8") ds = DataSenderThread.sendSingleFile(addr, other_tcp_port, fileToSend, getCoreLogger(), parent=self) ds.finished.connect(ds.deleteLater) ds.start()
def __init__(self, controller): super(LunchinatorWindow, self).__init__(None) self.guiHandler = controller self.setWindowTitle("Lunchinator") self.setWindowIcon(QIcon(get_settings().get_resource("images", "lunchinator.png"))) self.setDockNestingEnabled(True) self.setTabPosition(Qt.AllDockWidgetAreas, QTabWidget.North) self.pluginNameToDockWidget = {} self.objectNameToPluginName = {} self.pluginNameToMenus = {} self.settings = QSettings(get_settings().get_config("gui_settings.ini"), QSettings.IniFormat) savedGeometry = self.settings.value("geometry", None) savedState = self.settings.value("state", None) self.locked = self.settings.value("locked", QVariant(False)).toBool() self._prepareMenuBar() if savedState == None: # first run, create initial state get_plugin_manager().activatePluginByName(u"Simple View", "gui") get_plugin_manager().activatePluginByName(u"Auto Update", "general") # add plugins try: if get_settings().get_plugins_enabled(): for pluginInfo in get_plugin_manager().getPluginsOfCategory("gui"): if pluginInfo.plugin_object.is_activated: self.addPluginWidget(pluginInfo.plugin_object, pluginInfo.name, noTabs=True) except: getCoreLogger().exception("while including plugins %s", str(sys.exc_info())) if savedGeometry != None: self.restoreGeometry(savedGeometry.toByteArray()) else: self.centerOnScreen() if savedState != None: self.restoreState(savedState.toByteArray()) get_notification_center().connectPluginActivated(self._pluginActivated) get_notification_center().connectPluginWillBeDeactivated(self._pluginWillBeDeactivated) if len(self.pluginNameToDockWidget) == 0 and get_settings().get_plugins_enabled(): # no gui plugins activated, show about plugins get_plugin_manager().activatePluginByName(u"About Plugins", "gui") if self.locked: self.lockDockWidgets() # prevent from closing twice self.closed = False
def _check_lunch_time(self, new_value, old_value): if new_value == old_value: return new_value try: time = datetime.strptime(new_value, lunch_settings.LUNCH_TIME_FORMAT) if time: return new_value except: getCoreLogger().warning("Problem while checking the lunch time") getCoreLogger().warning("Illegal time format: %s", new_value) return old_value
def _enqueue_event(self, xmsg, ip, eventTime): getCoreLogger().debug("Peer of IP %s is unknown, enqueuing message", ip) with self.message_queues_lock: if ip in self._message_queues: queue = self._message_queues[ip] else: queue = (time(), []) queue[1].append((eventTime, xmsg)) self._message_queues[ip] = queue
def testReceive(openPort, targetPath, totalSize, sendDict): global errorReceive try: if sendDict is not None: dt = DataReceiverThreadBase.receive(SENDER, targetPath, openPort, sendDict, getCoreLogger()) else: dt = DataReceiverThreadBase.receiveSingleFile(SENDER, targetPath, totalSize, openPort, getCoreLogger()) dt.performReceive() except: errorReceive = True getCoreLogger().error(u"Error receiving: %s", formatException())
def run(self): while True: req, args, kwargs = self.reqs.get() getCoreLogger().debug("processing Signal: %s", req) if req == 'exit': break try: req(*args, **kwargs) except Exception, e: getCoreLogger().exception("Error in Signal handling; executed method: %s; Error: %s", str(req), str(e)) except:
def get_next_lunch_reset_time(self): if self._next_lunch_end == None: return None from lunchinator.utilities import getTimeDelta # reset after next_lunch_end, but not before default_lunch_end tdn = getTimeDelta(self._next_lunch_end, getCoreLogger()) tdd = getTimeDelta(self.get_default_lunch_end(), getCoreLogger()) return max(tdn, tdd)
def toggle_plugin(self, p_name, p_cat, new_state): try: p_cat = convert_string(p_cat) p_name = convert_string(p_name) if new_state: get_plugin_manager().activatePluginByName(p_name, p_cat) else: get_plugin_manager().deactivatePluginByName(p_name, p_cat) except: getCoreLogger().exception("Error toggling plugin")