Browse Source

Added folder picker capability in the file picker

pull/23/head
Eugenio Parodi 4 years ago
parent
commit
4342b96540
  1. 1
      README.md
  2. 10
      TermTk/TTkCore/constant.py
  3. 121
      TermTk/TTkWidgets/TTkPickers/filepicker.py
  4. 19
      demo/showcase/filepicker.py

1
README.md

@ -82,6 +82,7 @@ cprofilev -f profiler.txt
## Related Projects
- Python
- [urwid](https://github.com/urwid/urwid) - Console user interface library for Python
- [pyTermGUI](https://github.com/bczsalba/pytermgui) - A simple yet powerful TUI framework for your Python (3.7+) applications
- [Textual](https://github.com/Textualize/textual) - TUI (Text User Interface) framework for Python inspired by modern web development
- [Rich](https://github.com/Textualize/rich) - Python library for rich text and beautiful formatting in the terminal

10
TermTk/TTkCore/constant.py

@ -187,6 +187,16 @@ class TTkConstant:
CENTER_ALIGN = Alignment.CENTER_ALIGN
JUSTIFY = Alignment.JUSTIFY
class FileMode():
AnyFile = 0 #The name of a file, whether it exists or not.
# ExistingFile = 1 #The name of a single existing file.
Directory = 2 #The name of a directory. Both files and directories are displayed. However, the native Windows file dialog does not support displaying files in the directory chooser.
# ExistingFiles = 3 #The names of zero or more existing files.
# AnyFile = FileMode.AnyFile
# ExistingFile = FileMode.ExistingFile
# Directory = FileMode.Directory
# ExistingFiles = FileMode.ExistingFiles
# LayoutItem Types
class LayoutItemTypes:

121
TermTk/TTkWidgets/TTkPickers/filepicker.py

@ -24,7 +24,6 @@
import os
import re
import datetime
from TermTk.TTkCore.color import TTkColor
@ -60,16 +59,19 @@ from TermTk.TTkWidgets.TTkModelView.filetreewidgetitem import TTkFileTreeWidgetI
'''
class TTkFileDialogPicker(TTkWindow):
__slots__ = ('_path', '_recentPath', '_recentPathId', '_filters', '_filter', '_caption',
__slots__ = ('_path', '_recentPath', '_recentPathId', '_filters', '_filter', '_caption', '_fileMode',
# Widgets
'_fileTree', '_lookPath', '_btnPrev', '_btnNext', '_btnUp',
'_fileName', '_fileType', '_btnOpen', '_btnCancel',
# Signals
'filePicked')
'pathPicked', 'filePicked', 'filesPicked', 'folderPicked')
def __init__(self, *args, **kwargs):
# Signals
self.pathPicked = pyTTkSignal(str)
self.filePicked = pyTTkSignal(str)
self.filesPicked = pyTTkSignal(list)
self.folderPicked = pyTTkSignal(str)
TTkWindow.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkFileDialogPicker' )
@ -77,10 +79,11 @@ class TTkFileDialogPicker(TTkWindow):
self._recentPathId = -1
self._recentPath = []
self._path = kwargs.get('path','.')
self._filter = '*'
self._filters = kwargs.get('filter','All Files (*)')
self._caption = kwargs.get('caption','File Dialog')
self._path = kwargs.get('path','.')
self._filter = '*'
self._filters = kwargs.get('filter','All Files (*)')
self._caption = kwargs.get('caption','File Dialog')
self._fileMode = kwargs.get('fileMode',TTkK.FileMode.AnyFile)
self.setTitle(self._caption)
self.setLayout(TTkGridLayout())
@ -162,7 +165,14 @@ class TTkFileDialogPicker(TTkWindow):
@pyTTkSlot(str)
def _checkFileName(self, fileName):
if os.path.exists(fileName) and os.path.isfile(fileName):
valid = False
if self._fileMode == TTkK.FileMode.AnyFile:
valid = os.path.exists(fileName) and os.path.isfile(fileName)
elif self._fileMode == TTkK.FileMode.Directory:
valid = os.path.exists(fileName) and os.path.isdir(fileName)
else:
pass
if valid:
self._btnOpen.setEnabled()
else:
self._btnOpen.setDisabled()
@ -171,12 +181,19 @@ class TTkFileDialogPicker(TTkWindow):
def _open(self):
fileName = self._fileName.text()
if not os.path.exists(fileName): return
self.filePicked.emit(fileName)
if self._fileMode == TTkK.FileMode.AnyFile and not os.path.isfile(fileName): return
if self._fileMode == TTkK.FileMode.Directory and not os.path.isdir(fileName): return
if self._fileMode == TTkK.FileMode.AnyFile:
self.filePicked.emit(fileName)
if self._fileMode == TTkK.FileMode.Directory:
self.folderPicked.emit(fileName)
self.pathPicked.emit(fileName)
self.close()
@pyTTkSlot(TTkFileTreeWidgetItem, int)
def _selectedItem(self, item, _):
if item.getType() != item.FILE: return
if self._fileMode == TTkK.FileMode.AnyFile and item.getType() != item.FILE: return
if self._fileMode == TTkK.FileMode.Directory and item.getType() != item.DIR : return
self._fileName.setText(item.path())
@pyTTkSlot(TTkFileTreeWidgetItem, int)
@ -187,6 +204,12 @@ class TTkFileDialogPicker(TTkWindow):
elif os.path.isfile(path):
self._open()
def filemode(self):
return self._fileMode
def setFileMode(self, fileMode):
self._fileMode = fileMode
def _openPrev(self):
if self._recentPathId<=0 or self._recentPathId>=len(self._recentPath):
self._btnPrev.setDisabled()
@ -239,84 +262,6 @@ class TTkFileDialogPicker(TTkWindow):
if not path or path=='/':
break
return ret
@staticmethod
def _getFileItems(path):
path = os.path.abspath(path)
if not os.path.exists(path): return []
dir_list = os.listdir(path)
ret = []
for n in dir_list:
nodePath = os.path.join(path,n)
def _getStat(_path):
info = os.stat(_path)
time = datetime.datetime.fromtimestamp(info.st_ctime).strftime('%Y-%m-%d %H:%M:%S')
if info.st_size > (1024*1024*1024):
size = f"{info.st_size/(1024*1024*1024):.2f} GB"
if info.st_size > (1024*1024):
size = f"{info.st_size/(1024*1024):.2f} MB"
elif info.st_size > 1024:
size = f"{info.st_size/1024:.2f} KB"
else:
size = f"{info.st_size} bytes"
return time, size, info.st_ctime, info.st_size
if os.path.isdir(nodePath):
if os.path.exists(nodePath):
time, _, rawTime, _ = _getStat(nodePath)
color = TTkCfg.theme.folderNameColor
else:
time, _, rawTime, _ = ""
color = TTkCfg.theme.failNameColor
if os.path.islink(nodePath):
name = TTkString()+TTkCfg.theme.linkNameColor+n+'/'+TTkColor.RST+' -> '+TTkCfg.theme.folderNameColor+os.readlink(nodePath)
typef = "Folder Link"
else:
name = TTkString()+color+n+'/'
typef = "Folder"
ret.append(TTkFileTreeWidgetItem(
[ name, "", typef, time],
raw = [ n , -1 , typef , rawTime ],
path=nodePath,
type=TTkFileTreeWidgetItem.DIR,
icon=TTkString() + TTkCfg.theme.folderIconColor + TTkCfg.theme.fileIcon.folderClose + TTkColor.RST,
childIndicatorPolicy=TTkK.ShowIndicator))
elif os.path.isfile(nodePath) or os.path.islink(nodePath):
if os.path.exists(nodePath):
time, size, rawTime, rawSize = _getStat(nodePath)
if os.access(nodePath, os.X_OK):
color = TTkCfg.theme.executableColor
typef="Exec"
else:
color = TTkCfg.theme.fileNameColor
typef="File"
else:
time, size, rawTime, rawSize = "", "", 0, 0
color = TTkCfg.theme.failNameColor
typef="Broken"
if os.path.islink(nodePath):
name = TTkString()+TTkCfg.theme.linkNameColor+n+TTkColor.RST+' -> '+color+os.readlink(nodePath)
typef += " Link"
else:
name = TTkString()+color+n
_, ext = os.path.splitext(n)
if ext: ext = f"{ext[1:]} "
ret.append(TTkFileTreeWidgetItem(
[ name, size, typef, time],
raw = [ n , rawSize , typef , rawTime ],
path=nodePath,
type=TTkFileTreeWidgetItem.FILE,
icon=TTkString() + TTkCfg.theme.fileIconColor + TTkCfg.theme.fileIcon.getIcon(n) + TTkColor.RST,
childIndicatorPolicy=TTkK.DontShowIndicator))
return ret
class TTkFileDialog:
def getOpenFileName(caption, dir=".", filter="All Files (*)", options=None):
pass

19
demo/showcase/filepicker.py

@ -32,15 +32,20 @@ def demoFilePicker(root=None):
frame = ttk.TTkFrame(parent=root, border=False)
# winFP = ttk.TTkWindow(parent=frame,pos = (0,0), size=(20,10), title="Test File Pickers", border=True)
btn = ttk.TTkButton(parent=frame, pos=( 0,0), size=(8,3), border=True, text='File' )
label = ttk.TTkLabel(parent=frame, pos=( 10,1), size=(30,1), text="...")
btn1 = ttk.TTkButton( parent=frame, pos=(0,0), size=(8,3), border=True, text='File' )
btn3 = ttk.TTkButton( parent=frame, pos=(8,0), size=(13,3), border=True, text='Directory' )
btn2 = ttk.TTkButton( parent=frame, pos=(21,0), size=(17,3), border=True, text='Existing File', enabled=False )
btn4 = ttk.TTkButton( parent=frame, pos=(38,0), size=(18,3), border=True, text='Existing Files', enabled=False )
label = ttk.TTkLabel(parent=frame, pos=(1,5), size=(30,1), text="...")
def _showDialog():
filePicker = ttk.TTkFileDialogPicker(pos = (3,3), size=(75,24), caption="Pick a File", path=".", filter="All Files (*);;Python Files (*.py);;Bash scripts (*.sh);;Markdown Files (*.md)")
filePicker.filePicked.connect(label.setText)
def _showDialog(fm):
filePicker = ttk.TTkFileDialogPicker(pos = (3,3), size=(75,24), caption="Pick Something", path=".", fileMode=fm ,filter="All Files (*);;Python Files (*.py);;Bash scripts (*.sh);;Markdown Files (*.md)")
filePicker.pathPicked.connect(label.setText)
ttk.TTkHelper.overlay(frame, filePicker, 2, 1)
btn.clicked.connect(_showDialog)
btn1.clicked.connect(lambda : _showDialog(ttk.TTkK.FileMode.AnyFile))
btn3.clicked.connect(lambda : _showDialog(ttk.TTkK.FileMode.Directory))
return frame
@ -58,7 +63,7 @@ def main():
root.setLayout(ttk.TTkGridLayout())
winColor1 = root
else:
winColor1 = ttk.TTkWindow(parent=root,pos = (0,0), size=(50,20), title="Test File Picker", border=True, layout=ttk.TTkGridLayout())
winColor1 = ttk.TTkWindow(parent=root,pos = (0,0), size=(58,20), title="Test File/Folder Picker", border=True, layout=ttk.TTkGridLayout())
demoFilePicker(winColor1)

Loading…
Cancel
Save