Revision feddc602
Added by dsorber almost 9 years ago
| software/pwmgr/pwmgr.py | ||
|---|---|---|
|
import sys
|
||
|
|
||
|
import gi
|
||
|
gi.require_version('Gtk', '3.0')
|
||
|
from gi.repository import Gtk, Pango
|
||
|
|
||
|
class SearchDialog(Gtk.Dialog):
|
||
|
|
||
|
def __init__(self, parent):
|
||
|
Gtk.Dialog.__init__(self, "Search", parent,
|
||
|
Gtk.DialogFlags.MODAL, buttons=(
|
||
|
Gtk.STOCK_FIND, Gtk.ResponseType.OK,
|
||
|
Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL))
|
||
|
|
||
|
box = self.get_content_area()
|
||
|
|
||
|
label = Gtk.Label("Insert text you want to search for:")
|
||
|
box.add(label)
|
||
|
|
||
|
self.entry = Gtk.Entry()
|
||
|
box.add(self.entry)
|
||
|
|
||
|
self.show_all()
|
||
|
|
||
|
class TextViewWindow(Gtk.Window):
|
||
|
|
||
|
def __init__(self):
|
||
|
Gtk.Window.__init__(self, title="TextView Example")
|
||
|
|
||
|
self.set_default_size(-1, 350)
|
||
|
|
||
|
self.grid = Gtk.Grid()
|
||
|
self.add(self.grid)
|
||
|
|
||
|
self.create_textview()
|
||
|
self.create_toolbar()
|
||
|
self.create_buttons()
|
||
|
|
||
|
def create_toolbar(self):
|
||
|
toolbar = Gtk.Toolbar()
|
||
|
self.grid.attach(toolbar, 0, 0, 3, 1)
|
||
|
|
||
|
button_bold = Gtk.ToolButton()
|
||
|
button_bold.set_icon_name("format-text-bold-symbolic")
|
||
|
toolbar.insert(button_bold, 0)
|
||
|
|
||
|
button_italic = Gtk.ToolButton()
|
||
|
button_italic.set_icon_name("format-text-italic-symbolic")
|
||
|
toolbar.insert(button_italic, 1)
|
||
|
|
||
|
button_underline = Gtk.ToolButton()
|
||
|
button_underline.set_icon_name("format-text-underline-symbolic")
|
||
|
toolbar.insert(button_underline, 2)
|
||
|
|
||
|
button_bold.connect("clicked", self.on_button_clicked, self.tag_bold)
|
||
|
button_italic.connect("clicked", self.on_button_clicked,
|
||
|
self.tag_italic)
|
||
|
button_underline.connect("clicked", self.on_button_clicked,
|
||
|
self.tag_underline)
|
||
|
|
||
|
toolbar.insert(Gtk.SeparatorToolItem(), 3)
|
||
|
|
||
|
radio_justifyleft = Gtk.RadioToolButton()
|
||
|
radio_justifyleft.set_icon_name("format-justify-left-symbolic")
|
||
|
toolbar.insert(radio_justifyleft, 4)
|
||
|
|
||
|
radio_justifycenter = Gtk.RadioToolButton.new_from_widget(radio_justifyleft)
|
||
|
radio_justifycenter.set_icon_name("format-justify-center-symbolic")
|
||
|
toolbar.insert(radio_justifycenter, 5)
|
||
|
|
||
|
radio_justifyright = Gtk.RadioToolButton.new_from_widget(radio_justifyleft)
|
||
|
radio_justifyright.set_icon_name("format-justify-right-symbolic")
|
||
|
toolbar.insert(radio_justifyright, 6)
|
||
|
|
||
|
radio_justifyfill = Gtk.RadioToolButton.new_from_widget(radio_justifyleft)
|
||
|
radio_justifyfill.set_icon_name("format-justify-fill-symbolic")
|
||
|
toolbar.insert(radio_justifyfill, 7)
|
||
|
|
||
|
radio_justifyleft.connect("toggled", self.on_justify_toggled,
|
||
|
Gtk.Justification.LEFT)
|
||
|
radio_justifycenter.connect("toggled", self.on_justify_toggled,
|
||
|
Gtk.Justification.CENTER)
|
||
|
radio_justifyright.connect("toggled", self.on_justify_toggled,
|
||
|
Gtk.Justification.RIGHT)
|
||
|
radio_justifyfill.connect("toggled", self.on_justify_toggled,
|
||
|
Gtk.Justification.FILL)
|
||
|
|
||
|
toolbar.insert(Gtk.SeparatorToolItem(), 8)
|
||
|
|
||
|
button_clear = Gtk.ToolButton()
|
||
|
button_clear.set_icon_name("edit-clear-symbolic")
|
||
|
button_clear.connect("clicked", self.on_clear_clicked)
|
||
|
toolbar.insert(button_clear, 9)
|
||
|
|
||
|
toolbar.insert(Gtk.SeparatorToolItem(), 10)
|
||
|
|
||
|
button_search = Gtk.ToolButton()
|
||
|
button_search.set_icon_name("system-search-symbolic")
|
||
|
button_search.connect("clicked", self.on_search_clicked)
|
||
|
toolbar.insert(button_search, 11)
|
||
|
|
||
|
def create_textview(self):
|
||
|
scrolledwindow = Gtk.ScrolledWindow()
|
||
|
scrolledwindow.set_hexpand(True)
|
||
|
scrolledwindow.set_vexpand(True)
|
||
|
self.grid.attach(scrolledwindow, 0, 1, 3, 1)
|
||
|
|
||
|
self.textview = Gtk.TextView()
|
||
|
self.textbuffer = self.textview.get_buffer()
|
||
|
self.textbuffer.set_text("This is some text inside of a Gtk.TextView. "
|
||
|
+ "Select text and click one of the buttons 'bold', 'italic', "
|
||
|
+ "or 'underline' to modify the text accordingly.")
|
||
|
scrolledwindow.add(self.textview)
|
||
|
|
||
|
self.tag_bold = self.textbuffer.create_tag("bold",
|
||
|
weight=Pango.Weight.BOLD)
|
||
|
self.tag_italic = self.textbuffer.create_tag("italic",
|
||
|
style=Pango.Style.ITALIC)
|
||
|
self.tag_underline = self.textbuffer.create_tag("underline",
|
||
|
underline=Pango.Underline.SINGLE)
|
||
|
self.tag_found = self.textbuffer.create_tag("found",
|
||
|
background="orange")
|
||
|
|
||
|
def create_buttons(self):
|
||
|
check_editable = Gtk.CheckButton("Editable")
|
||
|
check_editable.set_active(True)
|
||
|
check_editable.connect("toggled", self.on_editable_toggled)
|
||
|
self.grid.attach(check_editable, 0, 2, 1, 1)
|
||
|
|
||
|
check_cursor = Gtk.CheckButton("Cursor Visible")
|
||
|
check_cursor.set_active(True)
|
||
|
check_editable.connect("toggled", self.on_cursor_toggled)
|
||
|
self.grid.attach_next_to(check_cursor, check_editable,
|
||
|
Gtk.PositionType.RIGHT, 1, 1)
|
||
|
|
||
|
radio_wrapnone = Gtk.RadioButton.new_with_label_from_widget(None,
|
||
|
"No Wrapping")
|
||
|
self.grid.attach(radio_wrapnone, 0, 3, 1, 1)
|
||
|
|
||
|
radio_wrapchar = Gtk.RadioButton.new_with_label_from_widget(
|
||
|
radio_wrapnone, "Character Wrapping")
|
||
|
self.grid.attach_next_to(radio_wrapchar, radio_wrapnone,
|
||
|
Gtk.PositionType.RIGHT, 1, 1)
|
||
|
|
||
|
radio_wrapword = Gtk.RadioButton.new_with_label_from_widget(
|
||
|
radio_wrapnone, "Word Wrapping")
|
||
|
self.grid.attach_next_to(radio_wrapword, radio_wrapchar,
|
||
|
Gtk.PositionType.RIGHT, 1, 1)
|
||
|
|
||
|
radio_wrapnone.connect("toggled", self.on_wrap_toggled,
|
||
|
Gtk.WrapMode.NONE)
|
||
|
radio_wrapchar.connect("toggled", self.on_wrap_toggled,
|
||
|
Gtk.WrapMode.CHAR)
|
||
|
radio_wrapword.connect("toggled", self.on_wrap_toggled,
|
||
|
Gtk.WrapMode.WORD)
|
||
|
|
||
|
def on_button_clicked(self, widget, tag):
|
||
|
bounds = self.textbuffer.get_selection_bounds()
|
||
|
if len(bounds) != 0:
|
||
|
start, end = bounds
|
||
|
self.textbuffer.apply_tag(tag, start, end)
|
||
|
|
||
|
def on_clear_clicked(self, widget):
|
||
|
start = self.textbuffer.get_start_iter()
|
||
|
end = self.textbuffer.get_end_iter()
|
||
|
self.textbuffer.remove_all_tags(start, end)
|
||
|
|
||
|
def on_editable_toggled(self, widget):
|
||
|
self.textview.set_editable(widget.get_active())
|
||
|
|
||
|
def on_cursor_toggled(self, widget):
|
||
|
self.textview.set_cursor_visible(widget.get_active())
|
||
|
|
||
|
def on_wrap_toggled(self, widget, mode):
|
||
|
self.textview.set_wrap_mode(mode)
|
||
|
|
||
|
def on_justify_toggled(self, widget, justification):
|
||
|
self.textview.set_justification(justification)
|
||
|
|
||
|
def on_search_clicked(self, widget):
|
||
|
dialog = SearchDialog(self)
|
||
|
response = dialog.run()
|
||
|
if response == Gtk.ResponseType.OK:
|
||
|
cursor_mark = self.textbuffer.get_insert()
|
||
|
start = self.textbuffer.get_iter_at_mark(cursor_mark)
|
||
|
if start.get_offset() == self.textbuffer.get_char_count():
|
||
|
start = self.textbuffer.get_start_iter()
|
||
|
|
||
|
self.search_and_mark(dialog.entry.get_text(), start)
|
||
|
|
||
|
dialog.destroy()
|
||
|
|
||
|
def search_and_mark(self, text, start):
|
||
|
end = self.textbuffer.get_end_iter()
|
||
|
match = start.forward_search(text, 0, end)
|
||
|
|
||
|
if match != None:
|
||
|
match_start, match_end = match
|
||
|
self.textbuffer.apply_tag(self.tag_found, match_start, match_end)
|
||
|
self.search_and_mark(text, match_end)
|
||
|
|
||
|
def main():
|
||
|
|
||
|
win = TextViewWindow()
|
||
|
win.connect("delete-event", Gtk.main_quit)
|
||
|
win.show_all()
|
||
|
Gtk.main()
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
sys.exit(main())
|
||
Adding initial version of pwmgr which originates as the textview.py example from the PyGTK documentation.