|  | @@ -13,7 +13,7 @@ these comments stick to the symlink
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  """
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -import sys,os,argparse
 | 
	
		
			
				|  |  | +import sys,os,argparse,stat
 | 
	
		
			
				|  |  |  from dirWidget import DirWidget
 | 
	
		
			
				|  |  |  from PyQt4.QtGui import *
 | 
	
		
			
				|  |  |  from PyQt4 import QtGui, QtCore
 | 
	
	
		
			
				|  | @@ -64,11 +64,20 @@ class DataBase:
 | 
	
		
			
				|  |  |  		''' TODO: convert filename to canonical '''
 | 
	
		
			
				|  |  |  		c = self.db.cursor()
 | 
	
		
			
				|  |  |  		s = os.stat(fileName)
 | 
	
		
			
				|  |  | -		print "params: %s %f %d %s %f" % ((os.path.abspath(fileName), s.st_mtime, s.st_size, comment, time.time()))
 | 
	
		
			
				|  |  | +		print "params: %s %s %d %s %s" % ((os.path.abspath(fileName), 
 | 
	
		
			
				|  |  | +				DataBase.epochToDb(s.st_mtime), s.st_size, comment, 
 | 
	
		
			
				|  |  | +				DataBase.epochToDb(time.time())))
 | 
	
		
			
				|  |  |  		c.execute("insert into dirnotes values (?,datetime(?,'unixepoch','localtime'),?,?,datetime(?,'unixepoch','localtime'))",
 | 
	
		
			
				|  |  |  			(os.path.abspath(fileName), s.st_mtime, s.st_size, str(comment), time.time()))
 | 
	
		
			
				|  |  |  		self.db.commit()
 | 
	
		
			
				|  |  | +	@staticmethod
 | 
	
		
			
				|  |  | +	def epochToDb(epoch):
 | 
	
		
			
				|  |  | +		return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(epoch))
 | 
	
		
			
				|  |  | +	@staticmethod
 | 
	
		
			
				|  |  | +	def DbToEpoch(dbTime):
 | 
	
		
			
				|  |  | +		return time.mktime(time.strptime(dbTime,"%Y-%m-%d %H:%M:%S"))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +		
 | 
	
		
			
				|  |  |  def parse():
 | 
	
		
			
				|  |  |  	parser = argparse.ArgumentParser(description='dirnotes application')
 | 
	
		
			
				|  |  |  	parser.add_argument('dirname',metavar='dirname',type=str,
 | 
	
	
		
			
				|  | @@ -86,7 +95,12 @@ def parse():
 | 
	
		
			
				|  |  |  class FileObj():
 | 
	
		
			
				|  |  |  	def __init__(self, fileName):
 | 
	
		
			
				|  |  |  		self.fileName = fileName
 | 
	
		
			
				|  |  | -		# also get the date, directory or not, etc
 | 
	
		
			
				|  |  | +		s = os.stat(fileName)
 | 
	
		
			
				|  |  | +		self.date = DataBase.epochToDb(s.st_mtime)
 | 
	
		
			
				|  |  | +		if stat.S_ISDIR(s.st_mode):
 | 
	
		
			
				|  |  | +			self.size = -1
 | 
	
		
			
				|  |  | +		else:
 | 
	
		
			
				|  |  | +			self.size = s.st_size
 | 
	
		
			
				|  |  |  		self.comment = ''
 | 
	
		
			
				|  |  |  		try:
 | 
	
		
			
				|  |  |  			self.comment = xattr.getxattr(fileName,COMMENT_KEY)
 | 
	
	
		
			
				|  | @@ -112,13 +126,17 @@ class FileObj():
 | 
	
		
			
				|  |  |  			elif "Errno 95" in str(e):
 | 
	
		
			
				|  |  |  				print("is this a VFAT or EXFAT volume? these don't allow comments")
 | 
	
		
			
				|  |  |  			return False
 | 
	
		
			
				|  |  | +	def getDate(self):
 | 
	
		
			
				|  |  | +		return self.date
 | 
	
		
			
				|  |  | +	def getSize(self):
 | 
	
		
			
				|  |  | +		return self.size
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class DirNotes(QMainWindow):
 | 
	
		
			
				|  |  |  	''' the main window of the app
 | 
	
		
			
				|  |  |  		has 3 list boxes: dir_left, dir_right (may be invisible) and files
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  |  		'''
 | 
	
		
			
				|  |  | -	def __init__(self, filename, db, parent=None):
 | 
	
		
			
				|  |  | +	def __init__(self, argFilename, db, parent=None):
 | 
	
		
			
				|  |  |  		super(DirNotes,self).__init__(parent)
 | 
	
		
			
				|  |  |  		self.db = db
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -127,7 +145,7 @@ class DirNotes(QMainWindow):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		lb = QTableWidget()
 | 
	
		
			
				|  |  |  		self.lb = lb
 | 
	
		
			
				|  |  | -		lb.setColumnCount(2)
 | 
	
		
			
				|  |  | +		lb.setColumnCount(4)
 | 
	
		
			
				|  |  |  		lb.horizontalHeader().setResizeMode( 1, QHeaderView.Stretch );
 | 
	
		
			
				|  |  |  		lb.verticalHeader().setDefaultSectionSize(20);	# thinner rows
 | 
	
		
			
				|  |  |  		lb.verticalHeader().setVisible(False)
 | 
	
	
		
			
				|  | @@ -138,38 +156,28 @@ class DirNotes(QMainWindow):
 | 
	
		
			
				|  |  |  		# allow multiple entries on the line at this point
 | 
	
		
			
				|  |  |  		#d = os.listdir(p.filename[0])
 | 
	
		
			
				|  |  |  		#d.sort()
 | 
	
		
			
				|  |  | -		current, dirs, files = os.walk(filename,followlinks=True).next()
 | 
	
		
			
				|  |  | -		dirs = map(lambda x:x+'/', dirs)
 | 
	
		
			
				|  |  | -		dirs.sort()
 | 
	
		
			
				|  |  | -		files.sort()
 | 
	
		
			
				|  |  | +		self.curPath, filename = os.path.split(argFilename)
 | 
	
		
			
				|  |  | +		print("working on <"+self.curPath+"> and <"+filename+">")
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  | -		d = dirs + files
 | 
	
		
			
				|  |  | -		lb.setRowCount(len(d))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		self.files = []
 | 
	
		
			
				|  |  | -		for i in range(len(d)):
 | 
	
		
			
				|  |  | -			this_file = FileObj(current+'/'+d[i])
 | 
	
		
			
				|  |  | -			self.files = self.files + [this_file]
 | 
	
		
			
				|  |  | -			item = QTableWidgetItem(this_file.getName())
 | 
	
		
			
				|  |  | -			item.setFlags(QtCore.Qt.ItemIsEnabled)
 | 
	
		
			
				|  |  | -			lb.setItem(i,0,item)
 | 
	
		
			
				|  |  | -			#lb.itemAt(i,0).setFlags(Qt.ItemIsEnabled) #NoItemFlags)
 | 
	
		
			
				|  |  | -			comment = this_file.getComment()
 | 
	
		
			
				|  |  | -			lb.setItem(i,1,QTableWidgetItem(comment))
 | 
	
		
			
				|  |  | -		lb.setHorizontalHeaderItem(0,QTableWidgetItem("file"))
 | 
	
		
			
				|  |  | -		lb.setHorizontalHeaderItem(1,QTableWidgetItem("comment"))
 | 
	
		
			
				|  |  | +		self.refill()
 | 
	
		
			
				|  |  | +		
 | 
	
		
			
				|  |  | +		lb.setHorizontalHeaderItem(0,QTableWidgetItem("File"))
 | 
	
		
			
				|  |  | +		lb.setHorizontalHeaderItem(1,QTableWidgetItem("Date/Time"))
 | 
	
		
			
				|  |  | +		lb.setHorizontalHeaderItem(2,QTableWidgetItem("Size"))		
 | 
	
		
			
				|  |  | +		lb.setHorizontalHeaderItem(3,QTableWidgetItem("Comment"))
 | 
	
		
			
				|  |  |  		lb.resizeColumnsToContents()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		e = QLabel("View and edit file comments stored in extended attributes user.xdg.comment",win)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		b1 = QPushButton("restore from database",win)
 | 
	
		
			
				|  |  | -		dirLeft = DirWidget(current,win)
 | 
	
		
			
				|  |  | +		self.dirLeft = dirLeft = DirWidget(self.curPath,win)
 | 
	
		
			
				|  |  |  		dirLeft.setMaximumHeight(140)
 | 
	
		
			
				|  |  |  		dirLeft.setMaximumWidth(200)
 | 
	
		
			
				|  |  | -		dirRight = DirWidget(current,win)
 | 
	
		
			
				|  |  | +		dirRight = DirWidget(self.curPath,win)
 | 
	
		
			
				|  |  |  		dirRight.setMaximumHeight(140)
 | 
	
		
			
				|  |  |  		dirRight.setMaximumWidth(200)
 | 
	
		
			
				|  |  |  		dirRight.setEnabled(False)
 | 
	
		
			
				|  |  | +		dirLeft.selected.connect(self.newDir)
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  |  		rDate = QRadioButton("Sort by date",win)
 | 
	
		
			
				|  |  |  		rSize = QRadioButton("Sort by size",win)
 | 
	
	
		
			
				|  | @@ -191,12 +199,79 @@ class DirNotes(QMainWindow):
 | 
	
		
			
				|  |  |  		lb.itemChanged.connect(self.change)
 | 
	
		
			
				|  |  |  		b1.pressed.connect(self.restore_from_database)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +		mb = self.menuBar()
 | 
	
		
			
				|  |  | +		mf = mb.addMenu('&File')
 | 
	
		
			
				|  |  | +		mf.addAction("Sort by name", self.sbn, "Ctrl+N")
 | 
	
		
			
				|  |  | +		mf.addAction("Sort by date", self.sbd, "Ctrl+D")
 | 
	
		
			
				|  |  | +		mf.addAction("Sort by size", self.sbs, "Ctrl+Z")
 | 
	
		
			
				|  |  | +		mf.addAction("Sort by comment", self.sbc, "Ctrl+.")
 | 
	
		
			
				|  |  | +		mf.addAction("Restore comment from database", self.restore_from_database, "Ctrl+R")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		QShortcut(QKeySequence("Ctrl+Q"), self, self.close)	
 | 
	
		
			
				|  |  | -		self.setWindowTitle("test")
 | 
	
		
			
				|  |  | -		self.setMinimumSize(600,400)
 | 
	
		
			
				|  |  | +		self.setWindowTitle("DirNotes")
 | 
	
		
			
				|  |  | +		self.setMinimumSize(600,700)
 | 
	
		
			
				|  |  | +		lb.setFocus()
 | 
	
		
			
				|  |  |  	def closeEvent(self,e):
 | 
	
		
			
				|  |  |  		print("closing")
 | 
	
		
			
				|  |  | +	def sbd(self):
 | 
	
		
			
				|  |  | +		print("sort by date")
 | 
	
		
			
				|  |  | +		self.lb.sortItems(1,QtCore.Qt.DescendingOrder)
 | 
	
		
			
				|  |  | +	def sbs(self):
 | 
	
		
			
				|  |  | +		print("sort by size")
 | 
	
		
			
				|  |  | +		self.lb.sortItems(2)
 | 
	
		
			
				|  |  | +	def sbn(self):
 | 
	
		
			
				|  |  | +		print("sort by name")
 | 
	
		
			
				|  |  | +		self.lb.sortItems(0)
 | 
	
		
			
				|  |  | +	def sbc(self):
 | 
	
		
			
				|  |  | +		print("sort by comment")
 | 
	
		
			
				|  |  | +		self.lb.sortItems(3,QtCore.Qt.DescendingOrder)
 | 
	
		
			
				|  |  | +	def newDir(self):
 | 
	
		
			
				|  |  | +		print("change dir to "+self.dirLeft.currentPath())
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  | +	class DnTableWidgetItem(QTableWidgetItem):
 | 
	
		
			
				|  |  | +		def __init__(self, text, value):
 | 
	
		
			
				|  |  | +			QTableWidgetItem.__init__(self, text, QTableWidgetItem.UserType)
 | 
	
		
			
				|  |  | +			self.value = value
 | 
	
		
			
				|  |  | +		def __lt__(self, other):
 | 
	
		
			
				|  |  | +			return self.value < other.value
 | 
	
		
			
				|  |  | +			
 | 
	
		
			
				|  |  | +	def refill(self):
 | 
	
		
			
				|  |  | +		small_font = QFont("",8)
 | 
	
		
			
				|  |  | +		dirIcon = QIcon.fromTheme('folder')
 | 
	
		
			
				|  |  | +		fileIcon = QIcon.fromTheme('text-x-generic')
 | 
	
		
			
				|  |  | +		current, dirs, files = os.walk(self.curPath,followlinks=True).next()
 | 
	
		
			
				|  |  | +		dirs = map(lambda x:x+'/', dirs)
 | 
	
		
			
				|  |  | +		dirs.sort()
 | 
	
		
			
				|  |  | +		files.sort()
 | 
	
		
			
				|  |  | +		
 | 
	
		
			
				|  |  | +		d = dirs + files
 | 
	
		
			
				|  |  | +		self.lb.setRowCount(len(d))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		self.files = []
 | 
	
		
			
				|  |  | +		for i in range(len(d)):
 | 
	
		
			
				|  |  | +			this_file = FileObj(current+'/'+d[i])
 | 
	
		
			
				|  |  | +			self.files = self.files + [this_file]
 | 
	
		
			
				|  |  | +			item = QTableWidgetItem(d[i])
 | 
	
		
			
				|  |  | +			item.setFlags(QtCore.Qt.ItemIsEnabled)
 | 
	
		
			
				|  |  | +			self.lb.setItem(i,0,item)
 | 
	
		
			
				|  |  | +			#lb.itemAt(i,0).setFlags(Qt.ItemIsEnabled) #NoItemFlags) 
 | 
	
		
			
				|  |  | +			comment = this_file.getComment()
 | 
	
		
			
				|  |  | +			self.lb.setItem(i,3,QTableWidgetItem(comment))
 | 
	
		
			
				|  |  | +			da = QTableWidgetItem(this_file.getDate())
 | 
	
		
			
				|  |  | +			da.setFont(small_font)
 | 
	
		
			
				|  |  | +			da.setFlags(QtCore.Qt.ItemIsEnabled)
 | 
	
		
			
				|  |  | +			self.lb.setItem(i,1,da)
 | 
	
		
			
				|  |  | +			si = this_file.getSize()
 | 
	
		
			
				|  |  | +			if si>=0:
 | 
	
		
			
				|  |  | +				sa = self.DnTableWidgetItem(str(si),si)
 | 
	
		
			
				|  |  | +				item.setIcon(fileIcon)
 | 
	
		
			
				|  |  | +			else:
 | 
	
		
			
				|  |  | +				sa = self.DnTableWidgetItem('',0)
 | 
	
		
			
				|  |  | +				item.setIcon(dirIcon)
 | 
	
		
			
				|  |  | +			sa.setTextAlignment(QtCore.Qt.AlignRight)
 | 
	
		
			
				|  |  | +			sa.setFlags(QtCore.Qt.ItemIsEnabled)
 | 
	
		
			
				|  |  | +			self.lb.setItem(i,2,sa)
 | 
	
		
			
				|  |  | +			
 | 
	
		
			
				|  |  |  	def change(self,x):
 | 
	
		
			
				|  |  |  		print("debugging " + x.text() + " r:" + str(x.row()) + " c:" + str(x.column()))
 | 
	
		
			
				|  |  |  		the_file = dn.files[x.row()]
 | 
	
	
		
			
				|  | @@ -212,12 +287,14 @@ class DirNotes(QMainWindow):
 | 
	
		
			
				|  |  |  			print(fileName,fo_row[0],comment) 
 | 
	
		
			
				|  |  |  			the_file = dn.files[self.lb.currentRow()]
 | 
	
		
			
				|  |  |  			the_file.setComment(comment)
 | 
	
		
			
				|  |  | -			self.lb.setItem(self.lb.currentRow(),1,QTableWidgetItem(comment))
 | 
	
		
			
				|  |  | +			self.lb.setItem(self.lb.currentRow(),3,QTableWidgetItem(comment))
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  |  if __name__=="__main__":
 | 
	
		
			
				|  |  |  	p = parse()
 | 
	
		
			
				|  |  |  	if p.dirname[-1]=='/':
 | 
	
		
			
				|  |  |  		p.dirname = p.dirname[:-1]
 | 
	
		
			
				|  |  | +	if os.path.isdir(p.dirname):
 | 
	
		
			
				|  |  | +		p.dirname = p.dirname + '/'
 | 
	
		
			
				|  |  |  	print(p.dirname)
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  |  	db = DataBase()
 |