|
@@ -7,7 +7,7 @@
|
|
to view and create/edit file comments
|
|
to view and create/edit file comments
|
|
|
|
|
|
comments are stored in an SQLite3 database
|
|
comments are stored in an SQLite3 database
|
|
- default ~/.dirnotes.db
|
|
|
|
|
|
+ default ~/.local/share/dirnotes/dirnotes.db
|
|
where possible, comments are duplicated in
|
|
where possible, comments are duplicated in
|
|
xattr user.xdg.comment
|
|
xattr user.xdg.comment
|
|
|
|
|
|
@@ -17,11 +17,11 @@ where possible, comments are duplicated in
|
|
|
|
|
|
these comments stick to the symlink, not the deref
|
|
these comments stick to the symlink, not the deref
|
|
|
|
|
|
-nav tools are enabled, so you can double-click to go into a dir
|
|
|
|
|
|
+ you can double-click to go into a dir
|
|
|
|
|
|
"""
|
|
"""
|
|
|
|
|
|
-VERSION = "0.8"
|
|
|
|
|
|
+VERSION = "0.9"
|
|
|
|
|
|
helpMsg = f"""<table width=100%><tr><td><h1>Dirnotes</h1><td>
|
|
helpMsg = f"""<table width=100%><tr><td><h1>Dirnotes</h1><td>
|
|
<td align=right>Version: {VERSION}</td></tr></table>
|
|
<td align=right>Version: {VERSION}</td></tr></table>
|
|
@@ -81,21 +81,23 @@ mode = "db"
|
|
global mainWindow, dbName
|
|
global mainWindow, dbName
|
|
|
|
|
|
verbose = None
|
|
verbose = None
|
|
-def print_v(*a):
|
|
|
|
|
|
+def print_d(*a):
|
|
if verbose:
|
|
if verbose:
|
|
print(*a)
|
|
print(*a)
|
|
|
|
|
|
-############# the DnDataBase, UiHelper and FileObj code is shared with other dirnotes programs
|
|
|
|
|
|
+# >>> snip here <<<
|
|
|
|
+#============ the DnDataBase, UiHelper and FileObj code is shared with other dirnotes programs
|
|
|
|
+import getpass, time, stat, shutil
|
|
|
|
|
|
-DEFAULT_CONFIG_FILE = "~/.dirnotes.conf"
|
|
|
|
|
|
+DEFAULT_CONFIG_FILE = "~/.config/dirnotes/dirnotes.conf" # or /etc/dirnotes.conf
|
|
|
|
|
|
# config
|
|
# config
|
|
# we could store the config in the database, in a second table
|
|
# we could store the config in the database, in a second table
|
|
# or in a .json file
|
|
# or in a .json file
|
|
DEFAULT_CONFIG = {"xattr_tag":"user.xdg.comment",
|
|
DEFAULT_CONFIG = {"xattr_tag":"user.xdg.comment",
|
|
- "database":"~/.dirnotes.db",
|
|
|
|
|
|
+ "database":"~/.local/share/dirnotes/dirnotes.db",
|
|
"start_mode":"xattr",
|
|
"start_mode":"xattr",
|
|
- "options for database":("~/.dirnotes.db","/etc/dirnotes.db"),
|
|
|
|
|
|
+ "options for database":("~/.local/share/dirnotes/dirnotes.db","~/.dirnotes.db","/etc/dirnotes.db"),
|
|
"options for start_mode":("db","xattr")
|
|
"options for start_mode":("db","xattr")
|
|
}
|
|
}
|
|
|
|
|
|
@@ -112,6 +114,7 @@ class ConfigLoader: # singleton
|
|
errorBox(f"config file {configFile} not found; using the default settings")
|
|
errorBox(f"config file {configFile} not found; using the default settings")
|
|
config = DEFAULT_CONFIG
|
|
config = DEFAULT_CONFIG
|
|
try:
|
|
try:
|
|
|
|
+ os.makedirs(os.path.dirname(configFile),exist_ok = True)
|
|
with open(configFile,"w") as f:
|
|
with open(configFile,"w") as f:
|
|
json.dump(config,f,indent=4)
|
|
json.dump(config,f,indent=4)
|
|
except:
|
|
except:
|
|
@@ -132,7 +135,7 @@ class DnDataBase:
|
|
this object: 1) finds or creates the database
|
|
this object: 1) finds or creates the database
|
|
2) determine if it's readonly
|
|
2) determine if it's readonly
|
|
|
|
|
|
- TODO: the database is usually associated with a user, in $XDG_DATA_HOME (~/.local/share/)
|
|
|
|
|
|
+ TODO: the database is usually associated with a user, in $XDG_DATA_HOME (~/.local/share/)
|
|
TODO: if the database is not found, create it in $XDG_DATA_DIRS (/usr/local/share/)
|
|
TODO: if the database is not found, create it in $XDG_DATA_DIRS (/usr/local/share/)
|
|
make it 0666 permissions (rw-rw-rw-)
|
|
make it 0666 permissions (rw-rw-rw-)
|
|
'''
|
|
'''
|
|
@@ -141,16 +144,21 @@ class DnDataBase:
|
|
try:
|
|
try:
|
|
self.db = sqlite3.connect(dbFile)
|
|
self.db = sqlite3.connect(dbFile)
|
|
except sqlite3.OperationalError:
|
|
except sqlite3.OperationalError:
|
|
- logging.error(f"Database {dbFile} not found")
|
|
|
|
- raise
|
|
|
|
-
|
|
|
|
- # create new database if it doesn't exist
|
|
|
|
|
|
+ print_d(f"Database {dbFile} not found")
|
|
|
|
+ try:
|
|
|
|
+ os.makedirs(os.path.dirname(dbFile), exist_ok = True)
|
|
|
|
+ self.db = sqlite3.connect(dbFile)
|
|
|
|
+ except (sqlite3.OperationalError, PermissionError):
|
|
|
|
+ printd(f"Failed to create {dbFile}, aborting")
|
|
|
|
+ raise
|
|
|
|
+
|
|
|
|
+ # create new table if it doesn't exist
|
|
try:
|
|
try:
|
|
self.db.execute("select * from dirnotes")
|
|
self.db.execute("select * from dirnotes")
|
|
except sqlite3.OperationalError:
|
|
except sqlite3.OperationalError:
|
|
- print_v(f"Table dirnotes created")
|
|
|
|
self.db.execute("create table dirnotes (name TEXT, date DATETIME, size INTEGER, comment TEXT, comment_date DATETIME, author TEXT)")
|
|
self.db.execute("create table dirnotes (name TEXT, date DATETIME, size INTEGER, comment TEXT, comment_date DATETIME, author TEXT)")
|
|
self.db.execute("create index dirnotes_i on dirnotes(name)")
|
|
self.db.execute("create index dirnotes_i on dirnotes(name)")
|
|
|
|
+ print_d(f"Table dirnotes created")
|
|
# at this point, if a shared database is required, somebody needs to set perms to 0o666
|
|
# at this point, if a shared database is required, somebody needs to set perms to 0o666
|
|
|
|
|
|
self.writable = True
|
|
self.writable = True
|
|
@@ -159,6 +167,7 @@ class DnDataBase:
|
|
except sqlite3.OperationalError:
|
|
except sqlite3.OperationalError:
|
|
self.writable = False
|
|
self.writable = False
|
|
|
|
|
|
|
|
+DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
|
|
class UiHelper:
|
|
class UiHelper:
|
|
@staticmethod
|
|
@staticmethod
|
|
def epochToDb(epoch):
|
|
def epochToDb(epoch):
|
|
@@ -207,7 +216,7 @@ class FileObj:
|
|
""" returns the absolute pathname """
|
|
""" returns the absolute pathname """
|
|
return self.fileName
|
|
return self.fileName
|
|
def getDisplayName(self):
|
|
def getDisplayName(self):
|
|
- """ returns just this basename of the file; dirs end in / """
|
|
|
|
|
|
+ """ returns just the basename of the file; dirs end in / """
|
|
return self.displayName
|
|
return self.displayName
|
|
|
|
|
|
def getDbData(self):
|
|
def getDbData(self):
|
|
@@ -241,18 +250,18 @@ class FileObj:
|
|
# return
|
|
# return
|
|
s = os.lstat(self.fileName)
|
|
s = os.lstat(self.fileName)
|
|
try:
|
|
try:
|
|
- print_v(f"setDbComment db {self.db}, file: {self.fileName}")
|
|
|
|
|
|
+ print_d(f"setDbComment db {self.db}, file: {self.fileName}")
|
|
self.db.execute("insert into dirnotes (name,date,size,comment,comment_date,author) values (?,datetime(?,'unixepoch','localtime'),?,?,datetime(?,'unixepoch','localtime'),?)",
|
|
self.db.execute("insert into dirnotes (name,date,size,comment,comment_date,author) values (?,datetime(?,'unixepoch','localtime'),?,?,datetime(?,'unixepoch','localtime'),?)",
|
|
(self.fileName, s.st_mtime, s.st_size,
|
|
(self.fileName, s.st_mtime, s.st_size,
|
|
str(newComment), time.time(), getpass.getuser()))
|
|
str(newComment), time.time(), getpass.getuser()))
|
|
self.db.commit()
|
|
self.db.commit()
|
|
self.dbCommentAuthorDate = newComment, getpass.getuser(), UiHelper.epochToDb(time.time())
|
|
self.dbCommentAuthorDate = newComment, getpass.getuser(), UiHelper.epochToDb(time.time())
|
|
except sqlite3.OperationalError:
|
|
except sqlite3.OperationalError:
|
|
- print_v("database is locked or unwritable")
|
|
|
|
|
|
+ print_d("database is locked or unwritable")
|
|
errorBox("the database that stores comments is locked or unwritable")
|
|
errorBox("the database that stores comments is locked or unwritable")
|
|
|
|
|
|
def setXattrComment(self,newComment):
|
|
def setXattrComment(self,newComment):
|
|
- print_v(f"set comment {newComment} on file {self.fileName}")
|
|
|
|
|
|
+ print_d(f"set comment {newComment} on file {self.fileName}")
|
|
try:
|
|
try:
|
|
os.setxattr(self.fileName,xattr_comment,bytes(newComment,'utf8'),follow_symlinks=False)
|
|
os.setxattr(self.fileName,xattr_comment,bytes(newComment,'utf8'),follow_symlinks=False)
|
|
os.setxattr(self.fileName,xattr_author,bytes(getpass.getuser(),'utf8'),follow_symlinks=False)
|
|
os.setxattr(self.fileName,xattr_author,bytes(getpass.getuser(),'utf8'),follow_symlinks=False)
|
|
@@ -266,21 +275,22 @@ class FileObj:
|
|
elif self.isSock():
|
|
elif self.isSock():
|
|
errorBox("Linux does not allow comments on sockets; comment is stored in database")
|
|
errorBox("Linux does not allow comments on sockets; comment is stored in database")
|
|
elif os.access(self.fileName, os.W_OK)!=True:
|
|
elif os.access(self.fileName, os.W_OK)!=True:
|
|
- errorBox("you don't appear to have write permissions on this file")
|
|
|
|
|
|
+ errorBox(f"you don't appear to have write permissions on this file: {self.fileName}")
|
|
# change the listbox background to yellow
|
|
# change the listbox background to yellow
|
|
elif "Errno 95" in str(e):
|
|
elif "Errno 95" in str(e):
|
|
errorBox("is this a VFAT or EXFAT volume? these don't allow comments")
|
|
errorBox("is this a VFAT or EXFAT volume? these don't allow comments")
|
|
return False
|
|
return False
|
|
|
|
|
|
def getComment(self,mode):
|
|
def getComment(self,mode):
|
|
|
|
+ """ returns the comment for the given mode """
|
|
return self.getDbComment() if mode == "db" else self.getXattrComment()
|
|
return self.getDbComment() if mode == "db" else self.getXattrComment()
|
|
def getOtherComment(self,mode):
|
|
def getOtherComment(self,mode):
|
|
return self.getDbComment() if mode == "xattr" else self.getXattrComment()
|
|
return self.getDbComment() if mode == "xattr" else self.getXattrComment()
|
|
def getData(self,mode):
|
|
def getData(self,mode):
|
|
- """ returns (comment, author, comment_date) """
|
|
|
|
|
|
+ """ returns (comment, author, comment_date) for the given mode """
|
|
return self.getDbData() if mode == "db" else self.getXattrData()
|
|
return self.getDbData() if mode == "db" else self.getXattrData()
|
|
def getOtherData(self,mode):
|
|
def getOtherData(self,mode):
|
|
- """ returns (comment, author, comment_date) """
|
|
|
|
|
|
+ """ returns (comment, author, comment_date) for the 'other' mode """
|
|
return self.getDbData() if mode == "xattr" else self.getXattrData()
|
|
return self.getDbData() if mode == "xattr" else self.getXattrData()
|
|
|
|
|
|
def getDate(self):
|
|
def getDate(self):
|
|
@@ -294,38 +304,35 @@ class FileObj:
|
|
def isSock(self):
|
|
def isSock(self):
|
|
return stat.S_ISSOCK(self.stat.st_mode)
|
|
return stat.S_ISSOCK(self.stat.st_mode)
|
|
|
|
|
|
- def copyFile(self, destDir):
|
|
|
|
|
|
+ def copyFile(self, dest, doMove = False):
|
|
|
|
+ """ dest is either a FQ filename or a FQ directory, to be expanded with same basename """
|
|
# NOTE: this method copies the xattr (comment + old author + old date)
|
|
# NOTE: this method copies the xattr (comment + old author + old date)
|
|
# but creates new db (comment + this author + new date)
|
|
# but creates new db (comment + this author + new date)
|
|
- dest = os.path.join(destDir,self.displayName)
|
|
|
|
|
|
+ if os.path.isdir(dest):
|
|
|
|
+ dest = os.path.join(destDir,self.displayName)
|
|
try:
|
|
try:
|
|
- print_v("try copy from",self.fileName,"to",dest)
|
|
|
|
- shutil.copy2(self.fileName, dest)
|
|
|
|
|
|
+ print_d("try copy from",self.fileName,"to",dest)
|
|
|
|
+ # shutil methods preserve dates & chmod/chown & xattr
|
|
|
|
+ if doMove:
|
|
|
|
+ shutil.move(self.fileName, dest)
|
|
|
|
+ else:
|
|
|
|
+ shutil.copy2(self.fileName, dest)
|
|
|
|
+ # can raise FileNotFoundError, Permission Error, shutil.SameFileError, IsADirectoryError
|
|
except:
|
|
except:
|
|
- errorBox(f"file copy to <{dest}> failed; check permissions")
|
|
|
|
|
|
+ errorBox(f"file copy/move to <{dest}> failed; check permissions")
|
|
return
|
|
return
|
|
|
|
+ # and copy the database record
|
|
f = FileObj(dest, self.db)
|
|
f = FileObj(dest, self.db)
|
|
f.setDbComment(self.getDbComment())
|
|
f.setDbComment(self.getDbComment())
|
|
- def moveFile(self, destDir):
|
|
|
|
- # NOTE: this method moves the xattr (comment + old author + old date)
|
|
|
|
- # but creates new db (comment + this author + new date)
|
|
|
|
- src = self.fileName
|
|
|
|
- dest = os.path.join(destDir, self.displayName)
|
|
|
|
- # move preserves dates & chmod/chown & xattr
|
|
|
|
- print_v(f"move from {self.fileName} to {destDir}")
|
|
|
|
- try:
|
|
|
|
- shutil.move(src, dest)
|
|
|
|
- except:
|
|
|
|
- ErrorBox(f"file move to <{dest}> failed; check permissions")
|
|
|
|
- return
|
|
|
|
- # and copy the database record
|
|
|
|
- f = FileObj(dest,self.db)
|
|
|
|
- f.setDbComment(self.getDbComment())
|
|
|
|
|
|
+ def moveFile(self, dest):
|
|
|
|
+ """ dest is either a FQ filename or a FQ directory, to be expanded with same basename """
|
|
|
|
+ self.copyFile(dest, doMove = True)
|
|
|
|
+
|
|
|
|
+# >>> snip here <<<
|
|
|
|
|
|
class HelpWidget(QDialog):
|
|
class HelpWidget(QDialog):
|
|
def __init__(self, parent):
|
|
def __init__(self, parent):
|
|
super(QDialog, self).__init__(parent)
|
|
super(QDialog, self).__init__(parent)
|
|
- layout = QVBoxLayout(self)
|
|
|
|
|
|
|
|
tb = QLabel(self)
|
|
tb = QLabel(self)
|
|
tb.setWordWrap(True)
|
|
tb.setWordWrap(True)
|
|
@@ -335,8 +342,9 @@ class HelpWidget(QDialog):
|
|
pb.setFixedWidth(200)
|
|
pb.setFixedWidth(200)
|
|
kb = QPushButton('Keyboard Help',self)
|
|
kb = QPushButton('Keyboard Help',self)
|
|
|
|
|
|
|
|
+ layout = QVBoxLayout(self)
|
|
layout.addWidget(tb)
|
|
layout.addWidget(tb)
|
|
- lowerBox = QHBoxLayout(self)
|
|
|
|
|
|
+ lowerBox = QHBoxLayout()
|
|
lowerBox.addWidget(pb)
|
|
lowerBox.addWidget(pb)
|
|
lowerBox.addWidget(kb)
|
|
lowerBox.addWidget(kb)
|
|
layout.addLayout(lowerBox)
|
|
layout.addLayout(lowerBox)
|
|
@@ -350,12 +358,13 @@ class HelpWidget(QDialog):
|
|
class KeyboardHelpWidget(QDialog):
|
|
class KeyboardHelpWidget(QDialog):
|
|
def __init__(self, parent):
|
|
def __init__(self, parent):
|
|
super(QDialog, self).__init__(parent)
|
|
super(QDialog, self).__init__(parent)
|
|
- layout = QVBoxLayout(self)
|
|
|
|
tb = QLabel(self)
|
|
tb = QLabel(self)
|
|
tb.setWordWrap(True)
|
|
tb.setWordWrap(True)
|
|
tb.setText(keyboardHelpMsg)
|
|
tb.setText(keyboardHelpMsg)
|
|
tb.setFixedWidth(500)
|
|
tb.setFixedWidth(500)
|
|
pb = QPushButton('OK',self)
|
|
pb = QPushButton('OK',self)
|
|
|
|
+
|
|
|
|
+ layout = QVBoxLayout(self)
|
|
layout.addWidget(tb)
|
|
layout.addWidget(tb)
|
|
layout.addWidget(pb)
|
|
layout.addWidget(pb)
|
|
pb.clicked.connect(self.close)
|
|
pb.clicked.connect(self.close)
|
|
@@ -363,7 +372,7 @@ class KeyboardHelpWidget(QDialog):
|
|
|
|
|
|
class errorBox(QDialog):
|
|
class errorBox(QDialog):
|
|
def __init__(self, text):
|
|
def __init__(self, text):
|
|
- print_v(f"errorBox: {text}")
|
|
|
|
|
|
+ print_d(f"errorBox: {text}")
|
|
super(QDialog, self).__init__(mainWindow)
|
|
super(QDialog, self).__init__(mainWindow)
|
|
self.layout = QVBoxLayout(self)
|
|
self.layout = QVBoxLayout(self)
|
|
self.tb = QLabel(self)
|
|
self.tb = QLabel(self)
|
|
@@ -397,7 +406,7 @@ keyboardHelpMsg = """
|
|
<tr><td>Ctrl+Q</td><td>quit the app</td></tr>
|
|
<tr><td>Ctrl+Q</td><td>quit the app</td></tr>
|
|
</table>
|
|
</table>
|
|
<p>
|
|
<p>
|
|
-NOTE: In edit mode, Ctrl+C, Ctrl+V and Ctrl+P work for cut, copy and paste.
|
|
|
|
|
|
+NOTE: In edit mode, Ctrl+X, Ctrl+C and Ctrl+V work for cut, copy and paste.
|
|
"""
|
|
"""
|
|
|
|
|
|
icon = ["32 32 6 1", # the QPixmap constructor allows for str[]
|
|
icon = ["32 32 6 1", # the QPixmap constructor allows for str[]
|
|
@@ -464,13 +473,13 @@ class DirNotes(QMainWindow):
|
|
self.parent = parent
|
|
self.parent = parent
|
|
|
|
|
|
longPathName = os.path.abspath(argFilename)
|
|
longPathName = os.path.abspath(argFilename)
|
|
- print_v("longpathname is {}".format(longPathName))
|
|
|
|
|
|
+ print_d("longpathname is {}".format(longPathName))
|
|
if os.path.isdir(longPathName):
|
|
if os.path.isdir(longPathName):
|
|
self.curPath = longPathName
|
|
self.curPath = longPathName
|
|
filename = ''
|
|
filename = ''
|
|
else:
|
|
else:
|
|
self.curPath, filename = os.path.split(longPathName)
|
|
self.curPath, filename = os.path.split(longPathName)
|
|
- print_v("working on <"+self.curPath+"> and <"+filename+">")
|
|
|
|
|
|
+ print_d("working on <"+self.curPath+"> and <"+filename+">")
|
|
|
|
|
|
win = QWidget()
|
|
win = QWidget()
|
|
self.setCentralWidget(win)
|
|
self.setCentralWidget(win)
|
|
@@ -479,7 +488,7 @@ class DirNotes(QMainWindow):
|
|
mf = mb.addMenu('&File')
|
|
mf = mb.addMenu('&File')
|
|
mf.addAction("Sort by name", self.sbn, "Ctrl+N")
|
|
mf.addAction("Sort by name", self.sbn, "Ctrl+N")
|
|
mf.addAction("Sort by date", self.sbd, "Ctrl+D")
|
|
mf.addAction("Sort by date", self.sbd, "Ctrl+D")
|
|
- mf.addAction("Sort by size", self.sbs, "Ctrl+Z")
|
|
|
|
|
|
+ mf.addAction("Sort by size", self.sbs, "Ctrl+S")
|
|
mf.addAction("Sort by comment", self.sbc, "Ctrl+T")
|
|
mf.addAction("Sort by comment", self.sbc, "Ctrl+T")
|
|
mf.addSeparator()
|
|
mf.addSeparator()
|
|
mf.addAction("Change mode", self.switchMode, "Ctrl+M")
|
|
mf.addAction("Change mode", self.switchMode, "Ctrl+M")
|
|
@@ -542,25 +551,25 @@ class DirNotes(QMainWindow):
|
|
lb.setFocus()
|
|
lb.setFocus()
|
|
|
|
|
|
def sbd(self):
|
|
def sbd(self):
|
|
- print_v("sort by date")
|
|
|
|
|
|
+ print_d("sort by date")
|
|
self.lb.sortItems(1,Qt.DescendingOrder)
|
|
self.lb.sortItems(1,Qt.DescendingOrder)
|
|
def sbs(self):
|
|
def sbs(self):
|
|
- print_v("sort by size")
|
|
|
|
|
|
+ print_d("sort by size")
|
|
self.lb.sortItems(2)
|
|
self.lb.sortItems(2)
|
|
def sbn(self):
|
|
def sbn(self):
|
|
- print_v("sort by name")
|
|
|
|
|
|
+ print_d("sort by name")
|
|
self.lb.sortItems(0)
|
|
self.lb.sortItems(0)
|
|
def sbc(self):
|
|
def sbc(self):
|
|
- print_v("sort by comment")
|
|
|
|
|
|
+ print_d("sort by comment")
|
|
self.lb.sortItems(3)
|
|
self.lb.sortItems(3)
|
|
def about(self):
|
|
def about(self):
|
|
HelpWidget(self)
|
|
HelpWidget(self)
|
|
|
|
|
|
def double(self,row,col):
|
|
def double(self,row,col):
|
|
- print_v("double click {} {}".format(row, col))
|
|
|
|
|
|
+ print_d("double click {} {}".format(row, col))
|
|
fo = self.lb.item(row,0).file_object
|
|
fo = self.lb.item(row,0).file_object
|
|
if col==0 and fo.isDir():
|
|
if col==0 and fo.isDir():
|
|
- print_v("double click on {}".format(fo.getName()))
|
|
|
|
|
|
+ print_d("double click on {}".format(fo.getName()))
|
|
self.curPath = fo.getName()
|
|
self.curPath = fo.getName()
|
|
self.refill()
|
|
self.refill()
|
|
def keyPressEvent(self,e):
|
|
def keyPressEvent(self,e):
|
|
@@ -582,11 +591,11 @@ class DirNotes(QMainWindow):
|
|
r, c = self.lb.currentRow(), self.lb.currentColumn()
|
|
r, c = self.lb.currentRow(), self.lb.currentColumn()
|
|
fo = self.lb.item(r,c).file_object
|
|
fo = self.lb.item(r,c).file_object
|
|
if not fo.isDir() and not fo.isLink() and not fo.isSock():
|
|
if not fo.isDir() and not fo.isLink() and not fo.isSock():
|
|
- print_v(f"{'copy' if doCopy=='copy' else 'move'} file {fo.getName()}")
|
|
|
|
|
|
+ print_d(f"{'copy' if doCopy=='copy' else 'move'} file {fo.getName()}")
|
|
# open the dir.picker
|
|
# open the dir.picker
|
|
d = QFileDialog.getExistingDirectory(self.parent, pickerTitle)
|
|
d = QFileDialog.getExistingDirectory(self.parent, pickerTitle)
|
|
if d:
|
|
if d:
|
|
- print_v(f"senf file to {d}")
|
|
|
|
|
|
+ print_d(f"senf file to {d}")
|
|
fo.copyFile(d) if doCopy=='copy' else fo.moveFile(d)
|
|
fo.copyFile(d) if doCopy=='copy' else fo.moveFile(d)
|
|
def copyFile(self):
|
|
def copyFile(self):
|
|
self.copyMoveFile('copy',"Select destination for FileCopy")
|
|
self.copyMoveFile('copy',"Select destination for FileCopy")
|
|
@@ -625,7 +634,7 @@ class DirNotes(QMainWindow):
|
|
#~ print("insert {} items into cleared table {}".format(len(d),current))
|
|
#~ print("insert {} items into cleared table {}".format(len(d),current))
|
|
for i,name in enumerate(d):
|
|
for i,name in enumerate(d):
|
|
this_file = FileObj(os.path.join(current,name),self.db)
|
|
this_file = FileObj(os.path.join(current,name),self.db)
|
|
- print_v("FileObj created as {} and the db-comment is <{}>".format(this_file.displayName, this_file.getDbComment))
|
|
|
|
|
|
+ print_d("FileObj created as {} and the db-comment is <{}>".format(this_file.displayName, this_file.getDbComment))
|
|
#~ print("insert order check: {} {} {} {}".format(d[i],i,this_file.getName(),this_file.getDate()))
|
|
#~ print("insert order check: {} {} {} {}".format(d[i],i,this_file.getName(),this_file.getDate()))
|
|
display_name = this_file.getDisplayName()
|
|
display_name = this_file.getDisplayName()
|
|
if this_file.isDir():
|
|
if this_file.isDir():
|
|
@@ -643,7 +652,7 @@ class DirNotes(QMainWindow):
|
|
ci.setToolTip(f"comment: {comment}\ncomment date: {cdate}\nauthor: {auth}")
|
|
ci.setToolTip(f"comment: {comment}\ncomment date: {cdate}\nauthor: {auth}")
|
|
if other_comment != comment:
|
|
if other_comment != comment:
|
|
ci.setBackground(self.differBrush)
|
|
ci.setBackground(self.differBrush)
|
|
- print_v("got differing comments <{}> and <{}>".format(comment, other_comment))
|
|
|
|
|
|
+ print_d("got differing comments <{}> and <{}>".format(comment, other_comment))
|
|
ci.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled)
|
|
ci.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled)
|
|
self.lb.setItem(i,3,ci)
|
|
self.lb.setItem(i,3,ci)
|
|
|
|
|
|
@@ -681,8 +690,8 @@ class DirNotes(QMainWindow):
|
|
if self.refilling:
|
|
if self.refilling:
|
|
return
|
|
return
|
|
the_file = self.lb.item(x.row(),0).file_object
|
|
the_file = self.lb.item(x.row(),0).file_object
|
|
- print_v(f"debugging {x.text()} r:{str(x.row())} c:{str(x.column())}")
|
|
|
|
- print_v(f" selected file: {the_file.getName()}")
|
|
|
|
|
|
+ print_d(f"debugging {x.text()} r:{str(x.row())} c:{str(x.column())}")
|
|
|
|
+ print_d(f" selected file: {the_file.getName()} new text: >{x.text()}<")
|
|
the_file.setDbComment(str(x.text()))
|
|
the_file.setDbComment(str(x.text()))
|
|
the_file.setXattrComment(str(x.text()))
|
|
the_file.setXattrComment(str(x.text()))
|
|
|
|
|
|
@@ -728,12 +737,12 @@ if __name__=="__main__":
|
|
p.dirname = p.dirname[:-1]
|
|
p.dirname = p.dirname[:-1]
|
|
if os.path.isdir(p.dirname):
|
|
if os.path.isdir(p.dirname):
|
|
p.dirname = p.dirname + '/'
|
|
p.dirname = p.dirname + '/'
|
|
- print_v(f"using {p.dirname}")
|
|
|
|
|
|
+ print_d(f"using {p.dirname}")
|
|
verbose = p.verbose
|
|
verbose = p.verbose
|
|
|
|
|
|
config = ConfigLoader(p.config_file or DEFAULT_CONFIG_FILE)
|
|
config = ConfigLoader(p.config_file or DEFAULT_CONFIG_FILE)
|
|
|
|
|
|
- print_v(f"here is the .json {repr(config)}")
|
|
|
|
|
|
+ print_d(f"here is the .json {repr(config)}")
|
|
dbName = config.dbName
|
|
dbName = config.dbName
|
|
db = DnDataBase(dbName).db
|
|
db = DnDataBase(dbName).db
|
|
xattr_comment = config.xattr_comment
|
|
xattr_comment = config.xattr_comment
|
|
@@ -754,11 +763,6 @@ if __name__=="__main__":
|
|
if p.sort_by_date:
|
|
if p.sort_by_date:
|
|
mainWindow.sbd()
|
|
mainWindow.sbd()
|
|
mainWindow.show()
|
|
mainWindow.show()
|
|
-
|
|
|
|
- if p.sort_by_date:
|
|
|
|
- mainWindow.sbd()
|
|
|
|
- if p.sort_by_size:
|
|
|
|
- mainWindow.sbs()
|
|
|
|
|
|
|
|
a.exec_()
|
|
a.exec_()
|
|
|
|
|