1
0
mirror of https://github.com/gryf/pygtktalog.git synced 2025-12-17 11:30:19 +01:00

Lots of changes, callbacks for gui events, added details and so on

This commit is contained in:
2010-11-07 16:34:26 +01:00
parent 22c24fbaf7
commit 54b6a377bf
11 changed files with 919 additions and 59 deletions

View File

@@ -32,14 +32,17 @@ msgid "Add _Directory"
msgstr "Dodaj kata_log" msgstr "Dodaj kata_log"
#: pygtktalog/views/glade/main.glade.h:6 #: pygtktalog/views/glade/main.glade.h:6
#: pygtktalog/views/glade/files.glade.h:1
msgid "Add _Images" msgid "Add _Images"
msgstr "Dodaj _obrazy" msgstr "Dodaj _obrazy"
#: pygtktalog/views/glade/main.glade.h:7 #: pygtktalog/views/glade/main.glade.h:7
#: pygtktalog/views/glade/files.glade.h:2
msgid "Add _Thumbnail" msgid "Add _Thumbnail"
msgstr "Dodaj miniaturę" msgstr "Dodaj miniaturę"
#: pygtktalog/views/glade/main.glade.h:8 #: pygtktalog/views/glade/main.glade.h:8
#: pygtktalog/views/glade/files.glade.h:3
msgid "" msgid ""
"Add images to file. If file have no thumbnail,\n" "Add images to file. If file have no thumbnail,\n"
"thumbnail from first image will be generated." "thumbnail from first image will be generated."
@@ -48,182 +51,234 @@ msgstr ""
"zostanie wygenerowana miniatura z pierwszego obrazu." "zostanie wygenerowana miniatura z pierwszego obrazu."
#: pygtktalog/views/glade/main.glade.h:10 #: pygtktalog/views/glade/main.glade.h:10
#: pygtktalog/views/glade/main.glade.h:6
msgid "Cancel" msgid "Cancel"
msgstr "Analuj" msgstr "Analuj"
#: pygtktalog/views/glade/main.glade.h:11 #: pygtktalog/views/glade/main.glade.h:11
#: pygtktalog/views/glade/main.glade.h:7
msgid "Catalog _statistics" msgid "Catalog _statistics"
msgstr "_Statystyka katalogu" msgstr "_Statystyka katalogu"
#: pygtktalog/views/glade/main.glade.h:12 #: pygtktalog/views/glade/main.glade.h:12
#: pygtktalog/views/glade/discs.glade.h:1
msgid "Collapse all nodes" msgid "Collapse all nodes"
msgstr "Zwiń wszystkie gałęzie" msgstr "Zwiń wszystkie gałęzie"
#: pygtktalog/views/glade/main.glade.h:13 #: pygtktalog/views/glade/main.glade.h:13
#: pygtktalog/views/glade/main.glade.h:8
msgid "Create new catalog" msgid "Create new catalog"
msgstr "Utwórz nowy katalog" msgstr "Utwórz nowy katalog"
#: pygtktalog/views/glade/main.glade.h:14 #: pygtktalog/views/glade/main.glade.h:14
#: pygtktalog/views/glade/main.glade.h:9
msgid "Delete all images" msgid "Delete all images"
msgstr "Usuń wszystkie obrazy" msgstr "Usuń wszystkie obrazy"
#: pygtktalog/views/glade/main.glade.h:15 #: pygtktalog/views/glade/main.glade.h:15
#: pygtktalog/views/glade/main.glade.h:10
msgid "Delete all thumbnals" msgid "Delete all thumbnals"
msgstr "Usuń wszystkie miniatury" msgstr "Usuń wszystkie miniatury"
#: pygtktalog/views/glade/main.glade.h:16 #: pygtktalog/views/glade/main.glade.h:16
#: pygtktalog/views/glade/main.glade.h:11
msgid "Delete tag" msgid "Delete tag"
msgstr "Usuń tag" msgstr "Usuń tag"
#: pygtktalog/views/glade/main.glade.h:17 #: pygtktalog/views/glade/main.glade.h:17
#: pygtktalog/views/glade/main.glade.h:12
msgid "Deletes all images from files in current colection" msgid "Deletes all images from files in current colection"
msgstr "Usuwa wszystkie obrazy z plików w bieżącej kolekcji" msgstr "Usuwa wszystkie obrazy z plików w bieżącej kolekcji"
#: pygtktalog/views/glade/main.glade.h:18 #: pygtktalog/views/glade/main.glade.h:18
#: pygtktalog/views/glade/main.glade.h:13
msgid "Discs" msgid "Discs"
msgstr "Dyski" msgstr "Dyski"
#: pygtktalog/views/glade/main.glade.h:19 #: pygtktalog/views/glade/main.glade.h:19
#: pygtktalog/views/glade/details.glade.h:1
msgid "Double click to open image" msgid "Double click to open image"
msgstr "Dwukrotne kliknięcie otwiera obraz" msgstr "Dwukrotne kliknięcie otwiera obraz"
#: pygtktalog/views/glade/main.glade.h:20 #: pygtktalog/views/glade/main.glade.h:20
#: pygtktalog/views/glade/details.glade.h:2
msgid "EXIF" msgid "EXIF"
msgstr "EXIF" msgstr "EXIF"
#: pygtktalog/views/glade/main.glade.h:21 #: pygtktalog/views/glade/main.glade.h:21
#: pygtktalog/views/glade/discs.glade.h:2
msgid "Expand all nodes" msgid "Expand all nodes"
msgstr "Rozwiń wszystkie gałęzie" msgstr "Rozwiń wszystkie gałęzie"
#: pygtktalog/views/glade/main.glade.h:22 #: pygtktalog/views/glade/main.glade.h:22
#: pygtktalog/views/glade/main.glade.h:14
msgid "Export" msgid "Export"
msgstr "Eksport" msgstr "Eksport"
#: pygtktalog/views/glade/main.glade.h:23 #: pygtktalog/views/glade/main.glade.h:23
#: pygtktalog/views/glade/details.glade.h:3
msgid "File info" msgid "File info"
msgstr "Informacje o pliku" msgstr "Informacje o pliku"
#: pygtktalog/views/glade/main.glade.h:24 #: pygtktalog/views/glade/main.glade.h:24
#: pygtktalog/views/glade/main.glade.h:15
msgid "Find file" msgid "Find file"
msgstr "Znajdź plik" msgstr "Znajdź plik"
#: pygtktalog/views/glade/main.glade.h:25 #: pygtktalog/views/glade/main.glade.h:25
#: pygtktalog/views/glade/details.glade.h:4
msgid "Images" msgid "Images"
msgstr "Obrazy" msgstr "Obrazy"
#: pygtktalog/views/glade/main.glade.h:26 #: pygtktalog/views/glade/main.glade.h:26
#: pygtktalog/views/glade/main.glade.h:16
msgid "Import" msgid "Import"
msgstr "Import" msgstr "Import"
#: pygtktalog/views/glade/main.glade.h:27 #: pygtktalog/views/glade/main.glade.h:27
#: pygtktalog/views/glade/main.glade.h:17
msgid "Open catalog file" msgid "Open catalog file"
msgstr "Otwórz plik katalogu" msgstr "Otwórz plik katalogu"
#: pygtktalog/views/glade/main.glade.h:28 #: pygtktalog/views/glade/main.glade.h:28
#: pygtktalog/views/glade/main.glade.h:18
msgid "Quit pyGTKtalog" msgid "Quit pyGTKtalog"
msgstr "Zakończ pyGTKtalog" msgstr "Zakończ pyGTKtalog"
#: pygtktalog/views/glade/main.glade.h:29 #: pygtktalog/views/glade/main.glade.h:29
#: pygtktalog/views/glade/files.glade.h:5
msgid "Re_move Thumbnail" msgid "Re_move Thumbnail"
msgstr "Usuń miniaturę" msgstr "Usuń miniaturę"
#: pygtktalog/views/glade/main.glade.h:30 #: pygtktalog/views/glade/main.glade.h:30
#: pygtktalog/views/glade/main.glade.h:19
msgid "Recent files" msgid "Recent files"
msgstr "Ostatnio używane pliki" msgstr "Ostatnio używane pliki"
#: pygtktalog/views/glade/main.glade.h:31 #: pygtktalog/views/glade/main.glade.h:31
#: pygtktalog/views/glade/files.glade.h:6
msgid "Rem_ove All Images" msgid "Rem_ove All Images"
msgstr "Usuń wszystkie obrazy" msgstr "Usuń wszystkie obrazy"
#: pygtktalog/views/glade/main.glade.h:32 #: pygtktalog/views/glade/main.glade.h:32
#: pygtktalog/views/glade/files.glade.h:7
msgid "Remo_ve tag" msgid "Remo_ve tag"
msgstr "Usuń tag" msgstr "Usuń tag"
#: pygtktalog/views/glade/main.glade.h:33 #: pygtktalog/views/glade/main.glade.h:33
#: pygtktalog/views/glade/main.glade.h:20
msgid "Save all images..." msgid "Save all images..."
msgstr "Zapisz wszytkie obrazy..." msgstr "Zapisz wszytkie obrazy..."
#: pygtktalog/views/glade/main.glade.h:34 #: pygtktalog/views/glade/main.glade.h:34
#: pygtktalog/views/glade/main.glade.h:21
msgid "Save catalog" msgid "Save catalog"
msgstr "Zapisz katalog" msgstr "Zapisz katalog"
#: pygtktalog/views/glade/main.glade.h:35 #: pygtktalog/views/glade/main.glade.h:35
#: pygtktalog/views/glade/main.glade.h:22
msgid "Set as _thumbnail" msgid "Set as _thumbnail"
msgstr "Ustaw jako miniaturę" msgstr "Ustaw jako miniaturę"
#: pygtktalog/views/glade/main.glade.h:36 #: pygtktalog/views/glade/main.glade.h:36
#: pygtktalog/views/glade/main.glade.h:23
msgid "Status bar" msgid "Status bar"
msgstr "Pasek stanu" msgstr "Pasek stanu"
#: pygtktalog/views/glade/main.glade.h:37 #: pygtktalog/views/glade/main.glade.h:37
#: pygtktalog/views/glade/main.glade.h:24
msgid "Tags" msgid "Tags"
msgstr "Tagi" msgstr "Tagi"
#: pygtktalog/views/glade/main.glade.h:38 #: pygtktalog/views/glade/main.glade.h:38
#: pygtktalog/views/glade/main.glade.h:25
msgid "Toolbar" msgid "Toolbar"
msgstr "Pasek narzędzi" msgstr "Pasek narzędzi"
#: pygtktalog/views/glade/main.glade.h:39 #: pygtktalog/views/glade/main.glade.h:39
#: pygtktalog/views/glade/main.glade.h:26
msgid "_Add images" msgid "_Add images"
msgstr "Dodaj obrazy" msgstr "Dodaj obrazy"
#: pygtktalog/views/glade/main.glade.h:40 #: pygtktalog/views/glade/main.glade.h:40
#: pygtktalog/views/glade/files.glade.h:8
msgid "_Add tag" msgid "_Add tag"
msgstr "_Dodaj tag" msgstr "_Dodaj tag"
#: pygtktalog/views/glade/main.glade.h:41 #: pygtktalog/views/glade/main.glade.h:41
#: pygtktalog/views/glade/main.glade.h:27
msgid "_Catalog" msgid "_Catalog"
msgstr "_Katalog" msgstr "_Katalog"
#: pygtktalog/views/glade/main.glade.h:42 #: pygtktalog/views/glade/main.glade.h:42
#: pygtktalog/views/glade/discs.glade.h:3
msgid "_Collapse all" msgid "_Collapse all"
msgstr "_Zwiń wszystko" msgstr "_Zwiń wszystko"
#: pygtktalog/views/glade/main.glade.h:43 #: pygtktalog/views/glade/main.glade.h:43
#: pygtktalog/views/glade/discs.glade.h:4
#: pygtktalog/views/glade/files.glade.h:9
msgid "_Delete" msgid "_Delete"
msgstr "_Usuń" msgstr "_Usuń"
#: pygtktalog/views/glade/main.glade.h:44 #: pygtktalog/views/glade/main.glade.h:44
#: pygtktalog/views/glade/main.glade.h:28
msgid "_Delete images" msgid "_Delete images"
msgstr "Usuń obrazy" msgstr "Usuń obrazy"
#: pygtktalog/views/glade/main.glade.h:45 #: pygtktalog/views/glade/main.glade.h:45
#: pygtktalog/views/glade/main.glade.h:29
#: pygtktalog/views/glade/files.glade.h:10
#: pygtktalog/views/glade/test.glade.h:1
msgid "_Edit" msgid "_Edit"
msgstr "_Edycja" msgstr "_Edycja"
#: pygtktalog/views/glade/main.glade.h:46 #: pygtktalog/views/glade/main.glade.h:46
#: pygtktalog/views/glade/discs.glade.h:5
msgid "_Expand all" msgid "_Expand all"
msgstr "_Rozwiń wszystko" msgstr "_Rozwiń wszystko"
#: pygtktalog/views/glade/main.glade.h:47 #: pygtktalog/views/glade/main.glade.h:47 pygtktalog/views/main_menu.py:19
#: pygtktalog/views/glade/main.glade.h:30
#: pygtktalog/views/glade/test.glade.h:2
msgid "_File" msgid "_File"
msgstr "_Plik" msgstr "_Plik"
#: pygtktalog/views/glade/main.glade.h:48 #: pygtktalog/views/glade/main.glade.h:48
#: pygtktalog/views/glade/main.glade.h:31
#: pygtktalog/views/glade/test.glade.h:3
msgid "_Help" msgid "_Help"
msgstr "_Pomoc" msgstr "_Pomoc"
#: pygtktalog/views/glade/main.glade.h:49 #: pygtktalog/views/glade/main.glade.h:49
#: pygtktalog/views/glade/main.glade.h:32
msgid "_Remove Thumbnail" msgid "_Remove Thumbnail"
msgstr "Usuń miniaturę" msgstr "Usuń miniaturę"
#: pygtktalog/views/glade/main.glade.h:50 #: pygtktalog/views/glade/main.glade.h:50
#: pygtktalog/views/glade/discs.glade.h:6
#: pygtktalog/views/glade/files.glade.h:11
msgid "_Rename" msgid "_Rename"
msgstr "_Zmień nazwę" msgstr "_Zmień nazwę"
#: pygtktalog/views/glade/main.glade.h:51 #: pygtktalog/views/glade/main.glade.h:51
#: pygtktalog/views/glade/main.glade.h:33
msgid "_Save images to..." msgid "_Save images to..."
msgstr "Zapisz obrazy do..." msgstr "Zapisz obrazy do..."
#: pygtktalog/views/glade/main.glade.h:52 #: pygtktalog/views/glade/main.glade.h:52
#: pygtktalog/views/glade/discs.glade.h:7
msgid "_Statistics" msgid "_Statistics"
msgstr "_Statystyka" msgstr "_Statystyka"
#: pygtktalog/views/glade/main.glade.h:53 #: pygtktalog/views/glade/main.glade.h:53
#: pygtktalog/views/glade/discs.glade.h:8
msgid "_Update" msgid "_Update"
msgstr "_Uaktualnij" msgstr "_Uaktualnij"
#: pygtktalog/views/glade/main.glade.h:54 #: pygtktalog/views/glade/main.glade.h:54
#: pygtktalog/views/glade/main.glade.h:34
#: pygtktalog/views/glade/test.glade.h:4
msgid "_View" msgid "_View"
msgstr "_Widok" msgstr "_Widok"
@@ -232,10 +287,12 @@ msgid "gtk-clear"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:56 #: pygtktalog/views/glade/main.glade.h:56
#: pygtktalog/views/glade/main.glade.h:35
msgid "pyGTKtalog" msgid "pyGTKtalog"
msgstr "pyGTKtalog" msgstr "pyGTKtalog"
#: pygtktalog/views/glade/main.glade.h:57 #: pygtktalog/views/glade/main.glade.h:57
#: pygtktalog/views/glade/main.glade.h:36
msgid "pyGTKtalog - Image" msgid "pyGTKtalog - Image"
msgstr "pyGTKtalog - Obraz" msgstr "pyGTKtalog - Obraz"
@@ -251,6 +308,68 @@ msgstr "Bieżący katalog nie jest zapisany, wszelkie zmiany zostaną utracone."
msgid "Quit application" msgid "Quit application"
msgstr "Zakończ aplikację" msgstr "Zakończ aplikację"
#: pygtktalog/models/main.py:16 #: pygtktalog/models/main.py:16 pygtktalog/models/main.py:31
msgid "Idle" msgid "Idle"
msgstr "Bezczynny" msgstr "Bezczynny"
#: pygtktalog/controllers/files.py:33
#, fuzzy
msgid "Disc"
msgstr "Dyski"
#: pygtktalog/controllers/files.py:39
#, fuzzy
msgid "Filename"
msgstr "_Zmień nazwę"
#: pygtktalog/controllers/files.py:50
msgid "Path"
msgstr ""
#: pygtktalog/controllers/files.py:56
msgid "Size"
msgstr ""
#: pygtktalog/controllers/files.py:61
msgid "Date"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:5
msgid "gtk-about"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:6
msgid "gtk-copy"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:7
msgid "gtk-cut"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:8
msgid "gtk-delete"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:9
msgid "gtk-new"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:10
msgid "gtk-open"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:11
msgid "gtk-paste"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:12
msgid "gtk-quit"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:13
msgid "gtk-save"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:14
msgid "gtk-save-as"
msgstr ""

View File

@@ -31,196 +31,251 @@ msgid "Add _Directory"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:6 #: pygtktalog/views/glade/main.glade.h:6
#: pygtktalog/views/glade/files.glade.h:1
msgid "Add _Images" msgid "Add _Images"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:7 #: pygtktalog/views/glade/main.glade.h:7
#: pygtktalog/views/glade/files.glade.h:2
msgid "Add _Thumbnail" msgid "Add _Thumbnail"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:8 #: pygtktalog/views/glade/main.glade.h:8
#: pygtktalog/views/glade/files.glade.h:3
msgid "" msgid ""
"Add images to file. If file have no thumbnail,\n" "Add images to file. If file have no thumbnail,\n"
"thumbnail from first image will be generated." "thumbnail from first image will be generated."
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:10 #: pygtktalog/views/glade/main.glade.h:10
#: pygtktalog/views/glade/main.glade.h:6
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:11 #: pygtktalog/views/glade/main.glade.h:11
#: pygtktalog/views/glade/main.glade.h:7
msgid "Catalog _statistics" msgid "Catalog _statistics"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:12 #: pygtktalog/views/glade/main.glade.h:12
#: pygtktalog/views/glade/discs.glade.h:1
msgid "Collapse all nodes" msgid "Collapse all nodes"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:13 #: pygtktalog/views/glade/main.glade.h:13
#: pygtktalog/views/glade/main.glade.h:8
msgid "Create new catalog" msgid "Create new catalog"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:14 #: pygtktalog/views/glade/main.glade.h:14
#: pygtktalog/views/glade/main.glade.h:9
msgid "Delete all images" msgid "Delete all images"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:15 #: pygtktalog/views/glade/main.glade.h:15
#: pygtktalog/views/glade/main.glade.h:10
msgid "Delete all thumbnals" msgid "Delete all thumbnals"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:16 #: pygtktalog/views/glade/main.glade.h:16
#: pygtktalog/views/glade/main.glade.h:11
msgid "Delete tag" msgid "Delete tag"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:17 #: pygtktalog/views/glade/main.glade.h:17
#: pygtktalog/views/glade/main.glade.h:12
msgid "Deletes all images from files in current colection" msgid "Deletes all images from files in current colection"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:18 #: pygtktalog/views/glade/main.glade.h:18
#: pygtktalog/views/glade/main.glade.h:13
msgid "Discs" msgid "Discs"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:19 #: pygtktalog/views/glade/main.glade.h:19
#: pygtktalog/views/glade/details.glade.h:1
msgid "Double click to open image" msgid "Double click to open image"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:20 #: pygtktalog/views/glade/main.glade.h:20
#: pygtktalog/views/glade/details.glade.h:2
msgid "EXIF" msgid "EXIF"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:21 #: pygtktalog/views/glade/main.glade.h:21
#: pygtktalog/views/glade/discs.glade.h:2
msgid "Expand all nodes" msgid "Expand all nodes"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:22 #: pygtktalog/views/glade/main.glade.h:22
#: pygtktalog/views/glade/main.glade.h:14
msgid "Export" msgid "Export"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:23 #: pygtktalog/views/glade/main.glade.h:23
#: pygtktalog/views/glade/details.glade.h:3
msgid "File info" msgid "File info"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:24 #: pygtktalog/views/glade/main.glade.h:24
#: pygtktalog/views/glade/main.glade.h:15
msgid "Find file" msgid "Find file"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:25 #: pygtktalog/views/glade/main.glade.h:25
#: pygtktalog/views/glade/details.glade.h:4
msgid "Images" msgid "Images"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:26 #: pygtktalog/views/glade/main.glade.h:26
#: pygtktalog/views/glade/main.glade.h:16
msgid "Import" msgid "Import"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:27 #: pygtktalog/views/glade/main.glade.h:27
#: pygtktalog/views/glade/main.glade.h:17
msgid "Open catalog file" msgid "Open catalog file"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:28 #: pygtktalog/views/glade/main.glade.h:28
#: pygtktalog/views/glade/main.glade.h:18
msgid "Quit pyGTKtalog" msgid "Quit pyGTKtalog"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:29 #: pygtktalog/views/glade/main.glade.h:29
#: pygtktalog/views/glade/files.glade.h:5
msgid "Re_move Thumbnail" msgid "Re_move Thumbnail"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:30 #: pygtktalog/views/glade/main.glade.h:30
#: pygtktalog/views/glade/main.glade.h:19
msgid "Recent files" msgid "Recent files"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:31 #: pygtktalog/views/glade/main.glade.h:31
#: pygtktalog/views/glade/files.glade.h:6
msgid "Rem_ove All Images" msgid "Rem_ove All Images"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:32 #: pygtktalog/views/glade/main.glade.h:32
#: pygtktalog/views/glade/files.glade.h:7
msgid "Remo_ve tag" msgid "Remo_ve tag"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:33 #: pygtktalog/views/glade/main.glade.h:33
#: pygtktalog/views/glade/main.glade.h:20
msgid "Save all images..." msgid "Save all images..."
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:34 #: pygtktalog/views/glade/main.glade.h:34
#: pygtktalog/views/glade/main.glade.h:21
msgid "Save catalog" msgid "Save catalog"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:35 #: pygtktalog/views/glade/main.glade.h:35
#: pygtktalog/views/glade/main.glade.h:22
msgid "Set as _thumbnail" msgid "Set as _thumbnail"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:36 #: pygtktalog/views/glade/main.glade.h:36
#: pygtktalog/views/glade/main.glade.h:23
msgid "Status bar" msgid "Status bar"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:37 #: pygtktalog/views/glade/main.glade.h:37
#: pygtktalog/views/glade/main.glade.h:24
msgid "Tags" msgid "Tags"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:38 #: pygtktalog/views/glade/main.glade.h:38
#: pygtktalog/views/glade/main.glade.h:25
msgid "Toolbar" msgid "Toolbar"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:39 #: pygtktalog/views/glade/main.glade.h:39
#: pygtktalog/views/glade/main.glade.h:26
msgid "_Add images" msgid "_Add images"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:40 #: pygtktalog/views/glade/main.glade.h:40
#: pygtktalog/views/glade/files.glade.h:8
msgid "_Add tag" msgid "_Add tag"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:41 #: pygtktalog/views/glade/main.glade.h:41
#: pygtktalog/views/glade/main.glade.h:27
msgid "_Catalog" msgid "_Catalog"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:42 #: pygtktalog/views/glade/main.glade.h:42
#: pygtktalog/views/glade/discs.glade.h:3
msgid "_Collapse all" msgid "_Collapse all"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:43 #: pygtktalog/views/glade/main.glade.h:43
#: pygtktalog/views/glade/discs.glade.h:4
#: pygtktalog/views/glade/files.glade.h:9
msgid "_Delete" msgid "_Delete"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:44 #: pygtktalog/views/glade/main.glade.h:44
#: pygtktalog/views/glade/main.glade.h:28
msgid "_Delete images" msgid "_Delete images"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:45 #: pygtktalog/views/glade/main.glade.h:45
#: pygtktalog/views/glade/main.glade.h:29
#: pygtktalog/views/glade/files.glade.h:10
#: pygtktalog/views/glade/test.glade.h:1
msgid "_Edit" msgid "_Edit"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:46 #: pygtktalog/views/glade/main.glade.h:46
#: pygtktalog/views/glade/discs.glade.h:5
msgid "_Expand all" msgid "_Expand all"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:47 #: pygtktalog/views/glade/main.glade.h:47 pygtktalog/views/main_menu.py:19
#: pygtktalog/views/glade/main.glade.h:30
#: pygtktalog/views/glade/test.glade.h:2
msgid "_File" msgid "_File"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:48 #: pygtktalog/views/glade/main.glade.h:48
#: pygtktalog/views/glade/main.glade.h:31
#: pygtktalog/views/glade/test.glade.h:3
msgid "_Help" msgid "_Help"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:49 #: pygtktalog/views/glade/main.glade.h:49
#: pygtktalog/views/glade/main.glade.h:32
msgid "_Remove Thumbnail" msgid "_Remove Thumbnail"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:50 #: pygtktalog/views/glade/main.glade.h:50
#: pygtktalog/views/glade/discs.glade.h:6
#: pygtktalog/views/glade/files.glade.h:11
msgid "_Rename" msgid "_Rename"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:51 #: pygtktalog/views/glade/main.glade.h:51
#: pygtktalog/views/glade/main.glade.h:33
msgid "_Save images to..." msgid "_Save images to..."
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:52 #: pygtktalog/views/glade/main.glade.h:52
#: pygtktalog/views/glade/discs.glade.h:7
msgid "_Statistics" msgid "_Statistics"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:53 #: pygtktalog/views/glade/main.glade.h:53
#: pygtktalog/views/glade/discs.glade.h:8
msgid "_Update" msgid "_Update"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:54 #: pygtktalog/views/glade/main.glade.h:54
#: pygtktalog/views/glade/main.glade.h:34
#: pygtktalog/views/glade/test.glade.h:4
msgid "_View" msgid "_View"
msgstr "" msgstr ""
@@ -229,10 +284,12 @@ msgid "gtk-clear"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:56 #: pygtktalog/views/glade/main.glade.h:56
#: pygtktalog/views/glade/main.glade.h:35
msgid "pyGTKtalog" msgid "pyGTKtalog"
msgstr "" msgstr ""
#: pygtktalog/views/glade/main.glade.h:57 #: pygtktalog/views/glade/main.glade.h:57
#: pygtktalog/views/glade/main.glade.h:36
msgid "pyGTKtalog - Image" msgid "pyGTKtalog - Image"
msgstr "" msgstr ""
@@ -248,6 +305,66 @@ msgstr ""
msgid "Quit application" msgid "Quit application"
msgstr "" msgstr ""
#: pygtktalog/models/main.py:16 #: pygtktalog/models/main.py:16 pygtktalog/models/main.py:31
msgid "Idle" msgid "Idle"
msgstr "" msgstr ""
#: pygtktalog/controllers/files.py:33
msgid "Disc"
msgstr ""
#: pygtktalog/controllers/files.py:39
msgid "Filename"
msgstr ""
#: pygtktalog/controllers/files.py:50
msgid "Path"
msgstr ""
#: pygtktalog/controllers/files.py:56
msgid "Size"
msgstr ""
#: pygtktalog/controllers/files.py:61
msgid "Date"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:5
msgid "gtk-about"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:6
msgid "gtk-copy"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:7
msgid "gtk-cut"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:8
msgid "gtk-delete"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:9
msgid "gtk-new"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:10
msgid "gtk-open"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:11
msgid "gtk-paste"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:12
msgid "gtk-quit"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:13
msgid "gtk-save"
msgstr ""
#: pygtktalog/views/glade/test.glade.h:14
msgid "gtk-save-as"
msgstr ""

View File

@@ -9,6 +9,11 @@ import gtk
from gtkmvc import Controller from gtkmvc import Controller
from pygtktalog.pygtkutils import get_tv_item_under_cursor
from pygtktalog.logger import get_logger
LOG = get_logger("files ctrl")
class FilesController(Controller): class FilesController(Controller):
""" """
@@ -28,6 +33,20 @@ class FilesController(Controller):
Register view, and setup columns for files treeview Register view, and setup columns for files treeview
""" """
view['files'].set_model(self.model.files) view['files'].set_model(self.model.files)
sigs = {"add_tag": ("activate", self.on_add_tag1_activate),
"delete_tag": ("activate", self.on_delete_tag_activate),
"add_thumb": ("activate", self.on_add_thumb1_activate),
"remove_thumb": ("activate", self.on_remove_thumb1_activate),
"add_image": ("activate", self.on_add_image1_activate),
"remove_image": ("activate", self.on_remove_image1_activate),
"edit": ("activate", self.on_edit2_activate),
"delete": ("activate", self.on_delete3_activate),
"rename": ("activate", self.on_rename2_activate)}
for signal in sigs:
view.menu[signal].connect(sigs[signal][0], sigs[signal][1])
view['files'].get_selection().set_mode(gtk.SELECTION_MULTIPLE) view['files'].get_selection().set_mode(gtk.SELECTION_MULTIPLE)
col = gtk.TreeViewColumn(_('Disc'), gtk.CellRendererText(), text=1) col = gtk.TreeViewColumn(_('Disc'), gtk.CellRendererText(), text=1)
@@ -65,7 +84,178 @@ class FilesController(Controller):
self.view['files'].set_search_column(2) self.view['files'].set_search_column(2)
# setup d'n'd support # setup d'n'd support
view['files'].drag_source_set(gtk.gdk.BUTTON1_MASK, self.view['files'].drag_source_set(gtk.gdk.BUTTON1_MASK,
self.DND_TARGETS, self.DND_TARGETS,
gtk.gdk.ACTION_COPY) gtk.gdk.ACTION_COPY)
# signals
def on_files_drag_data_get(self, treeview, context, selection,
targetType, eventTime):
"""responce to "data get" DnD signal"""
# get selection, and send it to the client
if targetType == self.DND_TARGETS[0][2]:
# get selection
treesrl = treeview.get_selection()
model, list_of_paths = treesrl.get_selected_rows()
ids = []
for path in list_of_paths:
fid = model.get_value(model.get_iter(path), 0)
ids.append(fid)
string = str(tuple(ids)).replace(",)", ")")
selection.set(selection.target, 8, string)
def on_files_button_press_event(self, treeview, event):
"""
Handle right click on files treeview - show popup menu.
"""
LOG.debug(self.on_files_button_press_event.__doc__.strip())
pathinfo = treeview.get_path_at_pos(int(event.x), int(event.y))
if event.button == 3: # Right mouse button. Show context menu.
if pathinfo:
path = pathinfo[0]
# Make sure, that there is selected row
sel = treeview.get_selection()
sel.unselect_all()
sel.select_path(path)
self._popup_menu(sel, event, event.button)
else:
self._popup_menu(None, event, event.button)
return True
#try:
# selection = tree.get_selection()
# model, list_of_paths = selection.get_selected_rows()
#except TypeError:
# list_of_paths = []
#if len(list_of_paths) == 0:
# # try to select item under cursor
# try:
# path, column, x, y = tree.get_path_at_pos(int(event.x),
# int(event.y))
# except TypeError:
# # failed, do not show any popup and return
# tree.get_selection().unselect_all()
# return False
# selection.select_path(path[0])
#if len(list_of_paths) > 1:
# self.view['add_image'].set_sensitive(False)
# self.view['rename'].set_sensitive(False)
# self.view['edit'].set_sensitive(False)
#else:
# self.view['add_image'].set_sensitive(True)
# self.view['rename'].set_sensitive(True)
# self.view['edit'].set_sensitive(True)
#self.__popup_menu(event, 'files_popup')
#return True
def on_files_cursor_changed(self, treeview):
"""Show details of selected file/directory"""
file_id = get_tv_item_under_cursor(treeview)
LOG.debug("found item: %s" % file_id)
return
def on_files_key_release_event(self, treeview, event):
"""do something with pressed keys"""
if gtk.gdk.keyval_name(event.keyval) == 'Menu':
try:
selection = treeview.get_selection()
model, list_of_paths = selection.get_selected_rows()
if not list_of_paths:
return
except TypeError:
return
self._popup_menu(selection, event, 0)
if gtk.gdk.keyval_name(event.keyval) == 'BackSpace':
d_path, d_column = self.view['discs'].get_cursor()
if d_path and d_column:
# easy way
model = self.view['discs'].get_model()
child_iter = model.get_iter(d_path)
parent_iter = model.iter_parent(child_iter)
if parent_iter:
self.view['discs'].set_cursor(model.get_path(parent_iter))
else:
# hard way
f_model = treeview.get_model()
first_iter = f_model.get_iter_first()
first_child_value = f_model.get_value(first_iter, 0)
# get two steps up
val = self.model.get_parent_id(first_child_value)
parent_value = self.model.get_parent_id(val)
iter = self.model.discs_tree.get_iter_first()
while iter:
current_value = self.model.discs_tree.get_value(iter,
0)
if current_value == parent_value:
path = self.model.discs_tree.get_path(iter)
self.view['discs'].set_cursor(path)
iter = None
else:
iter = self.model.discs_tree.iter_next(iter)
#if gtk.gdk.keyval_name(event.keyval) == 'Delete':
# for file_id in self.__get_tv_selection_ids(treeview):
# self.main.delete(file_id)
#ids = self.__get_tv_selection_ids(self.view['files'])
def on_files_row_activated(self, files_obj, row, column):
"""On directory doubleclick in files listview dive into desired
branch."""
f_iter = self.model.files_list.get_iter(row)
current_id = self.model.files_list.get_value(f_iter, 0)
if self.model.files_list.get_value(f_iter, 6) == 1:
# ONLY directories. files are omitted.
self.__set_files_hiden_columns_visible(False)
self.model.get_root_entries(current_id)
d_path, d_column = self.view['discs'].get_cursor()
if d_path:
if not self.view['discs'].row_expanded(d_path):
self.view['discs'].expand_row(d_path, False)
discs_model = self.model.discs_tree
iterator = discs_model.get_iter(d_path)
new_iter = discs_model.iter_children(iterator)
if new_iter:
while new_iter:
current_value = discs_model.get_value(new_iter, 0)
if current_value == current_id:
path = discs_model.get_path(new_iter)
self.view['discs'].set_cursor(path)
new_iter = discs_model.iter_next(new_iter)
return
def on_add_tag1_activate(self, menu_item): pass
def on_delete_tag_activate(self, menuitem): pass
def on_add_thumb1_activate(self, menuitem): pass
def on_remove_thumb1_activate(self, menuitem): pass
def on_add_image1_activate(self, menuitem): pass
def on_remove_image1_activate(self, menuitem): pass
def on_edit2_activate(self, menuitem): pass
def on_delete3_activate(self, menuitem): pass
def on_rename2_activate(self, menuitem): pass
# private methods
def _popup_menu(self, selection, event, button):
"""
Popup menu for files treeview. Gather information from discs model,
and trigger menu popup.
"""
LOG.debug(self._popup_menu.__doc__.strip())
if selection is None:
self.view.menu.set_menu_items_sensitivity(False)
else:
model, list_of_paths = selection.get_selected_rows()
for path in list_of_paths:
self.view.menu.set_menu_items_sensitivity(True)
self.view.menu['files_popup'].popup(None, None, None,
button, event.time)

View File

@@ -9,15 +9,17 @@ import gtk
from gtkmvc import Controller from gtkmvc import Controller
#from pygtktalog.dialogs import yesno
from pygtktalog.dialogs import About
from pygtktalog.controllers.discs import DiscsController from pygtktalog.controllers.discs import DiscsController
from pygtktalog.controllers.files import FilesController from pygtktalog.controllers.files import FilesController
#from pygtktalog.controllers.details import DetailsController #from pygtktalog.controllers.details import DetailsController
#from pygtktalog.controllers.tags import TagcloudController #from pygtktalog.controllers.tags import TagcloudController
#from pygtktalog.dialogs import yesno, okcancel, info, warn, error #from pygtktalog.dialogs import yesno, okcancel, info, warn, error
from pygtktalog.dialogs import open_catalog, save_catalog, error, yesno
from pygtktalog.dialogs import About # TODO: how about make it like a functions above?
from pygtktalog.logger import get_logger from pygtktalog.logger import get_logger
from pygtktalog import __version__ from pygtktalog import __version__
# although it seems to be unused, it is necessary, because it contains
# definitions for additional connectable widgets for observers.
LOG = get_logger("main controller") LOG = get_logger("main controller")
@@ -25,6 +27,8 @@ class MainController(Controller):
""" """
Controller for main application window Controller for main application window
""" """
TITLE = "pyGTKtalog"
UNTITLED = _("untitled")
def __init__(self, model, view): def __init__(self, model, view):
""" """
@@ -48,6 +52,8 @@ class MainController(Controller):
LOG.debug("replace hardcoded defaults with configured!") LOG.debug("replace hardcoded defaults with configured!")
view['main'].set_default_size(800, 600) view['main'].set_default_size(800, 600)
view['hpaned1'].set_position(200) view['hpaned1'].set_position(200)
if not self.model.tmp_filename:
view.set_widgets_app_sensitivity(False)
view['main'].show() view['main'].show()
def register_adapters(self): def register_adapters(self):
@@ -55,6 +61,10 @@ class MainController(Controller):
progress bar/status bar adapters goes here progress bar/status bar adapters goes here
""" """
LOG.debug(self.register_adapters.__doc__.strip()) LOG.debug(self.register_adapters.__doc__.strip())
#title_ad = Adapter(self.model, "cat_fname")
#title_ad.connect_widget(self.view["main"],
# setter=lambda w,v: \
# w.set_title(self._get_title()))
pass pass
# signals # signals
@@ -79,10 +89,123 @@ class MainController(Controller):
gtk.main_quit() gtk.main_quit()
return False return False
def on_new_activate(self, widget):
"""
Create new catalog file
"""
LOG.debug(self.on_new_activate.__doc__.strip())
self.model.new()
self.view.discs['discs'].set_model(self.model.discs)
self.view.files['files'].set_model(self.model.files)
self._set_title()
self.view.set_widgets_app_sensitivity(True)
def on_open_activate(self, widget):
"""
Open catalog file
"""
LOG.debug(self.on_open_activate.__doc__.strip())
if self.model.db_unsaved and 'confirm' in self.model.config and \
self.model.config['confirm']:
if not yesno(_("Current database is not saved"),
_("Do you really want to open new file and abandon "
"current one?"),
_("Unsaved data")):
LOG.debug("Cancel opening catalog file - unsaved data remain")
return
initial_path = None
#if self.model.config.recent and self.model.config.recent[0]:
# initial_path = os.path.dirname(self.model.config.recent[0])
#if not path:
path = open_catalog(path=initial_path)
if not path:
return
# cleanup files and details
try:
self.model.files_list.clear()
except:
pass
#self.__hide_details()
#self.view['tag_path_box'].hide()
#buf = self.view['tag_cloud_textview'].get_buffer()
#buf.set_text('')
#self.view['tag_cloud_textview'].set_buffer(buf)
if not self.model.open(path):
error(_("Cannot open file."),
_("File %s cannot be open") % path,
_("Error opening file"))
else:
#self.__generate_recent_menu()
#self.__activate_ui(path)
#self.__tag_cloud()
self.view.set_widgets_app_sensitivity()
self._set_title()
return
def on_about1_activate(self, widget): def on_about1_activate(self, widget):
"""Show about dialog""" """Show about dialog"""
About("pyGTKtalog", About("pyGTKtalog", "%s" % __version__, "About",
"%s" % __version__, ["Roman 'gryf' Dobosz"], '')
"About",
["Roman 'gryf' Dobosz"], def on_save_activate(self, widget):
'') """
Save current catalog
"""
LOG.debug(self.on_save_activate.__doc__.strip())
if not self.model.cat_fname:
self.on_save_as_activate(widget)
else:
self.model.save()
self._set_title()
def on_save_as_activate(self, widget):
"""
Save current catalog under differnet file
"""
LOG.debug(self.on_save_as_activate.__doc__.strip())
initial_path = None
#if self.model.config.recent[0]:
# initial_path = os.path.dirname(self.model.config.recent[0])
path = save_catalog(path=initial_path)
if path:
ret, err = self.model.save(path)
if ret:
#self.model.config.add_recent(path)
self._set_title()
pass
else:
error(_("Cannot write file %s.") % path,
"%s" % err,
_("Error writing file"))
# helpers
def _set_title(self):
"""
Get title of the main window, to reflect state of the catalog file
Returns:
String with apropriate title for main form
"""
LOG.debug("change the title")
if not self.model.tmp_filename:
LOG.debug("application has been initialized, title should"
" be empty")
fname = ""
elif not self.model.cat_fname:
fname = self.UNTITLED
else:
fname = self.model.cat_fname
modified = self.model.db_unsaved and "*" or ""
self.view['main'].set_title("%s%s - %s" % (fname,
modified, self.TITLE))

View File

@@ -22,6 +22,8 @@ Meta = MetaData()
Base = declarative_base(metadata=Meta) Base = declarative_base(metadata=Meta)
Session = sessionmaker() Session = sessionmaker()
LOG = get_logger("dbcommon")
def connect(filename): def connect(filename):
""" """
@@ -30,8 +32,7 @@ def connect(filename):
@filename - string with absolute or relative path to sqlite database @filename - string with absolute or relative path to sqlite database
file. file.
""" """
get_logger("dbcommon").info("db filename: %s" % filename) LOG.info("db filename: %s" % filename)
engine = create_engine("sqlite:///%s" % filename) engine = create_engine("sqlite:///%s" % filename)
Meta.bind = engine Meta.bind = engine
Meta.create_all() Meta.create_all(engine)

View File

@@ -5,13 +5,15 @@
Author: Roman 'gryf' Dobosz, gryf73@gmail.com Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2009-05-12 Created: 2009-05-12
""" """
import os
import gtk import gtk
class Dialog(object): class Dialog(object):
"""Show simple dialog for questions """
if "OK" button pressed, return "True" Show simple dialog for questions
"Cancel" button return "False" Returns: Bool - True, if "OK" button pressed, False otherwise.
""" """
def __init__(self, dialog_type, message, secondary_msg="", title=""): def __init__(self, dialog_type, message, secondary_msg="", title=""):
@@ -29,7 +31,7 @@ class Dialog(object):
def run(self): def run(self):
"""Show the dialog""" """Show the dialog"""
if self.dialog is None: if self.dialog is None:
self.__create_dialog() self._create_dialog()
# Change default/focus from cancel/no to ok/yes. Suitable only for # Change default/focus from cancel/no to ok/yes. Suitable only for
# Question dialog. # Question dialog.
@@ -45,7 +47,7 @@ class Dialog(object):
return True return True
return False return False
def __create_dialog(self): def _create_dialog(self):
"""Create MessageDialog widgt""" """Create MessageDialog widgt"""
if self.type == gtk.MESSAGE_QUESTION and \ if self.type == gtk.MESSAGE_QUESTION and \
self.buttons not in (gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL): self.buttons not in (gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL):
@@ -74,6 +76,90 @@ class About(object):
# TODO: finish this, re-use Dialog class instead of copy/paste of old classes! # TODO: finish this, re-use Dialog class instead of copy/paste of old classes!
# def about(name, version, ) # def about(name, version, )
class ChooseFile(object):
"""
Common file chooser
"""
URI = None
BUTTON_PAIRS = {'cancel': (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
'ok': (gtk.STOCK_OK, gtk.RESPONSE_APPLY),
'save': (gtk.STOCK_SAVE, gtk.RESPONSE_APPLY),
'open': (gtk.STOCK_OPEN, gtk.RESPONSE_APPLY)}
CHOOSER_TYPES = {'open': gtk.FILE_CHOOSER_ACTION_OPEN,
'save': gtk.FILE_CHOOSER_ACTION_SAVE}
FILTERS = {'catalogs': {'name': "Catalog files",
'patterns': ("*.sqlite", "*.sqlite.bz2")},
'all': {'name': "All files", 'patterns': ("*.*",)}}
def __init__(self, title="", buttons=('cancel', 'ok'), path=None,
chooser_type="open"):
super(ChooseFile, self).__init__()
self.path = path
self.title = title
self.action = self.CHOOSER_TYPES[chooser_type]
self.buttons=[]
for button in buttons:
self.buttons.append(self.BUTTON_PAIRS[button][0])
self.buttons.append(self.BUTTON_PAIRS[button][1])
self.buttons = tuple(self.buttons)
self.confirmation = False
self.dialog = None
self.filters = []
def _mk_dialog(self):
"""
Create FileChooserDialog object
"""
self.dialog = gtk.FileChooserDialog(self.title, None, self.action,
self.buttons)
self.dialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
self.dialog.set_default_response(gtk.RESPONSE_OK)
self.dialog.set_do_overwrite_confirmation(self.confirmation)
self.dialog.set_title(self.title)
if self.URI:
self.dialog.set_current_folder_uri(self.URI)
elif self.path and os.path.exists(self.path):
self.path = "file://"+os.path.abspath(self.path)
self.dialog.set_current_folder_uri(self.path)
for filtr in self._get_filters():
self.dialog.add_filter(filtr)
def _get_filters(self):
"""
"""
filters = []
for filter_def in self.filters:
filtr = gtk.FileFilter()
filtr.set_name(self.FILTERS[filter_def]['name'])
for pat in self.FILTERS[filter_def]['patterns']:
filtr.add_pattern(pat)
filters.append(filtr)
return filters
def run(self):
"""
Show dialog, get response.
Returns:
Returns: String - with filename, None otherwise.
"""
if self.dialog is None:
self._mk_dialog()
response = self.dialog.run()
filename = None
if response == gtk.RESPONSE_APPLY:
filename = self.dialog.get_filename()
self.__class__.URI = self.dialog.get_current_folder_uri()
self.dialog.destroy()
return filename
def yesno(message, secondarymsg="", title="", default=False): def yesno(message, secondarymsg="", title="", default=False):
"""Question with yes-no buttons. Returns False on 'no', True on 'yes'""" """Question with yes-no buttons. Returns False on 'no', True on 'yes'"""
dialog = Dialog(gtk.MESSAGE_QUESTION, message, secondarymsg, title) dialog = Dialog(gtk.MESSAGE_QUESTION, message, secondarymsg, title)
@@ -116,3 +202,21 @@ def error(message, secondarymsg="", title="", button=gtk.BUTTONS_OK):
dialog.run() dialog.run()
return True return True
def open_catalog(title=_("Open catalog"), path=None):
"""
Request filename from user to open.
Returns: string - full path and filename or None
"""
requester = ChooseFile(title)
requester.filters = ['catalogs', 'all']
return requester.run()
def save_catalog(title=_("Open catalog"), path=None):
"""
Request filename from user for save.
Returns: string - full path and filename or None
"""
requester = ChooseFile(title, chooser_type="save")
requester.filters = ['catalogs', 'all']
requester.confirmation = True
return requester.run()

View File

@@ -40,12 +40,11 @@ def get_logger(module_name, level=None, to_file=False):
if to_file: if to_file:
log_handler = logging.FileHandler(path) log_handler = logging.FileHandler(path)
formatter = logging.Formatter("%(asctime)s %(filename)s:%(lineno) - " formatter = logging.Formatter("%(asctime)s %(filename)s:%(lineno)s - "
"%(name)s - %(levelname)s - " "%(levelname)s - %(message)s")
"%(message)s")
else: else:
log_handler = logging.StreamHandler(sys.stderr) log_handler = logging.StreamHandler(sys.stderr)
formatter = logging.Formatter("%(name)s - %(filename)s:%(lineno)s - " formatter = logging.Formatter("%(filename)s:%(lineno)s - "
"%(levelname)s - %(message)s") "%(levelname)s - %(message)s")
log_handler.setFormatter(formatter) log_handler.setFormatter(formatter)

View File

@@ -13,6 +13,7 @@ from tempfile import mkstemp
import gtk import gtk
import gobject import gobject
from gtkmvc import ModelMT from gtkmvc import ModelMT
from sqlalchemy import create_engine
from pygtktalog.dbobjects import File, Exif, Group, Gthumb from pygtktalog.dbobjects import File, Exif, Group, Gthumb
from pygtktalog.dbobjects import Image, Tag, Thumbnail from pygtktalog.dbobjects import Image, Tag, Thumbnail
@@ -45,17 +46,38 @@ class MainModel(ModelMT):
self.cat_fname = filename self.cat_fname = filename
# Temporary (usually in /tmp) working database. # Temporary (usually in /tmp) working database.
self.tmp_filename = None self.tmp_filename = None
self.config = {}
# SQLAlchemy session object for internal use # SQLAlchemy session object for internal use
self._session = None self._session = None
# Flag indicates, that db was compressed # Flag indicates, that db was compressed
# TODO: make it depend on configuration # TODO: make it depend on configuration
self.compressed = False self.compressed = False
self.db_unsaved = False self.db_unsaved = None
self.discs = None
self.files = None
self._init_discs()
self._init_files()
if self.cat_fname:
self.open(self.cat_fname)
def _init_discs(self):
"""
Create TreeStore model for the discs
"""
self.discs = gtk.TreeStore(gobject.TYPE_PYOBJECT, self.discs = gtk.TreeStore(gobject.TYPE_PYOBJECT,
gobject.TYPE_STRING, gobject.TYPE_STRING,
str) str)
def _init_files(self):
"""
Create ListStore model for the diles
"""
self.files = gtk.ListStore(gobject.TYPE_PYOBJECT, self.files = gtk.ListStore(gobject.TYPE_PYOBJECT,
gobject.TYPE_STRING, gobject.TYPE_STRING,
gobject.TYPE_STRING, gobject.TYPE_STRING,
@@ -64,8 +86,6 @@ class MainModel(ModelMT):
gobject.TYPE_STRING, gobject.TYPE_STRING,
gobject.TYPE_INT, gobject.TYPE_INT,
str) str)
if self.cat_fname:
self.open(self.cat_fname)
def open(self, filename): def open(self, filename):
""" """
@@ -87,12 +107,45 @@ class MainModel(ModelMT):
else: else:
return False return False
def save(self, filename=None):
"""
Save tared directory at given catalog fielname
Arguments:
@filename - see MainModel __init__ docstring.
Returns: tuple:
Bool - true for success, false otherwise.
String or None - error message
"""
if not filename and not self.cat_fname:
LOG.debug("no filename detected!")
return False, None
if filename:
if not '.sqlite' in filename:
filename += '.sqlite'
else:
filename = filename[:filename.rindex('.sqlite')] + '.sqlite'
if 'compress' in self.config and self.config['compress']:
filename += '.bz2'
self.cat_fname = filename
val, err = self._compress_and_save()
if not val:
self.cat_fname = None
return val, err
def new(self): def new(self):
""" """
Create new catalog Create new catalog
""" """
self.cleanup() self.cleanup()
self._create_temp_db_file() self._create_temp_db_file()
self._create_schema()
self._init_discs()
self._init_files()
self.db_unsaved = False
def cleanup(self): def cleanup(self):
""" """
@@ -108,20 +161,13 @@ class MainModel(ModelMT):
try: try:
os.unlink(self.tmp_filename) os.unlink(self.tmp_filename)
LOG.debug("file %s succesfully deleted", self.tmp_filename)
except OSError: except OSError:
LOG.exception("temporary db file doesn't exists!") LOG.error("temporary db file doesn't exists!")
except TypeError: except TypeError:
# TODO: file not exist - create? print error message? # TODO: file does not exist - create? print error message?
LOG.exception("temporary db file doesn't exists!") LOG.error("temporary db file doesn't exists!")
else:
LOG.debug("file %s succesfully deleted", self.tmp_filename)
def _create_empty_db(self):
"""
Create new DB
"""
self.cleanup()
self._create_temp_db_file()
def _examine_file(self, filename): def _examine_file(self, filename):
""" """
@@ -179,7 +225,7 @@ class MainModel(ModelMT):
open_file.close() open_file.close()
except IOError: except IOError:
self.cleanup() self.cleanup()
self.filename = None self.cat_fname = None
self.internal_dirname = None self.internal_dirname = None
LOG.exception("File is probably not a bz2!") LOG.exception("File is probably not a bz2!")
return False return False
@@ -195,7 +241,7 @@ class MainModel(ModelMT):
LOG.error("Error opening file '%s' - not a catalog file!", LOG.error("Error opening file '%s' - not a catalog file!",
self.tmp_filename) self.tmp_filename)
self.cleanup() self.cleanup()
self.filename = None self.cat_fname = None
self.internal_dirname = None self.internal_dirname = None
return False return False
@@ -204,11 +250,33 @@ class MainModel(ModelMT):
return True return True
def _create_temp_db_file(self): def _create_temp_db_file(self):
"""
Create new DB file, populate schema.
"""
fd, self.tmp_filename = mkstemp() fd, self.tmp_filename = mkstemp()
LOG.debug("new db filename: %s" % self.tmp_filename)
# close file descriptor, otherwise it can be source of app crash! # close file descriptor, otherwise it can be source of app crash!
# http://www.logilab.org/blogentry/17873 # http://www.logilab.org/blogentry/17873
os.close(fd) os.close(fd)
def _create_schema(self):
"""
"""
self._session = Session()
connect(os.path.abspath(self.tmp_filename))
root = File()
root.id = 1
root.filename = 'root'
root.size = 0
root.source = 0
root.type = 0
root.parent_id = 1
self._session.add(root)
self._session.commit()
def _populate_discs_from_db(self): def _populate_discs_from_db(self):
""" """
Read objects from database, fill TreeStore model with discs Read objects from database, fill TreeStore model with discs
@@ -222,7 +290,7 @@ class MainModel(ModelMT):
Get all children of the selected parent. Get all children of the selected parent.
Arguments: Arguments:
@parent_id - integer with id of the parent (from db) @parent_id - integer with id of the parent (from db)
@iterator - TODO @iterator - gtk.TreeIter, which points to a path inside model
""" """
for fileob in dirs: for fileob in dirs:
if fileob.parent_id == parent_id: if fileob.parent_id == parent_id:
@@ -263,5 +331,30 @@ class MainModel(ModelMT):
self.files.set_value(myiter, 7, gtk.STOCK_DIRECTORY \ self.files.set_value(myiter, 7, gtk.STOCK_DIRECTORY \
if child.type==1 else gtk.STOCK_FILE) if child.type==1 else gtk.STOCK_FILE)
def _compress_and_save(self):
"""
Create (and optionaly compress) tar archive from working directory and
write it to specified file.
"""
# flush all changes
self._session.commit()
try:
if 'compress' in self.config and self.config['compress']:
output_file = bz2.BZ2File(self.cat_fname, "w")
else:
output_file = open(self.cat_fname, "w")
LOG.debug("save (and optionally compress) successed")
except IOError, (errno, strerror):
LOG.error("error saving or compressing file", errno, strerror)
return False, strerror
dbpath = open(self.tmp_filename)
output_file.write(dbpath.read())
dbpath.close()
output_file.close()
self.db_unsaved = False
return True, None

25
pygtktalog/pygtkutils.py Normal file
View File

@@ -0,0 +1,25 @@
"""
Project: pyGTKtalog
Description: pyGTK common utility functions
Type: tility
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2010-11-07 13:30:37
"""
def get_tv_item_under_cursor(treeview):
"""
Get item (most probably id of the row) form tree view under cursor.
Arguments:
@treeview - gtk.TreeView
Returns:
Item in first column of TreeModel, which TreeView is connected with,
None in other cases
"""
path, column = treeview.get_cursor()
if path and column:
model = treeview.get_model()
tm_iter = model.get_iter(path)
item_id = model.get_value(tm_iter, 0)
return item_id
return None

View File

@@ -12,6 +12,7 @@ import shutil
from tempfile import mkdtemp, mkstemp from tempfile import mkdtemp, mkstemp
import math import math
import Image
from pygtktalog.misc import float_to_string from pygtktalog.misc import float_to_string
@@ -21,9 +22,15 @@ class Video(object):
Midentify script belongs to mplayer package. Midentify script belongs to mplayer package.
""" """
def __init__(self, filename): def __init__(self, filename, out_width=1024):
"""Init class instance. Filename of a video file is required.""" """
Init class instance.
Arguments:
@filename - Filename of a video file (required).
@out_width - width of final image to be scaled to.
"""
self.filename = filename self.filename = filename
self.out_width = out_width
self.tags = {} self.tags = {}
output = self.__get_movie_info() output = self.__get_movie_info()
@@ -52,14 +59,12 @@ class Video(object):
length_str = "%02d:%02d:%02d" % (hours, minutes, seconds) length_str = "%02d:%02d:%02d" % (hours, minutes, seconds)
self.tags['duration'] = length_str self.tags['duration'] = length_str
def capture(self, out_width=1024): def capture(self):
""" """
Extract images for given video filename and montage it into one, big Extract images for given video filename and montage it into one, big
picture, similar to output from Windows Media Player thing, but without picture, similar to output from Windows Media Player thing, but without
captions and time (who need it anyway?). captions and time (who need it anyway?).
Arguments:
@out_width - width of generated image. If actual image width
exceeds this number scale is performed.
Returns: image filename or None Returns: image filename or None
NOTE: You should remove returned file manually, or move it in some NOTE: You should remove returned file manually, or move it in some
@@ -93,7 +98,7 @@ class Video(object):
file_desc, image_fn = mkstemp() file_desc, image_fn = mkstemp()
os.close(file_desc) os.close(file_desc)
self.__make_captures(tempdir, no_pictures) self.__make_captures(tempdir, no_pictures)
self.__make_montage(tempdir, image_fn, no_pictures, out_width) self.__make_montage(tempdir, image_fn, no_pictures, self.out_width)
shutil.rmtree(tempdir) shutil.rmtree(tempdir)
return image_fn return image_fn
@@ -149,26 +154,71 @@ class Video(object):
shutil.move(os.path.join(directory, "00000001.jpg"), shutil.move(os.path.join(directory, "00000001.jpg"),
os.path.join(directory, "picture_%s.jpg" % time)) os.path.join(directory, "picture_%s.jpg" % time))
def __make_montage(self, directory, image_fn, no_pictures, out_width): def __make_montage2(self, directory, image_fn, no_pictures):
""" """
Generate one big image from screnshots and optionally resize it. Generate one big image from screnshots and optionally resize it.
Arguments: Arguments:
@directory - source directory containing images @directory - source directory containing images
@image_fn - destination final image @image_fn - destination final image
@no_pictures - number of pictures @no_pictures - number of pictures
@out_width - width of final image to be scaled to.
""" """
scale = False scale = False
row_length = 4 row_length = 4
if no_pictures < 8: if no_pictures < 8:
row_length = 2 row_length = 2
if (self.tags['width'] * row_length) > out_width: if (self.tags['width'] * row_length) > self.out_width:
scale = True scale = True
else: else:
for i in [8, 6, 5]: for i in [8, 6, 5]:
if (no_pictures % i) == 0 and \ if (no_pictures % i) == 0 and \
(i * self.tags['width']) <= out_width: (i * self.tags['width']) <= self.out_width:
row_length = i
break
tile = "%dx%d" % (row_length, no_pictures / row_length)
_curdir = os.path.abspath(os.path.curdir)
os.chdir(directory)
# composite pictures
# readlines trick will make to wait for process end
#cmd = "montage -tile %s -geometry +2+2 picture_*.jpg montage.jpg"
imgs = [Image.open(fn).resize((photow,photoh)) for fn in fnames]
os.popen(cmd % tile).readlines()
# scale it to minimum 'modern' width: 1024
if scale:
cmd = "convert -scale %s montage.jpg montage_scaled.jpg"
os.popen(cmd % out_width).readlines()
shutil.move(os.path.join(directory, 'montage_scaled.jpg'),
image_fn)
else:
shutil.move(os.path.join(directory, 'montage.jpg'),
image_fn)
os.chdir(_curdir)
def __make_montage(self, directory, image_fn, no_pictures):
"""
Generate one big image from screnshots and optionally resize it.
Arguments:
@directory - source directory containing images
@image_fn - destination final image
@no_pictures - number of pictures
"""
scale = False
row_length = 4
if no_pictures < 8:
row_length = 2
if (self.tags['width'] * row_length) > self.out_width:
scale = True
else:
for i in [8, 6, 5]:
if (no_pictures % i) == 0 and \
(i * self.tags['width']) <= self.ut_width:
row_length = i row_length = i
break break
@@ -185,7 +235,7 @@ class Video(object):
# scale it to minimum 'modern' width: 1024 # scale it to minimum 'modern' width: 1024
if scale: if scale:
cmd = "convert -scale %s montage.jpg montage_scaled.jpg" cmd = "convert -scale %s montage.jpg montage_scaled.jpg"
os.popen(cmd % out_width).readlines() os.popen(cmd % self.out_width).readlines()
shutil.move(os.path.join(directory, 'montage_scaled.jpg'), shutil.move(os.path.join(directory, 'montage_scaled.jpg'),
image_fn) image_fn)
else: else:

View File

@@ -30,14 +30,20 @@ class MainView(View):
Initialize view Initialize view
""" """
View.__init__(self) View.__init__(self)
self.app_sensitive = None
self['tag_path_box'].hide() self['tag_path_box'].hide()
self.discs = DiscsView() self.discs = DiscsView()
#self['scrolledwindow_discs'].add_with_viewport(self.discs.get_top_widget()) #self['scrolledwindow_discs'].add_with_viewport(\
# self.discs.get_top_widget())
self['scrolledwindow_discs'].add(self.discs.get_top_widget()) self['scrolledwindow_discs'].add(self.discs.get_top_widget())
self.files = FilesView() self.files = FilesView()
self['scrolledwindow_files'].add_with_viewport(self.files.get_top_widget()) self['scrolledwindow_files'].add_with_viewport(\
self.files.get_top_widget())
self.details = DetailsView()
self['vpaned1'].add2(self.details.get_top_widget())
def set_widgets_scan_sensitivity(self, sensitive=True): def set_widgets_scan_sensitivity(self, sensitive=True):
""" """
@@ -45,6 +51,23 @@ class MainView(View):
""" """
pass pass
def set_widgets_app_sensitivity(self, sensitive=True):
"""
Enable/disable widgets for empty application. Usefull for first run
of an application (without any db filename as an argument).
"""
if self.app_sensitive is sensitive:
return
for widget in ['scrolledwindow_discs', 'scrolledwindow_files',
'tb_save', 'tb_addcd', 'tb_adddir', 'tb_find',
'edit1', 'catalog1', 'save1', 'save_as1', 'import',
'export']:
self[widget].set_sensitive(sensitive)
# widgets from subclasses
self.details['notebook_details'].set_sensitive(sensitive)
class DiscsView(View): class DiscsView(View):
""" """
@@ -94,6 +117,7 @@ class DiscsPopupView(View):
for item in ['update', 'rename', 'delete', 'statistics']: for item in ['update', 'rename', 'delete', 'statistics']:
self[item].set_sensitive(state) self[item].set_sensitive(state)
class FilesView(View): class FilesView(View):
""" """
Separate subview of Files TreeView as a table. Separate subview of Files TreeView as a table.
@@ -106,6 +130,8 @@ class FilesView(View):
Initialize view Initialize view
""" """
View.__init__(self) View.__init__(self)
self.menu = FilesPopupView()
class FilesPopupView(View): class FilesPopupView(View):
""" """
@@ -120,6 +146,19 @@ class FilesPopupView(View):
""" """
View.__init__(self) View.__init__(self)
def set_menu_items_sensitivity(self, state):
"""
Set sensitivity for couple of popup menu items, which should be
disabled if user right-clicks on no item in treeview.
Arguments:
@state - Bool, if True update menu item will be sensitive,
otherwise not
"""
for item in ["add_tag", "delete_tag", "add_thumb", "remove_thumb",
"add_image", "remove_image", "edit", "delete", "rename"]:
self[item].set_sensitive(state)
class TagcloudView(View): class TagcloudView(View):
""" """
Textview subview with clickable tags. Textview subview with clickable tags.