bugfix #3544364 untruncated password on savefs command
buhfix #3544379 disable selection if vfat type devices featrq #3544379 add Tab Archives Infos
This commit is contained in:
parent
704d9fb0da
commit
93298ac71a
|
@ -1,15 +1,18 @@
|
||||||
GPyFSA 0.33 (2012-14-07)
|
GPyFSA 0.34 (2012-15-07)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
New General Features
|
New General Features
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
* Add Tab Archives Infos
|
||||||
* Add Archlinux Package
|
* Add Archlinux Package
|
||||||
|
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
* [#3544379] disable selection if vfat type devices
|
||||||
|
* [#3544364] untruncated password on savefs command
|
||||||
* [#3540527] images displaying
|
* [#3540527] images displaying
|
||||||
* [#3540526] application launching with strict call python2
|
* [#3540526] application launching with strict call python2
|
||||||
* [#2988575] add log file wich doesn't exist by default
|
* [#2988575] add log file wich doesn't exist by default
|
||||||
|
|
57
gpyfsa/GPyFSA/gpyfsa_about.py
Normal file
57
gpyfsa/GPyFSA/gpyfsa_about.py
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#!/usr/bin/env python2
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# #
|
||||||
|
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
||||||
|
# version : 0.34 #
|
||||||
|
# date : 2012-07-15 #
|
||||||
|
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
||||||
|
# author : a-Sansara <http://www.a-sansara.net/> #
|
||||||
|
# copyright : pluie.org <http://www.pluie.org/> #
|
||||||
|
# #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
#
|
||||||
|
# This file is part of GPyFSA.
|
||||||
|
#
|
||||||
|
# GPyFSA is free software (free as in speech) : 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 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GPyFSA 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 GPyFSA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
|
||||||
|
import gtk
|
||||||
|
import gpyfsa_conf as conf
|
||||||
|
|
||||||
|
class AboutDialog(gtk.AboutDialog):
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
gtk.AboutDialog.__init__(self)
|
||||||
|
|
||||||
|
# Set up the UI
|
||||||
|
self.__initialize_dialog_widgets()
|
||||||
|
|
||||||
|
#################### Private Methods ####################
|
||||||
|
|
||||||
|
def __initialize_dialog_widgets(self):
|
||||||
|
self.set_name(conf.APPNAME)
|
||||||
|
self.set_version(conf.APPVERSION)
|
||||||
|
self.set_copyright(conf.COPYRIGHTS)
|
||||||
|
self.set_logo(gtk.gdk.pixbuf_new_from_file(conf.SCALABLE_ICON))
|
||||||
|
self.set_translator_credits(conf.TRANSLATORS)
|
||||||
|
self.set_license(conf.LICENSE)
|
||||||
|
self.set_website(conf.WEBSITE)
|
||||||
|
self.set_website_label(conf.APPNAME)
|
||||||
|
self.set_authors(conf.AUTHORS)
|
||||||
|
self.set_artists(conf.ARTISTS)
|
||||||
|
|
||||||
|
# Show all widgets
|
||||||
|
self.show_all()
|
|
@ -3,8 +3,8 @@
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# #
|
# #
|
||||||
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
||||||
# version : 0.33 #
|
# version : 0.34 #
|
||||||
# date : 2012-07-14 #
|
# date : 2012-07-15 #
|
||||||
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
||||||
# author : a-Sansara <http://www.a-sansara.net/> #
|
# author : a-Sansara <http://www.a-sansara.net/> #
|
||||||
# copyright : pluie.org <http://www.pluie.org/> #
|
# copyright : pluie.org <http://www.pluie.org/> #
|
||||||
|
@ -33,6 +33,7 @@ def get_path(default, destination):
|
||||||
if not os.path.exists(destination):
|
if not os.path.exists(destination):
|
||||||
return os.path.abspath(default)+'/'
|
return os.path.abspath(default)+'/'
|
||||||
else:
|
else:
|
||||||
|
# print(os.path.abspath(destination)+'/')
|
||||||
return os.path.abspath(destination)+'/'
|
return os.path.abspath(destination)+'/'
|
||||||
|
|
||||||
PATH_SRC = os.path.abspath(os.path.dirname(sys.argv[0]))
|
PATH_SRC = os.path.abspath(os.path.dirname(sys.argv[0]))
|
||||||
|
@ -68,9 +69,13 @@ K_DEV_RWRIT = 8
|
||||||
####################### (K_NAME , K_NOVAL, K_SELFVAL)
|
####################### (K_NAME , K_NOVAL, K_SELFVAL)
|
||||||
SAVEOPT = (('o' , True , ),('v',True,),('d',True,),('L',False,True),('s',False,False),('e',False,False),('c',False,False),('z',False,True),('j',False,True))
|
SAVEOPT = (('o' , True , ),('v',True,),('d',True,),('L',False,True),('s',False,False),('e',False,False),('c',False,False),('z',False,True),('j',False,True))
|
||||||
K_DEV_PIX = 0
|
K_DEV_PIX = 0
|
||||||
K_DEV_ACTIVATABLE = 1
|
K_DEV_ROOT = 1
|
||||||
K_DEV_ACTIVE = 2
|
K_DEV_UNSUP = 2
|
||||||
K_DEV = 3
|
K_DEV_SUPPORT = 3
|
||||||
|
K_DEV_ACTIVATABLE = 4
|
||||||
|
K_DEV_ACTIVE = 5
|
||||||
|
K_DEV = 6
|
||||||
|
|
||||||
L_COLSNAME = ('',_('device'),_('type'),_('label'),_('size'),_('used'),_('free'),_('%used'),_('mount point'))
|
L_COLSNAME = ('',_('device'),_('type'),_('label'),_('size'),_('used'),_('free'),_('%used'),_('mount point'))
|
||||||
IMG_TV_DEVICE = PATH_IMG+'gpyfsa_dev.png'
|
IMG_TV_DEVICE = PATH_IMG+'gpyfsa_dev.png'
|
||||||
IMG_TV_DEVICE_LOCKED = PATH_IMG+'gpyfsa_devlocked.png'
|
IMG_TV_DEVICE_LOCKED = PATH_IMG+'gpyfsa_devlocked.png'
|
||||||
|
@ -79,6 +84,7 @@ K_TYPE = K_FILTER_NAME = PAGE_SAVE = 0
|
||||||
K_TITLE = K_FILTER_PATTERN = PAGE_REST = 1
|
K_TITLE = K_FILTER_PATTERN = PAGE_REST = 1
|
||||||
K_FILTER = PAGE_ARCH = 2
|
K_FILTER = PAGE_ARCH = 2
|
||||||
CBDT_SAVEFS = 'SAVE', _('Save archive') , ((_('all'),'*'),(_('fsa archive'),'*.fsa'))
|
CBDT_SAVEFS = 'SAVE', _('Save archive') , ((_('all'),'*'),(_('fsa archive'),'*.fsa'))
|
||||||
|
CBDT_ARCHFS = 'OPEN', _('Select archive') , ((_('all'),'*'),(_('fsa archive'),'*.fsa'))
|
||||||
|
|
||||||
COMPRESSION_LEVEL = ['lzo -3', 'gzip -2', 'gzip -6', 'gzip -9', 'bzip2 -2', 'bzip2 -5', 'lzma -1', 'lzma -6', 'lzma -9']
|
COMPRESSION_LEVEL = ['lzo -3', 'gzip -2', 'gzip -6', 'gzip -9', 'bzip2 -2', 'bzip2 -5', 'lzma -1', 'lzma -6', 'lzma -9']
|
||||||
|
|
||||||
|
@ -94,9 +100,35 @@ sh = Shell()
|
||||||
def getClDev(key) : return K_DEV+key
|
def getClDev(key) : return K_DEV+key
|
||||||
|
|
||||||
def getGladeXML() :
|
def getGladeXML() :
|
||||||
#print(PATH_RES+APP_NAME+'/glade/'+APP_NAME+'.glade')
|
#print(PATH_RES+APP_NAME+'/glade/'+APP_NAME+'2.glade')
|
||||||
return gtk.glade.XML(PATH_RES+APP_NAME+'/glade/'+APP_NAME+'.glade',APP_NAME)
|
return gtk.glade.XML(PATH_RES+APP_NAME+'/glade/'+APP_NAME+'2.glade',APP_NAME)
|
||||||
|
|
||||||
def chdir(path) : return os.chdir(path)
|
def chdir(path) : return os.chdir(path)
|
||||||
|
|
||||||
def getShell() : return sh
|
def getShell() : return sh
|
||||||
|
|
||||||
|
def file_get_contents(filename):
|
||||||
|
with open(filename) as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
# Application info
|
||||||
|
SCALABLE_ICON = PATH_IMG+'gpyfsa.png'
|
||||||
|
APPNAME = "GPyFSA"
|
||||||
|
APPVERSION = "0.33"
|
||||||
|
COPYRIGHTS = _("Copyright © 2010-2012 a-Sansara\n Copyright © 2010-2012 pluie.org")
|
||||||
|
WEBSITE = "https://sourceforge.net/projects/gpyfsa/"
|
||||||
|
AUTHORS = [
|
||||||
|
_('Developers:'),
|
||||||
|
'a-Sansara (http://www.a-sansara.net)',
|
||||||
|
'',
|
||||||
|
_('Contributors:'),
|
||||||
|
'Francois Dupoux for fsarchiver (http://www.fsarchiver.org/)',
|
||||||
|
]
|
||||||
|
|
||||||
|
ARTISTS = [
|
||||||
|
''
|
||||||
|
]
|
||||||
|
|
||||||
|
TRANSLATORS = _("translator-credits")
|
||||||
|
|
||||||
|
LICENSE = file_get_contents(os.path.abspath('../LICENSE'))
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# #
|
# #
|
||||||
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
||||||
# version : 0.33 #
|
# version : 0.34 #
|
||||||
# date : 2012-07-14 #
|
# date : 2012-07-15 #
|
||||||
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
||||||
# author : a-Sansara <http://www.a-sansara.net/> #
|
# author : a-Sansara <http://www.a-sansara.net/> #
|
||||||
# copyright : pluie.org <http://www.pluie.org/> #
|
# copyright : pluie.org <http://www.pluie.org/> #
|
||||||
|
@ -63,12 +63,13 @@ class DevListManager():
|
||||||
if not self.bseldev:
|
if not self.bseldev:
|
||||||
(model, miter) = self.gpyfsa['w_treedev'].get_selection().get_selected()
|
(model, miter) = self.gpyfsa['w_treedev'].get_selection().get_selected()
|
||||||
path = model.get_path(miter)
|
path = model.get_path(miter)
|
||||||
|
bunsup = model.get_value(miter, self.conf.K_DEV_UNSUP)
|
||||||
# disk expand
|
# disk expand
|
||||||
if len(path)==1 :
|
if len(path)==1 :
|
||||||
if self.gpyfsa['w_treedev'].row_expanded(path): self.gpyfsa['w_treedev'].collapse_row(path)
|
if self.gpyfsa['w_treedev'].row_expanded(path): self.gpyfsa['w_treedev'].collapse_row(path)
|
||||||
else : self.gpyfsa['w_treedev'].expand_row(path,True)
|
else : self.gpyfsa['w_treedev'].expand_row(path,True)
|
||||||
# device selection
|
# device selection
|
||||||
elif miter != None and not model.get_value(miter, self.conf.getClDev(self.conf.K_DEV_RWRIT)):
|
elif miter != None and not model.get_value(miter, self.conf.getClDev(self.conf.K_DEV_RWRIT)) and not bunsup:
|
||||||
toggled = model.get_value(miter, self.conf.K_DEV_ACTIVE)
|
toggled = model.get_value(miter, self.conf.K_DEV_ACTIVE)
|
||||||
model.set_value(miter, self.conf.K_DEV_ACTIVE, not toggled)
|
model.set_value(miter, self.conf.K_DEV_ACTIVE, not toggled)
|
||||||
self.setDevicesSelection(model.get_value(miter, self.conf.K_DEV),not toggled)
|
self.setDevicesSelection(model.get_value(miter, self.conf.K_DEV),not toggled)
|
||||||
|
@ -135,20 +136,24 @@ class DevListManager():
|
||||||
return ["/dev/%s" % k for k,v in ldev]
|
return ["/dev/%s" % k for k,v in ldev]
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def preformatStoreData(self,ldata,activatable,imgFileName,active=False):
|
def preformatStoreData(self,ldata,activatable,isRoot,imgFileName,active=False,unsupport=False):
|
||||||
ldata.insert(0,active)
|
#print(str((active,activatable,unsupport)))
|
||||||
ldata.insert(0,activatable)
|
ldata.insert(0,bool(active and not unsupport))
|
||||||
|
ldata.insert(0,bool(activatable and not unsupport))
|
||||||
|
ldata.insert(0,not unsupport and not isRoot)
|
||||||
|
ldata.insert(0,unsupport)
|
||||||
|
ldata.insert(0,isRoot)
|
||||||
ldata.insert(0,gtk.gdk.pixbuf_new_from_file(imgFileName))
|
ldata.insert(0,gtk.gdk.pixbuf_new_from_file(imgFileName))
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def getTreeStoreDevices(self,oldModel=None):
|
def getTreeStoreDevices(self,oldModel=None):
|
||||||
# ICO ACTIVATABLE ACTIVE _K_DEV_ NO READ-WRITE
|
# ICO ROOT UNSUPPORT SUPPORT ACTIVATABLE ACTIVE _K_DEV_ NO READ-WRITE UNSUPPORT
|
||||||
store = gtk.TreeStore(gtk.gdk.Pixbuf, 'gboolean', 'gboolean', str, str, str, str, str, str, str, str, 'gboolean')
|
store = gtk.TreeStore(gtk.gdk.Pixbuf, 'gboolean', 'gboolean', 'gboolean','gboolean','gboolean', str, str, str, str, str, str, str, str, 'gboolean')
|
||||||
ldev = ProbeReader(self.conf).getListDevices()
|
ldev = ProbeReader(self.conf).getListDevices()
|
||||||
|
|
||||||
for i,l in enumerate(ldev):
|
for i,l in enumerate(ldev):
|
||||||
hasntLockedDev = True
|
hasntLockedDev = True
|
||||||
self.preformatStoreData(l[self.conf.K_DISK],False,self.conf.IMG_TV_DEVICE)
|
self.preformatStoreData(l[self.conf.K_DISK],False,True,self.conf.IMG_TV_DEVICE)
|
||||||
diter = store.append(None,l[self.conf.K_DISK])
|
diter = store.append(None,l[self.conf.K_DISK])
|
||||||
for j,dev in enumerate(l[self.conf.K_DEVICE]):
|
for j,dev in enumerate(l[self.conf.K_DEVICE]):
|
||||||
imgn = self.conf.IMG_TV_DEVICE
|
imgn = self.conf.IMG_TV_DEVICE
|
||||||
|
@ -163,28 +168,35 @@ class DevListManager():
|
||||||
if oiter != None: active = oldModel.get_value(oiter,self.conf.K_DEV_ACTIVE)
|
if oiter != None: active = oldModel.get_value(oiter,self.conf.K_DEV_ACTIVE)
|
||||||
except :
|
except :
|
||||||
pass
|
pass
|
||||||
self.preformatStoreData(dev,not dev[self.conf.K_DEV_RWRIT],imgn,active)
|
bunsup = bool(dev[self.conf.K_DEV_TYPE]=="vfat")
|
||||||
|
self.preformatStoreData(dev,not dev[self.conf.K_DEV_RWRIT],False,imgn,active,bunsup)
|
||||||
# inspect later possible wrong length
|
# inspect later possible wrong length
|
||||||
store.append(diter,dev[:12])
|
|
||||||
|
if bunsup :
|
||||||
|
#print('dev[14] : '+str(dev[14]))
|
||||||
|
dev[14] = True
|
||||||
|
|
||||||
|
#print(str(dev[:15]))
|
||||||
|
store.append(diter,dev[:15])
|
||||||
return store
|
return store
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def buildTreeDevices(self):
|
def buildTreeDevices(self):
|
||||||
self.gpyfsa['w_treedev'].set_model(self.getTreeStoreDevices())
|
self.gpyfsa['w_treedev'].set_model(self.getTreeStoreDevices())
|
||||||
crtog = getNewWidget(gtk.CellRendererToggle(),(('activatable',False),('active',False)))
|
crtog = getNewWidget(gtk.CellRendererToggle(),(('activatable',True ),('active',False)))
|
||||||
crtxt = getNewWidget(gtk.CellRendererText() ,(('scale',1.0),('foreground','#6C6C6C')))
|
crtxt = getNewWidget(gtk.CellRendererText() ,(('scale',1.0),('foreground','#6C6C6C'),('background','#D4C8C8')))
|
||||||
for i,col in enumerate(self.conf.L_COLSNAME):
|
for i,col in enumerate(self.conf.L_COLSNAME):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
tvcol = gtk.TreeViewColumn(col, gtk.CellRendererPixbuf(), pixbuf=0)
|
tvcol = gtk.TreeViewColumn(col, gtk.CellRendererPixbuf(), pixbuf=0)
|
||||||
tvcol.pack_start(gtk.CellRendererPixbuf(),True)
|
tvcol.pack_start(gtk.CellRendererPixbuf(),True)
|
||||||
tvcol.pack_start(crtog,True)
|
tvcol.pack_start(crtog,True)
|
||||||
tvcol.set_attributes(crtog, active=self.conf.K_DEV_ACTIVE, visible=self.conf.K_DEV_ACTIVATABLE)
|
tvcol.set_attributes(crtog, active=self.conf.K_DEV_ACTIVE, sensitive=self.conf.K_DEV_ACTIVATABLE, visible=self.conf.K_DEV_SUPPORT)
|
||||||
tvcol.set_clickable(True)
|
tvcol.set_clickable(True)
|
||||||
insertWidget(self.gpyfsa['w_refresh_devices'],tvcol)
|
insertWidget(self.gpyfsa['w_refresh_devices'],tvcol)
|
||||||
else :
|
else :
|
||||||
tvcol = gtk.TreeViewColumn(col)
|
tvcol = gtk.TreeViewColumn(col)
|
||||||
tvcol.pack_start(crtxt,True)
|
tvcol.pack_start(crtxt,True)
|
||||||
tvcol.set_attributes(crtxt, text=i+2, foreground_set=self.conf.getClDev(self.conf.K_DEV_RWRIT))
|
tvcol.set_attributes(crtxt, text=i+5, background_set=self.conf.K_DEV_UNSUP,foreground_set=self.conf.getClDev(self.conf.K_DEV_RWRIT))
|
||||||
self.gpyfsa['w_treedev'].append_column(tvcol)
|
self.gpyfsa['w_treedev'].append_column(tvcol)
|
||||||
|
|
||||||
self.gpyfsa['w_treedev'].set_rules_hint(True)
|
self.gpyfsa['w_treedev'].set_rules_hint(True)
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# #
|
# #
|
||||||
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
||||||
# version : 0.33 #
|
# version : 0.34 #
|
||||||
# date : 2012-07-14 #
|
# date : 2012-07-15 #
|
||||||
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
||||||
# author : a-Sansara <http://www.a-sansara.net/> #
|
# author : a-Sansara <http://www.a-sansara.net/> #
|
||||||
# copyright : pluie.org <http://www.pluie.org/> #
|
# copyright : pluie.org <http://www.pluie.org/> #
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# #
|
# #
|
||||||
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
||||||
# version : 0.33 #
|
# version : 0.34 #
|
||||||
# date : 2012-07-14 #
|
# date : 2012-07-15 #
|
||||||
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
||||||
# author : a-Sansara <http://www.a-sansara.net/> #
|
# author : a-Sansara <http://www.a-sansara.net/> #
|
||||||
# copyright : pluie.org <http://www.pluie.org/> #
|
# copyright : pluie.org <http://www.pluie.org/> #
|
||||||
|
@ -38,10 +38,12 @@ except:
|
||||||
import gtk, pango, re #, thread, threading
|
import gtk, pango, re #, thread, threading
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from gpyfsa_devlistmanager import DevListManager
|
from gpyfsa_devlistmanager import DevListManager
|
||||||
|
from gpyfsa_about import AboutDialog
|
||||||
import gpyfsa_conf as conf
|
import gpyfsa_conf as conf
|
||||||
import gpyfsa_ui as ui
|
import gpyfsa_ui as ui
|
||||||
import gpyfsa_fsa as fsa
|
import gpyfsa_fsa as fsa
|
||||||
|
|
||||||
|
|
||||||
#gtk.gdk.threads_init()
|
#gtk.gdk.threads_init()
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
@ -49,6 +51,7 @@ class GPyFSA(gtk.Window):
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def bugFix_GladeComboBoxEntry(self):
|
def bugFix_GladeComboBoxEntry(self):
|
||||||
|
# save tab
|
||||||
self.w_saveArchiveHistory,combo,browse = gtk.combo_box_entry_new_text(),self.xml.get_widget('w_saveArchiveHistory'),self['w_saveArchiveBrowse']
|
self.w_saveArchiveHistory,combo,browse = gtk.combo_box_entry_new_text(),self.xml.get_widget('w_saveArchiveHistory'),self['w_saveArchiveBrowse']
|
||||||
self['w_saveArchiveHistory'].set_model(gtk.ListStore(str))
|
self['w_saveArchiveHistory'].set_model(gtk.ListStore(str))
|
||||||
box = browse.get_parent()
|
box = browse.get_parent()
|
||||||
|
@ -56,6 +59,14 @@ class GPyFSA(gtk.Window):
|
||||||
box.remove(browse)
|
box.remove(browse)
|
||||||
box.pack_start(self['w_saveArchiveHistory'],True,True,0)
|
box.pack_start(self['w_saveArchiveHistory'],True,True,0)
|
||||||
box.pack_start(browse,False,False,0)
|
box.pack_start(browse,False,False,0)
|
||||||
|
# archive tab
|
||||||
|
self.w_infoArchiveHistory,combo1,browse1 = gtk.combo_box_entry_new_text(),self.xml.get_widget('w_infoArchiveHistory'),self['w_infoArchiveBrowse']
|
||||||
|
self['w_infoArchiveHistory'].set_model(gtk.ListStore(str))
|
||||||
|
box1 = browse1.get_parent()
|
||||||
|
box1.remove(combo1)
|
||||||
|
box1.remove(browse1)
|
||||||
|
box1.pack_start(self['w_infoArchiveHistory'],True,True,0)
|
||||||
|
box1.pack_start(browse1,False,False,0)
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def cleaningSaveFS(self):
|
def cleaningSaveFS(self):
|
||||||
|
@ -66,6 +77,13 @@ class GPyFSA(gtk.Window):
|
||||||
self.timer = 0
|
self.timer = 0
|
||||||
if self.pfsa.poll()==0: self['w_nb_savefs'].set_current_page(0)
|
if self.pfsa.poll()==0: self['w_nb_savefs'].set_current_page(0)
|
||||||
|
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
def evt_aboutDialogActivate(self, widget):
|
||||||
|
about = AboutDialog()
|
||||||
|
ret = about.run()
|
||||||
|
about.destroy()
|
||||||
|
return ret
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def checkCleaningSaveFS(self):
|
def checkCleaningSaveFS(self):
|
||||||
self.endTime+=100
|
self.endTime+=100
|
||||||
|
@ -78,6 +96,15 @@ class GPyFSA(gtk.Window):
|
||||||
self.endSaveFSTime = 500
|
self.endSaveFSTime = 500
|
||||||
self.timer = ui.setTimeout(100, ui.endSaveFS, self.cleaningSaveFS, self.checkCleaningSaveFS, self['w_progress_savefs'])
|
self.timer = ui.setTimeout(100, ui.endSaveFS, self.cleaningSaveFS, self.checkCleaningSaveFS, self['w_progress_savefs'])
|
||||||
|
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
def terminateArchInfos(self):
|
||||||
|
ui.clearTimeout(self.timer)
|
||||||
|
self.endTime = 0
|
||||||
|
buff = self['w_info_log'].get_buffer();
|
||||||
|
content = conf.file_get_contents(conf.PATH_LOG)
|
||||||
|
buff.set_text(content)
|
||||||
|
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def switchControlSaveFS(self,active):
|
def switchControlSaveFS(self,active):
|
||||||
self['w_nb_savefs'].set_show_tabs(True)
|
self['w_nb_savefs'].set_show_tabs(True)
|
||||||
|
@ -102,13 +129,31 @@ class GPyFSA(gtk.Window):
|
||||||
def evt_setArchivePath(self,path):
|
def evt_setArchivePath(self,path):
|
||||||
self.archivePath = path.rpartition('/')
|
self.archivePath = path.rpartition('/')
|
||||||
if(self.archivePath[2]!=""):conf.chdir(self.archivePath[0])
|
if(self.archivePath[2]!=""):conf.chdir(self.archivePath[0])
|
||||||
|
if(self['w_notebook'].get_current_page() == self['w_notebook'].page_num(self['frame_save'])):
|
||||||
self['w_saveArchiveHistory'].insert_text(0, path)
|
self['w_saveArchiveHistory'].insert_text(0, path)
|
||||||
self['w_saveArchiveHistory'].set_active(0)
|
self['w_saveArchiveHistory'].set_active(0)
|
||||||
|
elif(self['w_notebook'].get_current_page() == self['w_notebook'].page_num(self['frame_archive'])):
|
||||||
|
self['w_infoArchiveHistory'].insert_text(0, path)
|
||||||
|
self['w_infoArchiveHistory'].set_active(0)
|
||||||
|
self.switchStateArchInfos()
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def evt_editComboBoxEntry(self,txt):
|
def evt_editComboBoxEntry(self,txt):
|
||||||
self['w_savefs'].set_sensitive(bool(self.dlm.dicseldev and txt and self.checkPassword(None,None,False)))
|
self['w_savefs'].set_sensitive(bool(self.dlm.dicseldev and txt and self.checkPassword(None,None,False)))
|
||||||
|
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
def evt_archInfos(self,widget):
|
||||||
|
buff = self['w_info_log'].get_buffer();
|
||||||
|
path = self['w_infoArchiveHistory'].get_model().get_value(self['w_infoArchiveHistory'].get_active_iter(),0)
|
||||||
|
self.archivePath = path.rpartition('/')
|
||||||
|
cmd = ['fsarchiver','archinfo',path]
|
||||||
|
if self['w_infopass'].get_active():
|
||||||
|
cmd.append('-c'+self['w_infopass_value'].get_text())
|
||||||
|
self.logFile.close()
|
||||||
|
self.logFile = open(conf.PATH_LOG, 'w')
|
||||||
|
self.pfsa = conf.getShell().call(cmd,self.logFile,False)
|
||||||
|
self.timer = ui.setTimeout(100, ui.waitTimeout, self.terminateArchInfos, self.checkProgressAborting, (self.logReader,))
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def evt_saveFS(self,widget):
|
def evt_saveFS(self,widget):
|
||||||
cmd = ui.buildFsaOptions(self,conf)
|
cmd = ui.buildFsaOptions(self,conf)
|
||||||
|
@ -122,8 +167,9 @@ class GPyFSA(gtk.Window):
|
||||||
self['w_saveArchiveHistory'].get_model().set_value(self['w_saveArchiveHistory'].get_active_iter(), 0, path)
|
self['w_saveArchiveHistory'].get_model().set_value(self['w_saveArchiveHistory'].get_active_iter(), 0, path)
|
||||||
cmd.append(path)
|
cmd.append(path)
|
||||||
cmd.extend(self.dlm.getSortedSelDevList())
|
cmd.extend(self.dlm.getSortedSelDevList())
|
||||||
pcmd = cmd
|
pcmd = list(cmd)
|
||||||
if self.tmp!=0: pcmd[self.tmp] = "-c"+re.sub(r".","*",pcmd[self.tmp][2:])
|
if self.tmp!=0:
|
||||||
|
pcmd[self.tmp] = "-c"+re.sub(r".","*",pcmd[self.tmp][2:])
|
||||||
del self.tmp
|
del self.tmp
|
||||||
self.logReader.clear("\n"+" ".join(pcmd)+"\n\n")
|
self.logReader.clear("\n"+" ".join(pcmd)+"\n\n")
|
||||||
self.logReader.setVerbooseMode(self['w_fsaOpt_v'].get_active())
|
self.logReader.setVerbooseMode(self['w_fsaOpt_v'].get_active())
|
||||||
|
@ -159,6 +205,15 @@ class GPyFSA(gtk.Window):
|
||||||
aiter = self['w_saveArchiveHistory'].get_active_iter()
|
aiter = self['w_saveArchiveHistory'].get_active_iter()
|
||||||
if(aiter != None): self['w_savefs'].set_sensitive(bool(self.dlm.dicseldev and self['w_saveArchiveHistory'].get_model().get_value(aiter,0) and password))
|
if(aiter != None): self['w_savefs'].set_sensitive(bool(self.dlm.dicseldev and self['w_saveArchiveHistory'].get_model().get_value(aiter,0) and password))
|
||||||
|
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
def switchStateArchInfos(self, data=None):
|
||||||
|
password = True
|
||||||
|
if self['w_infopass'].get_active():
|
||||||
|
pass1 = self['w_infopass_value'].get_text()
|
||||||
|
password = bool(len(pass1)>5 and len(pass1)<65)
|
||||||
|
aiter = self['w_infoArchiveHistory'].get_active_iter()
|
||||||
|
if(aiter != None): self['w_archinfo'].set_sensitive(bool(self['w_infoArchiveHistory'].get_model().get_value(aiter,0) and password))
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def setCompressionStore(self):
|
def setCompressionStore(self):
|
||||||
liststore = gtk.ListStore(int, str)
|
liststore = gtk.ListStore(int, str)
|
||||||
|
@ -175,6 +230,9 @@ class GPyFSA(gtk.Window):
|
||||||
self['w_log'].modify_base(gtk.STATE_NORMAL,gtk.gdk.color_parse('#2E3436'))
|
self['w_log'].modify_base(gtk.STATE_NORMAL,gtk.gdk.color_parse('#2E3436'))
|
||||||
self['w_log'].modify_text(gtk.STATE_NORMAL,gtk.gdk.color_parse('#FFF7BA'))
|
self['w_log'].modify_text(gtk.STATE_NORMAL,gtk.gdk.color_parse('#FFF7BA'))
|
||||||
self['w_log'].modify_font(pango.FontDescription("Liberation mono normal 10"))
|
self['w_log'].modify_font(pango.FontDescription("Liberation mono normal 10"))
|
||||||
|
self['w_info_log'].modify_base(gtk.STATE_NORMAL,gtk.gdk.color_parse('#2E3436'))
|
||||||
|
self['w_info_log'].modify_text(gtk.STATE_NORMAL,gtk.gdk.color_parse('#FFF7BA'))
|
||||||
|
self['w_info_log'].modify_font(pango.FontDescription("Liberation mono normal 10"))
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def checkPassword(self,widget=None,data=None,testRefresh=True):
|
def checkPassword(self,widget=None,data=None,testRefresh=True):
|
||||||
|
@ -207,11 +265,19 @@ class GPyFSA(gtk.Window):
|
||||||
self['w_savefs'].connect('clicked', self.evt_saveFS)
|
self['w_savefs'].connect('clicked', self.evt_saveFS)
|
||||||
self['w_cancel_savefs'].connect('clicked', self.evt_cancelSaveFS)
|
self['w_cancel_savefs'].connect('clicked', self.evt_cancelSaveFS)
|
||||||
self['gpyfsa'].connect("delete_event", gtk.main_quit)
|
self['gpyfsa'].connect("delete_event", gtk.main_quit)
|
||||||
|
dic = {"on_aboutDialog_activate" : self.evt_aboutDialogActivate }
|
||||||
|
self.xml.signal_autoconnect(dic)
|
||||||
|
self['w_infoArchiveBrowse'].connect("clicked", self.evt_browseFile, conf.CBDT_ARCHFS, self.evt_setArchivePath)
|
||||||
|
self['w_infopass'].connect("toggled", ui.setSensitivity , (self['w_infopass_value']))
|
||||||
|
self['w_infopass'].connect("toggled", self.switchStateArchInfos )
|
||||||
|
self['w_archinfo'].connect('clicked', self.evt_archInfos)
|
||||||
|
self['w_infopass_value'].connect("changed", self.switchStateArchInfos)
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
# # # # > BUG FIX ! see bugFix_GladeComboBoxEntry() # # # #
|
# # # # > BUG FIX ! see bugFix_GladeComboBoxEntry() # # # #
|
||||||
if key == 'w_saveArchiveHistory': return self.w_saveArchiveHistory
|
if key == 'w_saveArchiveHistory' : return self.w_saveArchiveHistory
|
||||||
|
if key == 'w_infoArchiveHistory': return self.w_infoArchiveHistory
|
||||||
# # # # < BUG FIX # # # # # # # # # # # # # # # # # # # # #
|
# # # # < BUG FIX # # # # # # # # # # # # # # # # # # # # #
|
||||||
return self.xml.get_widget(key)
|
return self.xml.get_widget(key)
|
||||||
|
|
||||||
|
@ -231,6 +297,7 @@ class GPyFSA(gtk.Window):
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def main():
|
def main():
|
||||||
GPyFSA()
|
GPyFSA()
|
||||||
|
gtk.window_set_default_icon_list(gtk.gdk.pixbuf_new_from_file(conf.SCALABLE_ICON))
|
||||||
gtk.main()
|
gtk.main()
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# #
|
# #
|
||||||
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
||||||
# version : 0.33 #
|
# version : 0.34 #
|
||||||
# date : 2012-07-14 #
|
# date : 2012-07-15 #
|
||||||
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
||||||
# author : a-Sansara <http://www.a-sansara.net/> #
|
# author : a-Sansara <http://www.a-sansara.net/> #
|
||||||
# copyright : pluie.org <http://www.pluie.org/> #
|
# copyright : pluie.org <http://www.pluie.org/> #
|
||||||
|
|
|
@ -50,7 +50,9 @@ class Shell:
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def __call(self,cmd,stdoe=subp.PIPE,fdsClose=False):
|
def __call(self,cmd,stdoe=subp.PIPE,fdsClose=False):
|
||||||
p = None
|
p = None
|
||||||
if self.authCmd.has_key(cmd[0]): p = subp.Popen(cmd, stdout=stdoe, stderr=stdoe, close_fds=fdsClose)
|
if self.authCmd.has_key(cmd[0]):
|
||||||
|
print cmd[0]+' auth => '+str(cmd)
|
||||||
|
p = subp.Popen(cmd, stdout=stdoe, stderr=stdoe, close_fds=fdsClose)
|
||||||
return p
|
return p
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# #
|
# #
|
||||||
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
||||||
# version : 0.33 #
|
# version : 0.34 #
|
||||||
# date : 2012-07-14 #
|
# date : 2012-07-15 #
|
||||||
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
||||||
# author : a-Sansara <http://www.a-sansara.net/> #
|
# author : a-Sansara <http://www.a-sansara.net/> #
|
||||||
# copyright : pluie.org <http://www.pluie.org/> #
|
# copyright : pluie.org <http://www.pluie.org/> #
|
||||||
|
@ -113,6 +113,7 @@ def buildFsaOptions(gpyfsa,conf):
|
||||||
if opt[conf.K_NAME]=="c": gpyfsa.tmp = len(cmd)
|
if opt[conf.K_NAME]=="c": gpyfsa.tmp = len(cmd)
|
||||||
if not noAdd : noAdd = v.strip() == ''
|
if not noAdd : noAdd = v.strip() == ''
|
||||||
if not noAdd : cmd.append('-'+opt[conf.K_NAME]+v)
|
if not noAdd : cmd.append('-'+opt[conf.K_NAME]+v)
|
||||||
|
print(str(cmd))
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
@ -141,6 +142,18 @@ def progressTimeout(callBack, clearCallback, fsaLogReader, progressbar, msgWait=
|
||||||
if not progress : callBack()
|
if not progress : callBack()
|
||||||
return progress
|
return progress
|
||||||
|
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
def waitTimeout(callBack, clearCallback, fsaLogReader):
|
||||||
|
progress = not clearCallback()
|
||||||
|
if not progress : callBack()
|
||||||
|
return progress
|
||||||
|
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
def endArchInfos(callBack,clearCallback):
|
||||||
|
bnotclear = not clearCallback()
|
||||||
|
if(bnotclear):callBack()
|
||||||
|
return bnotclear
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
def endSaveFS(callBack,clearCallback,progressbar):
|
def endSaveFS(callBack,clearCallback,progressbar):
|
||||||
progressbar.pulse()
|
progressbar.pulse()
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# #
|
# #
|
||||||
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
||||||
# version : 0.33 #
|
# version : 0.34 #
|
||||||
# date : 2012-07-14 #
|
# date : 2012-07-15 #
|
||||||
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
||||||
# author : a-Sansara <http://www.a-sansara.net/> #
|
# author : a-Sansara <http://www.a-sansara.net/> #
|
||||||
# copyright : pluie.org <http://www.pluie.org/> #
|
# copyright : pluie.org <http://www.pluie.org/> #
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=GPyFSA
|
Name=GPyFSA
|
||||||
Comment=GUI front end of fsarchiver with mounting facilities
|
Comment=GUI front end of fsarchiver with mounting facilities
|
||||||
Version=0.33
|
Version=0.34
|
||||||
Icon=gpyfsa
|
Icon=gpyfsa
|
||||||
Exec=gpyfsa
|
Exec=gpyfsa
|
||||||
Terminal=false
|
Terminal=false
|
||||||
|
|
1099
gpyfsa/resources/gpyfsa/glade/gpyfsa-0.33.glade
Normal file
1099
gpyfsa/resources/gpyfsa/glade/gpyfsa-0.33.glade
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -3,8 +3,8 @@
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# #
|
# #
|
||||||
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
# software : GPyFSA <http://gpyfsa.sourceforge.net/> #
|
||||||
# version : 0.33 #
|
# version : 0.34 #
|
||||||
# date : 2012-07-14 #
|
# date : 2012-07-15 #
|
||||||
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
# licence : GPLv3.0 <http://www.gnu.org/licenses/> #
|
||||||
# author : a-Sansara <http://www.a-sansara.net/> #
|
# author : a-Sansara <http://www.a-sansara.net/> #
|
||||||
# copyright : pluie.org <http://www.pluie.org/> #
|
# copyright : pluie.org <http://www.pluie.org/> #
|
||||||
|
|
Loading…
Reference in New Issue
Block a user