|
@@ -16,6 +16,30 @@ where possible, comments are duplicated in
|
|
|
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
+
|
|
|
|
+helpMsg = """<h1>Dirnotes</h1><h3>Overview</h3>
|
|
|
|
+This app allows you to add comments to files. The comments are stored in
|
|
|
|
+a database, and where possible, saved in the xattr (hidden attributes)
|
|
|
|
+field of the file system.
|
|
|
|
+<p>
|
|
|
|
+You can sort the directory listing by clicking on the column heading.
|
|
|
|
+<p>
|
|
|
|
+Double click on directory names to navigate the file system. Hover over
|
|
|
|
+fields for more information.
|
|
|
|
+<p>
|
|
|
|
+<h3>xattr extended attributes</h3>
|
|
|
|
+The xattr property is handy, but suffers from a few problems:
|
|
|
|
+<ul>
|
|
|
|
+<li>is not implemented on FAT/VFAT/EXFAT file systems (like USB sticks)
|
|
|
|
+<li>xattrs are not (by default) copied with the file when it's duplicated
|
|
|
|
+or backedup
|
|
|
|
+<li>xattrs are not available for symlinks
|
|
|
|
+<li>many programs which edit files do not preserve the xattrs during file-save
|
|
|
|
+</ul>
|
|
|
|
+When the database version of a comment differs from the xattr version, the
|
|
|
|
+comment box gets a light yellow background.
|
|
|
|
+"""
|
|
|
|
+
|
|
import sys,os,argparse,stat
|
|
import sys,os,argparse,stat
|
|
#~ from dirWidget import DirWidget
|
|
#~ from dirWidget import DirWidget
|
|
from PyQt4.QtGui import *
|
|
from PyQt4.QtGui import *
|
|
@@ -131,18 +155,20 @@ class FileObj():
|
|
self.size = s.st_size
|
|
self.size = s.st_size
|
|
self.comment = ''
|
|
self.comment = ''
|
|
try:
|
|
try:
|
|
- self.comment = xattr.getxattr(fileName,COMMENT_KEY)
|
|
|
|
|
|
+ self.comment = xattr.get(fileName,COMMENT_KEY,nofollow=True)
|
|
except Exception as e:
|
|
except Exception as e:
|
|
- #print("comment read on %s failed, execption %s" % (self.fileName,e))
|
|
|
|
|
|
+ print("comment read on %s failed, execption %s" % (self.fileName,e))
|
|
pass
|
|
pass
|
|
def getName(self):
|
|
def getName(self):
|
|
return self.fileName
|
|
return self.fileName
|
|
|
|
+ def getFileName(self):
|
|
|
|
+ return os.path.split(self.fileName)[1]
|
|
def getComment(self):
|
|
def getComment(self):
|
|
return self.comment
|
|
return self.comment
|
|
def setComment(self,newComment):
|
|
def setComment(self,newComment):
|
|
self.comment = newComment
|
|
self.comment = newComment
|
|
try:
|
|
try:
|
|
- xattr.setxattr(self.fileName,COMMENT_KEY,self.comment)
|
|
|
|
|
|
+ xattr.set(self.fileName,COMMENT_KEY,self.comment,nofollow=True)
|
|
return True
|
|
return True
|
|
# we need to move these cases out to a handler
|
|
# we need to move these cases out to a handler
|
|
except Exception as e:
|
|
except Exception as e:
|
|
@@ -169,18 +195,8 @@ class HelpWidget(QDialog):
|
|
self.layout = QVBoxLayout(self)
|
|
self.layout = QVBoxLayout(self)
|
|
self.tb = QLabel(self)
|
|
self.tb = QLabel(self)
|
|
self.tb.setWordWrap(True)
|
|
self.tb.setWordWrap(True)
|
|
- msg = """<h1>Overview</h1>
|
|
|
|
-This app allows you to add comments to files. The comments are stored in
|
|
|
|
-a database, and where possible, saved in the xattr (hidden attributes)
|
|
|
|
-field of the file system.
|
|
|
|
-<p>
|
|
|
|
-You can sort the directory listing by clicking on the column heading.
|
|
|
|
-<p>
|
|
|
|
-The small box at the top left lets you navigate the directory listings.
|
|
|
|
-
|
|
|
|
-"""
|
|
|
|
- self.tb.setText(msg)
|
|
|
|
- self.tb.setFixedWidth(600)
|
|
|
|
|
|
+ self.tb.setText(helpMsg)
|
|
|
|
+ self.tb.setFixedWidth(500)
|
|
self.pb = QPushButton('OK',self)
|
|
self.pb = QPushButton('OK',self)
|
|
self.pb.setFixedWidth(200)
|
|
self.pb.setFixedWidth(200)
|
|
self.layout.addWidget(self.tb)
|
|
self.layout.addWidget(self.tb)
|
|
@@ -243,6 +259,12 @@ class DirNotes(QMainWindow):
|
|
self.refill()
|
|
self.refill()
|
|
lb.resizeColumnsToContents()
|
|
lb.resizeColumnsToContents()
|
|
|
|
|
|
|
|
+ if len(filename)>0:
|
|
|
|
+ for i in range(lb.rowCount()):
|
|
|
|
+ if filename == lb.item(i,0).data(32).toPyObject().getFileName():
|
|
|
|
+ lb.setCurrentCell(i,3)
|
|
|
|
+ break
|
|
|
|
+
|
|
layout = QVBoxLayout()
|
|
layout = QVBoxLayout()
|
|
|
|
|
|
e = QLabel("View and edit file comments stored in extended attributes user.xdg.comment",win)
|
|
e = QLabel("View and edit file comments stored in extended attributes user.xdg.comment",win)
|
|
@@ -300,7 +322,7 @@ class DirNotes(QMainWindow):
|
|
print("change dir to "+self.dirLeft.currentPath())
|
|
print("change dir to "+self.dirLeft.currentPath())
|
|
def double(self,row,col):
|
|
def double(self,row,col):
|
|
print("double click {} {}".format(row, col))
|
|
print("double click {} {}".format(row, col))
|
|
- fo = self.lb.item(row,col).data(32).toPyObject()
|
|
|
|
|
|
+ fo = self.lb.item(row,0).data(32).toPyObject()
|
|
if col==0 and fo.getSize() == FileObj.FILE_IS_DIR:
|
|
if col==0 and fo.getSize() == FileObj.FILE_IS_DIR:
|
|
print("double click on {}".format(fo.getName()))
|
|
print("double click on {}".format(fo.getName()))
|
|
self.curPath = fo.getName()
|
|
self.curPath = fo.getName()
|
|
@@ -340,6 +362,7 @@ class DirNotes(QMainWindow):
|
|
item = SortableTableWidgetItem(d[i],d[i])
|
|
item = SortableTableWidgetItem(d[i],d[i])
|
|
item.setFlags(QtCore.Qt.ItemIsEnabled)
|
|
item.setFlags(QtCore.Qt.ItemIsEnabled)
|
|
item.setData(32,this_file) # keep a hidden copy of the file object
|
|
item.setData(32,this_file) # keep a hidden copy of the file object
|
|
|
|
+ item.setToolTip(this_file.getName())
|
|
self.lb.setItem(i,0,item)
|
|
self.lb.setItem(i,0,item)
|
|
#lb.itemAt(i,0).setFlags(Qt.ItemIsEnabled) #NoItemFlags)
|
|
#lb.itemAt(i,0).setFlags(Qt.ItemIsEnabled) #NoItemFlags)
|
|
comment = this_file.getComment()
|
|
comment = this_file.getComment()
|
|
@@ -347,6 +370,7 @@ class DirNotes(QMainWindow):
|
|
dt = this_file.getDate()
|
|
dt = this_file.getDate()
|
|
da = SortableTableWidgetItem(DataBase.getShortDate(dt),dt)
|
|
da = SortableTableWidgetItem(DataBase.getShortDate(dt),dt)
|
|
#da.setFont(small_font)
|
|
#da.setFont(small_font)
|
|
|
|
+ da.setToolTip(dt)
|
|
da.setFlags(QtCore.Qt.ItemIsEnabled)
|
|
da.setFlags(QtCore.Qt.ItemIsEnabled)
|
|
self.lb.setItem(i,1,da)
|
|
self.lb.setItem(i,1,da)
|
|
si = this_file.getSize()
|
|
si = this_file.getSize()
|
|
@@ -354,8 +378,10 @@ class DirNotes(QMainWindow):
|
|
sa = SortableTableWidgetItem('',0)
|
|
sa = SortableTableWidgetItem('',0)
|
|
item.setIcon(dirIcon)
|
|
item.setIcon(dirIcon)
|
|
elif si==FileObj.FILE_IS_LINK:
|
|
elif si==FileObj.FILE_IS_LINK:
|
|
- sa = SortableTableWidgetItem('',0)
|
|
|
|
|
|
+ sa = SortableTableWidgetItem('symlink',-1)
|
|
item.setIcon(linkIcon)
|
|
item.setIcon(linkIcon)
|
|
|
|
+ dst = os.path.realpath(this_file.getName())
|
|
|
|
+ sa.setToolTip("symlink: " + dst)
|
|
else:
|
|
else:
|
|
sa = SortableTableWidgetItem(str(si),si)
|
|
sa = SortableTableWidgetItem(str(si),si)
|
|
item.setIcon(fileIcon)
|
|
item.setIcon(fileIcon)
|
|
@@ -373,7 +399,7 @@ class DirNotes(QMainWindow):
|
|
print(" selected file: "+self.lb.item(x.row(),0).data(32).toPyObject().getName())
|
|
print(" selected file: "+self.lb.item(x.row(),0).data(32).toPyObject().getName())
|
|
the_file = self.lb.item(x.row(),0).data(32).toPyObject()
|
|
the_file = self.lb.item(x.row(),0).data(32).toPyObject()
|
|
print(" and the row file is "+the_file.getName())
|
|
print(" and the row file is "+the_file.getName())
|
|
- r = the_file.setComment(str(x.text()))
|
|
|
|
|
|
+ r = the_file.setComment(str(x.text())) # TODO: change priority
|
|
if r:
|
|
if r:
|
|
self.db.log(the_file.getName(),x.text())
|
|
self.db.log(the_file.getName(),x.text())
|
|
def restore_from_database(self):
|
|
def restore_from_database(self):
|
|
@@ -415,7 +441,6 @@ if __name__=="__main__":
|
|
|
|
|
|
#xattr.setxattr(filename,COMMENT_KEY,commentText)
|
|
#xattr.setxattr(filename,COMMENT_KEY,commentText)
|
|
|
|
|
|
-
|
|
|
|
''' files from directories
|
|
''' files from directories
|
|
use os.isfile()
|
|
use os.isfile()
|
|
os.isdir()
|
|
os.isdir()
|