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

Legacy, working version. Several patches included to conform new format of the DB

This commit is contained in:
2012-02-18 18:49:45 +01:00
parent c2926c96d6
commit 1424ce9c86
6 changed files with 156 additions and 61 deletions

31
README
View File

@@ -1,5 +1,5 @@
pyGTKtalog 1.0
==================
==============
pyGTKtalog is Linux/FreeBSD program for indexing CD/DVD or directories on
filesystem. It is similar to gtktalog <http://www.nongnu.org/gtktalog/> or
@@ -75,6 +75,7 @@ There are still minor aims for versions 1.x to be done:
- implement advanced search
For version 2.0:
- Export/Import
- Icon grid in files view
- command line support: query, adding media to collection etc
- internationalization
@@ -82,7 +83,8 @@ For version 2.0:
- user definied group of tags (represented by color in cloud tag)
- hiding specified files - configurable, like dot prefixed, cfg and manualy
selected
- tests
- warning about existing image in media directory
Removed:
- filetypes handling (movies, images, archives, documents etc). Now it have
common, unified external "plugin" system - simple text output from command
@@ -103,17 +105,22 @@ Removed:
NOTES
=====
Catalog file is tared and gziped sqlite database and directories with images and
thumbnails. If there are more images, the size of catalog file will grow. So be
carefull with adding big images in your catalog file!
Catalog file is plain sqlite database (optionally compressed with bzip2). All
images are stored in ~/.pygtktalog/images directory. Names for images are
generated sha512 hash from image file itself. There is small possibility for two
identical hash for different image files. However, no images are overwritten.
Thumbnail filename for each image is simply concatenation of image filename in
images directory and '_t' string.
There is also converter form old database to new. In fact no image are stored in
archive with katalog. All thumnails will be lost. All images without big image
will be lost. There ar serious changes with application design, and I decided,
that is better to keep media unpacked on disk, instead of pack it every time
with save and unpack with open methods. New design prevent from deleting eny
file from media directory (placed in ~/.pygtktalog/images). Functionality for
exporting images and corresponding db file is planned.
There is also converter from old database to new for internal use only. In
public release there will be no other formats so it will be useless, and
deleted. There are some issues with converting. All thumbnails will be lost. All
images without big image will be lost. There are serious changes with
application design, and I decided, that is better to keep media unpacked on
disk, instead of pack it every time with save and unpack with open methods. New
design prevent from deleting any file from media directory (placed in
~/.pygtktalog/images). Functionality for exporting images and corresponding db
file is planned.
BUGS
====

View File

@@ -64,13 +64,17 @@ def check_requirements():
pass
try:
from pysqlite2 import dbapi2 as sqlite
import sqlite3 as sqlite
except ImportError:
print "pyGTKtalog uses SQLite DB.\nYou'll need to get it and the",
print "python bindings as well.",
print "http://www.sqlite.org"
print "http://initd.org/tracker/pysqlite"
sys.exit(1)
try:
from pysqlite2 import dbapi2 as sqlite
except ImportError:
print "pyGTKtalog uses SQLite DB.\nYou'll need to get it and the",
print "python bindings as well.",
print "http://www.sqlite.org"
print "http://initd.org/tracker/pysqlite"
print "Alternatively install python 2.5 or higher"
sys.exit(1)
if conf.confd['exportxls']:
try:

View File

@@ -62,6 +62,27 @@
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="import">
<property name="visible">True</property>
<property name="label" translatable="yes">Import</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_import_activate"/>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="export">
<property name="visible">True</property>
<property name="label" translatable="yes">Export</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_export_activate"/>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator13">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="recent_files1">
<property name="visible">True</property>

View File

@@ -22,9 +22,9 @@
# -------------------------------------------------------------------------
__version__ = "1.0 RC2"
LICENCE = open('LICENCE').read()
__version__ = "1.0.1"
#LICENCE = open('LICENCE').read()
LICENCE = ''
import os.path
from os import popen
from utils import deviceHelper
@@ -871,6 +871,25 @@ class MainController(Controller):
self.view['discs'].expand_all()
return
def on_export_activate(self, menu_item):
"""export db file and coressponding images to tar.bz2 archive"""
dialog = Dialogs.ChooseFilename(None, "Choose export file")
filepath = dialog.run()
if not filepath:
return
list_of_paths = self.view['images'].get_selected_items()
model = self.view['images'].get_model()
count = 0
if len(list_of_paths) == 0:
# no picture was selected. default to save all of them
for image in model:
if self.model.save_image(image[0], filepath):
count += 1
def on_collapse_all1_activate(self, menu_item):
self.view['discs'].collapse_all()
return
@@ -1579,7 +1598,10 @@ class MainController(Controller):
buf.insert_with_tags(buf.get_end_iter(), "Filename: ", tag)
buf.insert(buf.get_end_iter(), set['filename'] + "\n")
buf.insert_with_tags(buf.get_end_iter(), "Date: ", tag)
buf.insert(buf.get_end_iter(), str(set['fileinfo']['date']) + "\n")
try:
buf.insert(buf.get_end_iter(), str(set['fileinfo']['date']) + "\n")
except:
import ipdb; ipdb.set_trace()
buf.insert_with_tags(buf.get_end_iter(), "Size: ", tag)
buf.insert(buf.get_end_iter(), str(set['fileinfo']['size']) + "\n")

View File

@@ -23,11 +23,9 @@
# -------------------------------------------------------------------------
from shutil import copy
from os import path, mkdir
from os import path
from hashlib import sha512
from tempfile import mkstemp
from utils import EXIF
import Image
class Img(object):
@@ -53,7 +51,8 @@ class Img(object):
# check wheter image already exists
if path.exists(image_filename) and path.exists(thumbnail):
if __debug__:
print "image", self.filename, "with hash", self.sha512, "already exist"
print "image", self.filename, "with hash",
print self.sha512, "already exist"
return self.sha512
if not path.exists(thumbnail):

View File

@@ -45,10 +45,11 @@ class Qst(object):
def run(self):
retval = self.dialog.run()
self.dialog.destroy()
retval = False
if retval == gtk.RESPONSE_OK:
return True
return False
retval = True
self.dialog.destroy()
return retval
class Inf(object):
"""Show simple dialog for notices"""
@@ -139,10 +140,11 @@ class InputDiskLabel(object):
entry = gladexml.get_widget("volname")
entry.set_text(self.label)
result = dialog.run()
dialog.destroy()
res = None
if result == gtk.RESPONSE_OK:
return entry.get_text()
return None
res = entry.get_text()
dialog.destroy()
return res
class InputNewName(object):
"""Sepcific dialog for quering user for a disc label"""
@@ -158,10 +160,11 @@ class InputNewName(object):
entry = gladexml.get_widget("name")
entry.set_text(self.name)
result = dialog.run()
dialog.destroy()
res = None
if result == gtk.RESPONSE_OK:
return entry.get_text()
return None
res = entry.get_text()
dialog.destroy()
return res
class PointDirectoryToAdd(object):
"""Sepcific dialog for quering user for selecting directory to add"""
@@ -206,7 +209,7 @@ class PointDirectoryToAdd(object):
ch = True
result = dialog.run()
while ch:
if result == gtk.RESPONSE_OK and (self.volname.get_text()=='' or \
if result == gtk.RESPONSE_OK and (self.volname.get_text() == '' or \
self.directory.get_text() == ''):
a = Err("Error - pyGTKtalog",
"There are fields needed to be filled.",
@@ -215,11 +218,15 @@ class PointDirectoryToAdd(object):
result = dialog.run()
else:
ch = False
dialog.destroy()
volname = self.volname.get_text()
directory = self.directory.get_text()
res = (None,None)
if result == gtk.RESPONSE_OK:
return self.volname.get_text(),self.directory.get_text()
else:
return None,None
res = (volname, directory)
dialog.destroy()
return res
class SelectDirectory(object):
"""Sepcific dialog for quering user for selecting directory to add"""
@@ -257,15 +264,15 @@ class SelectDirectory(object):
dialog.destroy()
return retval
class ChooseDBFilename(object):
"""Sepcific dialog for quering user for selecting filename for database"""
class ChooseFilename(object):
"""Dialog for quering user for selecting filename"""
URI=None
def __init__(self, path=None):
def __init__(self, path=None, title=''):
self.path = path
self.dialog = gtk.FileChooserDialog(
title="Save catalog as...",
title="",
action=gtk.FILE_CHOOSER_ACTION_SAVE,
buttons=(
gtk.STOCK_CANCEL,
@@ -276,7 +283,44 @@ class ChooseDBFilename(object):
self.dialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
self.dialog.set_default_response(gtk.RESPONSE_OK)
self.dialog.set_do_overwrite_confirmation(True)
self.dialog.set_title('Save catalog to file...')
self.dialog.set_title(title)
f = gtk.FileFilter()
f.set_name("Catalog files")
f.add_pattern("*.sqlite")
f.add_pattern("*.sqlite.bz2")
self.dialog.add_filter(f)
f = gtk.FileFilter()
f.set_name("All files")
f.add_pattern("*.*")
self.dialog.add_filter(f)
def run(self):
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)
response = self.dialog.run()
if response == gtk.RESPONSE_OK:
filename = self.dialog.get_filename()
self.__class__.URI = self.dialog.get_current_folder_uri()
self.dialog.destroy()
return filename
else:
self.dialog.destroy()
return None
pass
class ChooseDBFilename(ChooseFilename):
"""Sepcific dialog for quering user for selecting filename for database"""
URI=None
def __init__(self, path=None):
ChooseFilename.__init__(self)
self.dialog.set_title('Save catalog as...')
f = gtk.FileFilter()
f.set_name("Catalog files")
@@ -298,11 +342,6 @@ class ChooseDBFilename(object):
response = self.dialog.run()
if response == gtk.RESPONSE_OK:
filename = self.dialog.get_filename()
print filename, ' do ',
if filename[-11:].lower() != '.sqlite.bz2' and \
filename[-7:].lower() != '.sqlite':
filename = filename + '.sqlite.bz2'
print filename
self.__class__.URI = self.dialog.get_current_folder_uri()
self.dialog.destroy()
return filename
@@ -488,10 +527,11 @@ class StatsDialog(object):
entry.set_text(str(self.values['size']))
result = dialog.run()
dialog.destroy()
retval = None
if result == gtk.RESPONSE_OK:
return entry.get_text()
return None
retval = entry.get_text()
dialog.destroy()
return retval
class TagsDialog(object):
"""Sepcific dialog for display stats"""
@@ -507,10 +547,11 @@ class TagsDialog(object):
result = dialog.run()
dialog.destroy()
retval = None
if result == gtk.RESPONSE_OK:
return entry.get_text()
return None
retval = entry.get_text()
dialog.destroy()
return retval
class TagsRemoveDialog(object):
"""Sepcific dialog for display stats"""
@@ -572,14 +613,15 @@ class TagsRemoveDialog(object):
result = dialog.run()
dialog.destroy()
retval = (None, None)
if result == gtk.RESPONSE_OK:
ids = []
for i in model:
if i[2]:
ids.append(i[0])
return "ok", ids
return None, None
retval = ("ok", ids)
dialog.destroy()
return retval
class EditDialog(object):
"""Sepcific dialog for display stats"""