Ejemplo n.º 1
0
class SourceViewObject(CustomObjectClass):

	def __init__(self, attrib, data, ui=None):
		if data.endswith('\n'):
			data = data[:-1]
			# If we have trailing \n it looks like an extra empty line
			# in the buffer, so we default remove one
		CustomObjectClass.__init__(self, attrib, data, ui)
		if self.ui and self.ui.__class__.__name__ == 'GtkInterface': # XXX seperate widget and object
			from zim.gui.widgets import ScrolledWindow

			# SourceView scrolled window
			self.buffer = gtksourceview2.Buffer()
			self.buffer.set_text(self._data)
			self.buffer.connect('modified-changed', self.on_modified_changed)
			self.buffer.set_highlight_matching_brackets(True)
			self.buffer.set_modified(False)
			self._data = None
			self.view = gtksourceview2.View(self.buffer)
			self.view.modify_font(pango.FontDescription('monospace'))
			self.view.set_auto_indent(True)
			self.view.set_smart_home_end(True)
			self.view.set_highlight_current_line(True)
			self.view.set_right_margin_position(80)
			self.view.set_show_right_margin(True)
			self.view.set_tab_width(4)

			win = ScrolledWindow(self.view, gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
				# only horizontal scroll
			win.set_border_width(5)

			self._attrib.setdefault('lang', None)
			self._attrib.setdefault('linenumbers', 'true') # FIXME make boolean
			self.set_language(self._attrib['lang'], save=False)
			self.show_line_numbers(self._attrib['linenumbers'], save=False)

			self.view.connect('populate-popup', self.on_populate_popup)

			# simple toolbar
			#~ bar = gtk.HBox() # FIXME: use gtk.Toolbar stuff
			#~ lang_selector = gtk.combo_box_new_text()
			#~ lang_selector.append_text('(None)')
			#~ for l in lang_names: lang_selector.append_text(l)
			#~ try:
				#~ lang_selector.set_active(lang_ids.index(self._attrib['lang'])+1)
				#~ self.set_language(self._attrib['lang'] or None, False)
			#~ except (ValueError, KeyError):
				#~ lang_selector.set_active(0)
				#~ self.set_language(None, False)
			#~ lang_selector.connect('changed', self.on_lang_changed)
			#~ bar.pack_start(lang_selector, False, False)
		#~
			#~ line_numbers = gtk.ToggleButton('Line numbers')
			#~ try:
				#~ line_numbers.set_active(self._attrib['linenumbers']=='true')
				#~ self.show_line_numbers(self._attrib['linenumbers'], False)
			#~ except (ValueError, KeyError):
				#~ line_numbers.set_active(True)
				#~ self.show_line_numbers(True, False)
			#~ line_numbers.connect('toggled', self.on_line_numbers_toggled)
			#~ bar.pack_start(line_numbers, False, False)

			# TODO: other toolbar options
			# TODO: autohide toolbar if textbuffer is not active

			# Pack everything
			box = gtk.VBox()
			#~ box.pack_start(bar, False, False)
			box.pack_start(win)
			self._widget = CustomObjectBin()
			self._widget.set_has_cursor(True)
			self._widget.add(box)

			# Hook up integration with pageview cursor movement
			def on_grab_cursor(bin, position):
				begin, end = self.buffer.get_bounds()
				if position == POSITION_BEGIN:
					self.buffer.place_cursor(begin)
				else:
					self.buffer.place_cursor(end)
				self.view.grab_focus()

			def on_move_cursor(view, step_size, count, extend_selection):
				buffer = view.get_buffer()
				iter = buffer.get_iter_at_mark(buffer.get_insert())
				if (iter.is_start() or iter.is_end()) \
				and not extend_selection:
					if iter.is_start() and count < 0:
						self._widget.release_cursor(POSITION_BEGIN)
						return None
					elif iter.is_end() and count > 0:
						self._widget.release_cursor(POSITION_END)
						return None

				return gtksourceview2.View.do_move_cursor(view, step_size, count, extend_selection)

			self._widget.connect('grab-cursor', on_grab_cursor)
			self.view.connect('move-cursor', on_move_cursor)

			# Resize widget if parent TextView has been resized -- XXX
			self.ui.mainwindow.pageview.view.connect_after('size-allocate',
												self.on_parent_view_resized)
		else:
			self.view = None

	def set_preferences(self, preferences):
		if self.view:
			self.view.set_auto_indent(preferences['auto_indent'])
			self.view.set_smart_home_end(preferences['smart_home_end'])
			self.view.set_highlight_current_line(preferences['highlight_current_line'])
			self.view.set_right_margin_position(preferences['right_margin_position'])
			self.view.set_show_right_margin(preferences['show_right_margin'])
			self.view.set_tab_width(preferences['tab_width'])

	def get_data(self):
		'''Returns data as text.'''
		if self._widget:
			buffer = self.view.get_buffer()
			bounds = buffer.get_bounds()
			text = buffer.get_text(bounds[0], bounds[1])
			text += '\n' # Make sure we always have a trailing \n
			return text
		return self._data

	def dump(self, format, dumper, linker=None):
		if format == "html":
			if 'lang' in self._attrib:
				# class="brush: language;" works with SyntaxHighlighter 2.0.278
				# by Alex Gorbatchev <http://alexgorbatchev.com/SyntaxHighlighter/>
				# TODO: not all GtkSourceView language ids match with SyntaxHighlighter
				# language ids.
				output = ['<pre class="brush: %s;">\n' % html_encode(self._attrib['lang'])]
			else:
				output = ['<pre>\n']
			data = html_encode(self.get_data())
			if self._attrib['linenumbers'] == 'true':
				for i, l in enumerate(data.splitlines(1)):
					output.append('%i ' % (i+1) + l)
			else:
				output.append(data)
			output.append('</pre>\n')
			return output
		return CustomObjectClass.dump(self, format, dumper, linker)

	def on_lang_changed(self, selector):
		'''Callback for language selector'''
		lang = selector.get_active()
		self.set_language(lang_ids[lang-1] if lang>0 else '')

	def set_language(self, lang, save=True):
		'''Set language in SourceView.'''
		if lang is None:
			self.buffer.set_language(None)
		else:
			self.buffer.set_language(lm.get_language(lang))
		if save:
			self._attrib['lang'] = lang
			self.set_modified(True)

	def on_line_numbers_toggled(self, button):
		'''Callback for toggling line numbers.'''
		self.show_line_numbers(button.get_active())

	def show_line_numbers(self, show, save=True):
		'''Toggles line numbers in SourceView.'''
		if isinstance(show, basestring): show = show == 'true'
		self.view.set_show_line_numbers(show)
		if save:
			self._attrib['linenumbers'] = 'true' if show else 'false'
			self.set_modified(True)

	def on_modified_changed(self, buffer):
		'''Requests saving date from TextBuffer.'''
		if buffer.get_modified():
			self.set_modified(True)
			buffer.set_modified(False)

	def on_parent_view_resized(self, view, size):
		'''Resizes widget if parent textview size has been changed.'''
		win = view.get_window(gtk.TEXT_WINDOW_TEXT)
		if win:

			vmargin =  2 * 5 + view.get_left_margin()+ view.get_right_margin() \
			+ 2 * self._widget.get_border_width()
			hmargin =  2 * 20 + 2 * self._widget.get_border_width()
			width, height = win.get_geometry()[2:4]
			#~ self._widget.set_size_request(width - vmargin, height - hmargin)
			self._widget.set_size_request(width - vmargin, -1)

	def on_populate_popup(self, view, menu):
		menu.prepend(gtk.SeparatorMenuItem())

		def activate_linenumbers(item):
			self.show_line_numbers(item.get_active())

		item = gtk.CheckMenuItem(_('Show Line Numbers'))
		item.set_active(self._attrib['linenumbers'] == 'true') # FIXME - make this attrib boolean
		item.connect_after('activate', activate_linenumbers)
		menu.prepend(item)


		def activate_lang(item):
			self.set_language(item.zim_sourceview_languageid)

		item = gtk.MenuItem(_('Syntax'))
		submenu = gtk.Menu()
		for lang in sorted(LANGUAGES, key=lambda k: k.lower()):
			langitem = gtk.MenuItem(lang)
			langitem.connect('activate', activate_lang)
			langitem.zim_sourceview_languageid = LANGUAGES[lang]
			submenu.append(langitem)
		item.set_submenu(submenu)
		menu.prepend(item)

		menu.show_all()
Ejemplo n.º 2
0
class FallbackObject(CustomObjectClass):
	'''Fallback object displays data as TextView and
	preserves attributes unmodified.
	'''

	def __init__(self, attrib, data, ui=None):
		CustomObjectClass.__init__(self, attrib, data, ui)
		if self.ui and self.ui.__class__.__name__ == 'GtkInterface':  # XXX seperate widget and object
			import gtk
			from zim.gui.pageview import CustomObjectBin
			from zim.gui.widgets import ScrolledTextView

			self._widget = CustomObjectBin()
			box = gtk.VBox()
			box.set_border_width(5)
			type = attrib.get('type')
			plugin = ObjectManager.find_plugin(type) if type else None
			if plugin:
				key, name, activatable, klass = plugin
				hbox = gtk.HBox(False, 5)
				box.pack_start(hbox)
				label = gtk.Label(_("Plugin %s is required to display this object.") % name)
				hbox.pack_start(label)
				if activatable: # and False:
					# Plugin can be enabled
					button = gtk.Button(_("Enable plugin"))
					def load_plugin(button):
						self.ui.plugins.load_plugin(key)
						self.ui.reload_page()
					button.connect("clicked", load_plugin)
				else:
					# Plugin has some unresolved dependencies
					def plugin_info(button):
						from zim.gui.preferencesdialog import PreferencesDialog
						dialog = PreferencesDialog(self.ui, "Plugins", select_plugin=name)
						dialog.run()
						self.ui.reload_page()
					button = gtk.Button(_("Show plugin details"))
					button.connect("clicked", plugin_info)
				hbox.pack_start(button)
			else:
				label = gtk.Label(_("No plugin is available to display this object."))
				box.pack_start(label)

			win, self.view = ScrolledTextView(self._data, monospace=True)
			self.view.set_editable(True)
			buffer = self.view.get_buffer();
			buffer.connect('modified-changed', self.on_modified_changed)
			buffer.set_modified(False)
			self._data = None

			win.set_border_width(5)
			win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
			box.pack_start(win)
			self._widget.add(box)

	def get_data(self):
		if self._widget:
			buffer = self.view.get_buffer()
			bounds = buffer.get_bounds()
			return buffer.get_text(bounds[0], bounds[1])
		return self._data

	def on_modified_changed(self, buffer):
		'''Callback for TextBuffer's modifications.'''
		if buffer.get_modified():
			self.set_modified(True)
			buffer.set_modified(False)

	def set_label(self, label):
		'''Sets label at the top area of widget.'''
		self.label.set_text(label)
Ejemplo n.º 3
0
class BibTexBibObject(CustomObjectClass):

    bibliographies = {}

    def __init__(self, attrib, text, pageview, ui=None):
        if not text is None and text.endswith('\n'):
            text = text[:-1]
            # If we have trailing \n it looks like an extra empty line
            # in the buffer, so we default remove one
        CustomObjectClass.__init__(self, attrib, text, ui)
        self.pageview = pageview
        self.referenceIds = {}
        self.references = {}
        ui.connect('close-page', self.on_close_page)

        #self.referenceStore = gtk.ListStore(str, str, str, str)
        self.referenceStore = gtk.ListStore(str, str, str)
        self.name = attrib['name']
        self.path = attrib['path']

        if not attrib.has_key('filedir'):
            self.fileDir = None
        else:
            self.fileDir = attrib['filedir']

        if not BibTexBibObject.bibliographies.has_key(pageview):
            BibTexBibObject.bibliographies[pageview] = []
        BibTexBibObject.bibliographies[pageview].append(self)

        # parse bibtex file
        def customizations(record):
            def getnames(names):
                tidynames = []
                for namestring in names:
                    namestring = namestring.strip()
                    if len(namestring) < 1:
                        continue
                    if ',' in namestring:
                        namesplit = namestring.split(',', 1)
                        last = namesplit[0].strip()
                    else:
                        namesplit = namestring.split()
                        last = namesplit.pop()
                    if last in ['jnr', 'jr', 'junior']:
                        last = firsts.pop()
                    tidynames.append(last)
                return tidynames

            def author(record):
                if "author" in record:
                    if record["author"]:
                        record["author"] = getnames([
                            i.strip() for i in record["author"].replace(
                                '\n', ' ').split(" and ")
                        ])
                    else:
                        del record["author"]
                return record

            record = author(record)
            return record

        self.parser = BibTexParser()
        self.parser.customization = customizations
        self.parse_bibtex_file()

    def parse_bibtex_file(self):
        with open(self.path) as bibtex_file:
            bibtex_str = bibtex_file.read()
        self.bib_database = bibtexparser.loads(bibtex_str, parser=self.parser)

    def on_close_page(self, param1, param2, param3):
        BibTexBibObject.bibliographies.clear()
        BibTexEditorPlugin.unregisteredReferences.clear()

    def get_widget(self):
        if not self._widget:
            self._init_widget()
        return self._widget

    def get_data(self):
        '''Returns data as text.'''
        if self._widget:
            text = ""
            for row in self.referenceStore:
                text += (row[0] + ";" + row[1] + ";" + row[2] + "\n")
            return text
        return self._data

    def _init_widget(self):
        box = gtk.VBox()

        self.treeview = gtk.TreeView(self.referenceStore)
        self.treeview.set_headers_visible(False)

        column = gtk.TreeViewColumn()
        cellrender = gtk.CellRendererText()
        cellrender.props.wrap_width = 100
        cellrender.props.wrap_mode = gtk.WRAP_WORD
        column.pack_start(cellrender, True)
        column.add_attribute(cellrender, 'text', 0)
        self.treeview.append_column(column)
        column = gtk.TreeViewColumn()
        cellrender = gtk.CellRendererText()
        print(self.pageview.get_allocation()[3])
        cellrender.props.wrap_width = self.pageview.get_allocation()[2]
        cellrender.props.wrap_mode = gtk.WRAP_WORD
        column.pack_start(cellrender, True)
        column.add_attribute(cellrender, 'text', 2)
        self.treeview.append_column(column)

        box.pack_start(self.treeview)
        box.show_all()

        self._widget = CustomObjectBin()
        self._widget.add(box)

        self.treeview.connect('button-press-event', self.on_button_pressed)

    def on_button_pressed(self, treeview, event):
        if event.button == 3:
            x = int(event.x)
            y = int(event.y)
            pthinfo = treeview.get_path_at_pos(x, y)
            if pthinfo is not None:
                time = event.time
                path, col, cellx, celly = pthinfo
                treeview.grab_focus()
                treeview.set_cursor(path, col, 0)

                bibKey = treeview.get_model()[path][1]

                self.popup = gtk.Menu()
                win = treeview.get_parent_window()

                item = gtk.MenuItem(_('Reparse BibTeX file'))
                item.connect_after('activate',
                                   lambda o: self.parse_bibtex_file())
                self.popup.prepend(item)

                if self.fileDir is not None and self.bib_database.entries_dict[
                        bibKey].has_key('file'):
                    fileLink = self.bib_database.entries_dict[bibKey][
                        'file'].split(':')[1]
                    item = gtk.MenuItem(_('Open File'))
                    item.connect_after(
                        'activate', lambda o: self.open_file(
                            os.path.join(self.fileDir, fileLink)))
                    self.popup.prepend(item)

                self.popup.show_all()
                self.popup.popup(None, None, None, event.button, time)
            return True

    def open_file(self, filepath):
        if sys.platform.startswith('darwin'):
            subprocess.call(('open', filepath))
        elif os.name == 'nt':
            os.startfile(filepath)
        elif os.name == 'posix':
            subprocess.call(('xdg-open', filepath))

    def register_reference(self, reference):
        if not self.bib_database.entries_dict.has_key(reference.bibKey):
            return

        if not self.referenceIds.has_key(reference.bibKey):
            self.referenceIds[reference.bibKey] = len(self.referenceStore) + 1
            self.references[reference.bibKey] = []
            #self.referenceStore.append([self.get_reference_id(reference.bibKey), reference.bibKey, self.bib_database.entries_dict[reference.bibKey]['author'], self.bib_database.entries_dict[reference.bibKey]['title']])
            refString = "%s et al., %s. (%s)." % (
                self.bib_database.entries_dict[reference.bibKey]['author'][0],
                self.bib_database.entries_dict[reference.bibKey]['title'],
                self.bib_database.entries_dict[reference.bibKey]['year'])
            self.referenceStore.append([
                self.get_reference_id(reference.bibKey), reference.bibKey,
                refString
            ])
        reference.bibliography = self
        reference.label.set_text("[%d]" % self.referenceIds[reference.bibKey])
        self.references[reference.bibKey].append(reference)
        self.set_modified(True)

    def unregister_reference(self, reference):
        if self.references.has_key(reference.bibKey):
            if reference in self.references[reference.bibKey]:
                self.references[reference.bibKey].remove(reference)

                if len(self.references[reference.bibKey]) == 0:
                    id = self.referenceIds[reference.bibKey]
                    self.referenceStore.remove(
                        self.referenceStore.get_iter(id - 1))
                    del self.references[reference.bibKey]
                    del self.referenceIds[reference.bibKey]

                    # update indices
                    for bibKey in self.referenceIds.keys():
                        if self.referenceIds[bibKey] > id:
                            self.referenceIds[
                                bibKey] = self.referenceIds[bibKey] - 1
                            self.referenceStore[self.referenceStore.get_iter(
                                self.referenceIds[bibKey] -
                                1)][0] = self.referenceIds[bibKey]
                            for ref in self.references[bibKey]:
                                ref.label.set_text("[%d]" %
                                                   self.referenceIds[bibKey])
                                ref.set_modified(True)
                    self.set_modified(True)

    def get_reference_id(self, reference):
        return self.referenceIds[reference]
Ejemplo n.º 4
0
class BibTexRefObject(CustomObjectClass):
    def __init__(self, attrib, data, bibliography, pageview, ui=None):
        #if data.endswith('\n'):
        #	data = data[:-1]
        # If we have trailing \n it looks like an extra empty line
        # in the buffer, so we default remove one
        CustomObjectClass.__init__(self, attrib, data, ui)
        self.data = None
        self.pageview = pageview
        self.pageview.view.get_buffer().connect_after('delete-range',
                                                      self.on_delete_range)
        self.anchor = None
        self.label = gtk.Label("")
        #self.label = gtk.LinkButton("")

        self.bibKey = attrib['bibkey']
        self.bibliography = bibliography
        if not bibliography is None:
            self.bibliography.register_reference(self)

    def on_delete_range(self, textbuffer, start, end):
        if self.anchor.get_deleted():
            if not self.bibliography is None:
                self.bibliography.unregister_reference(self)

    def get_widget(self):
        if not self._widget:
            self._init_widget()
        return self._widget

    def get_data(self):
        '''Returns data as text.'''
        if self._widget:
            text = ""
            return text
        return self._data

    def _init_widget(self):
        if not self.bibliography is None:
            self.label.set_text(
                "[%d]" % self.bibliography.get_reference_id(self.bibKey))
            #self.label.set_uri("[%d]" % self.bibliography.get_reference_id(self.bibKey))
        else:
            self.label.set_text("[...]")
            #self.label.set_uri("[...]")
        self.label.set_padding(0, 0)

        self._widget = CustomObjectBin()
        self._widget.set_border_width(0)
        self._widget.add_events(gtk.gdk.BUTTON_PRESS_MASK)
        self._widget.connect('button_press_event', self.on_label_clicked)

        self._widget.add(self.label)

    def on_label_clicked(self, bla1, bla2):
        # scroll
        self.pageview.view.scroll_to_iter(
            self.pageview.view.get_buffer().get_iter_at_child_anchor(
                self.bibliography.anchor),
            within_margin=0)

        # set selected entry in bib
        id = self.bibliography.get_reference_id(self.bibKey)
        self.bibliography.treeview.get_selection().select_path(id - 1)
        #self.bibliography.treeview.grab_focus()
        self.bibliography.treeview.click()
Ejemplo n.º 5
0
class TableObject(CustomObjectClass):

	def __init__(self, attrib, data, ui=None):
		if data.endswith('\n'):
			data = data[:-1]
			# If we have trailing \n it looks like an extra empty line
			# in the buffer, so we default remove one
		CustomObjectClass.__init__(self, attrib, data, ui)
		self.data = None
		self.rowheader = None
		self.columnheader = None
		#self.connect('modified-changed', self.dump)
		
		self._init_widget()

	def get_widget(self):
		if not self._widget:
			self._init_widget()
		return self._widget
		
	def get_data(self):
		'''Returns data as text.'''
		if self._widget:
			text = ""
			for row in self.treeview.get_model():
				for value in row:
					text += value + "|"
				text += "\n"
			return text
		return self._data

	def _init_widget(self):
		import gobject

		box = gtk.VBox()
		
		rows = self._data.split("\n")
		# count number of columns
		nrow = len(rows)
		ncol = rows[0].count("|")

		self.rowheader = []
		self.columnheader = []
		self.data = []
		
		columnTypes = []
		for c in range(0,ncol):
			columnTypes.append(gobject.TYPE_STRING)
		store = gtk.ListStore(*columnTypes)
		
		for r in range(0,nrow):
			values = rows[r].split("|")
			
			store.append(values[0:ncol])
			
		treeview = gtk.TreeView(store)
		treeview.set_headers_visible(False)
		for c in range(0,ncol):
			column = gtk.TreeViewColumn()
			cellrender = gtk.CellRendererText()
			column.pack_start(cellrender, True)
			column.add_attribute(cellrender, 'text', c)
			treeview.append_column(column)
		
		treeview.connect('button-press-event', self.on_button_press)
		box.pack_start(treeview)
		
		self.treeview = treeview
		
		self._widget = CustomObjectBin()
		self._widget.add(box)
		
	def on_button_press(self, treeview, event):
		if event.button == 3:			
			time = event.time
			x = int(event.x)
			y = int(event.y)
			pthinfo = treeview.get_path_at_pos(x, y)
			if pthinfo is not None:
				path, col, cellx, celly = pthinfo
				treeview.grab_focus()
				treeview.set_cursor( path, col, 0)

				pageview = treeview.get_parent().get_parent().get_parent().get_parent().get_parent()
				win = treeview.get_parent_window()
						
				self.popup = gtk.Menu()
				item = gtk.MenuItem(_('Edit'))
				item.connect_after('activate', 
					lambda o: self.edit_table(pageview, win))
				self.popup.prepend(item)
				self.popup.show_all()
				
				self.popup.popup( None, None, None, event.button, time)
			return True
			
	def edit_table(self, pageview, win):
		'''Run the InsertTableDialog'''
		lang = InsertTableDialog(win, pageview, table=self, edit=True).run()
		self.set_modified(True)
		if not lang:
			return # dialog cancelled
		else:
			return