def __init__(self, webconf, parent=None): super(ServeDialog, self).__init__(parent) self.setWindowFlags((self.windowFlags() | Qt.WindowMinimizeButtonHint) & ~Qt.WindowContextHelpButtonHint) # TODO: choose appropriate icon self.setWindowIcon(qtlib.geticon('proxy')) self._qui = Ui_ServeDialog() self._qui.setupUi(self) self._initwebconf(webconf) self._initcmd() self._initactions() self._updateform()
def __init__(self, ui, webconf, parent=None): super(ServeDialog, self).__init__(parent) self.setWindowFlags((self.windowFlags() | Qt.WindowMinimizeButtonHint) & ~Qt.WindowContextHelpButtonHint) self.setWindowIcon(qtlib.geticon('hg-serve')) self._qui = Ui_ServeDialog() self._qui.setupUi(self) self._initwebconf(webconf) self._initcmd(ui) self._initactions() self._updateform()
def __init__(self, webconf, parent=None): super(ServeDialog, self).__init__(parent) self.setWindowFlags((self.windowFlags() | Qt.WindowMinimizeButtonHint) & ~Qt.WindowContextHelpButtonHint) # TODO: choose appropriate icon self.setWindowIcon(qtlib.geticon("proxy")) self._qui = Ui_ServeDialog() self._qui.setupUi(self) self._initwebconf(webconf) self._initcmd() self._initactions() self._updateform()
class ServeDialog(QDialog): """Dialog for serving repositories via web""" def __init__(self, webconf, parent=None): super(ServeDialog, self).__init__(parent) self.setWindowFlags((self.windowFlags() | Qt.WindowMinimizeButtonHint) & ~Qt.WindowContextHelpButtonHint) # TODO: choose appropriate icon self.setWindowIcon(qtlib.geticon('proxy')) self._qui = Ui_ServeDialog() self._qui.setupUi(self) self._initwebconf(webconf) self._initcmd() self._initactions() self._updateform() def _initcmd(self): self._cmd = cmdui.Widget(True, False, self) # TODO: forget old logs? self._log_edit = self._cmd.core.outputLog self._qui.details_tabs.addTab(self._log_edit, _('Log')) self._cmd.hide() self._cmd.commandStarted.connect(self._updateform) self._cmd.commandFinished.connect(self._updateform) def _initwebconf(self, webconf): self._webconf_form = WebconfForm(webconf=webconf, parent=self) self._qui.details_tabs.addTab(self._webconf_form, _('Repositories')) def _initactions(self): self._qui.start_button.clicked.connect(self.start) self._qui.stop_button.clicked.connect(self.stop) @pyqtSlot() def _updateform(self): """update form availability and status text""" self._updatestatus() self._qui.start_button.setEnabled(not self.isstarted()) self._qui.stop_button.setEnabled(self.isstarted()) self._qui.settings_button.setEnabled(not self.isstarted()) self._qui.port_edit.setEnabled(not self.isstarted()) self._webconf_form.setEnabled(not self.isstarted()) def _updatestatus(self): if self.isstarted(): # TODO: escape special chars link = '<a href="%s">%s</a>' % (self.rooturl, self.rooturl) msg = _('Running at %s') % link else: msg = _('Stopped') self._qui.status_edit.setText(msg) @pyqtSlot() def start(self): """Start web server""" if self.isstarted(): return _setupwrapper() self._cmd.run(self._cmdargs()) def _cmdargs(self): """Build command args to run server""" a = ['serve', '--port', str(self.port), '--debug'] if self._singlerepo: a += ['-R', self._singlerepo] else: a += ['--web-conf', self._tempwebconf()] return a def _tempwebconf(self): """Save current webconf to temporary file; return its path""" if not hasattr(self._webconf, 'write'): return self._webconf.path fd, fname = tempfile.mkstemp(prefix='webconf_', dir=qtlib.gettempdir()) f = os.fdopen(fd, 'w') try: self._webconf.write(f) return fname finally: f.close() @property def _webconf(self): """Selected webconf object""" return self._webconf_form.webconf @property def _singlerepo(self): """Return repository path if serving single repository""" # NOTE: we cannot use web-conf to serve single repository at '/' path if len(self._webconf['paths']) != 1: return path = self._webconf.get('paths', '/') if path and '*' not in path: # exactly a single repo (no wildcard) return path @pyqtSlot() def stop(self): """Stop web server""" if not self.isstarted(): return self._cmd.cancel() self._fake_request() def _fake_request(self): """Send fake request for server to run python code""" TIMEOUT = 0.5 # [sec] conn = httplib.HTTPConnection('localhost:%d' % self.port) origtimeout = socket.getdefaulttimeout() socket.setdefaulttimeout(TIMEOUT) try: try: conn.request('GET', '/') res = conn.getresponse() res.read() except (socket.error, httplib.HTTPException): pass finally: socket.setdefaulttimeout(origtimeout) conn.close() def reject(self): self.stop() super(ServeDialog, self).reject() def isstarted(self): """Is the web server running?""" return self._cmd.core.running() @property def rooturl(self): """Returns the root URL of the web server""" # TODO: scheme, hostname ? return 'http://localhost:%d' % self.port @property def port(self): """Port number of the web server""" return int(self._qui.port_edit.value()) def setport(self, port): self._qui.port_edit.setValue(port) def keyPressEvent(self, event): if self.isstarted() and event.key() == Qt.Key_Escape: self.stop() return return super(ServeDialog, self).keyPressEvent(event) def closeEvent(self, event): if self.isstarted(): self._minimizetotray() event.ignore() return return super(ServeDialog, self).closeEvent(event) @util.propertycache def _trayicon(self): icon = QSystemTrayIcon(self.windowIcon(), parent=self) icon.activated.connect(self._restorefromtray) icon.setToolTip(self.windowTitle()) # TODO: context menu return icon # TODO: minimize to tray by minimize button @pyqtSlot() def _minimizetotray(self): self._trayicon.show() self._trayicon.showMessage(_('TortoiseHg Web Server'), _('Running at %s') % self.rooturl) self.hide() @pyqtSlot() def _restorefromtray(self): self._trayicon.hide() self.show() @pyqtSlot() def on_settings_button_clicked(self): from tortoisehg.hgqt import settings settings.SettingsDialog(parent=self, focus='web.name').exec_()
class ServeDialog(QDialog): """Dialog for serving repositories via web""" def __init__(self, ui, webconf, parent=None): super(ServeDialog, self).__init__(parent) self.setWindowFlags((self.windowFlags() | Qt.WindowMinimizeButtonHint) & ~Qt.WindowContextHelpButtonHint) self.setWindowIcon(qtlib.geticon('hg-serve')) self._qui = Ui_ServeDialog() self._qui.setupUi(self) self._initwebconf(webconf) self._initcmd(ui) self._initactions() self._updateform() def _initcmd(self, ui): # TODO: forget old logs? self._log_edit = cmdui.LogWidget(self) self._qui.details_tabs.addTab(self._log_edit, _('Log')) # as of hg 3.0, hgweb does not cooperate with command-server channel self._agent = cmdcore.CmdAgent(ui, self, worker='proc') self._agent.outputReceived.connect(self._log_edit.appendLog) self._agent.busyChanged.connect(self._updateform) def _initwebconf(self, webconf): self._webconf_form = WebconfForm(webconf=webconf, parent=self) self._qui.details_tabs.addTab(self._webconf_form, _('Repositories')) def _initactions(self): self._qui.start_button.clicked.connect(self.start) self._qui.stop_button.clicked.connect(self.stop) @pyqtSlot() def _updateform(self): """update form availability and status text""" self._updatestatus() self._qui.start_button.setEnabled(not self.isstarted()) self._qui.stop_button.setEnabled(self.isstarted()) self._qui.settings_button.setEnabled(not self.isstarted()) self._qui.port_edit.setEnabled(not self.isstarted()) self._webconf_form.setEnabled(not self.isstarted()) def _updatestatus(self): if self.isstarted(): # TODO: escape special chars link = '<a href="%s">%s</a>' % (self.rooturl, self.rooturl) msg = _('Running at %s') % link else: msg = _('Stopped') self._qui.status_edit.setText(msg) @pyqtSlot() def start(self): """Start web server""" if self.isstarted(): return self._agent.runCommand(map(hglib.tounicode, self._cmdargs())) def _cmdargs(self): """Build command args to run server""" a = ['serve', '--port', str(self.port), '-v'] if self._singlerepo: a += ['-R', self._singlerepo] else: a += ['--web-conf', self._tempwebconf()] return a def _tempwebconf(self): """Save current webconf to temporary file; return its path""" if not hasattr(self._webconf, 'write'): return self._webconf.path fd, fname = tempfile.mkstemp(prefix='webconf_', dir=qtlib.gettempdir()) f = os.fdopen(fd, 'w') try: self._webconf.write(f) return fname finally: f.close() @property def _webconf(self): """Selected webconf object""" return self._webconf_form.webconf @property def _singlerepo(self): """Return repository path if serving single repository""" # NOTE: we cannot use web-conf to serve single repository at '/' path if len(self._webconf['paths']) != 1: return path = self._webconf.get('paths', '/') if path and '*' not in path: # exactly a single repo (no wildcard) return path @pyqtSlot() def stop(self): """Stop web server""" self._agent.abortCommands() def reject(self): self.stop() super(ServeDialog, self).reject() def isstarted(self): """Is the web server running?""" return self._agent.isBusy() @property def rooturl(self): """Returns the root URL of the web server""" # TODO: scheme, hostname ? return 'http://localhost:%d' % self.port @property def port(self): """Port number of the web server""" return int(self._qui.port_edit.value()) def setport(self, port): self._qui.port_edit.setValue(port) def keyPressEvent(self, event): if self.isstarted() and event.key() == Qt.Key_Escape: self.stop() return return super(ServeDialog, self).keyPressEvent(event) def closeEvent(self, event): if self.isstarted(): self._minimizetotray() event.ignore() return return super(ServeDialog, self).closeEvent(event) @util.propertycache def _trayicon(self): icon = QSystemTrayIcon(self.windowIcon(), parent=self) icon.activated.connect(self._restorefromtray) icon.setToolTip(self.windowTitle()) # TODO: context menu return icon # TODO: minimize to tray by minimize button @pyqtSlot() def _minimizetotray(self): self._trayicon.show() self._trayicon.showMessage(_('TortoiseHg Web Server'), _('Running at %s') % self.rooturl) self.hide() @pyqtSlot() def _restorefromtray(self): self._trayicon.hide() self.show() @pyqtSlot() def on_settings_button_clicked(self): from tortoisehg.hgqt import settings settings.SettingsDialog(parent=self, focus='web.name').exec_()