def __init__(self, ui, notebook=None, namespace=None, basename=None, append=None, text=None, template_options=None, attachments=None): self.config = get_config('quicknote.conf') self.uistate = self.config['QuickNoteDialog'] Dialog.__init__(self, ui, _('Quick Note')) self._updating_title = False self._title_set_manually = not basename is None self.attachments = attachments if notebook and not isinstance(notebook, basestring): notebook = notebook.uri self.uistate.setdefault('lastnotebook', None, basestring) if self.uistate['lastnotebook']: notebook = notebook or self.uistate['lastnotebook'] self.config['Namespaces'].setdefault(notebook, None, basestring) namespace = namespace or self.config['Namespaces'][notebook] self.form = InputForm() self.vbox.pack_start(self.form, False) # TODO dropdown could use an option "Other..." label = gtk.Label(_('Notebook')+': ') label.set_alignment(0.0, 0.5) self.form.attach(label, 0,1, 0,1, xoptions=gtk.FILL) # T: Field to select Notebook from drop down list self.notebookcombobox = NotebookComboBox(current=notebook) self.notebookcombobox.connect('changed', self.on_notebook_changed) self.form.attach(self.notebookcombobox, 1,2, 0,1) self._init_inputs(namespace, basename, append, text, template_options) self.uistate['lastnotebook'] = notebook self._set_autocomplete(notebook)
def __init__(self, window, notebook=None, page=None, namespace=None, basename=None, append=None, text=None, template_options=None, attachments=None): assert page is None, 'TODO' manager = ConfigManager() # FIXME should be passed in self.config = manager.get_config_dict('quicknote.conf') self.uistate = self.config['QuickNoteDialog'] Dialog.__init__(self, window, _('Quick Note')) self._updating_title = False self._title_set_manually = not basename is None self.attachments = attachments if notebook and not isinstance(notebook, str): notebook = notebook.uri self.uistate.setdefault('lastnotebook', None, str) if self.uistate['lastnotebook']: notebook = notebook or self.uistate['lastnotebook'] self.config['Namespaces'].setdefault(notebook, None, str) namespace = namespace or self.config['Namespaces'][notebook] self.form = InputForm() self.vbox.pack_start(self.form, False, True, 0) # TODO dropdown could use an option "Other..." label = Gtk.Label(label=_('Notebook') + ': ') label.set_alignment(0.0, 0.5) self.form.attach(label, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL) # T: Field to select Notebook from drop down list self.notebookcombobox = NotebookComboBox(current=notebook) self.notebookcombobox.connect('changed', self.on_notebook_changed) self.form.attach(self.notebookcombobox, 1, 2, 0, 1) self._init_inputs(namespace, basename, append, text, template_options) self.uistate['lastnotebook'] = notebook self._set_autocomplete(notebook)
class QuickNoteDialog(Dialog): '''Dialog bound to a specific notebook''' def __init__(self, window, notebook=None, page=None, namespace=None, basename=None, append=None, text=None, template_options=None, attachments=None): assert page is None, 'TODO' manager = ConfigManager() # FIXME should be passed in self.config = manager.get_config_dict('quicknote.conf') self.uistate = self.config['QuickNoteDialog'] Dialog.__init__(self, window, _('Quick Note')) self._updating_title = False self._title_set_manually = not basename is None self.attachments = attachments if notebook and not isinstance(notebook, str): notebook = notebook.uri self.uistate.setdefault('lastnotebook', None, str) if self.uistate['lastnotebook']: notebook = notebook or self.uistate['lastnotebook'] self.config['Namespaces'].setdefault(notebook, None, str) namespace = namespace or self.config['Namespaces'][notebook] self.form = InputForm() self.vbox.pack_start(self.form, False, True, 0) # TODO dropdown could use an option "Other..." label = Gtk.Label(label=_('Notebook') + ': ') label.set_alignment(0.0, 0.5) self.form.attach(label, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL) # T: Field to select Notebook from drop down list self.notebookcombobox = NotebookComboBox(current=notebook) self.notebookcombobox.connect('changed', self.on_notebook_changed) self.form.attach(self.notebookcombobox, 1, 2, 0, 1) self._init_inputs(namespace, basename, append, text, template_options) self.uistate['lastnotebook'] = notebook self._set_autocomplete(notebook) def _init_inputs(self, namespace, basename, append, text, template_options, custom=None): if template_options is None: template_options = {} else: template_options = template_options.copy() if namespace is not None and basename is not None: page = namespace + ':' + basename else: page = namespace or basename self.form.add_inputs(( ('page', 'page', _('Page')), ('namespace', 'namespace', _('Page section')), # T: text entry field ('new_page', 'bool', _('Create a new page for each note') ), # T: checkbox in Quick Note dialog ('basename', 'string', _('Title')) # T: text entry field )) self.form.update({ 'page': page, 'namespace': namespace, 'new_page': True, 'basename': basename, }) self.uistate.setdefault('open_page', True) self.uistate.setdefault('new_page', True) if basename: self.uistate['new_page'] = True # Be consistent with input # Set up the inputs and set page/ namespace to switch on # toggling the checkbox self.form.widgets['page'].set_no_show_all(True) self.form.widgets['namespace'].set_no_show_all(True) if append is None: self.form['new_page'] = bool(self.uistate['new_page']) else: self.form['new_page'] = not append def switch_input(*a): if self.form['new_page']: self.form.widgets['page'].hide() self.form.widgets['namespace'].show() self.form.widgets['basename'].set_sensitive(True) else: self.form.widgets['page'].show() self.form.widgets['namespace'].hide() self.form.widgets['basename'].set_sensitive(False) switch_input() self.form.widgets['new_page'].connect('toggled', switch_input) self.open_page_check = Gtk.CheckButton.new_with_mnemonic( _('Open _Page')) # T: Option in quicknote dialog # Don't use "O" as accelerator here to avoid conflict with "Ok" self.open_page_check.set_active(self.uistate['open_page']) self.action_area.pack_start(self.open_page_check, False, True, 0) self.action_area.set_child_secondary(self.open_page_check, True) # Add the main textview and hook up the basename field to # sync with first line of the textview window, textview = ScrolledTextView() self.textview = textview self.textview.set_editable(True) self.vbox.pack_start(window, True, True, 0) self.form.widgets['basename'].connect('changed', self.on_title_changed) self.textview.get_buffer().connect('changed', self.on_text_changed) # Initialize text from template template = get_template('plugins', 'quicknote.txt') template_options['text'] = text or '' template_options.setdefault('url', '') lines = [] template.process(lines, template_options) buffer = self.textview.get_buffer() buffer.set_text(''.join(lines)) begin, end = buffer.get_bounds() buffer.place_cursor(begin) buffer.set_modified(False) self.connect('delete-event', self.do_delete_event) def on_notebook_changed(self, o): notebook = self.notebookcombobox.get_notebook() if not notebook or notebook == self.uistate['lastnotebook']: return self.uistate['lastnotebook'] = notebook self.config['Namespaces'].setdefault(notebook, None, str) namespace = self.config['Namespaces'][notebook] if namespace: self.form['namespace'] = namespace self._set_autocomplete(notebook) def _set_autocomplete(self, notebook): if notebook: try: if isinstance(notebook, str): notebook = NotebookInfo(notebook) obj, x = build_notebook(notebook) self.form.widgets['namespace'].notebook = obj self.form.widgets['page'].notebook = obj logger.debug('Notebook for autocomplete: %s (%s)', obj, notebook) except: logger.exception('Could not set notebook: %s', notebook) else: self.form.widgets['namespace'].notebook = None self.form.widgets['page'].notebook = None logger.debug('Notebook for autocomplete unset') def do_response(self, id): if id == Gtk.ResponseType.DELETE_EVENT: if self.textview.get_buffer().get_modified(): ok = QuestionDialog(self, _('Discard note?')).run() # T: confirm closing quick note dialog if ok: Dialog.do_response(self, id) # else pass else: Dialog.do_response(self, id) else: Dialog.do_response(self, id) def do_delete_event(self, *a): # Block deletion if do_response did not yet destroy the dialog return True def run(self): self.textview.grab_focus() Dialog.run(self) def show(self): self.textview.grab_focus() Dialog.show(self) def save_uistate(self): notebook = self.notebookcombobox.get_notebook() self.uistate['lastnotebook'] = notebook self.uistate['new_page'] = self.form['new_page'] self.uistate['open_page'] = self.open_page_check.get_active() if notebook is not None: if self.uistate['new_page']: self.config['Namespaces'][notebook] = self.form['namespace'] else: self.config['Namespaces'][notebook] = self.form['page'] self.config.write() def on_title_changed(self, o): o.set_input_valid(True) if not self._updating_title: self._title_set_manually = True def on_text_changed(self, buffer): if not self._title_set_manually: # Automatically generate a (valid) page name self._updating_title = True start, end = buffer.get_bounds() title = start.get_text(end).strip()[:50] # Cut off at 50 characters to prevent using a whole paragraph title = title.replace(':', '') if '\n' in title: title, _ = title.split('\n', 1) try: title = Path.makeValidPageName(title.replace(':', '')) self.form['basename'] = title except ValueError: pass self._updating_title = False def do_response_ok(self): buffer = self.textview.get_buffer() start, end = buffer.get_bounds() text = start.get_text(end) # HACK: change "[]" at start of line into "[ ]" so checkboxes get inserted correctly text = re.sub(r'(?m)^(\s*)\[\](\s)', r'\1[ ]\2', text) # Specify "(?m)" instead of re.M since "flags" keyword is not # supported in python 2.6 notebook = self._get_notebook() if notebook is None: return False if self.form['new_page']: if not self.form.widgets['namespace'].get_input_valid() \ or not self.form['basename']: if not self.form['basename']: entry = self.form.widgets['basename'] entry.set_input_valid(False, show_empty_invalid=True) return False path = self.form['namespace'] + self.form['basename'] self.create_new_page(notebook, path, text) else: if not self.form.widgets['page'].get_input_valid() \ or not self.form['page']: return False path = self.form['page'] self.append_to_page(notebook, path, '\n------\n' + text) if self.attachments: self.import_attachments(notebook, path, self.attachments) if self.open_page_check.get_active(): self.hide() ZIM_APPLICATION.present(notebook, path) return True def _get_notebook(self): uri = self.notebookcombobox.get_notebook() notebook, p = build_notebook(Dir(uri)) return notebook def create_new_page(self, notebook, path, text): page = notebook.get_new_page(path) page.parse('wiki', text) # FIXME format hard coded notebook.store_page(page) def append_to_page(self, notebook, path, text): page = notebook.get_page(path) page.parse('wiki', text, append=True) # FIXME format hard coded notebook.store_page(page) def import_attachments(self, notebook, path, dir): attachments = notebook.get_attachments_dir(path) attachments = Dir(attachments.path) # XXX for name in dir.list(): # FIXME could use list objects, or list_files() file = dir.file(name) if not file.isdir(): file.copyto(attachments)
class QuickNoteDialog(BoundQuickNoteDialog): '''Dialog which includes a notebook chooser''' def __init__(self, window, notebook=None, page=None, namespace=None, basename=None, append=None, text=None, template_options=None, attachments=None): assert page is None, 'TODO' manager = ConfigManager() # FIXME should be passed in self.config = manager.get_config_dict('quicknote.conf') self.uistate = self.config['QuickNoteDialog'] Dialog.__init__(self, window, _('Quick Note')) self._updating_title = False self._title_set_manually = not basename is None self.attachments = attachments if notebook and not isinstance(notebook, basestring): notebook = notebook.uri self.uistate.setdefault('lastnotebook', None, basestring) if self.uistate['lastnotebook']: notebook = notebook or self.uistate['lastnotebook'] self.config['Namespaces'].setdefault(notebook, None, basestring) namespace = namespace or self.config['Namespaces'][notebook] self.form = InputForm() self.vbox.pack_start(self.form, False) # TODO dropdown could use an option "Other..." label = gtk.Label(_('Notebook') + ': ') label.set_alignment(0.0, 0.5) self.form.attach(label, 0, 1, 0, 1, xoptions=gtk.FILL) # T: Field to select Notebook from drop down list self.notebookcombobox = NotebookComboBox(current=notebook) self.notebookcombobox.connect('changed', self.on_notebook_changed) self.form.attach(self.notebookcombobox, 1, 2, 0, 1) self._init_inputs(namespace, basename, append, text, template_options) self.uistate['lastnotebook'] = notebook self._set_autocomplete(notebook) def save_uistate(self): notebook = self.notebookcombobox.get_notebook() self.uistate['lastnotebook'] = notebook self.uistate['new_page'] = self.form['new_page'] self.uistate['open_page'] = self.open_page.get_active() if notebook is not None: if self.uistate['new_page']: self.config['Namespaces'][notebook] = self.form['namespace'] else: self.config['Namespaces'][notebook] = self.form['page'] self.config.write() def on_notebook_changed(self, o): notebook = self.notebookcombobox.get_notebook() if not notebook or notebook == self.uistate['lastnotebook']: return self.uistate['lastnotebook'] = notebook self.config['Namespaces'].setdefault(notebook, None, basestring) namespace = self.config['Namespaces'][notebook] if namespace: self.form['namespace'] = namespace self._set_autocomplete(notebook) def _set_autocomplete(self, notebook): if notebook: if isinstance(notebook, basestring): notebook = NotebookInfo(notebook) obj, x = build_notebook(notebook) self.form.widgets['namespace'].notebook = obj self.form.widgets['page'].notebook = obj logger.debug('Notebook for autocomplete: %s (%s)', obj, notebook) else: self.form.widgets['namespace'].notebook = None self.form.widgets['page'].notebook = None logger.debug('Notebook for autocomplete unset') def _get_ui(self): start_server_if_not_running() notebook = self.notebookcombobox.get_notebook() if notebook: return ServerProxy().get_notebook(notebook) else: return None
def __init__(self, notebookinfo=None, port=8080, public=True, **opts): '''Constructor @param notebookinfo: the notebook location @param port: the http port to serve on @param public: allow connections to the server from other computers - if C{False} can only connect from localhost @param opts: options for L{WWWInterface.__init__()} ''' gtk.Window.__init__(self) self.set_title('Zim - ' + _('Web Server')) # T: Window title self.set_border_width(10) self.connect('destroy', lambda a: gtk.main_quit()) self.interface_opts = opts self.httpd = None self._source_id = None # Widgets self.status_label = gtk.Label() self.status_label.set_markup('<i>' + _('Server not started') + '</i>') # T: Status in web server gui self.start_button = IconButton('gtk-media-play') self.start_button.connect('clicked', lambda o: self.start()) self.stop_button = IconButton('gtk-media-stop') self.stop_button.connect('clicked', lambda o: self.stop()) self.stop_button.set_sensitive(False) if gtk.gtk_version >= (2, 10): self.link_button = gtk.LinkButton('') self.link_button.set_sensitive(False) gtk.link_button_set_uri_hook(lambda o, url: webbrowser.open(url)) else: self.link_button = None self.notebookcombobox = NotebookComboBox(current=notebookinfo) self.open_button = IconButton('gtk-index') self.open_button.connect('clicked', lambda *a: NotebookDialog(self).run()) self.portentry = gtk.SpinButton() self.portentry.set_numeric(True) self.portentry.set_range(80, 10000) self.portentry.set_increments(1, 80) self.portentry.set_value(port) self.public_checkbox = gtk.CheckButton(label=_('Allow public access')) # T: Checkbox in web server gui self.public_checkbox.set_active(public) # Build the interface vbox = gtk.VBox() self.add(vbox) hbox = gtk.HBox(spacing=12) hbox.pack_start(self.start_button, False) hbox.pack_start(self.stop_button, False) hbox.pack_start(self.status_label, False) vbox.add(hbox) table = input_table_factory(( (_('Notebook'), self.notebookcombobox, self.open_button), # T: Field in web server gui (_('Port'), self.portentry), # T: Field in web server gui for HTTP port (e.g. port 80) self.public_checkbox)) vbox.add(table) if self.link_button: hbox = gtk.HBox() hbox.pack_end(self.link_button, False) vbox.add(hbox)
class ServerWindow(gtk.Window): def __init__(self, notebookinfo=None, port=8080, public=True, **opts): '''Constructor @param notebookinfo: the notebook location @param port: the http port to serve on @param public: allow connections to the server from other computers - if C{False} can only connect from localhost @param opts: options for L{WWWInterface.__init__()} ''' gtk.Window.__init__(self) self.set_title('Zim - ' + _('Web Server')) # T: Window title self.set_border_width(10) self.connect('destroy', lambda a: gtk.main_quit()) self.interface_opts = opts self.httpd = None self._source_id = None # Widgets self.status_label = gtk.Label() self.status_label.set_markup('<i>' + _('Server not started') + '</i>') # T: Status in web server gui self.start_button = IconButton('gtk-media-play') self.start_button.connect('clicked', lambda o: self.start()) self.stop_button = IconButton('gtk-media-stop') self.stop_button.connect('clicked', lambda o: self.stop()) self.stop_button.set_sensitive(False) if gtk.gtk_version >= (2, 10): self.link_button = gtk.LinkButton('') self.link_button.set_sensitive(False) gtk.link_button_set_uri_hook(lambda o, url: webbrowser.open(url)) else: self.link_button = None self.notebookcombobox = NotebookComboBox(current=notebookinfo) self.open_button = IconButton('gtk-index') self.open_button.connect('clicked', lambda *a: NotebookDialog(self).run()) self.portentry = gtk.SpinButton() self.portentry.set_numeric(True) self.portentry.set_range(80, 10000) self.portentry.set_increments(1, 80) self.portentry.set_value(port) self.public_checkbox = gtk.CheckButton(label=_('Allow public access')) # T: Checkbox in web server gui self.public_checkbox.set_active(public) # Build the interface vbox = gtk.VBox() self.add(vbox) hbox = gtk.HBox(spacing=12) hbox.pack_start(self.start_button, False) hbox.pack_start(self.stop_button, False) hbox.pack_start(self.status_label, False) vbox.add(hbox) table = input_table_factory(( (_('Notebook'), self.notebookcombobox, self.open_button), # T: Field in web server gui (_('Port'), self.portentry), # T: Field in web server gui for HTTP port (e.g. port 80) self.public_checkbox)) vbox.add(table) if self.link_button: hbox = gtk.HBox() hbox.pack_end(self.link_button, False) vbox.add(hbox) def open_notebook(self, notebook): '''Sets the notebook in the combobox This method is called by the NotebookDialog when a notebook is opened. ''' self.notebookcombobox.set_notebook(notebook) def start(self): # Start server try: uri = self.notebookcombobox.get_notebook() if uri: notebook, x = build_notebook(NotebookInfo(uri)) if not notebook: return else: return port = int(self.portentry.get_value()) public = self.public_checkbox.get_active() self.httpd = make_server(notebook, port, public, **self.interface_opts) if sys.platform == 'win32': # glib io watch conflicts with socket use on windows.. # idle handler uses a bit to much CPU for my taste, # timeout every 0.5 sec is better self.httpd.timeout = 0.1 # 100 ms self._source_id = glib.timeout_add(500, self.do_serve_on_poll) else: self.httpd.timeout = 3 # if no response after 3 sec, drop it self._source_id = glib.io_add_watch( self.httpd.fileno(), glib.IO_IN | glib.IO_OUT | glib.IO_ERR | glib.IO_HUP | glib.IO_PRI, # any event.. self.do_serve_on_io) logger.info("Serving HTTP on %s port %i...", self.httpd.server_name, self.httpd.server_port) except Exception, error: ErrorDialog(self, error).run() return # Update UI self.notebookcombobox.set_sensitive(False) self.portentry.set_sensitive(False) self.public_checkbox.set_sensitive(False) self.open_button.set_sensitive(False) self.start_button.set_sensitive(False) self.stop_button.set_sensitive(True) self.status_label.set_markup('<i>' + _('Server started') + '</i>') # T: Status in web server gui #if self.public_checkbox.get_active(): # url = 'http://%s:%i' % (self.httpd.server_name, self.httpd.server_port) #else: # url = 'http://localhost:%i' % self.httpd.server_port url = 'http://localhost:%i' % self.httpd.server_port if self.link_button: self.link_button.set_uri(url) self.link_button.set_label(url) self.link_button.set_sensitive(True)
def __init__(self, notebookinfo=None, port=8080, public=True, **opts): '''Constructor @param notebookinfo: the notebook location @param port: the http port to serve on @param public: allow connections to the server from other computers - if C{False} can only connect from localhost @param opts: options for L{WWWInterface.__init__()} ''' gtk.Window.__init__(self) self.set_title('Zim - ' + _('Web Server')) # T: Window title self.set_border_width(10) self.connect('destroy', lambda a: gtk.main_quit()) self.interface_opts = opts self.httpd = None self._source_id = None # Widgets self.status_label = gtk.Label() self.status_label.set_markup('<i>'+_('Server not started')+'</i>') # T: Status in web server gui self.start_button = IconButton('gtk-media-play') self.start_button.connect('clicked', lambda o: self.start()) self.stop_button = IconButton('gtk-media-stop') self.stop_button.connect('clicked', lambda o: self.stop()) self.stop_button.set_sensitive(False) if gtk.gtk_version >= (2, 10): self.link_button = gtk.LinkButton('') self.link_button.set_sensitive(False) gtk.link_button_set_uri_hook(lambda o, url: webbrowser.open(url)) else: self.link_button = None self.notebookcombobox = NotebookComboBox(current=notebookinfo) self.open_button = IconButton('gtk-index') self.open_button.connect('clicked', lambda *a: NotebookDialog(self).run()) self.portentry = gtk.SpinButton() self.portentry.set_numeric(True) self.portentry.set_range(80, 10000) self.portentry.set_increments(1, 80) self.portentry.set_value(port) self.public_checkbox = gtk.CheckButton(label=_('Allow public access')) # T: Checkbox in web server gui self.public_checkbox.set_active(public) # Build the interface vbox = gtk.VBox() self.add(vbox) hbox = gtk.HBox(spacing=12) hbox.pack_start(self.start_button, False) hbox.pack_start(self.stop_button, False) hbox.pack_start(self.status_label, False) vbox.add(hbox) table = input_table_factory(( (_('Notebook'), self.notebookcombobox, self.open_button), # T: Field in web server gui (_('Port'), self.portentry), # T: Field in web server gui for HTTP port (e.g. port 80) self.public_checkbox )) vbox.add(table) if self.link_button: hbox = gtk.HBox() hbox.pack_end(self.link_button, False) vbox.add(hbox)
class ServerWindow(gtk.Window): def __init__(self, notebookinfo=None, port=8080, public=True, **opts): '''Constructor @param notebookinfo: the notebook location @param port: the http port to serve on @param public: allow connections to the server from other computers - if C{False} can only connect from localhost @param opts: options for L{WWWInterface.__init__()} ''' gtk.Window.__init__(self) self.set_title('Zim - ' + _('Web Server')) # T: Window title self.set_border_width(10) self.connect('destroy', lambda a: gtk.main_quit()) self.interface_opts = opts self.httpd = None self._source_id = None # Widgets self.status_label = gtk.Label() self.status_label.set_markup('<i>'+_('Server not started')+'</i>') # T: Status in web server gui self.start_button = IconButton('gtk-media-play') self.start_button.connect('clicked', lambda o: self.start()) self.stop_button = IconButton('gtk-media-stop') self.stop_button.connect('clicked', lambda o: self.stop()) self.stop_button.set_sensitive(False) if gtk.gtk_version >= (2, 10): self.link_button = gtk.LinkButton('') self.link_button.set_sensitive(False) gtk.link_button_set_uri_hook(lambda o, url: webbrowser.open(url)) else: self.link_button = None self.notebookcombobox = NotebookComboBox(current=notebookinfo) self.open_button = IconButton('gtk-index') self.open_button.connect('clicked', lambda *a: NotebookDialog(self).run()) self.portentry = gtk.SpinButton() self.portentry.set_numeric(True) self.portentry.set_range(80, 10000) self.portentry.set_increments(1, 80) self.portentry.set_value(port) self.public_checkbox = gtk.CheckButton(label=_('Allow public access')) # T: Checkbox in web server gui self.public_checkbox.set_active(public) # Build the interface vbox = gtk.VBox() self.add(vbox) hbox = gtk.HBox(spacing=12) hbox.pack_start(self.start_button, False) hbox.pack_start(self.stop_button, False) hbox.pack_start(self.status_label, False) vbox.add(hbox) table = input_table_factory(( (_('Notebook'), self.notebookcombobox, self.open_button), # T: Field in web server gui (_('Port'), self.portentry), # T: Field in web server gui for HTTP port (e.g. port 80) self.public_checkbox )) vbox.add(table) if self.link_button: hbox = gtk.HBox() hbox.pack_end(self.link_button, False) vbox.add(hbox) def open_notebook(self, notebook): '''Sets the notebook in the combobox This method is called by the NotebookDialog when a notebook is opened. ''' self.notebookcombobox.set_notebook(notebook) def start(self): # Start server try: uri = self.notebookcombobox.get_notebook() if uri: notebook, x = build_notebook(NotebookInfo(uri)) if not notebook: return else: return port = int(self.portentry.get_value()) public = self.public_checkbox.get_active() self.httpd = make_server(notebook, port, public, **self.interface_opts) if sys.platform == 'win32': # glib io watch conflicts with socket use on windows.. # idle handler uses a bit to much CPU for my taste, # timeout every 0.5 sec is better self.httpd.timeout = 0.1 # 100 ms self._source_id = glib.timeout_add(500, self.do_serve_on_poll) else: self.httpd.timeout = 3 # if no response after 3 sec, drop it self._source_id = glib.io_add_watch( self.httpd.fileno(), glib.IO_IN | glib.IO_OUT | glib.IO_ERR | glib.IO_HUP | glib.IO_PRI, # any event.. self.do_serve_on_io ) logger.info("Serving HTTP on %s port %i...", self.httpd.server_name, self.httpd.server_port) except Exception, error: ErrorDialog(self, error).run() return # Update UI self.notebookcombobox.set_sensitive(False) self.portentry.set_sensitive(False) self.public_checkbox.set_sensitive(False) self.open_button.set_sensitive(False) self.start_button.set_sensitive(False) self.stop_button.set_sensitive(True) self.status_label.set_markup('<i>'+_('Server started')+'</i>') # T: Status in web server gui #if self.public_checkbox.get_active(): # url = 'http://%s:%i' % (self.httpd.server_name, self.httpd.server_port) #else: # url = 'http://localhost:%i' % self.httpd.server_port url = 'http://localhost:%i' % self.httpd.server_port if self.link_button: self.link_button.set_uri(url) self.link_button.set_label(url) self.link_button.set_sensitive(True)
def runTest(self): from zim.gui.notebookdialog import NotebookComboBox, NotebookTreeModel class MyList(list): pass notebooklist = MyList([ NotebookInfo('file:///test/foo', name='Foo'), NotebookInfo('file:///test/bar', name='Bar') ]) notebooklist.default = notebooklist[1] notebooklist.write = lambda: None model = NotebookTreeModel(notebooklist) combobox = NotebookComboBox(model) self.assertEqual(combobox.get_notebook(), notebooklist[1].uri) # default combobox.set_active(-1) self.assertEqual(combobox.get_notebook(), None) combobox.set_notebook(notebooklist[0].uri) self.assertEqual(combobox.get_notebook(), notebooklist[0].uri) combobox.set_notebook('file:///yet/another/notebook') self.assertEqual(combobox.get_notebook(), None) combobox.set_notebook('file:///yet/another/notebook', append=True) self.assertEqual(combobox.get_notebook(), 'file:///yet/another/notebook')
def __init__(self, server): '''Constructor needs a Server object to control''' gtk.Window.__init__(self) self.set_icon_from_file(data_file('zim.png').path) # TODO new icon for WWW frontend self.set_border_width(10) self.connect('destroy', lambda a: gtk.main_quit()) self.server = server self.server.connect_after('started', self.do_server_started) self.server.connect_after('stopped', self.do_server_stopped) def _start(*a): self.server.set_notebook( self.notebookcombobox.get_notebook() ) self.server.start() def _stop(*a): self.server.stop() # Build the interface vbox = gtk.VBox() self.add(vbox) # first some art work #~ path = data_file('globe_banner_small.png').path #~ image = gtk.Image() #~ image.set_from_file(path) # new_from_file not in 2.6 #~ align = gtk.Alignment(0,0.5, 0,0) #~ align.add(image) #~ vbox.add(align) # Table with status table = gtk.Table(4, 2, False) table.set_col_spacings(12) table.set_row_spacings(5) hbox = gtk.HBox() hbox.pack_start(table, False) vbox.pack_start(hbox, False) self.status_icon = gtk.image_new_from_stock(*stock_stopped) table.attach(self.status_icon, 0,2, 0,2) self.status_label = gtk.Label() self.status_label.set_markup('<i>'+_('Server not started')+'</i>') # T: Status in web server gui table.attach(self.status_label, 4,5, 0,1) self.link_button = gtk.LinkButton('') # FIXME since 2.10 self.link_button.set_sensitive(False) gtk.link_button_set_uri_hook(lambda o, url: webbrowser.open(url)) table.attach(self.link_button, 4,5, 1,2) start_button = IconButton('gtk-media-play') start_button.connect('clicked', _start) table.attach(start_button, 2,3, 0,1) stop_button = IconButton('gtk-media-stop') stop_button.connect('clicked', _stop) table.attach(stop_button, 3,4, 0,1) # Table with server properties table = gtk.Table(3, 3, False) table.set_col_spacings(12) table.set_row_spacings(5) vbox.add(table) table.attach(gtk.Label(_('Notebook')+': '), 0,1, 0,1) # T: Field in web server gui self.notebookcombobox = NotebookComboBox(current=server.interface.notebook) self.notebookcombobox.connect('changed', _stop) table.attach(self.notebookcombobox, 1,2, 0,1) open_button = IconButton('gtk-index') open_button.connect('clicked', lambda *a: NotebookDialog(self).run()) table.attach(open_button, 2,3, 0,1) table.attach(gtk.Label(_('Port')+': '), 0,1, 1,2) # T: Field in web server gui for HTTLP port (e.g. port 80) self.portentry = gtk.SpinButton() self.portentry.set_numeric(True) self.portentry.set_range(80, 10000) self.portentry.set_increments(1, 80) self.portentry.set_value(self.server.port) self.portentry.connect('value-changed', _stop) self.portentry.connect('value-changed', lambda o: self.server.set_port(self.portentry.get_value_as_int())) table.attach(self.portentry, 1,2, 1,2)
def __init__(self, notebookinfo=None, port=8080, public=True, **opts): '''Constructor @param notebookinfo: the notebook location @param port: the http port to serve on @param public: allow connections to the server from other computers - if C{False} can only connect from localhost @param opts: options for L{WWWInterface.__init__()} ''' GObject.GObject.__init__(self) self.set_title('Zim - ' + _('Web Server')) # T: Window title self.set_border_width(10) self.interface_opts = opts self.httpd = None self._source_id = None # Widgets self.status_label = Gtk.Label() self.status_label.set_markup('<i>' + _('Server not started') + '</i>') # T: Status in web server gui self.start_button = IconButton('gtk-media-play') self.start_button.connect('clicked', lambda o: self.start()) self.stop_button = IconButton('gtk-media-stop') self.stop_button.connect('clicked', lambda o: self.stop()) self.stop_button.set_sensitive(False) self.link_button = Gtk.LinkButton('') self.link_button.set_sensitive(False) self.notebookcombobox = NotebookComboBox(current=notebookinfo) self.open_button = IconButton('gtk-index') self.open_button.connect('clicked', lambda *a: NotebookDialog(self).run()) self.portentry = Gtk.SpinButton() self.portentry.set_numeric(True) self.portentry.set_range(80, 10000) self.portentry.set_increments(1, 80) self.portentry.set_value(port) self.public_checkbox = Gtk.CheckButton.new_with_mnemonic( _('Allow public access')) # T: Checkbox in web server gui self.public_checkbox.set_active(public) self.templatecombobox = Gtk.ComboBoxText.new() template_names = [name for name, _ in list_templates('html')] for name in template_names: self.templatecombobox.append_text(name) self.templatecombobox.set_active(template_names.index('Default')) self.auth_checkbox = Gtk.CheckButton.new_with_mnemonic( _('Require authentication')) # T: checkbox in dialog for starting webserver self.username_input = InputEntry() self.password_input = InputEntry() self.password_input.set_visibility(False) # Build the interface vbox = Gtk.VBox() self.add(vbox) hbox = Gtk.HBox(spacing=12) hbox.pack_start(self.start_button, False, True, 0) hbox.pack_start(self.stop_button, False, True, 0) hbox.pack_start(self.status_label, False, True, 0) vbox.pack_start(hbox, False, False, 0) table = input_table_factory(( (_('Notebook'), self.notebookcombobox, self.open_button), # T: Field in web server gui (_('Port'), self.portentry), # T: Field in web server gui for HTTP port (e.g. port 80) (_('Template'), self.templatecombobox), # T: Field in web server gui for webpage template self.public_checkbox, self.auth_checkbox, (_('Username'), self.username_input), # T: Field in web server gui (_('Password'), self.password_input) # T: Field in web server gui )) vbox.pack_start(table, False, False, 0) if self.link_button: hbox = Gtk.HBox() hbox.pack_end(self.link_button, False, True, 0) vbox.pack_start(hbox, False, False, 0)
class ServerWindow(Gtk.Window): def __init__(self, notebookinfo=None, port=8080, public=True, **opts): '''Constructor @param notebookinfo: the notebook location @param port: the http port to serve on @param public: allow connections to the server from other computers - if C{False} can only connect from localhost @param opts: options for L{WWWInterface.__init__()} ''' GObject.GObject.__init__(self) self.set_title('Zim - ' + _('Web Server')) # T: Window title self.set_border_width(10) self.interface_opts = opts self.httpd = None self._source_id = None # Widgets self.status_label = Gtk.Label() self.status_label.set_markup('<i>' + _('Server not started') + '</i>') # T: Status in web server gui self.start_button = IconButton('gtk-media-play') self.start_button.connect('clicked', lambda o: self.start()) self.stop_button = IconButton('gtk-media-stop') self.stop_button.connect('clicked', lambda o: self.stop()) self.stop_button.set_sensitive(False) self.link_button = Gtk.LinkButton('') self.link_button.set_sensitive(False) self.notebookcombobox = NotebookComboBox(current=notebookinfo) self.open_button = IconButton('gtk-index') self.open_button.connect('clicked', lambda *a: NotebookDialog(self).run()) self.portentry = Gtk.SpinButton() self.portentry.set_numeric(True) self.portentry.set_range(80, 10000) self.portentry.set_increments(1, 80) self.portentry.set_value(port) self.public_checkbox = Gtk.CheckButton.new_with_mnemonic( _('Allow public access')) # T: Checkbox in web server gui self.public_checkbox.set_active(public) self.templatecombobox = Gtk.ComboBoxText.new() template_names = [name for name, _ in list_templates('html')] for name in template_names: self.templatecombobox.append_text(name) self.templatecombobox.set_active(template_names.index('Default')) self.auth_checkbox = Gtk.CheckButton.new_with_mnemonic( _('Require authentication')) # T: checkbox in dialog for starting webserver self.username_input = InputEntry() self.password_input = InputEntry() self.password_input.set_visibility(False) # Build the interface vbox = Gtk.VBox() self.add(vbox) hbox = Gtk.HBox(spacing=12) hbox.pack_start(self.start_button, False, True, 0) hbox.pack_start(self.stop_button, False, True, 0) hbox.pack_start(self.status_label, False, True, 0) vbox.pack_start(hbox, False, False, 0) table = input_table_factory(( (_('Notebook'), self.notebookcombobox, self.open_button), # T: Field in web server gui (_('Port'), self.portentry), # T: Field in web server gui for HTTP port (e.g. port 80) (_('Template'), self.templatecombobox), # T: Field in web server gui for webpage template self.public_checkbox, self.auth_checkbox, (_('Username'), self.username_input), # T: Field in web server gui (_('Password'), self.password_input) # T: Field in web server gui )) vbox.pack_start(table, False, False, 0) if self.link_button: hbox = Gtk.HBox() hbox.pack_end(self.link_button, False, True, 0) vbox.pack_start(hbox, False, False, 0) def open_notebook(self, notebook): '''Sets the notebook in the combobox This method is called by the NotebookDialog when a notebook is opened. ''' self.notebookcombobox.set_notebook(notebook) def start(self): # Start server try: uri = self.notebookcombobox.get_notebook() if uri: notebook, x = build_notebook(NotebookInfo(uri)) if not notebook: return else: return if not notebook.index.is_uptodate: for info in notebook.index.update_iter(): #logger.info('Indexing %s', info) pass # TODO meaningful info for above message port = int(self.portentry.get_value()) public = self.public_checkbox.get_active() self.interface_opts[ 'template'] = self.templatecombobox.get_active_text() require_auth = self.auth_checkbox.get_active() auth_creds = None if require_auth: auth_creds = (self.username_input.get_text(), self.password_input.get_text()) self.httpd = make_server(notebook, port, public, auth_creds=auth_creds, **self.interface_opts) if sys.platform == 'win32': # GObject io watch conflicts with socket use on windows.. # idle handler uses a bit to much CPU for my taste, # timeout every 0.5 sec is better self.httpd.timeout = 0.1 # 100 ms self._source_id = GObject.timeout_add(500, self.do_serve_on_poll) else: self.httpd.timeout = 3 # if no response after 3 sec, drop it self._source_id = GObject.io_add_watch( self.httpd.fileno(), GObject.IO_IN | GObject.IO_OUT | GObject.IO_ERR | GObject.IO_HUP | GObject.IO_PRI, # any event.. self.do_serve_on_io) logger.info("Serving HTTP on %s port %i...", self.httpd.server_name, self.httpd.server_port) except Exception as error: ErrorDialog(self, error).run() return # Update UI self.notebookcombobox.set_sensitive(False) self.portentry.set_sensitive(False) self.public_checkbox.set_sensitive(False) self.templatecombobox.set_sensitive(False) self.open_button.set_sensitive(False) self.start_button.set_sensitive(False) self.stop_button.set_sensitive(True) self.auth_checkbox.set_sensitive(False) self.username_input.set_sensitive(False) self.password_input.set_sensitive(False) self.status_label.set_markup('<i>' + _('Server started') + '</i>') # T: Status in web server gui #if self.public_checkbox.get_active(): # url = 'http://%s:%i' % (self.httpd.server_name, self.httpd.server_port) #else: # url = 'http://localhost:%i' % self.httpd.server_port url = 'http://localhost:%i' % self.httpd.server_port if self.link_button: self.link_button.set_uri(url) self.link_button.set_label(url) self.link_button.set_sensitive(True) def do_serve_on_io(self, fd, event): try: if event & GObject.IO_HUP: self.stop() raise Exception('Socket disconnected') else: self.httpd.handle_request() except: logger.exception('Exception while handling IO request:') return True # keep event running def do_serve_on_poll(self): self.httpd.handle_request() return True # keep event running def stop(self): # Stop server logger.debug('Stop server') if self._source_id is not None: GObject.source_remove(self._source_id) self._source_id = None if self.httpd: self.httpd.socket.close() # There is also a httpd.server_close(), but undocumented (!?) self.httpd = None # Update UI self.status_label.set_markup('<i>' + _('Server stopped') + '</i>') # T: Status in web server gui if self.link_button: self.link_button.set_sensitive(False) self.notebookcombobox.set_sensitive(True) self.portentry.set_sensitive(True) self.public_checkbox.set_sensitive(True) self.templatecombobox.set_sensitive(True) self.open_button.set_sensitive(True) self.stop_button.set_sensitive(False) self.start_button.set_sensitive(True) self.auth_checkbox.set_sensitive(True) self.username_input.set_sensitive(True) self.password_input.set_sensitive(True)
class QuickNoteDialog(BoundQuickNoteDialog): '''Dialog which includes a notebook chooser''' def __init__(self, ui, notebook=None, namespace=None, basename=None, append=None, text=None, template_options=None, attachments=None): self.config = get_config('quicknote.conf') self.uistate = self.config['QuickNoteDialog'] Dialog.__init__(self, ui, _('Quick Note')) self._updating_title = False self._title_set_manually = not basename is None self.attachments = attachments if notebook and not isinstance(notebook, basestring): notebook = notebook.uri self.uistate.setdefault('lastnotebook', None, basestring) if self.uistate['lastnotebook']: notebook = notebook or self.uistate['lastnotebook'] self.config['Namespaces'].setdefault(notebook, None, basestring) namespace = namespace or self.config['Namespaces'][notebook] self.form = InputForm() self.vbox.pack_start(self.form, False) # TODO dropdown could use an option "Other..." label = gtk.Label(_('Notebook')+': ') label.set_alignment(0.0, 0.5) self.form.attach(label, 0,1, 0,1, xoptions=gtk.FILL) # T: Field to select Notebook from drop down list self.notebookcombobox = NotebookComboBox(current=notebook) self.notebookcombobox.connect('changed', self.on_notebook_changed) self.form.attach(self.notebookcombobox, 1,2, 0,1) self._init_inputs(namespace, basename, append, text, template_options) self.uistate['lastnotebook'] = notebook self._set_autocomplete(notebook) def save_uistate(self): notebook = self.notebookcombobox.get_notebook() self.uistate['lastnotebook'] = notebook self.uistate['new_page'] = self.form['new_page'] self.uistate['open_page'] = self.open_page.get_active() if notebook is not None: if self.uistate['new_page']: self.config['Namespaces'][notebook] = self.form['namespace'] else: self.config['Namespaces'][notebook] = self.form['page'] self.config.write() def on_notebook_changed(self, o): notebook = self.notebookcombobox.get_notebook() if not notebook or notebook == self.uistate['lastnotebook']: return self.uistate['lastnotebook'] = notebook self.config['Namespaces'].setdefault(notebook, None, basestring) namespace = self.config['Namespaces'][notebook] if namespace: self.form['namespace'] = namespace self._set_autocomplete(notebook) def _set_autocomplete(self, notebook): if notebook: obj = get_notebook(notebook) self.form.widgets['namespace'].notebook = obj self.form.widgets['page'].notebook = obj # Could still be None, e.g. if the notebook folder is not mounted logger.debug('Notebook for autocomplete: %s (%s)', obj, notebook) else: self.form.widgets['namespace'].notebook = None self.form.widgets['page'].notebook = None logger.debug('Notebook for autocomplete unset') def do_response_ok(self): def get_ui(): start_server_if_not_running() notebook = self.notebookcombobox.get_notebook() if notebook: return ServerProxy().get_notebook(notebook) else: return None return BoundQuickNoteDialog.do_response_ok(self, get_ui)