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:
123
locale/pl.po
123
locale/pl.po
@@ -32,14 +32,17 @@ msgid "Add _Directory"
|
||||
msgstr "Dodaj kata_log"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:6
|
||||
#: pygtktalog/views/glade/files.glade.h:1
|
||||
msgid "Add _Images"
|
||||
msgstr "Dodaj _obrazy"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:7
|
||||
#: pygtktalog/views/glade/files.glade.h:2
|
||||
msgid "Add _Thumbnail"
|
||||
msgstr "Dodaj miniaturę"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:8
|
||||
#: pygtktalog/views/glade/files.glade.h:3
|
||||
msgid ""
|
||||
"Add images to file. If file have no thumbnail,\n"
|
||||
"thumbnail from first image will be generated."
|
||||
@@ -48,182 +51,234 @@ msgstr ""
|
||||
"zostanie wygenerowana miniatura z pierwszego obrazu."
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:10
|
||||
#: pygtktalog/views/glade/main.glade.h:6
|
||||
msgid "Cancel"
|
||||
msgstr "Analuj"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:11
|
||||
#: pygtktalog/views/glade/main.glade.h:7
|
||||
msgid "Catalog _statistics"
|
||||
msgstr "_Statystyka katalogu"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:12
|
||||
#: pygtktalog/views/glade/discs.glade.h:1
|
||||
msgid "Collapse all nodes"
|
||||
msgstr "Zwiń wszystkie gałęzie"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:13
|
||||
#: pygtktalog/views/glade/main.glade.h:8
|
||||
msgid "Create new catalog"
|
||||
msgstr "Utwórz nowy katalog"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:14
|
||||
#: pygtktalog/views/glade/main.glade.h:9
|
||||
msgid "Delete all images"
|
||||
msgstr "Usuń wszystkie obrazy"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:15
|
||||
#: pygtktalog/views/glade/main.glade.h:10
|
||||
msgid "Delete all thumbnals"
|
||||
msgstr "Usuń wszystkie miniatury"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:16
|
||||
#: pygtktalog/views/glade/main.glade.h:11
|
||||
msgid "Delete tag"
|
||||
msgstr "Usuń tag"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:17
|
||||
#: pygtktalog/views/glade/main.glade.h:12
|
||||
msgid "Deletes all images from files in current colection"
|
||||
msgstr "Usuwa wszystkie obrazy z plików w bieżącej kolekcji"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:18
|
||||
#: pygtktalog/views/glade/main.glade.h:13
|
||||
msgid "Discs"
|
||||
msgstr "Dyski"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:19
|
||||
#: pygtktalog/views/glade/details.glade.h:1
|
||||
msgid "Double click to open image"
|
||||
msgstr "Dwukrotne kliknięcie otwiera obraz"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:20
|
||||
#: pygtktalog/views/glade/details.glade.h:2
|
||||
msgid "EXIF"
|
||||
msgstr "EXIF"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:21
|
||||
#: pygtktalog/views/glade/discs.glade.h:2
|
||||
msgid "Expand all nodes"
|
||||
msgstr "Rozwiń wszystkie gałęzie"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:22
|
||||
#: pygtktalog/views/glade/main.glade.h:14
|
||||
msgid "Export"
|
||||
msgstr "Eksport"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:23
|
||||
#: pygtktalog/views/glade/details.glade.h:3
|
||||
msgid "File info"
|
||||
msgstr "Informacje o pliku"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:24
|
||||
#: pygtktalog/views/glade/main.glade.h:15
|
||||
msgid "Find file"
|
||||
msgstr "Znajdź plik"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:25
|
||||
#: pygtktalog/views/glade/details.glade.h:4
|
||||
msgid "Images"
|
||||
msgstr "Obrazy"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:26
|
||||
#: pygtktalog/views/glade/main.glade.h:16
|
||||
msgid "Import"
|
||||
msgstr "Import"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:27
|
||||
#: pygtktalog/views/glade/main.glade.h:17
|
||||
msgid "Open catalog file"
|
||||
msgstr "Otwórz plik katalogu"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:28
|
||||
#: pygtktalog/views/glade/main.glade.h:18
|
||||
msgid "Quit pyGTKtalog"
|
||||
msgstr "Zakończ pyGTKtalog"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:29
|
||||
#: pygtktalog/views/glade/files.glade.h:5
|
||||
msgid "Re_move Thumbnail"
|
||||
msgstr "Usuń miniaturę"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:30
|
||||
#: pygtktalog/views/glade/main.glade.h:19
|
||||
msgid "Recent files"
|
||||
msgstr "Ostatnio używane pliki"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:31
|
||||
#: pygtktalog/views/glade/files.glade.h:6
|
||||
msgid "Rem_ove All Images"
|
||||
msgstr "Usuń wszystkie obrazy"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:32
|
||||
#: pygtktalog/views/glade/files.glade.h:7
|
||||
msgid "Remo_ve tag"
|
||||
msgstr "Usuń tag"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:33
|
||||
#: pygtktalog/views/glade/main.glade.h:20
|
||||
msgid "Save all images..."
|
||||
msgstr "Zapisz wszytkie obrazy..."
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:34
|
||||
#: pygtktalog/views/glade/main.glade.h:21
|
||||
msgid "Save catalog"
|
||||
msgstr "Zapisz katalog"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:35
|
||||
#: pygtktalog/views/glade/main.glade.h:22
|
||||
msgid "Set as _thumbnail"
|
||||
msgstr "Ustaw jako miniaturę"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:36
|
||||
#: pygtktalog/views/glade/main.glade.h:23
|
||||
msgid "Status bar"
|
||||
msgstr "Pasek stanu"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:37
|
||||
#: pygtktalog/views/glade/main.glade.h:24
|
||||
msgid "Tags"
|
||||
msgstr "Tagi"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:38
|
||||
#: pygtktalog/views/glade/main.glade.h:25
|
||||
msgid "Toolbar"
|
||||
msgstr "Pasek narzędzi"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:39
|
||||
#: pygtktalog/views/glade/main.glade.h:26
|
||||
msgid "_Add images"
|
||||
msgstr "Dodaj obrazy"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:40
|
||||
#: pygtktalog/views/glade/files.glade.h:8
|
||||
msgid "_Add tag"
|
||||
msgstr "_Dodaj tag"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:41
|
||||
#: pygtktalog/views/glade/main.glade.h:27
|
||||
msgid "_Catalog"
|
||||
msgstr "_Katalog"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:42
|
||||
#: pygtktalog/views/glade/discs.glade.h:3
|
||||
msgid "_Collapse all"
|
||||
msgstr "_Zwiń wszystko"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:43
|
||||
#: pygtktalog/views/glade/discs.glade.h:4
|
||||
#: pygtktalog/views/glade/files.glade.h:9
|
||||
msgid "_Delete"
|
||||
msgstr "_Usuń"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:44
|
||||
#: pygtktalog/views/glade/main.glade.h:28
|
||||
msgid "_Delete images"
|
||||
msgstr "Usuń obrazy"
|
||||
|
||||
#: 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"
|
||||
msgstr "_Edycja"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:46
|
||||
#: pygtktalog/views/glade/discs.glade.h:5
|
||||
msgid "_Expand all"
|
||||
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"
|
||||
msgstr "_Plik"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:48
|
||||
#: pygtktalog/views/glade/main.glade.h:31
|
||||
#: pygtktalog/views/glade/test.glade.h:3
|
||||
msgid "_Help"
|
||||
msgstr "_Pomoc"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:49
|
||||
#: pygtktalog/views/glade/main.glade.h:32
|
||||
msgid "_Remove Thumbnail"
|
||||
msgstr "Usuń miniaturę"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:50
|
||||
#: pygtktalog/views/glade/discs.glade.h:6
|
||||
#: pygtktalog/views/glade/files.glade.h:11
|
||||
msgid "_Rename"
|
||||
msgstr "_Zmień nazwę"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:51
|
||||
#: pygtktalog/views/glade/main.glade.h:33
|
||||
msgid "_Save images to..."
|
||||
msgstr "Zapisz obrazy do..."
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:52
|
||||
#: pygtktalog/views/glade/discs.glade.h:7
|
||||
msgid "_Statistics"
|
||||
msgstr "_Statystyka"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:53
|
||||
#: pygtktalog/views/glade/discs.glade.h:8
|
||||
msgid "_Update"
|
||||
msgstr "_Uaktualnij"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:54
|
||||
#: pygtktalog/views/glade/main.glade.h:34
|
||||
#: pygtktalog/views/glade/test.glade.h:4
|
||||
msgid "_View"
|
||||
msgstr "_Widok"
|
||||
|
||||
@@ -232,10 +287,12 @@ msgid "gtk-clear"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:56
|
||||
#: pygtktalog/views/glade/main.glade.h:35
|
||||
msgid "pyGTKtalog"
|
||||
msgstr "pyGTKtalog"
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:57
|
||||
#: pygtktalog/views/glade/main.glade.h:36
|
||||
msgid "pyGTKtalog - Image"
|
||||
msgstr "pyGTKtalog - Obraz"
|
||||
|
||||
@@ -251,6 +308,68 @@ msgstr "Bieżący katalog nie jest zapisany, wszelkie zmiany zostaną utracone."
|
||||
msgid "Quit application"
|
||||
msgstr "Zakończ aplikację"
|
||||
|
||||
#: pygtktalog/models/main.py:16
|
||||
#: pygtktalog/models/main.py:16 pygtktalog/models/main.py:31
|
||||
msgid "Idle"
|
||||
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 ""
|
||||
|
||||
@@ -31,196 +31,251 @@ msgid "Add _Directory"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:6
|
||||
#: pygtktalog/views/glade/files.glade.h:1
|
||||
msgid "Add _Images"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:7
|
||||
#: pygtktalog/views/glade/files.glade.h:2
|
||||
msgid "Add _Thumbnail"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:8
|
||||
#: pygtktalog/views/glade/files.glade.h:3
|
||||
msgid ""
|
||||
"Add images to file. If file have no thumbnail,\n"
|
||||
"thumbnail from first image will be generated."
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:10
|
||||
#: pygtktalog/views/glade/main.glade.h:6
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:11
|
||||
#: pygtktalog/views/glade/main.glade.h:7
|
||||
msgid "Catalog _statistics"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:12
|
||||
#: pygtktalog/views/glade/discs.glade.h:1
|
||||
msgid "Collapse all nodes"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:13
|
||||
#: pygtktalog/views/glade/main.glade.h:8
|
||||
msgid "Create new catalog"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:14
|
||||
#: pygtktalog/views/glade/main.glade.h:9
|
||||
msgid "Delete all images"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:15
|
||||
#: pygtktalog/views/glade/main.glade.h:10
|
||||
msgid "Delete all thumbnals"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:16
|
||||
#: pygtktalog/views/glade/main.glade.h:11
|
||||
msgid "Delete tag"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:17
|
||||
#: pygtktalog/views/glade/main.glade.h:12
|
||||
msgid "Deletes all images from files in current colection"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:18
|
||||
#: pygtktalog/views/glade/main.glade.h:13
|
||||
msgid "Discs"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:19
|
||||
#: pygtktalog/views/glade/details.glade.h:1
|
||||
msgid "Double click to open image"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:20
|
||||
#: pygtktalog/views/glade/details.glade.h:2
|
||||
msgid "EXIF"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:21
|
||||
#: pygtktalog/views/glade/discs.glade.h:2
|
||||
msgid "Expand all nodes"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:22
|
||||
#: pygtktalog/views/glade/main.glade.h:14
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:23
|
||||
#: pygtktalog/views/glade/details.glade.h:3
|
||||
msgid "File info"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:24
|
||||
#: pygtktalog/views/glade/main.glade.h:15
|
||||
msgid "Find file"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:25
|
||||
#: pygtktalog/views/glade/details.glade.h:4
|
||||
msgid "Images"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:26
|
||||
#: pygtktalog/views/glade/main.glade.h:16
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:27
|
||||
#: pygtktalog/views/glade/main.glade.h:17
|
||||
msgid "Open catalog file"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:28
|
||||
#: pygtktalog/views/glade/main.glade.h:18
|
||||
msgid "Quit pyGTKtalog"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:29
|
||||
#: pygtktalog/views/glade/files.glade.h:5
|
||||
msgid "Re_move Thumbnail"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:30
|
||||
#: pygtktalog/views/glade/main.glade.h:19
|
||||
msgid "Recent files"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:31
|
||||
#: pygtktalog/views/glade/files.glade.h:6
|
||||
msgid "Rem_ove All Images"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:32
|
||||
#: pygtktalog/views/glade/files.glade.h:7
|
||||
msgid "Remo_ve tag"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:33
|
||||
#: pygtktalog/views/glade/main.glade.h:20
|
||||
msgid "Save all images..."
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:34
|
||||
#: pygtktalog/views/glade/main.glade.h:21
|
||||
msgid "Save catalog"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:35
|
||||
#: pygtktalog/views/glade/main.glade.h:22
|
||||
msgid "Set as _thumbnail"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:36
|
||||
#: pygtktalog/views/glade/main.glade.h:23
|
||||
msgid "Status bar"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:37
|
||||
#: pygtktalog/views/glade/main.glade.h:24
|
||||
msgid "Tags"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:38
|
||||
#: pygtktalog/views/glade/main.glade.h:25
|
||||
msgid "Toolbar"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:39
|
||||
#: pygtktalog/views/glade/main.glade.h:26
|
||||
msgid "_Add images"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:40
|
||||
#: pygtktalog/views/glade/files.glade.h:8
|
||||
msgid "_Add tag"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:41
|
||||
#: pygtktalog/views/glade/main.glade.h:27
|
||||
msgid "_Catalog"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:42
|
||||
#: pygtktalog/views/glade/discs.glade.h:3
|
||||
msgid "_Collapse all"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:43
|
||||
#: pygtktalog/views/glade/discs.glade.h:4
|
||||
#: pygtktalog/views/glade/files.glade.h:9
|
||||
msgid "_Delete"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:44
|
||||
#: pygtktalog/views/glade/main.glade.h:28
|
||||
msgid "_Delete images"
|
||||
msgstr ""
|
||||
|
||||
#: 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"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:46
|
||||
#: pygtktalog/views/glade/discs.glade.h:5
|
||||
msgid "_Expand all"
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:48
|
||||
#: pygtktalog/views/glade/main.glade.h:31
|
||||
#: pygtktalog/views/glade/test.glade.h:3
|
||||
msgid "_Help"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:49
|
||||
#: pygtktalog/views/glade/main.glade.h:32
|
||||
msgid "_Remove Thumbnail"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:50
|
||||
#: pygtktalog/views/glade/discs.glade.h:6
|
||||
#: pygtktalog/views/glade/files.glade.h:11
|
||||
msgid "_Rename"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:51
|
||||
#: pygtktalog/views/glade/main.glade.h:33
|
||||
msgid "_Save images to..."
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:52
|
||||
#: pygtktalog/views/glade/discs.glade.h:7
|
||||
msgid "_Statistics"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:53
|
||||
#: pygtktalog/views/glade/discs.glade.h:8
|
||||
msgid "_Update"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:54
|
||||
#: pygtktalog/views/glade/main.glade.h:34
|
||||
#: pygtktalog/views/glade/test.glade.h:4
|
||||
msgid "_View"
|
||||
msgstr ""
|
||||
|
||||
@@ -229,10 +284,12 @@ msgid "gtk-clear"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:56
|
||||
#: pygtktalog/views/glade/main.glade.h:35
|
||||
msgid "pyGTKtalog"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/views/glade/main.glade.h:57
|
||||
#: pygtktalog/views/glade/main.glade.h:36
|
||||
msgid "pyGTKtalog - Image"
|
||||
msgstr ""
|
||||
|
||||
@@ -248,6 +305,66 @@ msgstr ""
|
||||
msgid "Quit application"
|
||||
msgstr ""
|
||||
|
||||
#: pygtktalog/models/main.py:16
|
||||
#: pygtktalog/models/main.py:16 pygtktalog/models/main.py:31
|
||||
msgid "Idle"
|
||||
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 ""
|
||||
|
||||
@@ -9,6 +9,11 @@ import gtk
|
||||
|
||||
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):
|
||||
"""
|
||||
@@ -28,6 +33,20 @@ class FilesController(Controller):
|
||||
Register view, and setup columns for files treeview
|
||||
"""
|
||||
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)
|
||||
|
||||
col = gtk.TreeViewColumn(_('Disc'), gtk.CellRendererText(), text=1)
|
||||
@@ -65,7 +84,178 @@ class FilesController(Controller):
|
||||
self.view['files'].set_search_column(2)
|
||||
|
||||
# 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,
|
||||
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)
|
||||
|
||||
|
||||
@@ -9,15 +9,17 @@ import gtk
|
||||
|
||||
from gtkmvc import Controller
|
||||
|
||||
#from pygtktalog.dialogs import yesno
|
||||
from pygtktalog.dialogs import About
|
||||
from pygtktalog.controllers.discs import DiscsController
|
||||
from pygtktalog.controllers.files import FilesController
|
||||
#from pygtktalog.controllers.details import DetailsController
|
||||
#from pygtktalog.controllers.tags import TagcloudController
|
||||
#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 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")
|
||||
|
||||
@@ -25,6 +27,8 @@ class MainController(Controller):
|
||||
"""
|
||||
Controller for main application window
|
||||
"""
|
||||
TITLE = "pyGTKtalog"
|
||||
UNTITLED = _("untitled")
|
||||
|
||||
def __init__(self, model, view):
|
||||
"""
|
||||
@@ -48,6 +52,8 @@ class MainController(Controller):
|
||||
LOG.debug("replace hardcoded defaults with configured!")
|
||||
view['main'].set_default_size(800, 600)
|
||||
view['hpaned1'].set_position(200)
|
||||
if not self.model.tmp_filename:
|
||||
view.set_widgets_app_sensitivity(False)
|
||||
view['main'].show()
|
||||
|
||||
def register_adapters(self):
|
||||
@@ -55,6 +61,10 @@ class MainController(Controller):
|
||||
progress bar/status bar adapters goes here
|
||||
"""
|
||||
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
|
||||
|
||||
# signals
|
||||
@@ -79,10 +89,123 @@ class MainController(Controller):
|
||||
gtk.main_quit()
|
||||
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):
|
||||
"""Show about dialog"""
|
||||
About("pyGTKtalog",
|
||||
"%s" % __version__,
|
||||
"About",
|
||||
["Roman 'gryf' Dobosz"],
|
||||
'')
|
||||
About("pyGTKtalog", "%s" % __version__, "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))
|
||||
|
||||
@@ -22,6 +22,8 @@ Meta = MetaData()
|
||||
Base = declarative_base(metadata=Meta)
|
||||
Session = sessionmaker()
|
||||
|
||||
LOG = get_logger("dbcommon")
|
||||
|
||||
|
||||
def connect(filename):
|
||||
"""
|
||||
@@ -30,8 +32,7 @@ def connect(filename):
|
||||
@filename - string with absolute or relative path to sqlite database
|
||||
file.
|
||||
"""
|
||||
get_logger("dbcommon").info("db filename: %s" % filename)
|
||||
LOG.info("db filename: %s" % filename)
|
||||
engine = create_engine("sqlite:///%s" % filename)
|
||||
Meta.bind = engine
|
||||
Meta.create_all()
|
||||
|
||||
Meta.create_all(engine)
|
||||
|
||||
@@ -5,13 +5,15 @@
|
||||
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
|
||||
Created: 2009-05-12
|
||||
"""
|
||||
import os
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class Dialog(object):
|
||||
"""Show simple dialog for questions
|
||||
if "OK" button pressed, return "True"
|
||||
"Cancel" button return "False"
|
||||
"""
|
||||
Show simple dialog for questions
|
||||
Returns: Bool - True, if "OK" button pressed, False otherwise.
|
||||
"""
|
||||
|
||||
def __init__(self, dialog_type, message, secondary_msg="", title=""):
|
||||
@@ -29,7 +31,7 @@ class Dialog(object):
|
||||
def run(self):
|
||||
"""Show the dialog"""
|
||||
if self.dialog is None:
|
||||
self.__create_dialog()
|
||||
self._create_dialog()
|
||||
|
||||
# Change default/focus from cancel/no to ok/yes. Suitable only for
|
||||
# Question dialog.
|
||||
@@ -45,7 +47,7 @@ class Dialog(object):
|
||||
return True
|
||||
return False
|
||||
|
||||
def __create_dialog(self):
|
||||
def _create_dialog(self):
|
||||
"""Create MessageDialog widgt"""
|
||||
if self.type == gtk.MESSAGE_QUESTION and \
|
||||
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!
|
||||
# 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):
|
||||
"""Question with yes-no buttons. Returns False on 'no', True on 'yes'"""
|
||||
dialog = Dialog(gtk.MESSAGE_QUESTION, message, secondarymsg, title)
|
||||
@@ -116,3 +202,21 @@ def error(message, secondarymsg="", title="", button=gtk.BUTTONS_OK):
|
||||
dialog.run()
|
||||
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()
|
||||
|
||||
@@ -40,12 +40,11 @@ def get_logger(module_name, level=None, to_file=False):
|
||||
|
||||
if to_file:
|
||||
log_handler = logging.FileHandler(path)
|
||||
formatter = logging.Formatter("%(asctime)s %(filename)s:%(lineno) - "
|
||||
"%(name)s - %(levelname)s - "
|
||||
"%(message)s")
|
||||
formatter = logging.Formatter("%(asctime)s %(filename)s:%(lineno)s - "
|
||||
"%(levelname)s - %(message)s")
|
||||
else:
|
||||
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")
|
||||
|
||||
log_handler.setFormatter(formatter)
|
||||
|
||||
@@ -13,6 +13,7 @@ from tempfile import mkstemp
|
||||
import gtk
|
||||
import gobject
|
||||
from gtkmvc import ModelMT
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
from pygtktalog.dbobjects import File, Exif, Group, Gthumb
|
||||
from pygtktalog.dbobjects import Image, Tag, Thumbnail
|
||||
@@ -45,17 +46,38 @@ class MainModel(ModelMT):
|
||||
self.cat_fname = filename
|
||||
# Temporary (usually in /tmp) working database.
|
||||
self.tmp_filename = None
|
||||
self.config = {}
|
||||
# SQLAlchemy session object for internal use
|
||||
self._session = None
|
||||
# Flag indicates, that db was compressed
|
||||
# TODO: make it depend on configuration
|
||||
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,
|
||||
gobject.TYPE_STRING,
|
||||
str)
|
||||
|
||||
|
||||
def _init_files(self):
|
||||
"""
|
||||
Create ListStore model for the diles
|
||||
"""
|
||||
self.files = gtk.ListStore(gobject.TYPE_PYOBJECT,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
@@ -64,8 +86,6 @@ class MainModel(ModelMT):
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_INT,
|
||||
str)
|
||||
if self.cat_fname:
|
||||
self.open(self.cat_fname)
|
||||
|
||||
def open(self, filename):
|
||||
"""
|
||||
@@ -87,12 +107,45 @@ class MainModel(ModelMT):
|
||||
else:
|
||||
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):
|
||||
"""
|
||||
Create new catalog
|
||||
"""
|
||||
self.cleanup()
|
||||
self._create_temp_db_file()
|
||||
self._create_schema()
|
||||
self._init_discs()
|
||||
self._init_files()
|
||||
self.db_unsaved = False
|
||||
|
||||
def cleanup(self):
|
||||
"""
|
||||
@@ -108,20 +161,13 @@ class MainModel(ModelMT):
|
||||
|
||||
try:
|
||||
os.unlink(self.tmp_filename)
|
||||
LOG.debug("file %s succesfully deleted", self.tmp_filename)
|
||||
except OSError:
|
||||
LOG.exception("temporary db file doesn't exists!")
|
||||
LOG.error("temporary db file doesn't exists!")
|
||||
except TypeError:
|
||||
# TODO: file not exist - create? print error message?
|
||||
LOG.exception("temporary db file doesn't exists!")
|
||||
|
||||
|
||||
def _create_empty_db(self):
|
||||
"""
|
||||
Create new DB
|
||||
"""
|
||||
self.cleanup()
|
||||
self._create_temp_db_file()
|
||||
# TODO: file does not exist - create? print error message?
|
||||
LOG.error("temporary db file doesn't exists!")
|
||||
else:
|
||||
LOG.debug("file %s succesfully deleted", self.tmp_filename)
|
||||
|
||||
def _examine_file(self, filename):
|
||||
"""
|
||||
@@ -179,7 +225,7 @@ class MainModel(ModelMT):
|
||||
open_file.close()
|
||||
except IOError:
|
||||
self.cleanup()
|
||||
self.filename = None
|
||||
self.cat_fname = None
|
||||
self.internal_dirname = None
|
||||
LOG.exception("File is probably not a bz2!")
|
||||
return False
|
||||
@@ -195,7 +241,7 @@ class MainModel(ModelMT):
|
||||
LOG.error("Error opening file '%s' - not a catalog file!",
|
||||
self.tmp_filename)
|
||||
self.cleanup()
|
||||
self.filename = None
|
||||
self.cat_fname = None
|
||||
self.internal_dirname = None
|
||||
return False
|
||||
|
||||
@@ -204,11 +250,33 @@ class MainModel(ModelMT):
|
||||
return True
|
||||
|
||||
def _create_temp_db_file(self):
|
||||
"""
|
||||
Create new DB file, populate schema.
|
||||
"""
|
||||
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!
|
||||
# http://www.logilab.org/blogentry/17873
|
||||
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):
|
||||
"""
|
||||
Read objects from database, fill TreeStore model with discs
|
||||
@@ -222,7 +290,7 @@ class MainModel(ModelMT):
|
||||
Get all children of the selected parent.
|
||||
Arguments:
|
||||
@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:
|
||||
if fileob.parent_id == parent_id:
|
||||
@@ -263,5 +331,30 @@ class MainModel(ModelMT):
|
||||
self.files.set_value(myiter, 7, gtk.STOCK_DIRECTORY \
|
||||
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
25
pygtktalog/pygtkutils.py
Normal 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
|
||||
|
||||
@@ -12,6 +12,7 @@ import shutil
|
||||
from tempfile import mkdtemp, mkstemp
|
||||
import math
|
||||
|
||||
import Image
|
||||
from pygtktalog.misc import float_to_string
|
||||
|
||||
|
||||
@@ -21,9 +22,15 @@ class Video(object):
|
||||
Midentify script belongs to mplayer package.
|
||||
"""
|
||||
|
||||
def __init__(self, filename):
|
||||
"""Init class instance. Filename of a video file is required."""
|
||||
def __init__(self, filename, out_width=1024):
|
||||
"""
|
||||
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.out_width = out_width
|
||||
self.tags = {}
|
||||
|
||||
output = self.__get_movie_info()
|
||||
@@ -52,14 +59,12 @@ class Video(object):
|
||||
length_str = "%02d:%02d:%02d" % (hours, minutes, seconds)
|
||||
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
|
||||
picture, similar to output from Windows Media Player thing, but without
|
||||
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
|
||||
|
||||
NOTE: You should remove returned file manually, or move it in some
|
||||
@@ -93,7 +98,7 @@ class Video(object):
|
||||
file_desc, image_fn = mkstemp()
|
||||
os.close(file_desc)
|
||||
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)
|
||||
return image_fn
|
||||
@@ -149,26 +154,71 @@ class Video(object):
|
||||
shutil.move(os.path.join(directory, "00000001.jpg"),
|
||||
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.
|
||||
Arguments:
|
||||
@directory - source directory containing images
|
||||
@image_fn - destination final image
|
||||
@no_pictures - number of pictures
|
||||
@out_width - width of final image to be scaled to.
|
||||
"""
|
||||
scale = False
|
||||
row_length = 4
|
||||
if no_pictures < 8:
|
||||
row_length = 2
|
||||
|
||||
if (self.tags['width'] * row_length) > out_width:
|
||||
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']) <= 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
|
||||
break
|
||||
|
||||
@@ -185,7 +235,7 @@ class Video(object):
|
||||
# scale it to minimum 'modern' width: 1024
|
||||
if scale:
|
||||
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'),
|
||||
image_fn)
|
||||
else:
|
||||
|
||||
@@ -30,14 +30,20 @@ class MainView(View):
|
||||
Initialize view
|
||||
"""
|
||||
View.__init__(self)
|
||||
self.app_sensitive = None
|
||||
self['tag_path_box'].hide()
|
||||
|
||||
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.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):
|
||||
"""
|
||||
@@ -45,6 +51,23 @@ class MainView(View):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
@@ -94,6 +117,7 @@ class DiscsPopupView(View):
|
||||
for item in ['update', 'rename', 'delete', 'statistics']:
|
||||
self[item].set_sensitive(state)
|
||||
|
||||
|
||||
class FilesView(View):
|
||||
"""
|
||||
Separate subview of Files TreeView as a table.
|
||||
@@ -106,6 +130,8 @@ class FilesView(View):
|
||||
Initialize view
|
||||
"""
|
||||
View.__init__(self)
|
||||
self.menu = FilesPopupView()
|
||||
|
||||
|
||||
class FilesPopupView(View):
|
||||
"""
|
||||
@@ -120,6 +146,19 @@ class FilesPopupView(View):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
Textview subview with clickable tags.
|
||||
|
||||
Reference in New Issue
Block a user