# FileChooserDialog (Python)

Marta Maria Casetti
mmcasetti@gmail.com 2012
Dialogové okno vhodné pro příkazy „Otevřít“ a „Uložit“

# FileChooserDialog

Tento FileChooserDialog ukládá textové dokumenty, které mohou být otevřeny nebo napsány od nuly v TextView (viz dále).

Je také možné zavolat FileChooserDialog pro otevření nového dokumentu.

# Kroky k reprodukci příkladu

Vytvořte soubor .ui, který bude popisovat aplikační nabídku s položkami „New“, „Open“, „Save“, „Save As“ a „Quit“. To můžete udělat v Glade nebo v textovém editoru. Viz .

Vytvořte program v jazyce Python pro Gtk.TextView s Gtk.Buffer `self.buffer` a `self.file`, což bude Gio.File nastavený na počátku na `None`.

V tomto programu vytvoříme také akce odpovídající položkám v aplikační nabídce, napojíme je na funkce zpětného volání a naimportujeme nabídku pomocí metody `do_startup()` třídy `Gtk.Builder`.

Akce New a Quit a jejich funkce zpětného volání jsou velmi jednoduché, viz . Podrobnější vysvětlení signálů a funkcí zpětného volání najdete v .

Zpětné volání akce Open by mělo vytvořit a otevřít `Gtk.FileChooserDialog` pro otevření souboru. Toto dialogové okno je napojeno na jiné funkce zpětného volání, jednu pro tlačítko Open a druhou pro tlačítko Cancel dialogového okna.

Akce Save as funguje podobně jako Open, akorát funkce zpětného volání pro tlačítko Save závisí na mnohem komplexnější metodě `save_to_file()`.

Akci Save lze zúžit na případ, kdy soubor je `None`, což je případ, kdy `self.file` je nový soubor, a tím pádem to změníme na akci Save as, a případ, kdy soubor není `None`, což se zúží na `save_to_file()`.

A nakonec metoda `save_to_file()`: viz , řádky 146 – 175.

# Soubor XML, který vytváří nabídku aplikace

<?xml version="1.0"?> <interface> <menu id="appmenu"> <section> <item> <attribute name="label">New</attribute> <attribute name="action">win.new</attribute> </item> <item> <attribute name="label">Open</attribute> <attribute name="action">win.open</attribute> </item> </section> <section> <item> <attribute name="label">Save</attribute> <attribute name="action">win.save</attribute> </item> <item> <attribute name="label">Save As...</attribute> <attribute name="action">win.save-as</attribute> </item> </section> <section> <item> <attribute name="label">Quit</attribute> <attribute name="action">app.quit</attribute> </item> </section> </menu> </interface>

# Kód použitý k vygenerování tohoto příkladu

from gi.repository import Gtk from gi.repository import Gdk from gi.repository import Gio from gi.repository import GObject import sys

class MyWindow(Gtk.ApplicationWindow):

def __init__(self, app): Gtk.Window.__init__( self, title="FileChooserDialog Example", application=app) self.set_default_size(400, 400)

# Akce pro nabídku okna, napojí se na funkci zpětného volání new_action = Gio.SimpleAction.new("new", None) new_action.connect("activate", self.new_callback) self.add_action(new_action)

open_action = Gio.SimpleAction.new("open", None) open_action.connect("activate", self.open_callback) self.add_action(open_action)

save_action = Gio.SimpleAction.new("save", None) save_action.connect("activate", self.save_callback) self.add_action(save_action)

save_as_action = Gio.SimpleAction.new("save-as", None) save_as_action.connect("activate", self.save_as_callback) self.add_action(save_as_action)

# Soubor self.file = None

# TextView s vyrovnávací pamětí self.buffer = Gtk.TextBuffer() textview = Gtk.TextView(buffer=self.buffer) textview.set_wrap_mode(Gtk.WrapMode.WORD)

# Okno s posuvníky pro TextView self.scrolled_window = Gtk.ScrolledWindow() self.scrolled_window.set_policy( Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.scrolled_window.add(textview) self.scrolled_window.set_border_width(5)

# Přidá okno s posuvníky do okna self.add(self.scrolled_window)

# Zpětné volání pro "new" def new_callback(self, action, parameter): self.buffer.set_text("") print("New file created")

# Zpětné volání pro "open" def open_callback(self, action, parameter): # Vytvoří FileChooserDialog pro otevření # argumenty jsou: název okna, rodičovské okno, akce, # (tlačítka, odpověď) open_dialog = Gtk.FileChooserDialog("Pick a file", self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT))

# Lze vybírat nejen místní soubory open_dialog.set_local_only(False) # Dialogové okno bude vždy nad oknem s TextView open_dialog.set_modal(True) # Napojí dialogové okno na funci zpětného volání open_response_cb() open_dialog.connect("response", self.open_response_cb) # Zobrazí dialogové okno open_dialog.show()

# Funkce zpětného volání pro dialogové okno open_dialog def open_response_cb(self, dialog, response_id): open_dialog = dialog # Pokud odpověď je "ACCEPT" (bylo kliknuto na tlačítko "Open") if response_id == Gtk.ResponseType.ACCEPT: # self.file je soubor, který jsme od FileChooserDialog dostali self.file = open_dialog.get_file() # Prázdný řetězec (prozatímně) content = "" try: # Načte obsah souboru do paměti # success: pravdivostní hodnota závisející na úspěchu operace # content: obsah # etags: je značka entity (může být použit k rychlému určení, jestli # byl soubor změněn vůči verzi v souborovém systému) [success, content, etags] = self.file.load_contents(None) except GObject.GError as e: print("Error: " + e.message) # Nastaví obsah jako text do vyrovnávací paměti self.buffer.set_text(content, len(content)) print("opened: " + open_dialog.get_filename()) # Pokud odpověď je "CANCEL" (vylo kliknuto na tlačítko "Cancel") elif response_id == Gtk.ResponseType.CANCEL: print("cancelled: FileChooserAction.OPEN") # Zlikviduje FileChooserDialog dialog.destroy()

# Funkce zpětného volání pro "save_as" def save_as_callback(self, action, parameter): # Vytvoří FileChooserDialog pro uložení # argumenty jsou: název okna, rodičovské okno, akce, # (tlačítka, odpověď) save_dialog = Gtk.FileChooserDialog("Pick a file", self, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT)) # Pokud uživatel zadá název souboru, který již existuje, zobrazí dialogové okno # dotaz na potvrzení save_dialog.set_do_overwrite_confirmation(True) # Dialogové okno bude vždy nad oknem s TextView save_dialog.set_modal(True) # Pokud byl self.file již uložen if self.file is not None: try: # Nastaví self.file jako aktuální název do výběru souboru save_dialog.set_file(self.file) except GObject.GError as e: print("Error: " + e.message) # Napojí dialogové okno na funkci zpětného volání save_response_cb() save_dialog.connect("response", self.save_response_cb) # Zobrazí dialogové okno save_dialog.show()

# Funkce zpětného volání pro dialogové okno save_dialog def save_response_cb(self, dialog, response_id): save_dialog = dialog # Pokud odpověď je "ACCEPT" (bylo kliknuto na tlačítko "Save") if response_id == Gtk.ResponseType.ACCEPT: # self.file je aktuálně vybraný soubor self.file = save_dialog.get_file() # Uloží do souboru (viz níže) self.save_to_file() # Pokud odpověď je "CANCEL" (bylo kliknuto na tlačítko "Cancel") elif response_id == Gtk.ResponseType.CANCEL: print("cancelled: FileChooserAction.SAVE") # Zlikviduje FileChooserDialog dialog.destroy()

# Funkce zpětného volání pro uložení def save_callback(self, action, parameter): # Pokud tam self.file zatím není if self.file is not None: self.save_to_file() # self.file je nový soubor else: # Použije save_as self.save_as_callback(action, parameter)

# Uložení do souboru def save_to_file(self): # Získá obsah vyrovnávací paměti, bez skrytých znaků [start, end] = self.buffer.get_bounds() current_contents = self.buffer.get_text(start, end, False) # Pokud je nějaký obsah if current_contents != "": # Nastaví obsah jako obsah souboru self.file # argumenty: obsah, značka entity, vytvořit zálohu?, příznaky, GError try: self.file.replace_contents(current_contents, None, False, Gio.FileCreateFlags.NONE, None) print("saved: " + self.file.get_path()) except GObject.GError as e: print("Error: " + e.message) # Pokud je obsah prázdný else: # Vytvoří (když soubor neexistuje) nebo přepíše soubor v režimu zápisu # argumenty: značka entity, vytvořit zálohu?, příznaky, GError try: self.file.replace_readwrite(None, False, Gio.FileCreateFlags.NONE, None) print("saved: " + self.file.get_path()) except GObject.GError as e: print("Error: " + e.message)

class MyApplication(Gtk.Application):

def __init__(self): Gtk.Application.__init__(self)

def do_activate(self): win = MyWindow(self) win.show_all()

def do_startup(self): Gtk.Application.do_startup(self)

# Akce "quit" aplikace, napojí se na funkci zpětného volání quit_action = Gio.SimpleAction.new("quit", None) quit_action.connect("activate", self.quit_callback) self.add_action(quit_action)

# Získá nabídku ze souboru s UI pomocí Builderu builder = Gtk.Builder() try: builder.add_from_file("filechooserdialog.ui") except: print("file not found") sys.exit() menu = builder.get_object("appmenu") self.set_app_menu(menu)

# Funkce zpětného volání pro "quit" def quit_callback(self, action, parameter): self.quit()

app = MyApplication() exit_status = app.run(sys.argv) sys.exit(exit_status)

# Užitečné metody pro FileChooserDialog

Poznamenejme, že akce u dialogového okna pro výběr souboru může být některá z následujících: `Gtk.FileChooserAction.OPEN` (umožní uživateli jen vybrat existující soubor) `Gtk.FileChooserAction.SAVE` (umožní uživateli vybrat existující soubor nebo napsat název nového), `Gtk.FileChooserAction.SELECT_FOLDER` (umožní uživateli jen vybrat existující složku), `Gtk.FileChooserAction.CREATE_FOLDER` (umožní uživateli vybrat existující složku nebo napsat název nové).

Mimo metod použitých v , máme:

`set_show_hidden(True)` se používá k zobrazení skrytých souborů a složek.

`set_select_multiple(True)` nastavuje možnost vybrat více souborů naráz. To má význam jen v případě, že režim je `Gtk.FileChooserAction.OPEN` nebo `Gtk.FileChooserAction.SELECT_FOLDER`.

V dialogovém okně Uložení jako funkce `set_current_name(aktuální_název)` nastavuje ve výběru souboru `aktuální_název`, jako by jej zadal uživatel. `aktuální_název` může být něco jako Untitled.txt. Tato metoda by se neměla používat jinde než pro „Uložit jako“.

Výchozí aktuální složkou jsou nedávné položky. Pro nastavení jiné složky použijte `set_current_folder_uri(uri)`. Upozorňujeme ale, že tuto metodu byste měli použít, a přimět tím výběr souboru zobrazit zadanou složku, jen když provádíte „Uložit jako“ a máte již soubor někde uložený.

# Odkazy k API

V této ukázce se používá následující:

GtkFileChooserDialog

GtkFileChooser

GtkWindow

GtkTextView

GtkTextBuffer

GtkScrolledWindow

GFile

GSimpleAction

GtkBuilder