mirror of
https://github.com/gryf/pygtktalog.git
synced 2025-12-17 11:30:19 +01:00
* Lots of changes, code cleanup, import/export in GUI.
This commit is contained in:
31
README
31
README
@@ -1,5 +1,5 @@
|
|||||||
pyGTKtalog 1.0
|
pyGTKtalog 1.0
|
||||||
==================
|
==============
|
||||||
|
|
||||||
pyGTKtalog is Linux/FreeBSD program for indexing CD/DVD or directories on
|
pyGTKtalog is Linux/FreeBSD program for indexing CD/DVD or directories on
|
||||||
filesystem. It is similar to gtktalog <http://www.nongnu.org/gtktalog/> or
|
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
|
- implement advanced search
|
||||||
|
|
||||||
For version 2.0:
|
For version 2.0:
|
||||||
|
- Export/Import
|
||||||
- Icon grid in files view
|
- Icon grid in files view
|
||||||
- command line support: query, adding media to collection etc
|
- command line support: query, adding media to collection etc
|
||||||
- internationalization
|
- internationalization
|
||||||
@@ -82,7 +83,8 @@ For version 2.0:
|
|||||||
- user definied group of tags (represented by color in cloud tag)
|
- user definied group of tags (represented by color in cloud tag)
|
||||||
- hiding specified files - configurable, like dot prefixed, cfg and manualy
|
- hiding specified files - configurable, like dot prefixed, cfg and manualy
|
||||||
selected
|
selected
|
||||||
|
- tests
|
||||||
|
- warning about existing image in media directory
|
||||||
Removed:
|
Removed:
|
||||||
- filetypes handling (movies, images, archives, documents etc). Now it have
|
- filetypes handling (movies, images, archives, documents etc). Now it have
|
||||||
common, unified external "plugin" system - simple text output from command
|
common, unified external "plugin" system - simple text output from command
|
||||||
@@ -103,17 +105,22 @@ Removed:
|
|||||||
NOTES
|
NOTES
|
||||||
=====
|
=====
|
||||||
|
|
||||||
Catalog file is tared and gziped sqlite database and directories with images and
|
Catalog file is plain sqlite database (optionally compressed with bzip2). All
|
||||||
thumbnails. If there are more images, the size of catalog file will grow. So be
|
images are stored in ~/.pygtktalog/images directory. Names for images are
|
||||||
carefull with adding big images in your catalog file!
|
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
|
There is also converter from old database to new for internal use only. In
|
||||||
archive with katalog. All thumnails will be lost. All images without big image
|
public release there will be no other formats so it will be useless, and
|
||||||
will be lost. There ar serious changes with application design, and I decided,
|
deleted. There are some issues with converting. All thumbnails will be lost. All
|
||||||
that is better to keep media unpacked on disk, instead of pack it every time
|
images without big image will be lost. There are serious changes with
|
||||||
with save and unpack with open methods. New design prevent from deleting eny
|
application design, and I decided, that is better to keep media unpacked on
|
||||||
file from media directory (placed in ~/.pygtktalog/images). Functionality for
|
disk, instead of pack it every time with save and unpack with open methods. New
|
||||||
exporting images and corresponding db file is planned.
|
design prevent from deleting any file from media directory (placed in
|
||||||
|
~/.pygtktalog/images). Functionality for exporting images and corresponding db
|
||||||
|
file is planned.
|
||||||
|
|
||||||
BUGS
|
BUGS
|
||||||
====
|
====
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ def setup_path():
|
|||||||
"""Sets up the python include paths to include needed directories"""
|
"""Sets up the python include paths to include needed directories"""
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
from src.utils.globals import TOPDIR
|
from src.lib.globs import TOPDIR
|
||||||
sys.path = [os.path.join(TOPDIR, "src")] + sys.path
|
sys.path = [os.path.join(TOPDIR, "src")] + sys.path
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
from shutil import copy
|
from shutil import copy
|
||||||
|
|
||||||
from utils.img import Img
|
from lib.img import Img
|
||||||
from models.m_main import MainModel as NewModel
|
from models.m_main import MainModel as NewModel
|
||||||
|
|
||||||
model = OldModel()
|
model = OldModel()
|
||||||
|
|||||||
@@ -27,18 +27,16 @@ try:
|
|||||||
import gtk
|
import gtk
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "You need to install pyGTK v2.10.x or newer."
|
print "You need to install pyGTK v2.10.x or newer."
|
||||||
sys.exit(1)
|
raise
|
||||||
|
|
||||||
|
|
||||||
def setup_path():
|
def setup_path():
|
||||||
"""Sets up the python include paths to include needed directories"""
|
"""Sets up the python include paths to include needed directories"""
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
from src.utils.globals import TOPDIR
|
from src.lib.globs import TOPDIR
|
||||||
sys.path = [os.path.join(TOPDIR, "src")] + sys.path
|
sys.path = [os.path.join(TOPDIR, "src")] + sys.path
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def check_requirements():
|
def check_requirements():
|
||||||
"""Checks versions and other requirements"""
|
"""Checks versions and other requirements"""
|
||||||
import sys
|
import sys
|
||||||
@@ -50,7 +48,7 @@ def check_requirements():
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
print "Some fundamental files are missing.",
|
print "Some fundamental files are missing.",
|
||||||
print "Try runnig pyGTKtalog in his root directory"
|
print "Try runnig pyGTKtalog in his root directory"
|
||||||
sys.exit(1)
|
raise
|
||||||
|
|
||||||
conf = ConfigModel()
|
conf = ConfigModel()
|
||||||
conf.load()
|
conf.load()
|
||||||
@@ -63,6 +61,9 @@ def check_requirements():
|
|||||||
#Some distributions come with GTK2, but not pyGTK
|
#Some distributions come with GTK2, but not pyGTK
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
import sqlite3 as sqlite
|
||||||
|
except ImportError:
|
||||||
try:
|
try:
|
||||||
from pysqlite2 import dbapi2 as sqlite
|
from pysqlite2 import dbapi2 as sqlite
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -70,7 +71,8 @@ def check_requirements():
|
|||||||
print "python bindings as well.",
|
print "python bindings as well.",
|
||||||
print "http://www.sqlite.org"
|
print "http://www.sqlite.org"
|
||||||
print "http://initd.org/tracker/pysqlite"
|
print "http://initd.org/tracker/pysqlite"
|
||||||
sys.exit(1)
|
print "Alternatively install python 2.5 or higher"
|
||||||
|
raise
|
||||||
|
|
||||||
if conf.confd['exportxls']:
|
if conf.confd['exportxls']:
|
||||||
try:
|
try:
|
||||||
@@ -98,7 +100,7 @@ if __name__ == "__main__":
|
|||||||
os.chdir(libraries_dir)
|
os.chdir(libraries_dir)
|
||||||
|
|
||||||
setup_path()
|
setup_path()
|
||||||
check_requirements()
|
#check_requirements()
|
||||||
|
|
||||||
from models.m_main import MainModel
|
from models.m_main import MainModel
|
||||||
from ctrls.c_main import MainController
|
from ctrls.c_main import MainController
|
||||||
@@ -113,6 +115,6 @@ if __name__ == "__main__":
|
|||||||
try:
|
try:
|
||||||
gtk.main()
|
gtk.main()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
model.config.save()
|
#model.config.save()
|
||||||
model.cleanup()
|
#model.cleanup()
|
||||||
gtk.main_quit
|
gtk.main_quit
|
||||||
|
|||||||
@@ -62,6 +62,27 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</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>
|
<child>
|
||||||
<widget class="GtkMenuItem" id="recent_files1">
|
<widget class="GtkMenuItem" id="recent_files1">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|||||||
@@ -22,27 +22,26 @@
|
|||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
__version__ = "1.0 RC2"
|
|
||||||
LICENCE = open('LICENCE').read()
|
LICENCE = open('LICENCE').read()
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
from os import popen
|
from os import popen
|
||||||
from utils import deviceHelper
|
|
||||||
from gtkmvc import Controller
|
|
||||||
|
|
||||||
from c_config import ConfigController
|
|
||||||
from views.v_config import ConfigView
|
|
||||||
|
|
||||||
from c_search import SearchController
|
|
||||||
from views.v_search import SearchView
|
|
||||||
|
|
||||||
import views.v_dialogs as Dialogs
|
|
||||||
|
|
||||||
from views.v_image import ImageView
|
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
import pango
|
import pango
|
||||||
|
|
||||||
|
from gtkmvc import Controller
|
||||||
|
|
||||||
|
from lib import device_helper
|
||||||
|
from lib.globs import APPL_VERSION
|
||||||
|
from c_config import ConfigController
|
||||||
|
from views.v_config import ConfigView
|
||||||
|
from c_search import SearchController
|
||||||
|
from views.v_search import SearchView
|
||||||
|
import views.v_dialogs as Dialogs
|
||||||
|
from views.v_image import ImageView
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MainController(Controller):
|
class MainController(Controller):
|
||||||
"""Controller for main application window"""
|
"""Controller for main application window"""
|
||||||
scan_cd = False
|
scan_cd = False
|
||||||
@@ -526,9 +525,9 @@ class MainController(Controller):
|
|||||||
|
|
||||||
def on_add_cd_activate(self, widget, label=None, current_id=None):
|
def on_add_cd_activate(self, widget, label=None, current_id=None):
|
||||||
"""Add directory structure from cd/dvd disc"""
|
"""Add directory structure from cd/dvd disc"""
|
||||||
mount = deviceHelper.volmount(self.model.config.confd['cd'])
|
mount = device_helper.volmount(self.model.config.confd['cd'])
|
||||||
if mount == 'ok':
|
if mount == 'ok':
|
||||||
guessed_label = deviceHelper.volname(self.model.config.confd['cd'])
|
guessed_label = device_helper.volname(self.model.config.confd['cd'])
|
||||||
if not label:
|
if not label:
|
||||||
label = Dialogs.InputDiskLabel(guessed_label).run()
|
label = Dialogs.InputDiskLabel(guessed_label).run()
|
||||||
if label:
|
if label:
|
||||||
@@ -541,7 +540,7 @@ class MainController(Controller):
|
|||||||
self.model.unsaved_project = True
|
self.model.unsaved_project = True
|
||||||
self.__set_title(filepath=self.model.filename, modified=True)
|
self.__set_title(filepath=self.model.filename, modified=True)
|
||||||
else:
|
else:
|
||||||
deviceHelper.volumount(self.model.config.confd['cd'])
|
device_helper.volumount(self.model.config.confd['cd'])
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
Dialogs.Wrn("Error mounting device - pyGTKtalog",
|
Dialogs.Wrn("Error mounting device - pyGTKtalog",
|
||||||
@@ -571,7 +570,7 @@ class MainController(Controller):
|
|||||||
# NOTE: about
|
# NOTE: about
|
||||||
def on_about1_activate(self, widget):
|
def on_about1_activate(self, widget):
|
||||||
"""Show about dialog"""
|
"""Show about dialog"""
|
||||||
Dialogs.Abt("pyGTKtalog", __version__, "About",
|
Dialogs.Abt("pyGTKtalog", "%d.%d.%d" % APPL_VERSION, "About",
|
||||||
["Roman 'gryf' Dobosz"], LICENCE)
|
["Roman 'gryf' Dobosz"], LICENCE)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -871,6 +870,16 @@ class MainController(Controller):
|
|||||||
self.view['discs'].expand_all()
|
self.view['discs'].expand_all()
|
||||||
return
|
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
|
||||||
|
|
||||||
|
# TODO: dokończyć ten shit
|
||||||
|
|
||||||
def on_collapse_all1_activate(self, menu_item):
|
def on_collapse_all1_activate(self, menu_item):
|
||||||
self.view['discs'].collapse_all()
|
self.view['discs'].collapse_all()
|
||||||
return
|
return
|
||||||
@@ -1354,7 +1363,7 @@ class MainController(Controller):
|
|||||||
# umount/eject cd
|
# umount/eject cd
|
||||||
ejectapp = self.model.config.confd['ejectapp']
|
ejectapp = self.model.config.confd['ejectapp']
|
||||||
if self.model.config.confd['eject'] and ejectapp:
|
if self.model.config.confd['eject'] and ejectapp:
|
||||||
msg = deviceHelper.eject_cd(ejectapp,
|
msg = device_helper.eject_cd(ejectapp,
|
||||||
self.model.config.confd['cd'])
|
self.model.config.confd['cd'])
|
||||||
if msg != 'ok':
|
if msg != 'ok':
|
||||||
Dialogs.Wrn("error ejecting device - pyGTKtalog",
|
Dialogs.Wrn("error ejecting device - pyGTKtalog",
|
||||||
@@ -1362,7 +1371,7 @@ class MainController(Controller):
|
|||||||
self.model.config.confd['cd'],
|
self.model.config.confd['cd'],
|
||||||
"Last eject message:\n%s" % msg)
|
"Last eject message:\n%s" % msg)
|
||||||
else:
|
else:
|
||||||
msg = deviceHelper.volumount(self.model.config.confd['cd'])
|
msg = device_helper.volumount(self.model.config.confd['cd'])
|
||||||
if msg != 'ok':
|
if msg != 'ok':
|
||||||
Dialogs.Wrn("error unmounting device - pyGTKtalog",
|
Dialogs.Wrn("error unmounting device - pyGTKtalog",
|
||||||
"Cannot unmount device pointed to %s" %
|
"Cannot unmount device pointed to %s" %
|
||||||
|
|||||||
@@ -21,91 +21,71 @@
|
|||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
"""
|
|
||||||
device (cd, dvd) helper
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
def volname(mntp):
|
def volname(mntp):
|
||||||
"""read volume name from cd/dvd"""
|
"""read volume name from cd/dvd"""
|
||||||
dev = mountpoint_to_dev(mntp)
|
dev = mountpoint_to_dev(mntp)
|
||||||
if dev != None:
|
if dev != None:
|
||||||
try:
|
try:
|
||||||
a = open(dev,"rb")
|
disk = open(dev, "rb")
|
||||||
a.seek(32808)
|
disk.seek(32808)
|
||||||
b = a.read(32).strip()
|
label = disk.read(32).strip()
|
||||||
a.close()
|
disk.close()
|
||||||
except:
|
except IOError:
|
||||||
return None
|
return None
|
||||||
return b
|
return label
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def volmount(mntp):
|
def volmount(mntp):
|
||||||
"""mount device, return 'ok' or error message"""
|
"""mount device, return 'ok' or error message"""
|
||||||
_in, _out, _err = os.popen3("mount %s" % mntp)
|
_in, _out, _err = os.popen3("mount %s" % mntp)
|
||||||
inf = _err.readlines()
|
inf = _err.readlines()
|
||||||
if len(inf) > 0:
|
if len(inf) > 0:
|
||||||
for i in inf:
|
return inf[0].strip()
|
||||||
i.strip()
|
|
||||||
return i
|
|
||||||
else:
|
else:
|
||||||
return 'ok'
|
return 'ok'
|
||||||
|
|
||||||
|
|
||||||
def volumount(mntp):
|
def volumount(mntp):
|
||||||
"""mount device, return 'ok' or error message"""
|
"""mount device, return 'ok' or error message"""
|
||||||
_in, _out, _err = os.popen3("umount %s" % mntp)
|
_in, _out, _err = os.popen3("umount %s" % mntp)
|
||||||
inf = _err.readlines()
|
inf = _err.readlines()
|
||||||
if len(inf) > 0:
|
if len(inf) > 0:
|
||||||
for error in inf:
|
return inf[0].strip()
|
||||||
error.strip()
|
|
||||||
|
|
||||||
if error.strip()[:7] == 'umount:':
|
|
||||||
return error.strip()
|
|
||||||
return 'ok'
|
return 'ok'
|
||||||
|
|
||||||
|
|
||||||
def check_mount(dev):
|
def check_mount(dev):
|
||||||
"""Refresh the entries from fstab or mount."""
|
"""Refresh the entries from fstab or mount."""
|
||||||
mounts = os.popen('mount')
|
mounts = os.popen('mount')
|
||||||
for line in mounts.readlines():
|
for line in mounts.readlines():
|
||||||
parts = line.split()
|
parts = line.split()
|
||||||
device, txt1, mount_point, txt2, filesystem, options = parts
|
device = parts
|
||||||
if device == dev:
|
if device[0] == dev:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def mountpoint_to_dev(mntp):
|
def mountpoint_to_dev(mntp):
|
||||||
"""guess mountpoint from fstab"""
|
"""guess device name by mountpoint from fstab"""
|
||||||
fstab = open("/etc/fstab")
|
fstab = open("/etc/fstab")
|
||||||
|
device = None
|
||||||
for line in fstab.readlines():
|
for line in fstab.readlines():
|
||||||
a = line.split()
|
output = line.split()
|
||||||
try:
|
# lengtht of single valid fstab line is at least 5
|
||||||
if a[1] == mntp and a[0][0] != '#':
|
if len(output) > 5 and output[1] == mntp and output[0][0] != '#':
|
||||||
fstab.close()
|
device = output[0]
|
||||||
return a[0]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
fstab.close()
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
fstab.close()
|
||||||
|
return device
|
||||||
|
|
||||||
def eject_cd(eject_app, cd):
|
def eject_cd(eject_app, cdrom):
|
||||||
"""mount device, return 'ok' or error message"""
|
"""mount device, return 'ok' or error message"""
|
||||||
if len(eject_app) > 0:
|
if len(eject_app) > 0:
|
||||||
_in,_out,_err = os.popen3("%s %s" % (eject_app, cd))
|
_in, _out, _err = os.popen3("%s %s" % (eject_app, cdrom))
|
||||||
inf = _err.readlines()
|
inf = _err.readlines()
|
||||||
error = ''
|
|
||||||
|
|
||||||
for error in inf:
|
if len(inf) > 0 and inf[0].strip() != '':
|
||||||
error.strip()
|
return inf[0].strip()
|
||||||
|
|
||||||
if error !='':
|
|
||||||
return error
|
|
||||||
|
|
||||||
return 'ok'
|
return 'ok'
|
||||||
return "Eject program not specified"
|
return "Eject program not specified"
|
||||||
@@ -25,15 +25,17 @@
|
|||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if sys.argv[0]: top_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
|
if sys.argv[0]:
|
||||||
else: top_dir = "."
|
top_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||||
|
else:
|
||||||
|
top_dir = "."
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
TOPDIR = top_dir
|
TOPDIR = top_dir
|
||||||
RESOURCES_DIR = os.path.join(TOPDIR, "resources")
|
RESOURCES_DIR = os.path.join(TOPDIR, "resources")
|
||||||
GLADE_DIR = os.path.join(RESOURCES_DIR, "glade")
|
GLADE_DIR = os.path.join(RESOURCES_DIR, "glade")
|
||||||
STYLES_DIR = os.path.join(RESOURCES_DIR, "styles")
|
STYLES_DIR = os.path.join(RESOURCES_DIR, "styles")
|
||||||
APPL_SHORT_NAME = "pycolector"
|
APPL_SHORT_NAME = "pygtktalog2"
|
||||||
APPL_VERSION = (1, 0, 0)
|
APPL_VERSION = (1, 0, 1)
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -23,11 +23,9 @@
|
|||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
from shutil import copy
|
from shutil import copy
|
||||||
from os import path, mkdir
|
from os import path
|
||||||
from hashlib import sha512
|
from hashlib import sha512
|
||||||
from tempfile import mkstemp
|
|
||||||
|
|
||||||
from utils import EXIF
|
|
||||||
import Image
|
import Image
|
||||||
|
|
||||||
class Img(object):
|
class Img(object):
|
||||||
@@ -53,7 +51,8 @@ class Img(object):
|
|||||||
# check wheter image already exists
|
# check wheter image already exists
|
||||||
if path.exists(image_filename) and path.exists(thumbnail):
|
if path.exists(image_filename) and path.exists(thumbnail):
|
||||||
if __debug__:
|
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
|
return self.sha512
|
||||||
|
|
||||||
if not path.exists(thumbnail):
|
if not path.exists(thumbnail):
|
||||||
@@ -28,7 +28,7 @@ from shutil import move
|
|||||||
from os import path
|
from os import path
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from utils import EXIF
|
from lib import EXIF
|
||||||
import Image
|
import Image
|
||||||
|
|
||||||
class Thumbnail(object):
|
class Thumbnail(object):
|
||||||
@@ -34,21 +34,25 @@ import gobject
|
|||||||
|
|
||||||
from gtkmvc.model_mt import ModelMT
|
from gtkmvc.model_mt import ModelMT
|
||||||
|
|
||||||
|
try:
|
||||||
|
import sqlite3 as sqlite
|
||||||
|
except ImportError:
|
||||||
from pysqlite2 import dbapi2 as sqlite
|
from pysqlite2 import dbapi2 as sqlite
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
import threading as _threading
|
import threading as _threading
|
||||||
|
|
||||||
from m_config import ConfigModel
|
from m_config import ConfigModel
|
||||||
try:
|
try:
|
||||||
from utils.thumbnail import Thumbnail
|
from lib.thumbnail import Thumbnail
|
||||||
from utils.img import Img
|
from lib.img import Img
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
from utils.parse_exif import ParseExif
|
from lib.parse_exif import ParseExif
|
||||||
from utils.gthumb import GthumbCommentParser
|
from lib.gthumb import GthumbCommentParser
|
||||||
|
|
||||||
from utils.no_thumb import no_thumb as no_thumb_img
|
from lib.no_thumb import no_thumb as no_thumb_img
|
||||||
|
|
||||||
class MainModel(ModelMT):
|
class MainModel(ModelMT):
|
||||||
"""Create, load, save, manipulate db file which is container for data"""
|
"""Create, load, save, manipulate db file which is container for data"""
|
||||||
@@ -592,6 +596,14 @@ class MainModel(ModelMT):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if filename:
|
if filename:
|
||||||
|
if not '.sqlite' in filename:
|
||||||
|
filename += '.sqlite'
|
||||||
|
else:
|
||||||
|
filename = filename[:filename.rindex('.sqlite')] + '.sqlite'
|
||||||
|
|
||||||
|
if self.config.confd['compress']:
|
||||||
|
filename += '.bz2'
|
||||||
|
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
val, err = self.__compress_and_save()
|
val, err = self.__compress_and_save()
|
||||||
if not val:
|
if not val:
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
# This Python file uses the following encoding: utf-8
|
|
||||||
#
|
|
||||||
# Author: Roman 'gryf' Dobosz gryf@elysium.pl
|
|
||||||
#
|
|
||||||
# Copyright (C) 2007 by Roman 'gryf' Dobosz
|
|
||||||
#
|
|
||||||
# This file is part of pyGTKtalog.
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
|
||||||
"""
|
|
||||||
device (cd, dvd) helper
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def volname(mntp):
|
|
||||||
"""read volume name from cd/dvd"""
|
|
||||||
dev = mountpoint_to_dev(mntp)
|
|
||||||
if dev != None:
|
|
||||||
try:
|
|
||||||
a = open(dev,"rb")
|
|
||||||
a.seek(32808)
|
|
||||||
b = a.read(32).strip()
|
|
||||||
a.close()
|
|
||||||
except:
|
|
||||||
return None
|
|
||||||
return b
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def volmount(mntp):
|
|
||||||
"""mount device, return 'ok' or error message"""
|
|
||||||
_in,_out,_err = os.popen3("mount %s" % mntp)
|
|
||||||
inf = _err.readlines()
|
|
||||||
if len(inf) > 0:
|
|
||||||
for i in inf:
|
|
||||||
i.strip()
|
|
||||||
return i
|
|
||||||
else:
|
|
||||||
return 'ok'
|
|
||||||
|
|
||||||
|
|
||||||
def volumount(mntp):
|
|
||||||
"""mount device, return 'ok' or error message"""
|
|
||||||
_in,_out,_err = os.popen3("umount %s" % mntp)
|
|
||||||
inf = _err.readlines()
|
|
||||||
if len(inf) > 0:
|
|
||||||
for error in inf:
|
|
||||||
error.strip()
|
|
||||||
|
|
||||||
if error.strip()[:7] == 'umount:':
|
|
||||||
return error.strip()
|
|
||||||
return 'ok'
|
|
||||||
|
|
||||||
|
|
||||||
def check_mount(dev):
|
|
||||||
"""Refresh the entries from fstab or mount."""
|
|
||||||
mounts = os.popen('mount')
|
|
||||||
for line in mounts.readlines():
|
|
||||||
parts = line.split()
|
|
||||||
device, txt1, mount_point, txt2, filesystem, options = parts
|
|
||||||
if device == dev:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def mountpoint_to_dev(mntp):
|
|
||||||
"""guess mountpoint from fstab"""
|
|
||||||
fstab = open("/etc/fstab")
|
|
||||||
for line in fstab.readlines():
|
|
||||||
a = line.split()
|
|
||||||
try:
|
|
||||||
if a[1] == mntp and a[0][0] != '#':
|
|
||||||
fstab.close()
|
|
||||||
return a[0]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
fstab.close()
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def eject_cd(eject_app, cd):
|
|
||||||
"""mount device, return 'ok' or error message"""
|
|
||||||
if len(eject_app) > 0:
|
|
||||||
_in,_out,_err = os.popen3("%s %s" % (eject_app, cd))
|
|
||||||
inf = _err.readlines()
|
|
||||||
error = ''
|
|
||||||
|
|
||||||
for error in inf:
|
|
||||||
error.strip()
|
|
||||||
|
|
||||||
if error !='':
|
|
||||||
return error
|
|
||||||
|
|
||||||
return 'ok'
|
|
||||||
return "Eject program not specified"
|
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@
|
|||||||
|
|
||||||
from gtkmvc import View
|
from gtkmvc import View
|
||||||
import os.path
|
import os.path
|
||||||
import utils.globals
|
import lib.globs
|
||||||
|
|
||||||
class ConfigView(View):
|
class ConfigView(View):
|
||||||
"""Preferences window from glade file """
|
"""Preferences window from glade file """
|
||||||
GLADE = os.path.join(utils.globals.GLADE_DIR, "config.glade")
|
GLADE = os.path.join(lib.globs.GLADE_DIR, "config.glade")
|
||||||
|
|
||||||
def __init__(self, ctrl):
|
def __init__(self, ctrl):
|
||||||
View.__init__(self, ctrl, self.GLADE)
|
View.__init__(self, ctrl, self.GLADE)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
import gtk
|
import gtk
|
||||||
import gobject
|
import gobject
|
||||||
import os
|
import os
|
||||||
import utils.globals
|
import lib.globs
|
||||||
|
|
||||||
class Qst(object):
|
class Qst(object):
|
||||||
"""Show simple dialog for questions
|
"""Show simple dialog for questions
|
||||||
@@ -128,7 +128,7 @@ class InputDiskLabel(object):
|
|||||||
"""Sepcific dialog for quering user for a disc label"""
|
"""Sepcific dialog for quering user for a disc label"""
|
||||||
|
|
||||||
def __init__(self, label=""):
|
def __init__(self, label=""):
|
||||||
self.gladefile = os.path.join(utils.globals.GLADE_DIR, "dialogs.glade")
|
self.gladefile = os.path.join(lib.globs.GLADE_DIR, "dialogs.glade")
|
||||||
self.label = ""
|
self.label = ""
|
||||||
if label!= None:
|
if label!= None:
|
||||||
self.label = label
|
self.label = label
|
||||||
@@ -148,7 +148,7 @@ class InputNewName(object):
|
|||||||
"""Sepcific dialog for quering user for a disc label"""
|
"""Sepcific dialog for quering user for a disc label"""
|
||||||
|
|
||||||
def __init__(self, name=""):
|
def __init__(self, name=""):
|
||||||
self.gladefile = os.path.join(utils.globals.GLADE_DIR, "dialogs.glade")
|
self.gladefile = os.path.join(lib.globs.GLADE_DIR, "dialogs.glade")
|
||||||
self.label = ""
|
self.label = ""
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ class PointDirectoryToAdd(object):
|
|||||||
URI="file://"+os.path.abspath(os.path.curdir)
|
URI="file://"+os.path.abspath(os.path.curdir)
|
||||||
|
|
||||||
def __init__(self,volname='',dirname=''):
|
def __init__(self,volname='',dirname=''):
|
||||||
self.gladefile = os.path.join(utils.globals.GLADE_DIR, "dialogs.glade")
|
self.gladefile = os.path.join(lib.globs.GLADE_DIR, "dialogs.glade")
|
||||||
self.gladexml = gtk.glade.XML(self.gladefile, "addDirDialog")
|
self.gladexml = gtk.glade.XML(self.gladefile, "addDirDialog")
|
||||||
self.volname = self.gladexml.get_widget("dirvolname")
|
self.volname = self.gladexml.get_widget("dirvolname")
|
||||||
self.volname.set_text(volname)
|
self.volname.set_text(volname)
|
||||||
@@ -257,15 +257,15 @@ class SelectDirectory(object):
|
|||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
class ChooseDBFilename(object):
|
class ChooseFilename(object):
|
||||||
"""Sepcific dialog for quering user for selecting filename for database"""
|
"""Dialog for quering user for selecting filename"""
|
||||||
|
|
||||||
URI=None
|
URI=None
|
||||||
|
|
||||||
def __init__(self, path=None):
|
def __init__(self, path=None, title=''):
|
||||||
self.path = path
|
self.path = path
|
||||||
self.dialog = gtk.FileChooserDialog(
|
self.dialog = gtk.FileChooserDialog(
|
||||||
title="Save catalog as...",
|
title="",
|
||||||
action=gtk.FILE_CHOOSER_ACTION_SAVE,
|
action=gtk.FILE_CHOOSER_ACTION_SAVE,
|
||||||
buttons=(
|
buttons=(
|
||||||
gtk.STOCK_CANCEL,
|
gtk.STOCK_CANCEL,
|
||||||
@@ -276,7 +276,44 @@ class ChooseDBFilename(object):
|
|||||||
self.dialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
|
self.dialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||||
self.dialog.set_default_response(gtk.RESPONSE_OK)
|
self.dialog.set_default_response(gtk.RESPONSE_OK)
|
||||||
self.dialog.set_do_overwrite_confirmation(True)
|
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 = gtk.FileFilter()
|
||||||
f.set_name("Catalog files")
|
f.set_name("Catalog files")
|
||||||
@@ -298,11 +335,6 @@ class ChooseDBFilename(object):
|
|||||||
response = self.dialog.run()
|
response = self.dialog.run()
|
||||||
if response == gtk.RESPONSE_OK:
|
if response == gtk.RESPONSE_OK:
|
||||||
filename = self.dialog.get_filename()
|
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.__class__.URI = self.dialog.get_current_folder_uri()
|
||||||
self.dialog.destroy()
|
self.dialog.destroy()
|
||||||
return filename
|
return filename
|
||||||
@@ -454,7 +486,7 @@ class StatsDialog(object):
|
|||||||
"""Sepcific dialog for display stats"""
|
"""Sepcific dialog for display stats"""
|
||||||
|
|
||||||
def __init__(self, values={}):
|
def __init__(self, values={}):
|
||||||
self.gladefile = os.path.join(utils.globals.GLADE_DIR, "dialogs.glade")
|
self.gladefile = os.path.join(lib.globs.GLADE_DIR, "dialogs.glade")
|
||||||
self.values = values
|
self.values = values
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -497,7 +529,7 @@ class TagsDialog(object):
|
|||||||
"""Sepcific dialog for display stats"""
|
"""Sepcific dialog for display stats"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.gladefile = os.path.join(utils.globals.GLADE_DIR, "dialogs.glade")
|
self.gladefile = os.path.join(lib.globs.GLADE_DIR, "dialogs.glade")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
gladexml = gtk.glade.XML(self.gladefile, "tagsDialog")
|
gladexml = gtk.glade.XML(self.gladefile, "tagsDialog")
|
||||||
@@ -516,7 +548,7 @@ class TagsRemoveDialog(object):
|
|||||||
"""Sepcific dialog for display stats"""
|
"""Sepcific dialog for display stats"""
|
||||||
|
|
||||||
def __init__(self, tag_dict=None):
|
def __init__(self, tag_dict=None):
|
||||||
self.gladefile = os.path.join(utils.globals.GLADE_DIR, "dialogs.glade")
|
self.gladefile = os.path.join(lib.globs.GLADE_DIR, "dialogs.glade")
|
||||||
self.tag_dict = tag_dict
|
self.tag_dict = tag_dict
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -585,7 +617,7 @@ class EditDialog(object):
|
|||||||
"""Sepcific dialog for display stats"""
|
"""Sepcific dialog for display stats"""
|
||||||
|
|
||||||
def __init__(self, values={}):
|
def __init__(self, values={}):
|
||||||
self.gladefile = os.path.join(utils.globals.GLADE_DIR, "dialogs.glade")
|
self.gladefile = os.path.join(lib.globs.GLADE_DIR, "dialogs.glade")
|
||||||
self.values = values
|
self.values = values
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|||||||
@@ -23,14 +23,14 @@
|
|||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
import utils.globals
|
import lib.globs
|
||||||
from gtkmvc import View
|
from gtkmvc import View
|
||||||
|
|
||||||
class MainView(View):
|
class MainView(View):
|
||||||
"""This handles only the graphical representation of the
|
"""This handles only the graphical representation of the
|
||||||
application. The widgets set is loaded from glade file"""
|
application. The widgets set is loaded from glade file"""
|
||||||
|
|
||||||
GLADE = os.path.join(utils.globals.GLADE_DIR, "main.glade")
|
GLADE = os.path.join(lib.globs.GLADE_DIR, "main.glade")
|
||||||
|
|
||||||
def __init__(self, ctrl):
|
def __init__(self, ctrl):
|
||||||
View.__init__(self, ctrl, self.GLADE)
|
View.__init__(self, ctrl, self.GLADE)
|
||||||
|
|||||||
@@ -24,12 +24,12 @@
|
|||||||
|
|
||||||
from gtkmvc import View
|
from gtkmvc import View
|
||||||
import os.path
|
import os.path
|
||||||
import utils.globals
|
import lib.globs
|
||||||
|
|
||||||
class SearchView(View):
|
class SearchView(View):
|
||||||
"""Search window from glade file """
|
"""Search window from glade file """
|
||||||
|
|
||||||
GLADE = os.path.join(utils.globals.GLADE_DIR, "search.glade")
|
GLADE = os.path.join(lib.globs.GLADE_DIR, "search.glade")
|
||||||
|
|
||||||
def __init__(self, ctrl):
|
def __init__(self, ctrl):
|
||||||
View.__init__(self, ctrl, self.GLADE)
|
View.__init__(self, ctrl, self.GLADE)
|
||||||
|
|||||||
Reference in New Issue
Block a user