|
@@ -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()
|