set up the entry of a combobox (gtk) - gtk

How could I set up the text of a combobox without knowing its id? I have a combobox populated with a list of name ('Jack','Emily','Paul',...). By default, the combo is set on -1 but I want it to be set on "Paul".
Here is my code to declare and populate the combo with tuple (id,fabName) :
self.cmbFabricant = builder.get_object("cmbFabricant")
self.cmbFabricant.set_model(lstStore)
self.cmbFabricant.set_entry_text_column(1)
Now, I'd like to set the combobox on the item called "Paul". I thought I could write :
self.cmbFabricant.set_active_id('Paul')
I was wrong.

I could be wrong, but I think set_active_id is new in GTK+ 3, and PyGTK is GTK+ 2. If you want to use GTK+ 3, you have to switch to PyGObject.
But if you're stuck on PyGTK, you can easily work around it by doing something like this:
import gtk
def set_active_name(combobox, col, name):
liststore = combobox.get_model()
for i in xrange(len(liststore)):
row = liststore[i]
if row[col] == name:
combobox.set_active(i)
window = gtk.Window()
window.connect("destroy", gtk.main_quit)
liststore = gtk.ListStore(int, str)
liststore.append([0, 'Jack'])
liststore.append([1, 'Emily'])
liststore.append([2, 'Paul'])
combobox = gtk.ComboBox()
cell = gtk.CellRendererText()
combobox.pack_start(cell)
combobox.add_attribute(cell, 'text', 1)
combobox.set_model(liststore)
set_active_name(combobox, 1, 'Paul')
window.add(combobox)
window.show_all()
gtk.main()
I'm not sure if there is a more elegant/efficient way, but this works at least.

Related

Adding checkable combobox in QGIS plugin builder plugin

I am developing a QGIS plugin in python and hit a roadblock when displaying my GUI. I am using the plugin builder framework to develop my plugin and I have trouble displaying a checkable combo box in a scrollArea in my GUI. The code with core functionality is as follows.
def run(self):
# Only create GUI ONCE in callback, so that it will only load when the plugin is started
if self.first_start == True:
self.first_start = False
# Sets up the pyqt user interface
self.dlg = EarthingToolDialog()
# Fetching the active layer in the QGIS project
layer = self.iface.activeLayer()
checkable_combo = CheckableComboBox()
# Going through each field of the layer
# and adding field names as items to the
# combo box
for j,field in enumerate(layer.fields()):
checkable_combo.addItem(str(field.name()))
# Setting the checked state to True by default
checkable_combo.setItemChecked(j, True)
# putting the check box inside the scroll area of the GUI
self.dlg.scrollArea.setWidget(checkable_combo)
self.dlg.scrollArea.setMinimumSize(QSize(700,400))
# show the dialog
self.dlg.show()
# Run the dialog event loop
self.dlg.exec_()
class EarthingToolDialog(QtWidgets.QDialog, FORM_CLASS):
def __init__(self, parent=None):
"""Constructor."""
super(EarthingToolDialog, self).__init__(parent)
self.setupUi(self)
class CheckableComboBox(QComboBox):
def __init__(self):
super().__init__()
self._changed = False
self.view().pressed.connect(self.handleItemPressed)
def setItemChecked(self, index, checked=False):
print('checked')
item = self.model().item(index, self.modelColumn()) # QStandardItem object
print(type(item))
if checked:
item.setCheckState(Qt.CheckState.Checked)
else:
item.setCheckState(Qt.CheckState.Unchecked)
def handleItemPressed(self, index):
print('pressed')
item = self.model().itemFromIndex(index)
if item.checkState() == Qt.Checked:
item.setCheckState(Qt.Unchecked)
else:
item.setCheckState(Qt.Checked)
self._changed = True
print('set ' + str(item.checkState()))
def hidePopup(self):
print('hide')
if not self._changed:
super().hidePopup()
self._changed = False
def itemChecked(self, index):
print('read')
item = self.model().item(index, self.modelColumn())
return item.checkState() == Qt.Checked
In summary, the run function is the main function called by the plugin when it is loaded. self.dlg is the instance of the actual pyqt python user interface. This is rendered with the help of the EarthingToolDialog class. The checkable combo box and it's functionalities are self contained in the CheckableComboBox class.
The run function executes without any error when the plugin is loaded but the checkboxes are not visible in the combobox. Just a normal combo box with a list of items (just the standard dropdown combo box) is seen on the GUI's scroll area and not the desired checkable combo box. The CheckableComboBox class was taken from https://morioh.com/p/d1e70112347c and it runs perfectly well in the demo code shown there.
I understand that this is a very specific question and it would be great if someone could figure out what the problem might be. Thanks in advance!
Within the run function, this piece of codes didn't work for me:
self.dlg.scrollArea.setWidget(checkable_combo)
self.dlg.scrollArea.setMinimumSize(QSize(700,400))
So instead, I use:
layout = QVBoxLayout()
layout.addWidget(checkable_combo)
self.dlg.setLayout(layout)
I didn't use directly this class (It was generated automatically since I use Plugin Builder, so in here I commented it):
class EarthingToolDialog(QtWidgets.QDialog, FORM_CLASS):
def __init__(self, parent=None):
"""Constructor."""
super(EarthingToolDialog, self).__init__(parent)
self.setupUi(self)
Now, in order to display checkable combo box, CheckableComboBox constructor is changed as :
def __init__(self):
super().__init__()
self._changed = False
self.view().pressed.connect(self.handleItemPressed)
delegate = QtWidgets.QStyledItemDelegate(self.view())
self.view().setItemDelegate(delegate)
The last two lines are from the answer listed here.
Codes display checkable combo box list with all items checked by default.

Editable label in Python GTK+ 3?

I'm new to GTK programming. I want to have a Label widget whose text can be edited, kind of like this: https://docs.gtk.org/gtk4/class.EditableLabel.html.
The problem is I have no idea how to implement this. I understand that Gtk.Button has a set_label() function, though I don't know how to use it to make an editable label.
You can do that with Gtk.Entry which you can set_editable based on "something". Example with check button would look something like this:
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
def on_editable_toggled(button, entry):
value = button.get_active()
entry.set_editable(value)
entry.set_sensitive(value)
win = Gtk.Window()
win.connect("destroy", Gtk.main_quit)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
win.add(vbox)
entry = Gtk.Entry()
entry.set_text("Hello World")
vbox.pack_start(entry, True, True, 0)
check_editable = Gtk.CheckButton(label="Editable")
check_editable.connect("toggled", on_editable_toggled, entry)
check_editable.set_active(True)
vbox.pack_start(check_editable, True, True, 0)
win.show_all()
Gtk.main()
It doesn't really look like a label, but you can use the Gtk CSS styling to change the background and border colors to make it look like one when it is set to non-editable.

ITextSharp errror "Off is not a valid name for a checkbox appearance (should be Off or Yes)"

Running the following code snippet under VS 2010 using iTextSharp 5.5.6:
PdfReader reader = new PdfReader("Test.pdf");
FileStream fs = new FileStream("New.pdf", FileMode.Create);
PdfStamper p = new PdfStamper(reader, fs);
AcroFields form = p.AcroFields;
...
RadioCheckField newField = new RadioCheckField(p.Writer, new iTextSharp.text.Rectangle(20, 20), "MyCheckBox", "Off");
PdfFormField RadioField = newField.CheckField;
p.AddAnnotation(RadioField, 1);
I receive the error "ITextSharp errror "Off is not a valid name for a checkbox appearance (should be Off or Yes)" at the line declaring the RadioField object. Is this a bug? How do I work around it?
A check box can have two values:
one you define yourself in your method. That will be the value of the check box when selected.
one that is defined in ISO-32000-1: Off. That's the value of the check box when it's not selected.
There is a bug in your code because you are trying to create a check box of which the value is always Off whether it's selected or not.
Choose another value. Off is reserved for the off state. You need yo define a value for the on state. ISO-32000-1 recommends Yes.
This is how you make sure the check box is selected:
newField.Checked = true;
Unchecked is done like this:
newField.Checked = false;

adding/changing 'text' to an item in a group

I'm designing a UI with Enthought's TraitsUI, and I can't figure out how to get done what I want...
Here's what I want:
I have Items() in the view that I want to display as either English or SI units. I can change the value in the 'edit' box based on a SI/English button, but I can't figure out how to change the text of the label. For example, if I have an item 'Length, ft [ 3.28]' and convert it to SI, I'd like it to show 'Length, m [ 1.00]'. I can handle the 3.28->1.00 conversion, but can't figure out how to change the 'ft' to 'm'.
Any suggestions?
One thing I've tried is to define a string which holds the units name (like 'm' or 'ft')...then, in the item, I set the label like this:
label = 'Top, '+lengthUnits
This works fine when the view is first built, but it doesn't update the label when I change the units control. Is there some way to force the view to update with all the new values?
Here's a small py program that shows what I'm trying to do (feel free to critique my style :)). I'll also try and add in a couple of images that shows what happens:
# NOTE: This version of the code has been modified so that it works as I want it to :)
# Example trying to change text on a View...
from traits.api \
import HasTraits, Enum, CFloat, String
from traitsui.api \
import View, Group, HGroup, Item, spring
class TestDialog ( HasTraits ):
length = CFloat(1.0)
choose_units = Enum('English', 'SI')
current_units = 'English'
unit_name = String('ft')
ft_to_m = CFloat(3.28)
view = View(
Group(
HGroup(
spring,
Item(name = "length", label = 'Test length'),
Item(name = 'unit_name', style = 'readonly', show_label = False),
spring
),
HGroup(
spring,
Item(name = "choose_units"),
spring
)
),
title = 'Test Changing View Test'
)
def _choose_units_changed(self):
if self.current_units != self.choose_units:
if self.choose_units == 'SI':
self.length /= self.ft_to_m
self.unit_name = 'm'
else:
self.length *= self.ft_to_m
self.unit_name = 'ft'
self.current_units = self.choose_units
# Run the program (if invoked from the command line):
if __name__ == '__main__':
# Create the dialog:
TestIt = TestDialog()
# put the actual dialog up...
TestIt.configure_traits()
Use a notification as described here: http://code.enthought.com/projects/traits/docs/html/traits_user_manual/notification.html
Update in response to updated question:
Right, labels are not dynamically updated. Instead, make a text field that looks like a label, e.g. with:
label_text = String('Test length, English:')
Then display it in your View with something like:
Item("label_text", style='readonly', show_label=False),
You'll probably also want to use an HGroup nested inside your (V)Group, to position it to the left of your "length" display.
Then modify label_text inside your listener.

PyQt4: Items disappear when using Drag and Drop with QComboBox

I would like to use drag-and-drop to rearrange the items in a QComboBox. I tried this:
from PyQt4.QtGui import QApplication, QComboBox, QAbstractItemView
a = QApplication([''])
c = QComboBox()
c.addItem('a')
c.addItem('b')
c.addItem('c')
c.addItem('d')
view = c.view()
view.setDragDropMode(QAbstractItemView.InternalMove)
c.show()
c.raise_()
a.exec_()
However, dragging an item on top of another item deletes the dragged item -- I want that item to be moved above/below the drop location. Am I doing this incorrectly?
Each combo item needs to be disabled as a drop target by setting the appropriate item flags.
Here's one way to achieve that:
import sys
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication(sys.argv)
combo = QtGui.QComboBox()
model = QtGui.QStandardItemModel()
for text in 'One Two Three Four'.split():
item = QtGui.QStandardItem(text)
item.setFlags(item.flags() & ~QtCore.Qt.ItemIsDropEnabled)
model.appendRow(item)
combo.setModel(model)
combo.view().setDragDropMode(QtGui.QAbstractItemView.InternalMove)
combo.show()
app.exec_()