It's my first time with curses module and I want make menu with this.
I have found example on internet for make this.
import curses
from curses import panel
class Menu(object):
def __init__(self, items, stdscreen):
self.window = stdscreen.subwin(0, 0)
self.window.keypad(1)
self.panel = panel.new_panel(self.window)
self.panel.hide()
panel.update_panels()
self.position = 0
self.items = items
self.items.append(("exit", "exit"))
def navigate(self, n):
self.position += n
if self.position < 0:
self.position = 0
elif self.position >= len(self.items):
self.position = len(self.items) - 1
def display(self):
self.panel.top()
self.panel.show()
self.window.clear()
while True:
self.window.refresh()
curses.doupdate()
for index, item in enumerate(self.items):
if index == self.position:
mode = curses.A_REVERSE
else:
mode = curses.A_NORMAL
msg = "%d. %s" % (index, item[0])
self.window.addstr(10 + index, 1, msg, mode)
key = self.window.getch()
if key in [curses.KEY_ENTER, ord("\n")]:
if self.position == len(self.items) - 1:
break
else:
self.items[self.position][1]()
elif key == curses.KEY_UP:
self.navigate(-1)
elif key == curses.KEY_DOWN:
self.navigate(1)
self.window.clear()
self.panel.hide()
panel.update_panels()
curses.doupdate()
class MyApp(object):
def __init__(self, stdscreen):
self.screen = stdscreen
curses.curs_set(0)
submenu_items = [("beep", curses.beep), ("flash", curses.flash)]
submenu = Menu(submenu_items, self.screen)
main_menu_items = [
("beep", curses.beep),
("flash", curses.flash),
("submenu", submenu.display),
]
main_menu = Menu(main_menu_items, self.screen)
main_menu.display()
if __name__ == "__main__":
curses.wrapper(MyApp)
It's work pretty good, but I want show a Banner for my title. For this I use rich module and pyfiglet like this :
from rich import print
from rich.text import Text
from rich.panel import Panel
banner = Text(pyfiglet.figlet_format("Title Test", font="bulbhead"), style="bold magenta")
bannerPanel = Panel(Text(pyfiglet.figlet_format("Title Test", font="bulbhead"), style="bold magenta").plain)
I can't add Text object or Panel object with self.window.addstr() because he want a string object.
Is it possible to show bannerPanel or banner above my menu?
Thanks in advance
The only thing I managed to do is add Text().plain.
what I need in this case is "uncheck or check" the items in QListView with mouse hold and press
I've added Items with check boxes , I need to change the state of the items (check or uncheck) for multi items with just press and hold , like making multi selection .
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
class items_List(QListView):
clicked = pyqtSignal()
def __init__(self,items):
QListView.__init__(self)
#self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.model = QStandardItemModel()
self.setModel(self.model)
self.model.itemChanged.connect(self.on_itemChanged)
self.items = items
self.add_items_(self.items)
self.show()
def add_items_(self,all_items=None):
self.active_items = []
if all_items == None:
return
for item in all_items:
#self.model.appendRow(str(i))
self.item = QStandardItem(str(item))
self.item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsSelectable)
self.item.setData(QVariant(Qt.Checked), Qt.CheckStateRole)
self.model.appendRow(self.item)
self.active_items.append(str(item))
def selected_item(self):
print "Selected "
#pyqtSlot(QStandardItem)
def on_itemChanged(self, item):
state = ['UNCHECKED', 'TRISTATE', 'CHECKED'][item.checkState()]
if state == 'UNCHECKED':
self.active_items.remove(item.text())
else:
if item.text() not in self.active_items:
self.active_items.append(str(item.text()))
print self.active_items
def main():
app = QApplication(sys.argv)
items = [1001,1002,1003,1004,1005]
win = items_List(items)
sys.exit(app.exec_())
if __name__ == "__main__":
main()
I have created subclass of QTreeWidget and QTreeWidgetItem where I am trying to highlight the new added items (where the text will be colored red).
The tree hierarchy that I have adopted is as follows:
|-- parent
|--|-- child
|--|-- child
The tree widget is initially populated from a dictionary.
To get the difference, I did it by converting the current hierarchy in the tree widget into a dictionary and have it compared against the initial dictionary that it was populated with.
However if I add in a new child to an existing parent in which the name of the new child already existed in another parent, the same method as mentioned above does not works, as it will colored the first result that it find.
To replicate:
select menuB
right mouse click > add new sub item
input name: a101
hit "Highlight Diff." button
a101 child item under menuA is highlighted instead of the one in menuB
What would be the best way to go in getting the index of newly added child(ren)?
Thank you for any replies.
P.S: If anyone has better suggestion for the parent highlighting, please feel free to chip in.
class CustomTreeWidgetItem(QtGui.QTreeWidgetItem):
def __init__(self, widget=None, text=None, is_tristate=False):
super(CustomTreeWidgetItem, self).__init__(widget)
self.setText(0, text)
if is_tristate:
# Solely for the Parent item
self.setFlags(
self.flags()
| QtCore.Qt.ItemIsTristate
| QtCore.Qt.ItemIsEditable
| QtCore.Qt.ItemIsUserCheckable
)
else:
self.setFlags(
self.flags()
| QtCore.Qt.ItemIsEditable
| QtCore.Qt.ItemIsUserCheckable
)
self.setCheckState(0, QtCore.Qt.Unchecked)
def setData(self, column, role, value):
state = self.checkState(column)
QtGui.QTreeWidgetItem.setData(self, column, role, value)
if (role == QtCore.Qt.CheckStateRole and
state != self.checkState(column)):
tree_widget = CustomTreeWidget()
if tree_widget is not None:
tree_widget.itemToggled.emit(self, column)
class CustomTreeWidget(QtGui.QTreeWidget):
def __init__(self, widget=None):
super(CustomTreeWidget, self).__init__(widget)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.show_custom_menu)
def show_custom_menu(self):
base_node = self.selectedItems()[0]
qmenu = QtGui.QMenu(self)
remove_action = QtGui.QAction("Remove item", self)
remove_action.triggered.connect(self.remove_selected_item)
qmenu.addAction(remove_action)
# The following options are only effected for top-level items
# top-level items do not have `parent()`
if not base_node.parent():
add_new_child_action = QtGui.QAction("Add new sub item", self)
add_new_child_action.triggered.connect(
partial(self.adds_new_child_item, base_node)
)
# qmenu.addAction(add_new_child_action)
qmenu.insertAction(remove_action, add_new_child_action)
qmenu.exec_(QtGui.QCursor.pos())
def add_item_dialog(self, title):
text, ok = QtGui.QInputDialog.getText(
self,
"Add {0} Item".format(title),
"Enter name for {0}-Item:".format(title)
)
if ok and text != "":
return text
def add_new_parent_item(self):
input_text = self.add_item_dialog("Parent")
if input_text:
CustomTreeWidgetItem(self, input_text, is_tristate=True)
def adds_new_child_item(self, base_node):
input_text = self.add_item_dialog("Sub")
if input_text:
CustomTreeWidgetItem(base_node, input_text)
self.setItemExpanded(base_node, True)
def remove_selected_item(self):
root = self.invisibleRootItem()
for item in self.selectedItems():
(item.parent() or root).removeChild(item)
def derive_tree_items(self, mode="all"):
all_items = defaultdict(list)
root_item = self.invisibleRootItem()
top_level_count = root_item.childCount()
for i in range(top_level_count):
top_level_item = root_item.child(i)
top_level_item_name = str(top_level_item.text(0))
child_num = top_level_item.childCount()
all_items[top_level_item_name] = []
for n in range(child_num):
child_item = top_level_item.child(n)
child_item_name = str(child_item.text(0)) or ""
if mode == "all":
all_items[top_level_item_name].append(child_item_name)
elif mode == "checked":
if child_item.checkState(0) == QtCore.Qt.Checked:
all_items[top_level_item_name].append(child_item_name)
elif mode == "unchecked":
if child_item.checkState(0) == QtCore.Qt.Unchecked:
all_items[top_level_item_name].append(child_item_name)
return all_items
class MainApp(QtGui.QWidget):
def __init__(self):
super(MainApp, self).__init__()
# initial dictionary that is populated into the tree widget
test_dict = {
"menuA": ["a101", "a102"],
"menuC": ["c101", "c102", "c103"],
"menuB": ["b101"],
}
self._tree = CustomTreeWidget()
self._tree.header().hide()
for pk, pv in sorted(test_dict.items()):
parent = CustomTreeWidgetItem(self._tree, pk, is_tristate=True)
for c in pv:
child = CustomTreeWidgetItem(parent, c)
self.orig_dict = self._tree.derive_tree_items()
# Expand the hierarchy by default
self._tree.expandAll()
tree_layout = QtGui.QVBoxLayout()
self.btn1 = QtGui.QPushButton("Add new item")
self.btn2 = QtGui.QPushButton("Highlight Diff.")
tree_layout.addWidget(self._tree)
tree_layout.addWidget(self.btn1)
tree_layout.addWidget(self.btn2)
main_layout = QtGui.QHBoxLayout()
main_layout.addLayout(tree_layout)
self.setLayout(main_layout)
self.setup_connections()
def setup_connections(self):
self.btn1.clicked.connect(self.add_parent_item)
self.btn2.clicked.connect(self.highlight_diff)
def add_parent_item(self):
# Get current selected in list widget
# CustomTreeWidgetItem(self._tree, "test", is_tristate=True)
self._tree.add_new_parent_item()
def highlight_diff(self):
self.current_dict = self._tree.derive_tree_items()
if self.orig_dict != self.current_dict:
# check for key difference
diff = [k for k in self.current_dict if k not in self.orig_dict]
if diff:
# get the difference of top-level items
for d in diff:
top_item = self._tree.findItems(d, QtCore.Qt.MatchExactly|QtCore.Qt.MatchRecursive)
#print aaa[0].childCount()
top_item[0].setTextColor(0, QtGui.QColor(255, 0, 0))
if top_item[0].childCount():
for n in range(top_item[0].childCount()):
top_item[0].child(n).setTextColor(0, QtGui.QColor(255, 0, 0))
# to highlight the child diff. of existing top-items
# issue with this portion if the new added item name already existed
for k, v in self.current_dict.items():
if k in self.orig_dict:
diff = set(v).difference(self.orig_dict.get(k), [])
for d in diff:
child_item = self._tree.findItems(d, QtCore.Qt.MatchExactly|QtCore.Qt.MatchRecursive)
child_item[0].setTextColor(0, QtGui.QColor(255, 0, 0))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = MainApp()
w.show()
sys.exit(app.exec_())
You can save in a role a flag indicating if it is a new item or not and change the color using a delegate:
import sys
from functools import partial
from PyQt4 import QtCore, QtGui
from collections import defaultdict
IsNewItemRole = QtCore.Qt.UserRole + 1000
class CustomTreeDelegate(QtGui.QStyledItemDelegate):
#property
def text_color(self):
if not hasattr(self, "_text_color"):
self._text_color = QtGui.QColor()
return self._text_color
#text_color.setter
def text_color(self, color):
self._text_color = color
def initStyleOption(self, option, index):
super(CustomTreeDelegate, self).initStyleOption(option, index)
if self.text_color.isValid() and index.data(IsNewItemRole):
option.palette.setBrush(QtGui.QPalette.Text, self.text_color)
class CustomTreeWidgetItem(QtGui.QTreeWidgetItem):
def __init__(self, parent=None, text="", is_tristate=False, is_new_item=False):
super(CustomTreeWidgetItem, self).__init__(parent)
self.setText(0, text)
flags = QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsUserCheckable
if is_tristate:
flags |= QtCore.Qt.ItemIsTristate
else:
self.setCheckState(0, QtCore.Qt.Unchecked)
self.setFlags(self.flags() | flags)
self.setData(0, IsNewItemRole, is_new_item)
def setData(self, column, role, value):
state = self.checkState(column)
QtGui.QTreeWidgetItem.setData(self, column, role, value)
if role == QtCore.Qt.CheckStateRole and state != self.checkState(column):
tree_widget = self.treeWidget()
if isinstance(tree_widget, CustomTreeWidget):
tree_widget.itemToggled.emit(self, column)
class CustomTreeWidget(QtGui.QTreeWidget):
itemToggled = QtCore.pyqtSignal(QtGui.QTreeWidgetItem, int)
def __init__(self, widget=None):
super(CustomTreeWidget, self).__init__(widget)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.show_custom_menu)
def show_custom_menu(self, pos):
base_node = self.itemAt(pos)
if base_node is None:
return
qmenu = QtGui.QMenu(self)
remove_action = QtGui.QAction("Remove item", self)
remove_action.triggered.connect(self.remove_selected_item)
qmenu.addAction(remove_action)
# The following options are only effected for top-level items
# top-level items do not have `parent()`
if base_node.parent() is None:
add_new_child_action = QtGui.QAction("Add new sub item", self)
add_new_child_action.triggered.connect(
partial(self.adds_new_child_item, base_node)
)
# qmenu.addAction(add_new_child_action)
qmenu.insertAction(remove_action, add_new_child_action)
qmenu.exec_(self.mapToGlobal(pos))
def add_item_dialog(self, title):
text, ok = QtGui.QInputDialog.getText(
self, "Add {0} Item".format(title), "Enter name for {0}-Item:".format(title)
)
if ok:
return text
def add_new_parent_item(self):
input_text = self.add_item_dialog("Parent")
if input_text:
it = CustomTreeWidgetItem(
self, input_text, is_tristate=True, is_new_item=True
)
def adds_new_child_item(self, base_node):
input_text = self.add_item_dialog("Sub")
if input_text:
it = CustomTreeWidgetItem(base_node, input_text, is_new_item=True)
self.setItemExpanded(base_node, True)
it.setData(0, IsNewItemRole, True)
def remove_selected_item(self):
root = self.invisibleRootItem()
for item in self.selectedItems():
(item.parent() or root).removeChild(item)
class MainApp(QtGui.QWidget):
def __init__(self, parent=None):
super(MainApp, self).__init__(parent)
# initial dictionary that is populated into the tree widget
test_dict = {
"menuA": ["a101", "a102"],
"menuC": ["c101", "c102", "c103"],
"menuB": ["b101"],
}
self._tree = CustomTreeWidget()
self._tree.header().hide()
self._tree_delegate = CustomTreeDelegate(self._tree)
self._tree.setItemDelegate(self._tree_delegate)
for pk, pv in sorted(test_dict.items()):
parent = CustomTreeWidgetItem(self._tree, pk, is_tristate=True)
for c in pv:
child = CustomTreeWidgetItem(parent, c)
# Expand the hierarchy by default
self._tree.expandAll()
tree_layout = QtGui.QVBoxLayout()
self.btn1 = QtGui.QPushButton("Add new item")
self.btn2 = QtGui.QPushButton("Highlight Diff.")
tree_layout.addWidget(self._tree)
tree_layout.addWidget(self.btn1)
tree_layout.addWidget(self.btn2)
main_layout = QtGui.QHBoxLayout(self)
main_layout.addLayout(tree_layout)
self.setup_connections()
def setup_connections(self):
self.btn1.clicked.connect(self.add_parent_item)
self.btn2.clicked.connect(self.highlight_diff)
def add_parent_item(self):
# Get current selected in list widget
# CustomTreeWidgetItem(self._tree, "test", is_tristate=True)
self._tree.add_new_parent_item()
def highlight_diff(self):
self._tree_delegate.text_color = QtGui.QColor(255, 0, 0)
self._tree.viewport().update()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = MainApp()
w.show()
sys.exit(app.exec_())
I working with gtk.fileselection and it works perfectly. But how can I block the access to a given path with fileselection widget.
If I do not block access to a certain path, the user can see sensitive information inside my system.
class FileSelection:
# Get the selected filename and print it to the console
def file_ok_sel(self, w):
print "%s" % self.filew.get_filename()
def destroy(self, widget):
gtk.main_quit()
def __init__(self):
#Create a new file selection widget
self.filew = gtk.FileSelection("File selection")
self.filew.hide_fileop_buttons()
self.filew.get_focus()
self.filew.connect("destroy", self.destroy)
# Connect the ok_button to file_ok_sel method
self.filew.ok_button.connect("clicked", self.file_ok_sel)
# Connect the cancel_button to destroy the widget
self.filew.cancel_button.connect("clicked",lambda w: self.filew.destroy())
# Lets set the filename, as if this were a save dialog,
# and we are giving a default filename
self.filew.set_filename("penguin.png")
self.filew.show()
def main(self):
gtk.main()
print "selection"*10
return 0
In fact I would like to allow access only to the paths that hang from "mnt/tnc/" and not allow access to any more.
archivosTNC = os.listdir("/mnt/tnc")
lista = []
for a in archivosTNC:
if a[-2:] == ".H":
lista.append(a)
elif a[-4:] == ".txt":
lista.append(a)
elif a[-4:] == ".png":
lista.append(a)
elif a[-4:] == ".jpg":
lista.append(a)
ventana = gtk.Window()
ventana.set_default_size(-1, 300)
scrolledWindow = gtk.ScrolledWindow()
scrolledWindow.set_policy (hscrollbar_policy=gtk.POLICY_NEVER, vscrollbar_policy=gtk.POLICY_AUTOMATIC)
ventana.add(scrolledWindow)
tabla=table()
vbox = gtk.VBox()
tabla.attachToCell(vbox, col=1, row=1)
scrolledWindow.add_with_viewport(tabla)
#ventana.add(vbox)
for item in lista:
boton = gtk.Button(str(item))
boton.connect('clicked', self.devolverNombreArchivo)
vbox.pack_start(boton)
I am creating a custom qtreewidget class that autoresizes its window to fit exactly the currently visible elements (I don't want to have to scroll). To do this, I run a count function to find the number of open qtreewidgetitems and their children and set a fixed height from there. However, when I expand a child widget (click the expand arrow on one of my items) the whole view suddenly needs to scroll because there is extra white space at the bottom, despite my count function accurately calculating the needed height. How do I get rid of it?
Below is a working class that can be run directly as is.
import sys
from PyQt4 import QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class TreeWidget(QTreeWidget):
def __init__(self, parent=None):
super(TreeWidget, self).__init__()
self.installEventFilter(self)
self.setStyleSheet('''
background: None;
border: None;
outline: None;
outline-width: 0px;
selection-background-color: blue;
''')
header = QtGui.QTreeWidgetItem(["Tree", "First"])
self.setAutoScroll(False)
self.setHeaderItem(header)
self.header().close()
# self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
def fill_item(self, item, value):
item.setExpanded(False)
if type(value) is dict:
for key, val in sorted(value.iteritems()):
child = QTreeWidgetItem()
child.setText(0, unicode(key))
# child.doubleClicked.connect(lambda: self.doubleClicked1(child))
item.addChild(child)
self.fill_item(child, val)
elif type(value) is list:
last = None
for val in value:
child = QTreeWidgetItem()
if type(val) is dict:
item.addChild(child)
child.setText(0, '[dict]')
# child.doubleClicked.connect(lambda: self.doubleClicked1(child))
self.fill_item(child, val)
last = child
elif type(val) is list:
self.fill_item(last, val)
else:
item.addChild(child)
child.setText(0, unicode(val))
child.setText(1, 'test')
# child.doubleClicked.connect(lambda: self.doubleClicked1(child))
child.setExpanded(False)
last = child
else:
child = QTreeWidgetItem()
child.setText(0, unicode(val))
child.setText(1, 'test')
# child.doubleClicked.connect(lambda: self.doubleClicked1(child))
item.addChild(child)
def fill_widget(self, value):
self.clear()
self.fill_item(self.invisibleRootItem(), value)
def resizeEvent(self, event):
self.resize()
def resize(self):
width = 50
self.header().resizeSection(1, width)
self.header().resizeSection(0, self.width()-width)
height = self.visibleCount()
print height/15
self.setFixedHeight(height+0)
def eventFilter(self, source, event):
if source is self:
if event.type() == 1:
self.resize()
elif event.type() == QEvent.Leave:
self.clearSelection()
return QtGui.QTreeWidget.eventFilter(self, source, event)
def visibleCount(self, parent=0):
height = 0
if parent == 0:
topHeight = 0
for a in xrange(self.topLevelItemCount()):
item = self.topLevelItem(a)
topHeight += self.visualItemRect(item).height()
if item.isExpanded():
height += self.visibleCount(item)
height += topHeight
else:
childHeight = 0
for a in xrange(parent.childCount()):
item = parent.child(a)
childHeight += self.visualItemRect(item).height()
if item.isExpanded():
height += self.visibleCount(item)
height += childHeight
return height
def editClicked(self, parent=0):
# print 'edit 2'
if parent == 0:
for a in xrange(self.topLevelItemCount()):
item = self.topLevelItem(a)
print type(item)
item.setExpanded(True)
self.editClicked(item)
else:
for a in xrange(parent.childCount()):
item = parent.child(a)
print type(item)
item.setText(1, '+')
item.setExpanded(True)
self.editClicked(item)
def doubleClicked1(self, widget):
print widget
def main():
app = QtGui.QApplication(sys.argv)
ex = TreeWidget()
data = [
'Make sure ZMQ remote button gets honored',
'Fill in plot',
'Remove cycle',
'Remove current control or make it working',
'Handle possible startup errors with dialogs',
'Get improved current read-out (requires hardware changes)',
['1','2','3'],
'Email quench notification'
]
ex.fill_widget(data)
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You can remove the event filter entirely. You need to resize the widget when the items are expanded or collapsed. Both actions trigger signals, so you can simply connect those signals to resize:
class TreeWidget(QTreeWidget):
def __init__(self, parent=None):
super(TreeWidget, self).__init__(parent)
self.expanded.connect(self.resize)
self.collapsed.connect(self.resize)