1
0
mirror of https://github.com/gryf/pygtktalog.git synced 2026-02-02 22:25:50 +01:00

* Moved experimental MVC project as a current mainstream.

This commit is contained in:
2007-09-05 16:13:58 +00:00
parent c779b83259
commit 3282000e03
33 changed files with 0 additions and 0 deletions

View File

@@ -1,526 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
<widget class="GtkDialog" id="config">
<property name="width_request">550</property>
<property name="height_request">400</property>
<property name="title" translatable="yes">Preferences - pyGTKtalog</property>
<property name="modal">True</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<child>
<widget class="GtkHPaned" id="hpaned1">
<property name="width_request">168</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="position">140</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<child>
<widget class="GtkTreeView" id="category_tree">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">False</property>
<property name="rules_hint">True</property>
<signal name="cursor_changed" handler="on_category_tree_cursor_changed"/>
</widget>
</child>
</widget>
<packing>
<property name="resize">False</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<child>
<widget class="GtkLabel" id="desc">
<property name="visible">True</property>
<property name="xpad">3</property>
<property name="ypad">3</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<child>
<widget class="GtkViewport" id="pref_group">
<property name="visible">True</property>
<child>
<widget class="GtkVBox" id="main_group_holder">
<property name="visible">True</property>
<child>
<widget class="GtkVBox" id="disk_group">
<property name="border_width">1</property>
<child>
<widget class="GtkFrame" id="frame2">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="label_xalign">0</property>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="has_focus">True</property>
<property name="border_width">5</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="n_rows">2</property>
<property name="n_columns">3</property>
<property name="column_spacing">3</property>
<property name="row_spacing">3</property>
<child>
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Mount point:</property>
<property name="mnemonic_widget">mnt_entry</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="mnt_entry">
<property name="width_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button_mnt">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Browse...</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_button_mnt_clicked"/>
<signal name="activate" handler="on_button_mnt_activate"/>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="ejt_entry">
<property name="width_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button_ejt">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Browse...</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_button_ejt_clicked"/>
<signal name="activate" handler="on_button_ejt_activate"/>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Eject program:</property>
<property name="mnemonic_widget">ejt_entry</property>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;CD/DVD drive options&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkVBox" id="general_group">
<property name="border_width">1</property>
<child>
<widget class="GtkFrame" id="frame3">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="label_xalign">0</property>
<child>
<widget class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="has_focus">True</property>
<property name="border_width">5</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkVBox" id="vbox4">
<property name="visible">True</property>
<child>
<widget class="GtkCheckButton" id="ch_win">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Save main window size</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="ch_pan">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Save paned window sizes</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="ch_eject">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Eject CD/DVD after scan</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;General options&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
</child>
<child>
<widget class="GtkFrame" id="frame5">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="label_xalign">0</property>
<child>
<widget class="GtkAlignment" id="alignment5">
<property name="visible">True</property>
<property name="has_focus">True</property>
<property name="border_width">5</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkVBox" id="vbox7">
<property name="visible">True</property>
<child>
<widget class="GtkCheckButton" id="ch_xls">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Possible export to XLS</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Misc&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkFrame" id="frame6">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="label_xalign">0</property>
<child>
<widget class="GtkAlignment" id="alignment6">
<property name="visible">True</property>
<property name="has_focus">True</property>
<property name="border_width">5</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkVBox" id="vbox8">
<property name="visible">True</property>
<child>
<widget class="GtkCheckButton" id="ch_quit">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Confirm quit if there are unsaved data</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="ch_warnnew">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Confirm "new" if there are unsaved data</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="ch_wrnmount">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Warn about mount/umount errors</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Confirmations&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="scan_group">
<property name="border_width">1</property>
<child>
<widget class="GtkFrame" id="frame4">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="label_xalign">0</property>
<child>
<widget class="GtkAlignment" id="alignment4">
<property name="visible">True</property>
<property name="has_focus">True</property>
<property name="border_width">5</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkVBox" id="vbox6">
<property name="visible">True</property>
<child>
<widget class="GtkCheckButton" id="ch_thumb">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Create thumbnails for images</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="ch_exif">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Scan EXIF data</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="ch_gthumb">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Include gThumb image description</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="scan_opt_label">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Scan options&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
</child>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="cancelbutton1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="response_id">-6</property>
<signal name="clicked" handler="on_cancelbutton_clicked"/>
</widget>
</child>
<child>
<widget class="GtkButton" id="okbutton1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="label">gtk-save</property>
<property name="use_stock">True</property>
<property name="response_id">-5</property>
<signal name="clicked" handler="on_okbutton_clicked"/>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@@ -1,373 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkDialog" id="inputDialog">
<property name="visible">True</property>
<property name="title" translatable="yes">Disk label - pyGTKtalog</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="has_separator">True</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="cancelbutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-6</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="okbutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
<property name="label">gtk-ok</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-5</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Disk label</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">3</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="volname">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char">*</property>
<property name="activates_default">True</property>
<signal name="activate" handler="on_volname_activate" last_modification_time="Sun, 26 Nov 2006 17:34:10 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
<widget class="GtkDialog" id="addDirDialog">
<property name="visible">True</property>
<property name="title" translatable="yes">dialog1</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="has_separator">True</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area2">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="cancelbutton2">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-6</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="okbutton2">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-ok</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-5</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="border_width">3</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkFrame" id="frame2">
<property name="border_width">3</property>
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="border_width">3</property>
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<child>
<widget class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="n_rows">2</property>
<property name="n_columns">3</property>
<property name="homogeneous">False</property>
<property name="row_spacing">3</property>
<property name="column_spacing">3</property>
<child>
<widget class="GtkEntry" id="dirvolname">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes">New</property>
<property name="has_frame">True</property>
<property name="invisible_char">*</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="directory">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char">*</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="label" translatable="yes">Disk Label:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="label" translatable="yes">Select directory:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkButton" id="browse">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Browse...</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_browse_clicked" last_modification_time="Sun, 03 Dec 2006 17:04:04 GMT"/>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Select directory and enter label&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@@ -1,130 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="visible">True</property>
<property name="title" translatable="yes">window1</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<signal name="delete_event" handler="on_window1_delete_event" last_modification_time="Mon, 30 Apr 2007 10:09:49 GMT"/>
<child>
<widget class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">label2</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">button1</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;frame1&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@@ -1,648 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="main">
<property name="title" translatable="yes">mainW</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<signal name="destroy" handler="on_main_destroy_event"/>
<signal name="delete_event" handler="on_main_destroy_event"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkMenuBar" id="mainMenubar">
<property name="visible">True</property>
<property name="pack_direction">GTK_PACK_DIRECTION_LTR</property>
<property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property>
<child>
<widget class="GtkMenuItem" id="file1">
<property name="visible">True</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="file1_menu">
<child>
<widget class="GtkImageMenuItem" id="new1">
<property name="visible">True</property>
<property name="label">gtk-new</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_new1_activate"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="open1">
<property name="visible">True</property>
<property name="label">gtk-open</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_open1_activate"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save1">
<property name="visible">True</property>
<property name="label">gtk-save</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save1_activate"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save_as1">
<property name="visible">True</property>
<property name="label">gtk-save-as</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save_as1_activate"/>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="recent_files1">
<property name="visible">True</property>
<property name="label" translatable="yes">Recent files</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_recent_files1_activate"/>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit1">
<property name="visible">True</property>
<property name="label">gtk-quit</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_quit1_activate"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="edit1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="edit1_menu">
<child>
<widget class="GtkImageMenuItem" id="cut1">
<property name="visible">True</property>
<property name="label">gtk-cut</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_cut1_activate"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="copy1">
<property name="visible">True</property>
<property name="label">gtk-copy</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_copy1_activate"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="paste1">
<property name="visible">True</property>
<property name="label">gtk-paste</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_paste1_activate"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="delete1">
<property name="visible">True</property>
<property name="label">gtk-delete</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_delete1_activate"/>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator2">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="properties1">
<property name="visible">True</property>
<property name="label">gtk-preferences</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_preferences_activate"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="catalog1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Catalog</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="catalog1_menu">
<child>
<widget class="GtkMenuItem" id="add_cd">
<property name="visible">True</property>
<property name="label" translatable="yes">Add CD/DVD</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_add_cd_activate"/>
<accelerator key="a" modifiers="GDK_CONTROL_MASK" signal="activate"/>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="add_directory1">
<property name="visible">True</property>
<property name="label" translatable="yes">Add Directory</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_add_directory1_activate"/>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator3">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="cancel1">
<property name="visible">True</property>
<property name="label" translatable="yes">Cancel</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_cancel1_activate" last_modification_time="Fri, 24 Aug 2007 07:50:10 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="stock">gtk-cancel</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="view1">
<property name="visible">True</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="view1_menu">
<child>
<widget class="GtkCheckMenuItem" id="toolbar1">
<property name="visible">True</property>
<property name="label" translatable="yes">Toolbar</property>
<property name="use_underline">True</property>
<property name="active">False</property>
<signal name="activate" handler="on_toolbar1_activate"/>
</widget>
</child>
<child>
<widget class="GtkCheckMenuItem" id="status_bar1">
<property name="visible">True</property>
<property name="label" translatable="yes">Status bar</property>
<property name="use_underline">True</property>
<property name="active">False</property>
<signal name="activate" handler="on_status_bar1_activate"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="help1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="help1_menu">
<child>
<widget class="GtkImageMenuItem" id="about1">
<property name="visible">True</property>
<property name="label">gtk-about</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_about1_activate"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkToolbar" id="maintoolbar">
<property name="visible">True</property>
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
<property name="tooltips">True</property>
<property name="show_arrow">True</property>
<child>
<widget class="GtkToolButton" id="tb_new">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Create new catalog</property>
<property name="stock_id">gtk-new</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<signal name="clicked" handler="on_tb_new_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="tb_open">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Open catalog file</property>
<property name="stock_id">gtk-open</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<signal name="clicked" handler="on_tb_open_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="tb_save">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Save catalog</property>
<property name="stock_id">gtk-save</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<signal name="clicked" handler="on_tb_save_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkToolItem" id="toolitem2">
<property name="visible">True</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<child>
<widget class="GtkVSeparator" id="vseparator1">
<property name="visible">True</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="tb_addcd">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Add CD/DVD to catalog</property>
<property name="label" translatable="yes">Add CD</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-cdrom</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<signal name="clicked" handler="on_tb_addcd_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="tb_find">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Find file</property>
<property name="stock_id">gtk-find</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<signal name="clicked" handler="on_tb_find_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkToolItem" id="toolitem3">
<property name="visible">True</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<child>
<widget class="GtkVSeparator" id="vseparator2">
<property name="visible">True</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="cancel">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="label" translatable="yes">Cancel</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-cancel</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<signal name="clicked" handler="on_cancel_clicked" last_modification_time="Fri, 24 Aug 2007 06:12:57 GMT"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="tb_quit">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Quit pyGTKtalog</property>
<property name="stock_id">gtk-quit</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<signal name="clicked" handler="on_tb_quit_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="debugbtn">
<property name="visible">True</property>
<property name="label" translatable="yes">Debug</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-dialog-info</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<signal name="clicked" handler="on_debugbtn_clicked" last_modification_time="Sun, 26 Aug 2007 09:56:05 GMT"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHPaned" id="hpaned1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="discs">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">False</property>
<property name="rules_hint">True</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property>
<property name="hover_expand">False</property>
<signal name="row_activated" handler="on_discs_row_activated"/>
<signal name="cursor_changed" handler="on_discs_cursor_changed"/>
</widget>
</child>
</widget>
<packing>
<property name="shrink">True</property>
<property name="resize">False</property>
</packing>
</child>
<child>
<widget class="GtkVPaned" id="vpaned1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="files">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">True</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property>
<property name="hover_expand">False</property>
<signal name="row_activated" handler="on_files_row_activated"/>
<signal name="cursor_changed" handler="on_files_cursor_changed"/>
</widget>
</child>
</widget>
<packing>
<property name="shrink">True</property>
<property name="resize">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="detailplace">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTextView" id="details">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="overwrite">False</property>
<property name="accepts_tab">False</property>
<property name="justification">GTK_JUSTIFY_LEFT</property>
<property name="wrap_mode">GTK_WRAP_WORD</property>
<property name="cursor_visible">False</property>
<property name="pixels_above_lines">0</property>
<property name="pixels_below_lines">0</property>
<property name="pixels_inside_wrap">0</property>
<property name="left_margin">0</property>
<property name="right_margin">0</property>
<property name="indent">0</property>
<property name="text" translatable="yes"></property>
</widget>
</child>
</widget>
<packing>
<property name="shrink">True</property>
<property name="resize">True</property>
</packing>
</child>
</widget>
<packing>
<property name="shrink">False</property>
<property name="resize">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="statusprogress">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkStatusbar" id="mainStatus">
<property name="visible">True</property>
<property name="has_resize_grip">False</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkProgressBar" id="progressbar1">
<property name="visible">True</property>
<property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property>
<property name="fraction">0</property>
<property name="pulse_step">0.10000000149</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@@ -1,48 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (c) 2005 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
__all__ = ["model", "view", "controller", "observable", "observer"]
__version = (1,0,1)
from model import Model, TreeStoreModel, ListStoreModel, TextBufferModel
from model_mt import ModelMT
from controller import Controller
from view import View
from observer import Observer
import observable
def get_version(): return __version
def require(ver):
if isinstance(ver, str): ver = ver.split(".")
ver = tuple(map(int, ver))
if get_version() < ver:
raise AssertionError("gtkmvc required version '%s', found '%s'"\
% (ver, get_version()))
pass
return

View File

@@ -1,46 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (c) 2005 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
from gtkmvc.observer import Observer
class Controller (Observer):
"""We put all of our gtk signal handlers into a class. This lets us bind
all of them at once, because their names are in the class dict.
This class automatically register its instances as observers into the
corresponding model.
Also, when a view is created, the view calls method register_view,
which can be oveloaded in order to connect signals and perform other
specific operation"""
def __init__(self, model):
Observer.__init__(self, model)
self.view = None
return
def register_view(self, view):
assert(self.view is None)
self.view = view
return
pass # end of class Controller

View File

@@ -1,318 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (c) 2005 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
import support.metaclasses
from support.wrappers import ObsWrapperBase
from observable import Signal
class Model (object):
"""This class is the application model base class.
It handles a set of observable properties which you are interested
in showing by one ore more view - via one or more observers of course.
The mechanism is the following:
1. You are interested in showing a set of model property, that you can
declare in the __properties__ member map.
2. You define one or more observers that observe one or more properties
you registered. When someone changes a property value the model notifies
the changing to each listening controller. The property-observer[s]
association is given by the implicit rule in observers method names: if
you want the model notified the changing event of the property 'p'
you must define the method called 'property_p_change_notification' in
each listening observer class.
Notice that tipically 'controllers' implement the observer pattern.
The notification method gets the
emitting model, the old value for the property and the new one.
Properties functionalities are automatically provided by the
ObservablePropertyMeta meta-class."""
__metaclass__ = support.metaclasses.ObservablePropertyMeta
__properties__ = {} # override this
def __init__(self):
object.__init__(self)
self.__observers = []
# keys are properties names, values are methods inside the observer:
self.__value_notifications = {}
self.__instance_notif_before = {}
self.__instance_notif_after = {}
self.__signal_notif = {}
for key in (self.__properties__.keys() + self.__derived_properties__.keys()):
self.register_property(key)
pass
return
def register_property(self, name):
"""Registers an existing property to be monitored, and sets up
notifiers for notifications"""
if not self.__value_notifications.has_key(name):
self.__value_notifications[name] = []
pass
# registers observable wrappers
prop = getattr(self, "_prop_%s" % name)
if isinstance(prop, ObsWrapperBase):
prop.__set_model__(self, name)
if isinstance(prop, Signal):
if not self.__signal_notif.has_key(name):
self.__signal_notif[name] = []
pass
pass
else:
if not self.__instance_notif_before.has_key(name):
self.__instance_notif_before[name] = []
pass
if not self.__instance_notif_after.has_key(name):
self.__instance_notif_after[name] = []
pass
pass
pass
return
def register_observer(self, observer):
if observer in self.__observers: return # not already registered
self.__observers.append(observer)
for key in (self.__properties__.keys() + self.__derived_properties__.keys()):
self.__add_observer_notification(observer, key)
pass
return
def unregister_observer(self, observer):
if observer not in self.__observers: return
for key in (self.__properties__.keys() + self.__derived_properties__.keys()):
self.__remove_observer_notification(observer, key)
pass
self.__observers.remove(observer)
return
def _reset_property_notification(self, prop_name):
"""Called when it has be done an assignment that changes the
type of a property or the instance of the property has been
changed to a different instance. In this case it must be
unregistered and registered again"""
self.register_property(prop_name)
for observer in self.__observers:
self.__remove_observer_notification(observer, prop_name)
self.__add_observer_notification(observer, prop_name)
pass
return
def __add_observer_notification(self, observer, prop_name):
"""Searches in the observer for any possible listener, and
stores the notification methods to be called later"""
method_name = "property_%s_value_change" % prop_name
if hasattr(observer, method_name):
method = getattr(observer, method_name)
if method not in self.__value_notifications[prop_name]:
list.append(self.__value_notifications[prop_name], method)
pass
pass
# is it a signal?
orig_prop = getattr(self, "_prop_%s" % prop_name)
if isinstance(orig_prop, Signal):
method_name = "property_%s_signal_emit" % prop_name
if hasattr(observer, method_name):
method = getattr(observer, method_name)
if method not in self.__signal_notif[prop_name]:
list.append(self.__signal_notif[prop_name], method)
pass
pass
pass
# is it an instance change notification type?
elif isinstance(orig_prop, ObsWrapperBase):
method_name = "property_%s_before_change" % prop_name
if hasattr(observer, method_name):
method = getattr(observer, method_name)
if method not in self.__instance_notif_before[prop_name]:
list.append(self.__instance_notif_before[prop_name], method)
pass
pass
method_name = "property_%s_after_change" % prop_name
if hasattr(observer, method_name):
method = getattr(observer, method_name)
if method not in self.__instance_notif_after[prop_name]:
list.append(self.__instance_notif_after[prop_name], method)
pass
pass
pass
return
def __remove_observer_notification(self, observer, prop_name):
if self.__value_notifications.has_key(prop_name):
method_name = "property_%s_value_change" % prop_name
if hasattr(observer, method_name):
method = getattr(observer, method_name)
if method in self.__value_notifications[prop_name]:
self.__value_notifications[prop_name].remove(method)
pass
pass
pass
orig_prop = getattr(self, "_prop_%s" % prop_name)
# is it a signal?
if isinstance(orig_prop, Signal):
method_name = "property_%s_signal_emit" % prop_name
if hasattr(observer, method_name):
method = getattr(observer, method_name)
if method in self.__signal_notif[prop_name]:
self.__signal_notif[prop_name].remove(method)
pass
pass
pass
# is it an instance change notification type?
elif isinstance(orig_prop, ObsWrapperBase):
if self.__instance_notif_before.has_key(prop_name):
method_name = "property_%s_before_change" % prop_name
if hasattr(observer, method_name):
method = getattr(observer, method_name)
if method in self.__instance_notif_before[prop_name]:
self.__instance_notif_before[prop_name].remove(method)
pass
pass
pass
if self.__instance_notif_after.has_key(prop_name):
method_name = "property_%s_after_change" % prop_name
if hasattr(observer, method_name):
method = getattr(observer, method_name)
if method in self.__instance_notif_after[prop_name]:
self.__instance_notif_after[prop_name].remove(method)
pass
pass
pass
pass
return
def __notify_observer__(self, observer, method, *args, **kwargs):
"""This can be overridden by derived class in order to call
the method in a different manner (for example, in
multithreading, or a rpc, etc.) This implementation simply
calls the given method with the given arguments"""
return method(*args, **kwargs)
# ---------- Notifiers:
def notify_property_value_change(self, prop_name, old, new):
assert(self.__value_notifications.has_key(prop_name))
for method in self.__value_notifications[prop_name] :
self.__notify_observer__(method.im_self, method,
self, old, new) # notifies the change
pass
return
def notify_method_before_change(self, prop_name, instance, meth_name,
args, kwargs):
assert(self.__instance_notif_before.has_key(prop_name))
for method in self.__instance_notif_before[prop_name] :
self.__notify_observer__(method.im_self, method, self, instance,
meth_name, args, kwargs) # notifies the change
pass
return
def notify_method_after_change(self, prop_name, instance, meth_name,
res, args, kwargs):
assert(self.__instance_notif_after.has_key(prop_name))
for method in self.__instance_notif_after[prop_name] :
self.__notify_observer__(method.im_self, method, self, instance,
meth_name, res, args, kwargs) # notifies the change
pass
return
def notify_signal_emit(self, prop_name, args, kwargs):
assert(self.__signal_notif.has_key(prop_name))
for method in self.__signal_notif[prop_name] :
self.__notify_observer__(method.im_self, method, self,
args, kwargs) # notifies the signal emit
pass
return
pass # end of class Model
# ----------------------------------------------------------------------
import gtk
# ----------------------------------------------------------------------
class TreeStoreModel (Model, gtk.TreeStore):
"""Use this class as base class for your model derived by
gtk.TreeStore"""
__metaclass__ = support.metaclasses.ObservablePropertyGObjectMeta
def __init__(self, column_type, *args):
Model.__init__(self)
gtk.TreeStore.__init__(self, column_type, *args)
return
pass
# ----------------------------------------------------------------------
class ListStoreModel (Model, gtk.ListStore):
"""Use this class as base class for your model derived by
gtk.ListStore"""
__metaclass__ = support.metaclasses.ObservablePropertyGObjectMeta
def __init__(self, column_type, *args):
Model.__init__(self)
gtk.ListStore.__init__(self, column_type, *args)
return
pass
# ----------------------------------------------------------------------
class TextBufferModel (Model, gtk.TextBuffer):
"""Use this class as base class for your model derived by
gtk.TextBuffer"""
__metaclass__ = support.metaclasses.ObservablePropertyGObjectMeta
def __init__(self, table=None):
Model.__init__(self)
gtk.TextBuffer.__init__(self, table)
return
pass

View File

@@ -1,123 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (c) 2006 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
from gtkmvc.model import Model
import support.metaclasses
try: import threading as _threading
except ImportError: import dummy_threading as _threading
import gobject
if hasattr(gobject, "threads_init"): gobject.threads_init()
else: import gtk; gtk.threads_init()
class ModelMT (Model):
"""A base class for models whose observable properties can be
changed by threads different than gtk main thread. Notification is
performed by exploiting the gtk idle loop only if needed,
otherwise the standard notification system (direct method call) is
used. In this model, the observer is expected to run in the gtk
main loop thread."""
__metaclass__ = support.metaclasses.ObservablePropertyMetaMT
def __init__(self):
Model.__init__(self)
self.__observer_threads = {}
self._prop_lock = _threading.Lock()
return
def register_observer(self, observer):
Model.register_observer(self, observer)
self.__observer_threads[observer] = _threading.currentThread()
return
def unregister_observer(self, observer):
Model.unregister_observer(self, observer)
del self.__observer_threads[observer]
return
# ---------- Notifiers:
def __notify_observer__(self, observer, method, *args, **kwargs):
"""This makes a call either through the gtk.idle list or a
direct method call depending whether the caller's thread is
different from the observer's thread"""
assert self.__observer_threads.has_key(observer)
if _threading.currentThread() == self.__observer_threads[observer]:
# standard call
return Model.__notify_observer__(self, observer, method,
*args, **kwargs)
# multi-threading call
gobject.idle_add(self.__idle_callback, observer, method, args, kwargs)
return
def __idle_callback(self, observer, method, args, kwargs):
method(*args, **kwargs)
return False
pass # end of class
import gtk
# ----------------------------------------------------------------------
class TreeStoreModelMT (ModelMT, gtk.TreeStore):
"""Use this class as base class for your model derived by
gtk.TreeStore"""
__metaclass__ = support.metaclasses.ObservablePropertyGObjectMetaMT
def __init__(self, column_type, *args):
ModelMT.__init__(self)
gtk.TreeStore.__init__(self, column_type, *args)
return
pass
# ----------------------------------------------------------------------
class ListStoreModelMT (ModelMT, gtk.ListStore):
"""Use this class as base class for your model derived by
gtk.ListStore"""
__metaclass__ = support.metaclasses.ObservablePropertyGObjectMetaMT
def __init__(self, column_type, *args):
ModelMT.__init__(self)
gtk.ListStore.__init__(self, column_type, *args)
return
pass
# ----------------------------------------------------------------------
class TextBufferModelMT (ModelMT, gtk.TextBuffer):
"""Use this class as base class for your model derived by
gtk.TextBuffer"""
__metaclass__ = support.metaclasses.ObservablePropertyGObjectMetaMT
def __init__(self, table=None):
ModelMT.__init__(self)
gtk.TextBuffer.__init__(self, table)
return
pass

View File

@@ -1,68 +0,0 @@
# -------------------------------------------------------------------------
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (C) 2006 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author <cavada@irst.itc.it>.
# -------------------------------------------------------------------------
from support import decorators
from support.wrappers import ObsWrapperBase
# ----------------------------------------------------------------------
class Observable (ObsWrapperBase):
def __init__(self):
ObsWrapperBase.__init__(self)
return
pass # end of class
@decorators.good_decorator
def observed(func):
"""Use this decorator to make your class methods observable.
Your observer will receive at most two notifications:
- property_<name>_before_change
- property_<name>_after_change
"""
def wrapper(*args, **kwargs):
self = args[0]
assert(isinstance(self, Observable))
self._notify_method_before(self, func.__name__, args, kwargs)
res = func(*args, **kwargs)
self._notify_method_after(self, func.__name__, res, args, kwargs)
return res
return wrapper
# ----------------------------------------------------------------------
class Signal (Observable):
"""Base class for signals properties"""
def __init__(self):
Observable.__init__(self)
return
def emit(self, *args, **kwargs):
return self.__get_model__().notify_signal_emit(
self.__get_prop_name__(), args, kwargs)
pass # end of class

View File

@@ -1,56 +0,0 @@
# -------------------------------------------------------------------------
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (C) 2006 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
# -------------------------------------------------------------------------
class Observer (object):
"""Use this class as base class of all observers"""
def __init__(self, model=None):
self.model = None
self.register_model(model)
return
def register_model(self, model):
self.unregister_model()
self.model = model
if self.model: self.model.register_observer(self)
return
def unregister_model(self):
if self.model:
self.model.unregister_observer(self)
self.model = None
pass
return
def __del__(self):
self.unregister_model()
return
def get_model(self): return self.model
pass # end of class

View File

@@ -1,24 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (c) 2005 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
__all__ = ["metaclass_base", "metaclasses", "wrappers", "decorators"]

View File

@@ -1,43 +0,0 @@
# -------------------------------------------------------------------------
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (C) 2006 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
# -------------------------------------------------------------------------
# This file contains decorators to be used (privately) by other parts
# of the framework
def good_decorator(decorator):
"""This decorator makes decorators behave well wrt to decorated
functions names, doc, etc."""
def new_decorator(f):
g = decorator(f)
g.__name__ = f.__name__
g.__doc__ = f.__doc__
g.__dict__.update(f.__dict__)
return g
new_decorator.__name__ = decorator.__name__
new_decorator.__doc__ = decorator.__doc__
new_decorator.__dict__.update(decorator.__dict__)
return new_decorator

View File

@@ -1,253 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (c) 2005 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
import new
import re
import types
import gtkmvc.support.wrappers as wrappers
# ----------------------------------------------------------------------
VERBOSE_LEVEL = 5
class PropertyMeta (type):
"""This is a meta-class that provides auto-property support.
The idea is to allow programmers to define some properties which
will be automatically connected to auto-generated code which handles
access to those properties.
How can you use this meta-class?
First, '__metaclass__ = PropertyMeta' must be class member of the class
you want to make the automatic properties handling.
Second, '__properties__' must be a map containing the properties names
as keys, values will be initial values for properties.
That's all: after the instantiation, your class will contain all properties
you named inside '__properties__'. Each of them will be also associated
to a couple of automatically-generated functions which get and set the
property value inside a generated member variable.
About names: suppose the property is called 'x'. The generated variable
(which keeps the real value of the property x) is called _prop_x.
The getter is called get_prop_x(self), and the setter is called
'set_prop_x(self, value)'.
Customization:
The base implementation of getter is to return the value stored in the
variable associate to the property. The setter simply sets its value.
Programmers can override basic behaviour for getters or setters simply by
defining their getters and setters (see at the names convention above).
The customized function can lie everywhere in the user classes hierarchy.
Every overrided function will not be generated by the metaclass.
To supply your own methods is good for few methods, but can result in a
very unconfortable way for many methods. In this case you can extend
the meta-class, and override methods get_[gs]etter_source with your
implementation (this can be probably made better).
An example is provided in meta-class PropertyMetaVerbose below.
"""
def __init__(cls, name, bases, dict):
"""class constructor"""
properties = {}
type.__init__(cls, name, bases, dict)
props = getattr(cls, '__properties__', {})
setattr(cls, '__derived_properties__', {})
der_props = getattr(cls, '__derived_properties__')
# Calculates derived properties:
for base in bases:
maps = ( getattr(base, '__properties__', {}),
getattr(base, '__derived_properties__', {}) )
for map in maps:
for p in map.keys():
if not props.has_key(p) and not der_props.has_key(p):
der_props[p] = map[p]
pass
pass
pass
pass
# Generates code for all properties (but not for derived props):
props = getattr(cls, '__properties__', {})
for prop in props.keys():
type(cls).__create_prop_accessors__(cls, prop, props[prop])
pass
return
def __msg__(cls, msg, level):
"""if level is less or equal to VERBOSE_LEVEL, ths message will
be printed"""
if level <= VERBOSE_LEVEL: print msg
return
def __create_prop_accessors__(cls, prop_name, default_val):
"""Private method that creates getter and setter, and the
corresponding property"""
getter_name = "get_prop_%s" % prop_name
setter_name = "set_prop_%s" % prop_name
members_names = cls.__dict__.keys()
# checks if accessors are already defined:
if getter_name not in members_names:
src = type(cls).get_getter_source(cls, getter_name, prop_name)
code = type(cls).get_func_code_from_func_src(cls, src)
type(cls).add_method_from_func_code(cls, getter_name, code)
else:
cls.__msg__("Warning: Custom member '%s' overloads generated accessor of property '%s'" \
% (getter_name, prop_name), 2)
pass
if setter_name not in members_names:
src = type(cls).get_setter_source(cls, setter_name, prop_name)
code = type(cls).get_func_code_from_func_src(cls, src)
type(cls).add_method_from_func_code(cls, setter_name, code)
else:
cls.__msg__("Warning: Custom member '%s' overloads generated accessor of property '%s'" \
% (setter_name, prop_name), 2)
pass
prop = property(getattr(cls, getter_name), getattr(cls, setter_name))
if prop_name in members_names:
cls.__msg__("Warning: automatic property builder is overriding property %s in class %s" \
% (prop_name, cls.__name__), 2)
pass
setattr(cls, prop_name, prop)
varname = "_prop_%s" % prop_name
if not varname in members_names: cls.__create_property(varname, default_val)
else: cls.__msg__("Warning: automatic property builder found a possible clashing for variable %s inside class %s" \
% (varname, cls.__name__), 2)
return
def __create_property(cls, name, default_val):
setattr(cls, name, cls.create_value(name, default_val))
return
def check_value_change(cls, old, new):
"""Checks whether the value of the property changed in type
or if the instance has been changed to a different instance.
If true, a call to model._reset_property_notification should
be called in order to re-register the new property instance
or type"""
return type(old) != type(new) or \
isinstance(old, wrappers.ObsWrapperBase) and (old != new)
def create_value(cls, prop_name, val, model=None):
"""This is used to create a value to be assigned to a
property. Depending on the type of the value, different values
are created and returned. For example, for a list, a
ListWrapper is created to wrap it, and returned for the
assignment. model is different from model when the value is
changed (a model exists). Otherwise, during property creation
model is None"""
if isinstance(val, tuple):
# this might be a class instance to be wrapped
if len(val) == 3 and \
isinstance(val[1], val[0]) and \
(isinstance(val[2], tuple) or isinstance(val[2], list)):
res = wrappers.ObsUserClassWrapper(val[1], val[2])
if model: res.__set_model__(model, prop_name)
return res
pass
elif isinstance(val, list):
res = wrappers.ObsListWrapper(val)
if model: res.__set_model__(model, prop_name)
return res
elif isinstance(val, dict):
res = wrappers.ObsMapWrapper(val)
if model: res.__set_model__(model, prop_name)
return res
return val
# Services:
def add_method_from_func_code(cls, meth_name, code):
"""Use this to add a code that is a new method for the class"""
func = new.function(code, globals(), meth_name)
meth = new.instancemethod(func, cls, cls.__name__)
setattr(cls, meth_name, func)
return
def get_func_code_from_func_src(cls, source):
"""Public service that provided code object from function source"""
m = re.compile("def\s+(\w+)\s*\(.*\):").match(source)
if m is None: raise BadFuncSource(source)
func_name = m.group(1)
exec source
code = eval("%s.func_code" % func_name)
return code
# Override these:
def get_getter_source(cls, getter_name, prop_name):
"""This must be overrided if you need a different implementation.
Simply the generated implementation returns the variable name
_prop_name"""
return "def %s(self): return self._prop_%s" % (getter_name, prop_name)
def get_setter_source(cls, setter_name, prop_name):
"""This must be overrided if you need a different implementation.
Simply the generated implementation sets the variable _prop_name"""
return "def %s(self, val): self._prop_%s = val" \
% (setter_name, prop_name)
pass # end of class
# ----------------------------------------------------------------------
# What follows underneath is a set of examples of usage
## class PropertyMetaVerbose (PropertyMeta):
## """An example of customization"""
## def get_getter_source(cls, getter_name, prop_name):
## return "def %s(self): print 'Calling %s!'; return self._prop_%s" \
## % (getter_name, getter_name, prop_name)
## def get_setter_source(cls, setter_name, prop_name):
## return "def %s(self, val): print 'Calling %s!'; self._prop_%s = val;" \
## % (setter_name, setter_name, prop_name)
## pass #end of class
# ----------------------------------------------------------------------
## class User:
## """An example of usage"""
## __metaclass__ = PropertyMetaVerbose
## __properties__ = {'x':10, 'y':20}
## def __init__(self):
## print self.x # x is 10
## self.x = self.y + 10 # x is now 30
## return
## pass
# ----------------------------------------------------------------------

View File

@@ -1,81 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (c) 2005 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
from metaclass_base import PropertyMeta
import types
class ObservablePropertyMeta (PropertyMeta):
"""Classes instantiated by this meta-class must provide a method named
notify_property_change(self, prop_name, old, new)"""
def __init__(cls, name, bases, dict):
PropertyMeta.__init__(cls, name, bases, dict)
return
def get_setter_source(cls, setter_name, prop_name):
return """def %(setter)s(self, val):
old = self._prop_%(prop)s
new = type(self).create_value('%(prop)s', val, self)
self._prop_%(prop)s = new
if type(self).check_value_change(old, new): self._reset_property_notification('%(prop)s')
self.notify_property_value_change('%(prop)s', old, val)
return
""" % {'setter':setter_name, 'prop':prop_name}
pass #end of class
class ObservablePropertyMetaMT (ObservablePropertyMeta):
"""This class provides multithreading support for accesing
properties, through a locking mechanism. It is assumed a lock is
owned by the class that uses it. A Lock object called _prop_lock
is assumed to be a member of the using class. see for example class
ModelMT"""
def __init__(cls, name, bases, dict):
ObservablePropertyMeta.__init__(cls, name, bases, dict)
return
def get_setter_source(cls, setter_name, prop_name):
return """def %(setter)s(self, val):
old = self._prop_%(prop)s
new = type(self).create_value('%(prop)s', val, self)
self._prop_lock.acquire()
self._prop_%(prop)s = new
self._prop_lock.release()
if type(self).check_value_change(old, new): self._reset_property_notification('%(prop)s')
self.notify_property_value_change('%(prop)s', old, val)
return
""" % {'setter':setter_name, 'prop':prop_name}
pass #end of class
try:
from gobject import GObjectMeta
class ObservablePropertyGObjectMeta (ObservablePropertyMeta, GObjectMeta): pass
class ObservablePropertyGObjectMetaMT (ObservablePropertyMetaMT, GObjectMeta): pass
except:
class ObservablePropertyGObjectMeta (ObservablePropertyMeta): pass
class ObservablePropertyGObjectMetaMT (ObservablePropertyMetaMT): pass
pass

View File

@@ -1,152 +0,0 @@
# -------------------------------------------------------------------------
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (C) 2006 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
# -------------------------------------------------------------------------
import new
# ----------------------------------------------------------------------
class ObsWrapperBase (object):
def __init__(self):
self.__prop_name = None
self.__gtkmvc_model = None
return
def __set_model__(self, model, prop_name):
self.__prop_name = prop_name
self.__gtkmvc_model = model
return
def __get_prop_name__(self): return self.__prop_name
def __get_model__(self): return self.__gtkmvc_model
def _notify_method_before(self, instance, name, args, kwargs):
self.__get_model__().notify_method_before_change(self.__prop_name,
instance,
name, args, kwargs)
return
def _notify_method_after(self, instance, name, res_val, args, kwargs):
self.__get_model__().notify_method_after_change(self.__prop_name,
instance,
name, res_val, args, kwargs)
return
pass
# ----------------------------------------------------------------------
class ObsWrapper (ObsWrapperBase):
def __init__(self, obj, method_names):
ObsWrapperBase.__init__(self)
self._obj = obj
self.__doc__ = obj.__doc__
for name in method_names:
if hasattr(self._obj, name) and not hasattr(self, name):
src = self.__get_wrapper_code(name)
exec src
code = eval("%s.func_code" % name)
func = new.function(code, globals())
meth = new.instancemethod(func, self, type(self).__name__)
setattr(self, name, meth)
pass
pass
return
def __get_wrapper_code(self, name):
return """def %(name)s(self, *args, **kwargs):
self._notify_method_before(self._obj, "%(name)s", args, kwargs)
res = self._obj.%(name)s(*args, **kwargs)
self._notify_method_after(self._obj, "%(name)s", res, args, kwargs)
return res""" % {'name' : name}
# For all fall backs
def __getattr__(self, name): return self._obj.__getattr__(name)
def __repr__(self): return self._obj.__repr__()
def __str__(self): return self._obj.__str__()
pass #end of class
# ----------------------------------------------------------------------
class ObsSeqWrapper (ObsWrapper):
def __init__(self, obj, method_names):
ObsWrapper.__init__(self, obj, method_names)
return
def __setitem__(self, key, val):
self._notify_method_before(self._obj, "__setitem__", (key,val), {})
res = self._obj.__setitem__(key, val)
self._notify_method_after(self._obj, res, "__setitem__", (key,val), {})
return res
def __delitem__(self, key):
self._notify_method_before(self._obj, "__delitem__", (key,), {})
res = self._obj.__delitem__(key)
self._notify_method_after(self._obj, res, "__delitem__", (key,), {})
return res
def __getitem__(self, key):
return self._obj.__getitem__(key)
pass #end of class
# ----------------------------------------------------------------------
class ObsMapWrapper (ObsSeqWrapper):
def __init__(self, m):
methods = ("clear", "pop", "popitem", "update",
"setdefault")
ObsSeqWrapper.__init__(self, m, methods)
return
pass #end of class
# ----------------------------------------------------------------------
class ObsListWrapper (ObsSeqWrapper):
def __init__(self, l):
methods = ("append", "extend", "insert",
"pop", "remove", "reverse", "sort")
ObsSeqWrapper.__init__(self, l, methods)
return
pass #end of class
# ----------------------------------------------------------------------
class ObsUserClassWrapper (ObsWrapper):
def __init__(self, user_class_instance, obs_method_names):
ObsWrapper.__init__(self, user_class_instance, obs_method_names)
return
pass #end of class

View File

@@ -1,170 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
# Modified by: Guillaume Libersat <glibersat AT linux62.org>
#
# Copyright (c) 2005 by Roberto Cavada
# Copyright (c) 2007 by Guillaume Libersat
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author Roberto Cavada <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
import gtk.glade
from controller import Controller
import types
class View (object):
def __init__(self, controller, glade_filename=None,
glade_top_widget_name=None, parent_view=None, register=True):
"""If register is False you *must* call 'controller.register_view(self)'
from the derived class constructor (i.e. registration is delayed)
If filename is not given (or None) all following parameters must be
not given (or None). In that case widgets must be connected manually.
glade_top_widget_name can be either a string name or list of names."""
self.manualWidgets = {}
self.xmlWidgets = []
# Sets a callback for custom widgets
gtk.glade.set_custom_handler(self._custom_widget_create)
if (( type(glade_top_widget_name) == types.StringType)
or (glade_top_widget_name is None) ):
wids = (glade_top_widget_name,)
else: wids = glade_top_widget_name # Already a list or tuple
if (glade_filename is not None):
for i in range(0,len(wids)):
self.xmlWidgets.append(gtk.glade.XML(glade_filename, wids[i]))
pass
pass
# top widget list or singleton:
if (glade_top_widget_name is not None):
if len(wids) > 1:
self.m_topWidget = []
for i in range(0, len(wids)):
self.m_topWidget.append(self[wids[i]])
pass
else: self.m_topWidget = self[wids[0]]
else: self.m_topWidget = None
if (glade_filename is not None): self.autoconnect_signals(controller)
if (register): controller.register_view(self)
if (not parent_view is None): self.set_parent_view(parent_view)
return
# Gives us the ability to do: view['widget_name'].action()
# Returns None if no widget name has been found.
def __getitem__(self, key):
wid = None
for xml in self.xmlWidgets:
wid = xml.get_widget(key)
if wid is not None: break
pass
if (wid is None):
# try with manually-added widgets:
if (self.manualWidgets.has_key(key)):
wid = self.manualWidgets[key]
pass
pass
return wid
# You can also add a single widget:
def __setitem__(self, key, wid):
self.manualWidgets[key] = wid
if (self.m_topWidget is None): self.m_topWidget = wid
return
# performs Controller's signals auto-connection:
def autoconnect_signals(self, controller):
dict = {}
member_names = dir(controller)
for name in member_names:
method = getattr(controller, name)
if (not callable(method)): continue
assert(not dict.has_key(name)) # not already connected!
dict[name] = method
pass
for xml in self.xmlWidgets: xml.signal_autoconnect(dict)
return
def show(self):
ret = True
top = self.get_top_widget()
if type(top) in (types.ListType, types.TupleType):
for t in top:
if t is not None: ret = ret and t.show()
pass
elif (top is not None): ret = top.show_all()
else: ret = False
return ret
def hide(self):
top = self.get_top_widget()
if type(top) in (types.ListType, types.TupleType):
for t in top:
if t is not None: t.hide_all()
pass
elif top is not None: top.hide_all()
return
# Returns the top-level widget, or a list of top widgets
def get_top_widget(self):
return self.m_topWidget
# Set parent view:
def set_parent_view(self, parent_view):
top = self.get_top_widget()
if type(top) in (types.ListType, types.TupleType):
for t in top:
if t is not None:
t.set_transient_for(parent_view.get_top_widget())
pass
pass
elif (top is not None):
top.set_transient_for(parent_view.get_top_widget())
pass
return
# Set the transient for the view:
def set_transient(self, transient_view):
top = self.get_top_widget()
if type(top) in (types.ListType, types.TupleType):
for t in top:
if t is not None:
transient_view.get_top_widget().set_transient_for(t)
pass
pass
elif (top is not None):
transient_view.get_top_widget().set_transient_for(top)
pass
return
# Finds the right callback for custom widget creation and call it
def _custom_widget_create(self, glade, function_name, widget_name,
str1, str2, int1, int2):
handler = getattr(self, function_name)
return handler(str1, str2, int1, int2)
pass # end of class View

View File

@@ -1,6 +0,0 @@
#!/bin/sh
# Simple wraper to launch python application from desired place.
cd ~/Devel/Python/pyGTKtalog/mvc
#export PYTHONPATH="$PYTHONPATH:/home/gryf/Devel/Python/pyGTKtalog/mvc"
#exec python -OO pygtktalog.py $@
exec python pygtktalog.py $@

View File

@@ -1,85 +0,0 @@
# This Python file uses the following encoding: utf-8
def setup_path():
"""Sets up the python include paths to include src"""
import os.path
import sys
if sys.argv[0]:
top_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
sys.path = [os.path.join(top_dir, "src")] + sys.path
pass
return
if __name__ == "__main__":
setup_path()
import sys
import os
try:
from models.m_config import ConfigModel
except:
print "Some fundamental files are missing. try runnig pyGTKtalog in his root directory"
sys.exit(1)
conf = ConfigModel()
conf.load()
try:
import pygtk
#tell pyGTK, if possible, that we want GTKv2
pygtk.require("2.0")
except:
#Some distributions come with GTK2, but not pyGTK
pass
try:
import gtk
import gtk.glade
except:
print "You need to install pyGTK or GTKv2 ",
print "or set your PYTHONPATH correctly."
print "try: export PYTHONPATH=",
print "/usr/local/lib/python2.2/site-packages/"
sys.exit(1)
try:
from pysqlite2 import dbapi2 as sqlite
except:
print "pyGTKtalog uses SQLite DB.\nYou'll need to get it and the python bindings as well.\nhttp://www.sqlite.org\nhttp://initd.org/tracker/pysqlite"
sys.exit(1)
try:
import mx.DateTime
except:
print "pyGTKtalog uses Egenix mx.DateTime.\nYou can instal it from your distribution repositry,\nor get it at: http://www.egenix.com"
sys.exit(1)
if conf.confd['exportxls']:
try:
import pyExcelerator
except:
print "You'll need pyExcelerator, if you want to export DB to XLS format.\nhttp://sourceforge.net/projects/pyexcelerator"
sys.exit(1)
if conf.confd['pil']:
try:
import Image, ImageEnhance
except:
print "You'll need Python Imaging Library (PIL), if you want to make thumbnails"
sys.exit(1)
from models.m_main import MainModel
from controllers.c_main import MainController
from views.v_main import MainView
m = MainModel()
c = MainController(m)
v = MainView(c)
try:
gtk.main()
except KeyboardInterrupt:
import os
m.config.save()
m.cleanup()
gtk.main_quit
pass

View File

@@ -1,3 +0,0 @@
__all__ = ["models", "views", "controllers", "utils"]

View File

@@ -1,299 +0,0 @@
# This Python file uses the following encoding: utf-8
import utils._importer
import utils.globals
from gtkmvc import Controller
import gtk
class ConfigController(Controller):
category_dict = {'Disk options':'disk_group','General':'general_group','Scan options':'scan_group'}
category_order = ['General','Disk options','Scan options']
def __init__(self, model):
Controller.__init__(self, model)
return
def register_view(self, view):
Controller.register_view(self, view)
# get data from Config object and put it into view
self.view['mnt_entry'].set_text(self.model.confd['cd'])
self.view['ejt_entry'].set_text(self.model.confd['ejectapp'])
self.view['ch_win'].set_active(self.model.confd['savewin'])
self.view['ch_pan'].set_active(self.model.confd['savepan'])
self.view['ch_eject'].set_active(self.model.confd['eject'])
self.view['ch_xls'].set_active(self.model.confd['exportxls'])
self.view['ch_quit'].set_active(self.model.confd['confirmquit'])
self.view['ch_wrnmount'].set_active(self.model.confd['mntwarn'])
self.view['ch_warnnew'].set_active(self.model.confd['confirmabandon'])
self.view['ch_thumb'].set_active(self.model.confd['pil'])
self.view['ch_exif'].set_active(self.model.confd['exif'])
self.view['ch_gthumb'].set_active(self.model.confd['gthumb'])
# initialize tree view
self.__setup_category_tree()
self.view['config'].show();
return
# Podłącz sygnały:
#################
# connect signals
def on_category_tree_cursor_changed(self, tree):
"""change view to selected row corresponding to group of properties"""
model = tree.get_model()
selected = model.get_value(model.get_iter(tree.get_cursor()[0]),0)
iterator = tree.get_model().get_iter_first();
while iterator != None:
if model.get_value(iterator,0) == selected:
self.view[self.category_dict[model.get_value(iterator,0)]].show()
self.view['desc'].set_markup("<b>%s</b>" % selected)
else:
self.view[self.category_dict[model.get_value(iterator,0)]].hide()
iterator = tree.get_model().iter_next(iterator);
return
def on_cancelbutton_clicked(self, button):
self.view['config'].destroy()
return
def on_okbutton_clicked(self, button):
# get data from view and put it into Config object
self.model.confd['cd'] = self.view['mnt_entry'].get_text()
self.model.confd['ejectapp'] = self.view['ejt_entry'].get_text()
self.model.confd['savewin'] = self.view['ch_win'].get_active()
self.model.confd['savepan'] = self.view['ch_pan'].get_active()
self.model.confd['eject'] = self.view['ch_eject'].get_active()
self.model.confd['exportxls'] = self.view['ch_xls'].get_active()
self.model.confd['confirmquit'] = self.view['ch_quit'].get_active()
self.model.confd['mntwarn'] = self.view['ch_wrnmount'].get_active()
self.model.confd['confirmabandon'] = self.view['ch_warnnew'].get_active()
self.model.confd['pil'] = self.view['ch_thumb'].get_active()
self.model.confd['exif'] = self.view['ch_exif'].get_active()
self.model.confd['gthumb'] = self.view['ch_gthumb'].get_active()
self.model.save()
self.view['config'].destroy()
return
def on_button_ejt_clicked(self,button):
self.__show_filechooser()
return
def on_button_mnt_clicked(self,button):
self.__show_dirchooser()
return
############################
# private controller methods
def __setup_category_tree(self):
category_tree = self.view['category_tree']
category_tree.set_model(self.model.category_tree)
self.model.category_tree.clear()
for i in ['General','Disk options','Scan options']:
myiter = self.model.category_tree.insert_before(None,None)
self.model.category_tree.set_value(myiter,0,i)
cell = gtk.CellRendererText()
column = gtk.TreeViewColumn("Name",cell,text=0)
column.set_resizable(True)
category_tree.append_column(column)
def __show_filechooser(self):
"""dialog for choose eject"""
dialog = gtk.FileChooserDialog(
title="Choose eject program",
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK
)
)
dialog.set_default_response(gtk.RESPONSE_OK)
response = dialog.run()
if response == gtk.RESPONSE_OK:
print dialog.get_filename()
self.view['ejt_entry'].set_text(dialog.get_filename())
dialog.destroy()
def __show_dirchooser(self):
"""dialog for point the mountpoint"""
dialog = gtk.FileChooserDialog(
title="Choose mount point",
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK
)
)
dialog.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
dialog.set_filename(self.view['mnt_entry'].get_text())
dialog.set_default_response(gtk.RESPONSE_OK)
response = dialog.run()
if response == gtk.RESPONSE_OK:
self.view['mnt_entry'].set_text(dialog.get_filename())
dialog.destroy()
pass # end of class
'''
import sys
import os
import pygtk
import gtk
import gtk.glade
import gobject
from config import Config
import dialogs
class Preferences:
def __init__(self):
self.category_dict = {'Disk options':'disk_group','General':'general_group','Scan options':'scan_group'}
self.category_order = ['General','Disk options','Scan options']
self.conf = Config()
self.conf.load()
self.gladefile = "glade/prefs.glade"
self.glade = gtk.glade.XML(self.gladefile,"prefs")
dic = {
"on_button_ejt_clicked" :self.show_filechooser,
"on_button_mnt_clicked" :self.show_dirchooser,
"on_category_tree_cursor_changed" :self.activate_pan,
}
self.glade.signal_autoconnect(dic)
self.pref = self.glade.get_widget("prefs")
self.pref.set_title("Preferences - pyGTKtalog")
self.desc = self.glade.get_widget("desc")
self.cd = self.glade.get_widget("mnt_entry")
self.cd.set_text(self.conf.confd['cd'])
self.eject = self.glade.get_widget("ejt_entry")
self.eject.set_text(self.conf.confd['ejectapp'])
self.ch_win = self.glade.get_widget("ch_win")
self.ch_win.set_active(self.conf.confd['savewin'])
self.ch_pan = self.glade.get_widget("ch_pan")
self.ch_pan.set_active(self.conf.confd['savepan'])
self.ch_eject = self.glade.get_widget("ch_eject")
self.ch_eject.set_active(self.conf.confd['eject'])
self.ch_xls = self.glade.get_widget("ch_xls")
self.ch_xls.set_active(self.conf.confd['exportxls'])
self.ch_quit = self.glade.get_widget("ch_quit")
self.ch_quit.set_active(self.conf.confd['confirmquit'])
self.ch_wrnmount = self.glade.get_widget("ch_wrnmount")
self.ch_wrnmount.set_active(self.conf.confd['mntwarn'])
self.ch_warnnew = self.glade.get_widget("ch_warnnew")
self.ch_warnnew.set_active(self.conf.confd['confirmabandon'])
self.ch_thumb = self.glade.get_widget("ch_thumb")
self.ch_thumb.set_active(self.conf.confd['pil'])
self.ch_exif = self.glade.get_widget("ch_exif")
self.ch_exif.set_active(self.conf.confd['exif'])
self.ch_gthumb = self.glade.get_widget("ch_gthumb")
self.ch_gthumb.set_active(self.conf.confd['gthumb'])
self.tree = self.glade.get_widget("category_tree")
self.model = gtk.ListStore(gobject.TYPE_STRING)
self.model.clear()
self.tree.set_model(self.model)
self.tree.set_headers_visible(False)
self.tree.show()
for i in self.category_order:
myiter = self.model.insert_before(None,None)
self.model.set_value(myiter,0,i)
renderer=gtk.CellRendererText()
column=gtk.TreeViewColumn("Name",renderer, text=0)
column.set_resizable(True)
self.tree.append_column(column)
if self.pref.run() == gtk.RESPONSE_OK:
self.conf.confd['cd'] = self.cd.get_text()
self.conf.confd['ejectapp'] = self.eject.get_text()
self.conf.confd['savewin'] = self.ch_win.get_active()
self.conf.confd['savepan'] = self.ch_pan.get_active()
self.conf.confd['eject'] = self.ch_eject.get_active()
self.conf.confd['pil'] = self.ch_thumb.get_active()
self.conf.confd['exif'] = self.ch_exif.get_active()
self.conf.confd['gthumb'] = self.ch_gthumb.get_active()
self.conf.confd['exportxls'] = self.ch_xls.get_active()
self.conf.confd['confirmquit'] = self.ch_quit.get_active()
self.conf.confd['mntwarn'] = self.ch_wrnmount.get_active()
self.conf.confd['confirmabandon'] = self.ch_warnnew.get_active()
self.conf.save()
self.pref.destroy()
def show_filechooser(self,widget):
"""dialog for choose eject"""
dialog = gtk.FileChooserDialog(
title="Choose eject program",
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK
)
)
dialog.set_default_response(gtk.RESPONSE_OK)
response = dialog.run()
if response == gtk.RESPONSE_OK:
self.eject.set_text(dialog.get_filename())
dialog.destroy()
def show_dirchooser(self,widget):
"""dialog for point the mountpoint"""
dialog = gtk.FileChooserDialog(
title="Choose mount point",
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK
)
)
dialog.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
dialog.set_filename(self.conf.confd['cd'])
dialog.set_default_response(gtk.RESPONSE_OK)
response = dialog.run()
if response == gtk.RESPONSE_OK:
self.cd.set_text(dialog.get_filename())
dialog.destroy()
def activate_pan(self,treeview):
model = treeview.get_model()
selected = model.get_value(model.get_iter(treeview.get_cursor()[0]),0)
iterator = treeview.get_model().get_iter_first();
while iterator != None:
if model.get_value(iterator,0) == selected:
self.glade.get_widget(self.category_dict[model.get_value(iterator,0)]).show()
self.desc.set_markup("<b>%s</b>" % selected)
else:
self.glade.get_widget(self.category_dict[model.get_value(iterator,0)]).hide()
iterator = treeview.get_model().iter_next(iterator);
if __name__ == "__main__":
try:
app=Preferences()
gtk.main()
except KeyboardInterrupt:
gtk.main_quit
'''

View File

@@ -1,464 +0,0 @@
# This Python file uses the following encoding: utf-8
__version__ = "0.7"
licence = \
"""
GPL v2
http://www.gnu.org/licenses/gpl.txt
"""
import utils._importer
import utils.globals
from utils import deviceHelper
from gtkmvc import Controller
from c_config import ConfigController
from views.v_config import ConfigView
from models.m_config import ConfigModel
import views.v_dialogs as Dialogs
import gtk
import datetime
class MainController(Controller):
"""Kontroler głównego okna aplikacji"""
scan_cd = False
widgets = (
"discs","files","details",
'save1','save_as1','cut1','copy1','paste1','delete1','add_cd','add_directory1',
'tb_save','tb_addcd','tb_find',
)
widgets_all = (
"discs","files","details",
'file1','edit1','add_cd','add_directory1','help1',
'tb_save','tb_addcd','tb_find','tb_new','tb_open','tb_quit',
)
widgets_cancel = ('cancel','cancel1')
def __init__(self, model):
"""Initialize controller"""
Controller.__init__(self, model)
return
def register_view(self, view):
Controller.register_view(self, view)
# deaktywuj na starcie te oto widżety
for widget in self.widgets:
self.view[widget].set_sensitive(False)
# dodatkowo deaktywuj knefle 'cancel'
for widget in self.widgets_cancel:
self.view[widget].set_sensitive(False)
# ukryj przycisk "debug", jeśli nie debugujemy.
if __debug__:
self.view['debugbtn'].show()
else:
self.view['debugbtn'].hide()
# ustaw domyślne właściwości dla poszczególnych widżetów
self.view['main'].set_title('pyGTKtalog');
self.view['main'].set_icon_list(gtk.gdk.pixbuf_new_from_file("pixmaps/mainicon.png"))
self.view['detailplace'].set_sensitive(False)
self.view['details'].hide()
# załaduj konfigurację/domyślne ustawienia i przypisz je właściwościom
self.view['toolbar1'].set_active(self.model.config.confd['showtoolbar'])
if self.model.config.confd['showtoolbar']:
self.view['maintoolbar'].show()
else:
self.view['maintoolbar'].hide()
self.view['status_bar1'].set_active(self.model.config.confd['showstatusbar'])
if self.model.config.confd['showstatusbar']:
self.view['statusprogress'].show()
else:
self.view['statusprogress'].hide()
self.view['hpaned1'].set_position(self.model.config.confd['h'])
self.view['vpaned1'].set_position(self.model.config.confd['v'])
self.view['main'].resize(self.model.config.confd['wx'],self.model.config.confd['wy'])
# zainicjalizuj statusbar
self.context_id = self.view['mainStatus'].get_context_id('detailed res')
self.statusbar_id = self.view['mainStatus'].push(self.context_id, "Idle")
# inicjalizacja drzew
self.__setup_disc_treeview()
self.__setup_files_treeview()
# Show main window
self.view['main'].show();
return
#########################################################################
# Connect signals from GUI, like menu objects, toolbar buttons and so on.
def on_main_destroy_event(self, window, event):
self.__doQuit()
return True
def on_tb_quit_clicked(self,widget):
self.__doQuit()
def on_quit1_activate(self,widget):
self.__doQuit()
def on_new1_activate(self,widget):
self.__newDB()
def on_tb_new_clicked(self,widget):
self.__newDB()
def on_add_cd_activate(self,widget):
self.__addCD()
def on_tb_addcd_clicked(self,widget):
self.__addCD()
def on_add_directory1_activate(self,widget):
"""Show dialog for choose drectory to add from filesystem."""
res = Dialogs.PointDirectoryToAdd().run()
if res !=(None,None):
self.model.scan(res[1],res[0])
return
def on_about1_activate(self,widget):
"""Show about dialog"""
Dialogs.Abt("pyGTKtalog", __version__, "About", ["Roman 'gryf' Dobosz"], licence)
return
def on_preferences_activate(self,widget):
c = ConfigController(self.model.config)
v = ConfigView(c)
return
def on_status_bar1_activate(self,widget):
"""Toggle visibility of statusbat and progress bar."""
self.model.config.confd['showstatusbar'] = self.view['status_bar1'].get_active()
if self.view['status_bar1'].get_active():
self.view['statusprogress'].show()
else:
self.view['statusprogress'].hide()
def on_toolbar1_activate(self,widget):
"""Toggle visibility of toolbar bar."""
self.model.config.confd['showtoolbar'] = self.view['toolbar1'].get_active()
if self.view['toolbar1'].get_active():
self.view['maintoolbar'].show()
else:
self.view['maintoolbar'].hide()
def on_save1_activate(self,widget):
self.__save()
def on_tb_save_clicked(self,widget):
self.__save()
def on_save_as1_activate(self,widget):
self.__save_as()
def on_tb_open_clicked(self,widget):
self.__open()
def on_open1_activate(self,widget):
self.__open()
def on_discs_cursor_changed(self,widget):
"""Show files on right treeview, after clicking the left disc treeview."""
model = self.view['discs'].get_model()
selected_item = self.model.discsTree.get_value(self.model.discsTree.get_iter(self.view['discs'].get_cursor()[0]),0)
if __debug__:
print "on_discs_cursor_changed ",selected_item
self.model.get_root_entries(selected_item)
self.view['details'].show()
txt = self.model.get_file_info(selected_item)
buf = self.view['details'].get_buffer()
buf.set_text(txt)
self.view['details'].set_buffer(buf)
return
def on_discs_row_activated(self, treeview, path, treecolumn):
"""If possible, expand or collapse branch of discs tree"""
if treeview.row_expanded(path):
treeview.collapse_row(path)
else:
treeview.expand_row(path,False)
def on_files_cursor_changed(self,treeview):
"""Show details of selected file"""
model, paths = treeview.get_selection().get_selected_rows()
try:
itera = model.get_iter(paths[0])
if model.get_value(itera,4) == 1:
#directory, do nothin', just turn off view
self.view['details'].hide()
buf = self.view['details'].get_buffer()
buf.set_text('')
self.view['details'].set_buffer(buf)
if __debug__:
print "on_files_cursor_changed: directory selected"
else:
#file, show what you got.
self.view['details'].show()
selected_item = self.model.filesList.get_value(model.get_iter(treeview.get_cursor()[0]),0)
txt = self.model.get_file_info(selected_item)
buf = self.view['details'].get_buffer()
buf.set_text(txt)
self.view['details'].set_buffer(buf)
if __debug__:
print "on_files_cursor_changed: some other thing selected"
except:
if __debug__:
print "on_files_cursor_changed: insufficient iterator"
return
def on_files_row_activated(self, files_obj, row, column):
"""On directory doubleclick in files listview dive into desired branch."""
# TODO: można by też podczepić klawisz backspace do przechodzenia poziom wyżej.
f_iter = self.model.filesList.get_iter(row)
current_id = self.model.filesList.get_value(f_iter,0)
if self.model.filesList.get_value(f_iter,4) == 1:
# ONLY directories. files are omitted.
self.model.get_root_entries(current_id)
d_path, d_column = self.view['discs'].get_cursor()
if d_path!=None:
if not self.view['discs'].row_expanded(d_path):
self.view['discs'].expand_row(d_path,False)
new_iter = self.model.discsTree.iter_children(self.model.discsTree.get_iter(d_path))
if new_iter:
while new_iter:
if self.model.discsTree.get_value(new_iter,0) == current_id:
self.view['discs'].set_cursor(self.model.discsTree.get_path(new_iter))
new_iter = self.model.discsTree.iter_next(new_iter)
return
def on_cancel1_activate(self,widget):
self.__abort()
def on_cancel_clicked(self,widget):
self.__abort()
def on_tb_find_clicked(self,widget):
# TODO: zaimplementować wyszukiwarkę
return
def on_debugbtn_clicked(self,widget):
"""Debug, do usunięcia w wersji stable, włącznie z kneflem w GUI"""
if __debug__:
print "\ndebug:"
print "------"
print "unsaved_project = %s" % self.model.unsaved_project
print "filename = %s" % self.model.filename
print "internal_filename = %s" % self.model.internal_filename
print "db_connection = %s" % self.model.db_connection
print "abort = %s" % self.model.abort
#####################
# observed properetis
def property_statusmsg_value_change(self, model, old, new):
if self.statusbar_id != 0:
self.view['mainStatus'].remove(self.context_id, self.statusbar_id)
self.statusbar_id = self.view['mainStatus'].push(self.context_id, "%s" % new)
return
def property_busy_value_change(self, model, old, new):
if new != old:
for w in self.widgets_all:
self.view[w].set_sensitive(not new)
for widget in self.widgets_cancel:
self.view[widget].set_sensitive(new)
if not new and self.scan_cd:
self.scan_cd = False
# umount/eject cd
if self.model.config.confd['eject']:
msg = deviceHelper.eject_cd(self.model.config.confd['ejectapp'],self.model.config.confd['cd'])
if msg != 'ok':
Dialogs.Wrn("error ejecting device - pyGTKtalog",
"Cannot eject device pointed to %s" % self.model.config.confd['cd'],
"Last eject message:\n%s" % msg)
else:
msg = deviceHelper.volumount(self.model.config.confd['cd'])
if msg != 'ok':
Dialogs.Wrn("error unmounting device - pyGTKtalog",
"Cannot unmount device pointed to %s" % self.model.config.confd['cd'],
"Last umount message:\n%s" % msg)
return
def property_progress_value_change(self, model, old, new):
self.view['progressbar1'].set_fraction(new)
return
#########################
# private class functions
def __open(self):
"""Open catalog file"""
if self.model.unsaved_project and self.model.config.confd['confirmabandon']:
obj = dialogs.Qst('Unsaved data - pyGTKtalog','There is not saved database','Pressing "Ok" will abandon catalog.')
if not obj.run():
return
path = Dialogs.LoadDBFile().run()
if path:
if not self.model.open(path):
Dialogs.Err("Error opening file - pyGTKtalog","Cannot open file %s." % self.opened_catalog)
else:
self.__activateUI(path)
def __save(self):
"""Save catalog to file"""
#{{{
if self.model.filename:
self.model.save()
else:
self.__save_as()
pass
def __save_as(self):
"""Save database to file under different filename."""
path = Dialogs.ChooseDBFilename().show_dialog()
if path:
self.view['main'].set_title("%s - pyGTKtalog" % path)
self.model.save(path)
pass
def __addCD(self):
"""Add directory structure from cd/dvd disc"""
mount = deviceHelper.volmount(self.model.config.confd['cd'])
if mount == 'ok':
guessed_label = deviceHelper.volname(self.model.config.confd['cd'])
label = Dialogs.InputDiskLabel(guessed_label).run()
if label != None:
self.scan_cd = True
for widget in self.widgets_all:
self.view[widget].set_sensitive(False)
self.model.scan(self.model.config.confd['cd'],label)
else:
Dialogs.Wrn("Error mounting device - pyGTKtalog",
"Cannot mount device pointed to %s" % self.model.config.confd['cd'],
"Last mount message:\n%s" % mount)
def __doQuit(self):
"""Quit and save window parameters to config file"""
# check if any unsaved project is on go.
if self.model.unsaved_project and self.model.config.confd['confirmquit']:
if not Dialogs.Qst('Quit application - pyGTKtalog',
'Do you really want to quit?',
"Current database is not saved, any changes will be lost.").run():
return
self.__storeSettings()
self.model.cleanup()
gtk.main_quit()
return False
def __newDB(self):
"""Create new database file"""
if self.model.unsaved_project:
if not Dialogs.Qst('Unsaved data - pyGTKtalog',
"Current database isn't saved",
'All changes will be lost. Do you really want to abandon it?').run():
return
self.model.new()
# clear "details" buffer
txt = ""
buf = self.view['details'].get_buffer()
buf.set_text(txt)
self.view['details'].set_buffer(buf)
self.__activateUI()
return
def __setup_disc_treeview(self):
"""Setup TreeView discs widget as tree."""
self.view['discs'].set_model(self.model.discsTree)
c = gtk.TreeViewColumn('Filename')
# one row contains image and text
cellpb = gtk.CellRendererPixbuf()
cell = gtk.CellRendererText()
c.pack_start(cellpb, False)
c.pack_start(cell, True)
c.set_attributes(cellpb, stock_id=2)
c.set_attributes(cell, text=1)
self.view['discs'].append_column(c)
# registration of treeview signals:
return
def __setup_files_treeview(self):
"""Setup TreeView files widget, as columned list."""
self.view['files'].set_model(self.model.filesList)
self.view['files'].get_selection().set_mode(gtk.SELECTION_MULTIPLE)
c = gtk.TreeViewColumn('Filename')
cellpb = gtk.CellRendererPixbuf()
cell = gtk.CellRendererText()
c.pack_start(cellpb, False)
c.pack_start(cell, True)
c.set_attributes(cellpb, stock_id=6)
c.set_attributes(cell, text=1)
c.set_sort_column_id(1)
c.set_resizable(True)
self.view['files'].append_column(c)
c = gtk.TreeViewColumn('Size',gtk.CellRendererText(), text=2)
c.set_sort_column_id(2)
c.set_resizable(True)
self.view['files'].append_column(c)
c = gtk.TreeViewColumn('Date',gtk.CellRendererText(), text=3)
c.set_sort_column_id(3)
c.set_resizable(True)
self.view['files'].append_column(c)
c = gtk.TreeViewColumn('Category',gtk.CellRendererText(), text=5)
c.set_sort_column_id(5)
c.set_resizable(True)
self.view['files'].append_column(c)
# registration of treeview signals:
return
def __abort(self):
"""When scanning thread is activated and user push the cancel button,
models abort attribute trigger cancelation for scan operation"""
self.model.abort = True
return
def __activateUI(self, name='untitled'):
"""Make UI active, and set title"""
self.model.unsaved_project = False
self.view['main'].set_title("%s - pyGTKtalog" % name)
for widget in self.widgets:
try:
self.view[widget].set_sensitive(True)
except:
pass
# PyGTK FAQ entry 23.20
while gtk.events_pending():
gtk.main_iteration()
return
def __storeSettings(self):
"""Store window size and pane position in config file (using config object from model)"""
if self.model.config.confd['savewin']:
self.model.config.confd['wx'], self.model.config.confd['wy'] = self.view['main'].get_size()
if self.model.config.confd['savepan']:
self.model.config.confd['h'],self.model.config.confd['v'] = self.view['hpaned1'].get_position(), self.view['vpaned1'].get_position()
self.model.config.save()
pass
pass # end of class

View File

@@ -1,155 +0,0 @@
# This Python file uses the following encoding: utf-8
import utils._importer
import utils.globals
from gtkmvc import Model
import sys
import os
import gtk
import gobject
from ConfigParser import ConfigParser
class Ini(object):
def __init__(self):
self.ini = []
def add_section(self, section):
self.ini.append("[%s]" % section)
def add_key(self, key, value):
self.ini.append("%s=%s" % (key, value))
def add_comment(self, comment):
self.ini.append(";%s" % comment)
def add_verb(self, verb):
self.ini.append(verb)
def show(self):
return "\n".join(self.ini)
class ConfigModel(Model):
ini = Ini()
__properties__ = {}
confd = {
'savewin' : True,
'savepan' : True,
'wx' : 800,
'wy' : 600,
'h' : 200,
'v' : 300,
'exportxls' : False,
'cd' : '/cdrom',
'ejectapp' : 'eject -r',
'eject' : True,
'pil': False,
'gthumb':False,
'exif':False,
'confirmquit':True,
'mntwarn':True,
'confirmabandon':True,
'showtoolbar':True,
'showstatusbar':True,
}
dictconf = {
"save main window size" : "savewin",
"save panes size" : "savepan",
"main window width" : "wx",
"main window height": "wy",
"horizontal panes": "h",
"vertical panes":"v",
"export xls":"exportxls",
"cd drive":"cd",
"eject command":"ejectapp",
"eject":"eject",
"image support":"pil",
'confirm quit':'confirmquit',
'warn mount/umount errors':'mntwarn',
'confirm abandon current catalog':'confirmabandon',
'show toolbar':'showtoolbar',
'show statusbar and progress bar':'showstatusbar',
}
dbool = (
'exportxls',
'pil',
'savewin',
'savepan',
'eject',
'gthumb',
'exif',
'confirmquit',
'mntwarn',
'confirmabandon',
'showtoolbar',
'showstatusbar',
)
dstring = ('cd','ejectapp')
try:
path = os.environ['HOME']
except:
path = "/tmp"
def __init__(self):
Model.__init__(self)
self.category_tree = gtk.ListStore(gobject.TYPE_STRING)
return
def save(self):
try:
os.lstat("%s/.pygtktalog" % self.path)
except:
if __debug__:
print "Saving preferences to %s/.pygtktalog" % self.path
newIni = Ini()
newIni.add_section("pyGTKtalog conf")
for opt in self.dictconf:
newIni.add_key(opt,self.confd[self.dictconf[opt]])
try:
f = open("%s/.pygtktalog" % self.path,"w")
success = True
except:
if __debug__:
print "Cannot open config file %s for writing." % (self.path, "/.pygtktalog")
success = False
f.write(newIni.show())
f.close()
return success
def load(self):
try:
# try to read config file
parser = ConfigParser()
parser.read("%s/.pygtktalog" % self.path)
for sec in parser.sections():
if sec == 'pyGTKtalog conf':
for opt in parser.options(sec):
try:
if self.dictconf[opt] in self.dbool:
self.confd[self.dictconf[opt]] = parser.getboolean(sec,opt)
elif self.dictconf[opt] in self.dstring:
self.confd[self.dictconf[opt]] = parser.get(sec,opt)
else:
self.confd[self.dictconf[opt]] = parser.getint(sec,opt)
except:
if __debug__:
print "failed to parse option:", opt
pass
except:
if __debug__:
print "load config file failed"
pass
def __str__(self):
"""show prefs in string way"""
string = "[varname]\tvalue\n"
for i in self.confd:
string+="%s\t%s\n" % (i,self.confd[i])
return string

View File

@@ -1,419 +0,0 @@
# This Python file uses the following encoding: utf-8
import utils._importer
import utils.globals
from gtkmvc.model_mt import ModelMT
try:
import threading as _threading
except ImportError:
if __debug__:
print "import exception: _threading"
import dummy_threading as _threading
from pysqlite2 import dbapi2 as sqlite
import datetime
import mx.DateTime
import os
import sys
import mimetypes
import bz2
import gtk
import gobject
from m_config import ConfigModel
class MainModel(ModelMT):
"""Create, load, save, manipulate db file which is container for our data"""
__properties__ = {'busy': False, 'statusmsg': '', 'progress': 0}
config = ConfigModel()
unsaved_project = False
filename = None
internal_filename = None
db_connection = None
db_cursor = None
abort = False
# Drzewo katalogów: id, nazwa
discsTree = gtk.TreeStore(gobject.TYPE_INT, gobject.TYPE_STRING,str)
# Lista plików wskazanego katalogu: child_id (?), filename, size, date, typ, ikonka
filesList = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_UINT64, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_STRING,str)
LAB = 0 # label/nazwa kolekcji --- najwyższy poziom drzewa przypiętego do korzenia
DIR = 1 # katalog - podlega innemu katalogu lub lejbelu
FIL = 2 # plik - podleka katalogu lub lejbelu
def __init__(self):
ModelMT.__init__(self)
self.config.load()
return
def cleanup(self):
self.__close_db_connection()
if self.internal_filename != None:
try:
os.unlink(self.internal_filename)
except:
if __debug__:
print "cleanup()", self.internal_filename
pass
try:
os.unlink(self.internal_filename + '-journal')
except:
if __debug__:
print "cleanup()", self.internal_filename+'-journal'
pass
return
def load(self):
pass
def new(self):
self.unsaved_project = False
self.__create_internal_filename()
self.__connect_to_db()
self.__create_database()
try:
self.discsTree.clear()
except:
pass
try:
self.filesList.clear()
except:
pass
return
def save(self, filename=None):
if filename:
self.filename = filename
self.__compress_and_save()
return
def open(self, filename=None):
"""try to open db file"""
self.unsaved_project = False
self.__create_internal_filename()
self.filename = filename
source = bz2.BZ2File(filename, 'rb')
destination = open(self.internal_filename, 'wb')
while True:
try:
data = source.read(1024000)
except:
# smth went wrong
if __debug__:
print "something goes bad"
self.filename = None
self.internal_filename = None
try:
self.discsTree.clear()
except:
pass
try:
self.filesList.clear()
except:
pass
return False
if not data: break
destination.write(data)
destination.close()
source.close()
self.__connect_to_db()
self.__fetch_db_into_treestore()
return True
def scan(self,path,label):
"""scan files in separated thread"""
# flush buffer to release db lock.
self.db_connection.commit()
self.path = path
self.label = label
if self.busy:
return
self.thread = _threading.Thread(target=self.__scan)
self.thread.start()
return
def get_root_entries(self,id=None):
try:
self.filesList.clear()
except:
pass
# parent for virtual '..' dir
#myiter = self.filemodel.insert_before(None,None)
#self.cur.execute("SELECT parent FROM files_connect WHERE child=? AND depth = 1",(id,))
#self.filemodel.set_value(myiter,0,self.cur.fetchone()[0])
#self.filemodel.set_value(myiter,1,'..')
#if __debug__:
# print datetime.datetime.fromtimestamp(ch[3])
# directories first
self.db_cursor.execute("SELECT id, filename, size, date FROM files WHERE parent_id=? AND type=1 ORDER BY filename",(id,))
data = self.db_cursor.fetchall()
for ch in data:
myiter = self.filesList.insert_before(None,None)
self.filesList.set_value(myiter,0,ch[0])
self.filesList.set_value(myiter,1,ch[1])
self.filesList.set_value(myiter,2,ch[2])
self.filesList.set_value(myiter,3,datetime.datetime.fromtimestamp(ch[3]))
self.filesList.set_value(myiter,4,1)
self.filesList.set_value(myiter,5,'direktorja')
self.filesList.set_value(myiter,6,gtk.STOCK_DIRECTORY)
# all the rest
self.db_cursor.execute("SELECT id, filename, size, date, type FROM files WHERE parent_id=? AND type!=1 ORDER BY filename",(id,))
data = self.db_cursor.fetchall()
for ch in data:
myiter = self.filesList.insert_before(None,None)
self.filesList.set_value(myiter,0,ch[0])
self.filesList.set_value(myiter,1,ch[1])
self.filesList.set_value(myiter,2,ch[2])
self.filesList.set_value(myiter,3,datetime.datetime.fromtimestamp(ch[3]))
self.filesList.set_value(myiter,4,ch[4])
self.filesList.set_value(myiter,5,'kategoria srategoria')
self.filesList.set_value(myiter,6,gtk.STOCK_FILE)
#print datetime.datetime.fromtimestamp(ch[3])
return
def get_file_info(self,id):
"""get file info from database"""
self.db_cursor.execute("SELECT filename, date, size, type FROM files WHERE id = ?",(id,))
set = self.db_cursor.fetchone()
if set == None:
return ''
string = "Filename: %s\nDate: %s\nSize: %s\ntype: %s" % (set[0],datetime.datetime.fromtimestamp(set[1]),set[2],set[3])
return string
# private class functions
def __connect_to_db(self):
self.db_connection = sqlite.connect("%s" % self.internal_filename, detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
self.db_cursor = self.db_connection.cursor()
return
def __close_db_connection(self):
if self.db_cursor != None:
self.db_cursor.close()
self.db_cursor = None
if self.db_connection != None:
self.db_connection.close()
self.db_connection = None
return
def __create_internal_filename(self):
self.cleanup()
self.internal_filename = "/tmp/pygtktalog%d.db" % datetime.datetime.now().microsecond
return
def __compress_and_save(self):
source = open(self.internal_filename, 'rb')
destination = bz2.BZ2File(self.filename, 'w')
while True:
data = source.read(1024000)
if not data: break
destination.write(data)
destination.close()
source.close()
self.unsaved_project = False
return
def __create_database(self):
"""make all necessary tables in db file"""
self.db_cursor.execute("""create table
files(id INTEGER PRIMARY KEY AUTOINCREMENT,
parent_id INTEGER,
filename TEXT,
filepath TEXT,
date datetime,
size integer,
type integer);""")
self.db_cursor.execute("insert into files values(1, 1, 'root', null, 0, 0, 0);")
def __scan(self):
"""scan content of the given path"""
# TODO: Recursive data processing is damn slow! Think about different, faster solution
self.busy = True
# jako, że to jest w osobnym wątku, a sqlite się przypieprza, że musi mieć
# konekszyn dla tego samego wątku, więc robimy osobne połączenie dla tego zadania.
db_connection = sqlite.connect("%s" % self.internal_filename,
detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES,
isolation_level="EXCLUSIVE")
db_cursor = db_connection.cursor()
timestamp = datetime.datetime.now()
mime = mimetypes.MimeTypes()
mov_ext = ('mkv','avi','ogg','mpg','wmv','mp4','mpeg')
img_ext = ('jpg','jpeg','png','gif','bmp','tga','tif','tiff','ilbm','iff','pcx')
# count files in directory tree
count = 0
self.statusmsg = "Calculating number of files in directory tree..."
for root,kat,plik in os.walk(self.path):
for p in plik:
count+=1
if count > 0:
step = 1.0/count
else:
step = 1.0
self.count = 0
# guess filesystem encoding
self.fsenc = sys.getfilesystemencoding()
def __recurse(parent_id, name, path, date, size, filetype):
"""recursive scans the path"""
if self.abort:
return -1
_size = size
db_cursor.execute("insert into files(parent_id, filename, filepath, date, size, type) values(?,?,?,?,?,?)",
(parent_id, name, path, date, size, filetype))
db_cursor.execute("select seq FROM sqlite_sequence WHERE name='files'")
currentid=db_cursor.fetchone()[0]
root,dirs,files = os.walk(path).next()
for i in dirs:
if self.fsenc:
j = i.decode(self.fsenc)
else:
j = i
try:
st = os.stat(os.path.join(root,i))
st_mtime = st.st_mtime
except OSError:
st_mtime = 0
dirsize = __recurse(currentid, j, os.path.join(path,i), st_mtime, 0, self.DIR)
if dirsize == -1:
break
else:
_size = _size + dirsize
for i in files:
if self.abort:
break
self.count = self.count + 1
try:
st = os.stat(os.path.join(root,i))
st_mtime = st.st_mtime
st_size = st.st_size
except OSError:
st_mtime = 0
st_size = 0
### scan files
# if i[-3:].lower() in mov_ext or \
# mime.guess_type(i)!= (None,None) and \
# mime.guess_type(i)[0].split("/")[0] == 'video':
# # video only
# info = filetypeHelper.guess_video(os.path.join(root,i))
# elif i[-3:].lower() in img_ext or \
# mime.guess_type(i)!= (None,None) and \
# mime.guess_type(i)[0].split("/")[0] == 'image':
# pass
### end of scan
### progress/status
# if wobj.sbid != 0:
# wobj.status.remove(wobj.sbSearchCId, wobj.sbid)
if self.count % 32 == 0:
self.statusmsg = "Scannig: %s" % (os.path.join(root,i))
self.progress = step * self.count
# # PyGTK FAQ entry 23.20
# while gtk.events_pending(): gtk.main_iteration()
_size = _size + st_size
j = i
if self.fsenc:
j = i.decode(self.fsenc)
db_cursor.execute("insert into files(parent_id, filename, filepath, date, size, type) values(?,?,?,?,?,?)",
(currentid, j, os.path.join(path,i), st_mtime, st_size, self.FIL))
db_cursor.execute("update files set size=? where id=?",(_size, currentid))
if self.abort:
return -1
else:
return _size
if __recurse(1, self.label, self.path, 0, 0, self.DIR) == -1:
if __debug__:
print "__scan: __recurse returns -1"
db_cursor.close()
db_connection.rollback()
else:
if __debug__:
print "__scan: __recurse returns something else"
db_cursor.close()
db_connection.commit()
self.__fetch_db_into_treestore()
db_connection.close()
if __debug__:
print "scan time: ", (datetime.datetime.now() - timestamp)
self.unsaved_project = True
self.busy = False
self.statusmsg = "Idle"
self.progress = 0
self.abort = False
def __fetch_db_into_treestore(self):
"""load data from DB to tree model"""
# cleanup treeStore
self.discsTree.clear()
#connect
db_connection = sqlite.connect("%s" % self.internal_filename,
detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
db_cursor = db_connection.cursor()
# fetch all the directories
db_cursor.execute("SELECT id, parent_id, filename FROM files WHERE type=1 ORDER BY parent_id, filename")
data = db_cursor.fetchall()
print data
def get_children(parent_id = 1, iterator = None):
"""fetch all children and place them in model"""
for row in data:
if row[1] == parent_id:
myiter = self.discsTree.insert_before(iterator,None)
self.discsTree.set_value(myiter,0,row[0])
self.discsTree.set_value(myiter,1,row[2])
get_children(row[0], myiter)
# isroot?
if iterator == None:
self.discsTree.set_value(myiter,2,gtk.STOCK_CDROM)
else:
self.discsTree.set_value(myiter,2,gtk.STOCK_DIRECTORY)
return
if __debug__:
start_date = datetime.datetime.now()
# launch scanning.
get_children()
if __debug__:
print "tree generation time: ", (datetime.datetime.now() - start_date)
db_connection.close()
return
pass # end of class

View File

@@ -1,3 +0,0 @@
__all__ = ["globals", "_importer"]

View File

@@ -1,44 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (c) 2006 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
# ======================================================================
# This module is used only as a utility to import gtkmvc when not
# installed.
import utils.globals
if __name__ != "__main__":
try: import gtkmvc
except:
import os.path; import sys
rel_path = os.path.join(utils.globals.TOP_DIR, "..")
top_dir = os.path.dirname(os.path.abspath(rel_path))
sys.path = [top_dir] + sys.path
import gtkmvc
pass
gtkmvc.require("1.0.0")
pass

View File

@@ -1,84 +0,0 @@
# This Python file uses the following encoding: utf-8
"""
device (cd, dvd) helper
"""
import string
import os
import popen2
def volname(mntp):
"""read volume name from cd/dvd"""
dev = mountpoint_to_dev(mntp)
if dev != None:
try:
a = open(dev,"rb")
a.seek(32808)
b = a.read(32).strip()
a.close()
except:
return None
return b
return None
def volmount(mntp):
"""mount device, return True/False"""
_in,_out,_err = popen2.popen3("mount %s" % mntp)
inf = _err.readlines()
if len(inf) > 0:
for i in inf:
i.strip()
return i
else:
return 'ok'
def volumount(mntp):
"""mount device, return True/False"""
_in,_out,_err = popen2.popen3("umount %s" % mntp)
inf = _err.readlines()
if len(inf) > 0:
for error in inf:
error.strip()
if error.strip()[:7] == 'umount:':
return error.strip()
return 'ok'
def check_mount(dev):
"""Refresh the entries from fstab or mount."""
mounts = os.popen('mount')
for line in mounts.readlines():
parts = line.split()
device, txt1, mount_point, txt2, filesystem, options = parts
if device == dev:
return True
return False
def mountpoint_to_dev(mntp):
"""guess mountpoint from fstab"""
fstab = open("/etc/fstab")
for line in fstab.readlines():
a = line.split()
try:
if a[1] == mntp and a[0][0] != '#':
fstab.close()
return a[0]
except:
pass
fstab.close()
return None
def eject_cd(eject_app,cd):
"""mount device, return True/False"""
if len(eject_app) > 0:
_in,_out,_err = popen2.popen3("%s %s" %(eject_app,cd))
inf = _err.readlines()
error = ''
for error in inf:
error.strip()
if error.strip()[:6] == 'eject:':
return error.strip()
else:
return 'ok'
return "Mount point does'nt exist in fstab"

View File

@@ -1,33 +0,0 @@
# Author: Roberto Cavada <cavada@irst.itc.it>
#
# Copyright (c) 2006 by Roberto Cavada
#
# pygtkmvc is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# pygtkmvc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
#
# For more information on pygtkmvc see <http://pygtkmvc.sourceforge.net>
# or email to the author <cavada@irst.itc.it>.
# Please report bugs to <cavada@irst.itc.it>.
import os.path
import sys
if sys.argv[0]: top_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
else: top_dir = "."
# A set of global vars
TOP_DIR = top_dir
GLADE_DIR = os.path.join(TOP_DIR, "glade")

View File

@@ -1,14 +0,0 @@
# This Python file uses the following encoding: utf-8
import utils._importer
import utils.globals
from gtkmvc import View
import os.path
class ConfigView(View):
"""Preferences window from glade file """
GLADE = os.path.join(utils.globals.GLADE_DIR, "config.glade")
def __init__(self, ctrl):
View.__init__(self, ctrl, self.GLADE)
return
pass # end of class

View File

@@ -1,257 +0,0 @@
# This Python file uses the following encoding: utf-8
import gtk
import os
class Qst(object):
"""Show simple dialog for questions
if "OK" button pressed, return "True"
"Cancel" button return "False"
"""
def __init__(self, title="", message="", secondarymsg=""):
self.dialog = gtk.MessageDialog(
flags = gtk.DIALOG_DESTROY_WITH_PARENT,
type = gtk.MESSAGE_QUESTION,
buttons = gtk.BUTTONS_OK_CANCEL,
message_format = message,
)
self.dialog.set_title(title)
self.dialog.format_secondary_text(secondarymsg)
def run(self):
retval = self.dialog.run()
self.dialog.destroy()
if retval == gtk.RESPONSE_OK:
return True
return False
class Inf(object):
"""Show simple dialog for notices"""
def __init__(self, title="", message="", secondarymsg=""):
self.dialog = gtk.MessageDialog(
flags = gtk.DIALOG_DESTROY_WITH_PARENT,
type = gtk.MESSAGE_INFO,
buttons = gtk.BUTTONS_OK,
message_format = message,
)
self.dialog.set_title(title)
self.dialog.format_secondary_text(secondarymsg)
self.dialog.connect('response', lambda dialog, response: self.ret(response))
self.dialog.show()
def ret(self,result):
self.dialog.destroy()
return True
class Wrn(object):
"""Show simple dialog for warnings"""
def __init__(self, title="", message="", secondarymsg=""):
self.dialog = gtk.MessageDialog(
flags = gtk.DIALOG_DESTROY_WITH_PARENT,
type = gtk.MESSAGE_WARNING,
buttons = gtk.BUTTONS_CLOSE,
message_format = message,
)
self.dialog.set_title(title)
self.dialog.format_secondary_text(secondarymsg)
self.dialog.connect('response', lambda dialog, response: self.ret(response))
self.dialog.show()
def ret(self,result):
self.dialog.destroy()
return True
class Err(object):
"""Show simple dialog for errors"""
def __init__(self, title="", message="", secondarymsg=""):
self.dialog = gtk.MessageDialog(
flags = gtk.DIALOG_DESTROY_WITH_PARENT,
type = gtk.MESSAGE_ERROR,
buttons = gtk.BUTTONS_CLOSE,
message_format = message,
)
self.dialog.set_title(title)
self.dialog.format_secondary_text(secondarymsg)
self.dialog.connect('response', lambda dialog, response: self.ret(response))
self.dialog.run()
def ret(self,result):
self.dialog.destroy()
return True
class Abt(object):
"""Show simple about dialog"""
#{{{
def __init__(self, name=None, ver="", title="", authors=[],licence=""):
self.dialog = gtk.AboutDialog()
self.dialog.set_title(title)
self.dialog.set_version(ver)
self.dialog.set_license(licence)
self.dialog.set_name(name)
self.dialog.set_authors(authors)
self.dialog.connect('response', lambda dialog, response: self.dialog.destroy())
self.dialog.show()
#}}}
class InputDiskLabel(object):
"""Sepcific dialog for quering user for a disc label"""
def __init__(self, label=""):
self.gladefile = "glade/dialogs.glade"
self.label = ""
if label!= None:
self.label = label
def run(self):
gladexml = gtk.glade.XML(self.gladefile, "inputDialog")
dialog = gladexml.get_widget("inputDialog")
entry = gladexml.get_widget("volname")
entry.set_text(self.label)
result = dialog.run()
dialog.destroy()
if result == gtk.RESPONSE_OK:
return entry.get_text()
return None
class PointDirectoryToAdd(object):
"""Sepcific dialog for quering user for selecting directory to add"""
def __init__(self,volname='',dirname=''):
self.gladefile = "glade/dialogs.glade"
self.gladexml = gtk.glade.XML(self.gladefile, "addDirDialog")
self.volname = self.gladexml.get_widget("dirvolname")
self.volname.set_text(volname)
self.directory = self.gladexml.get_widget("directory")
self.directory.set_text(dirname)
self.gladexml.signal_autoconnect({"on_browse_activate":self.show_dirchooser,"on_browse_clicked":self.show_dirchooser})
def show_dirchooser(self,widget):
"""dialog for point the mountpoint"""
dialog = gtk.FileChooserDialog(
title="Choose directory to add",
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK
)
)
dialog.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
dialog.set_default_response(gtk.RESPONSE_OK)
response = dialog.run()
if response == gtk.RESPONSE_OK:
self.directory.set_text(dialog.get_filename())
dialog.destroy()
def run(self):
dialog = self.gladexml.get_widget("addDirDialog")
ch = True
result = dialog.run()
while ch:
if result == gtk.RESPONSE_OK and (self.volname.get_text()=='' or self.directory.get_text() == ''):
a = Err("Error - pyGTKtalog","There are fields needed to be filled.","Cannot add directory without path and disc label.")
ch = True
result = dialog.run()
else:
ch = False
dialog.destroy()
if result == gtk.RESPONSE_OK:
return self.volname.get_text(),self.directory.get_text()
else:
return None,None
class ChooseDBFilename(object):
"""Sepcific dialog for quering user for selecting filename for database"""
def __init__(self):
self.dialog = gtk.FileChooserDialog(
title="Save catalog as...",
action=gtk.FILE_CHOOSER_ACTION_SAVE,
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE,
gtk.RESPONSE_OK
)
)
self.dialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
self.dialog.set_default_response(gtk.RESPONSE_OK)
self.dialog.set_do_overwrite_confirmation(True)
self.dialog.set_title('Save catalog to file...')
f = gtk.FileFilter()
f.set_name("Catalog files")
f.add_pattern("*.pgt")
self.dialog.add_filter(f)
f = gtk.FileFilter()
f.set_name("All files")
f.add_pattern("*.*")
self.dialog.add_filter(f)
def show_dialog(self):
response = self.dialog.run()
if response == gtk.RESPONSE_OK:
filename = self.dialog.get_filename()
if filename[-4] == '.':
if filename[-3:].lower() != 'pgt':
filename = filename + '.pgt'
else:
filename = filename[:-3] + 'pgt'
else:
filename = filename + '.pgt'
self.dialog.destroy()
return filename
else:
self.dialog.destroy()
return None
pass
class LoadDBFile(object):
"""Specific class for displaying openFile dialog. It has veryfication for file existence."""
def __init__(self):
self.dialog = gtk.FileChooserDialog(
title="Open catalog",
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK
)
)
self.dialog.set_default_response(gtk.RESPONSE_OK)
f = gtk.FileFilter()
f.set_name("Catalog files")
f.add_pattern("*.pgt")
self.dialog.add_filter(f)
f = gtk.FileFilter()
f.set_name("All files")
f.add_pattern("*.*")
self.dialog.add_filter(f)
def show_dialog(self):
response = self.dialog.run()
filename = None
if response == gtk.RESPONSE_OK:
try:
filename = self.dialog.get_filename()
except:
pass
#self.dialog.destroy()
return 'ok',filename
else:
return 'cancel',None
def run(self):
res,filename = self.show_dialog()
ch = True
while ch:
if res == 'cancel':
self.dialog.destroy()
return None
try:
os.stat(filename)
self.dialog.destroy()
return filename
except:
a = Err("Error - pyGTKtalog","File doesn't exist.","The file that you choose does not exist. Choose another one, or cancel operation.")
ch = True
res,filename = self.show_dialog()

View File

@@ -1,17 +0,0 @@
# This Python file uses the following encoding: utf-8
import utils._importer
import utils.globals
from gtkmvc import View
import os.path
class MainView(View):
"""This handles only the graphical representation of the
application. The widgets set is loaded from glade file"""
GLADE = os.path.join(utils.globals.GLADE_DIR, "main.glade")
def __init__(self, ctrl):
View.__init__(self, ctrl, self.GLADE)
return
pass # end of class