Getting selected text (python-gtk) - python

I want to get selected text automatically in python, using gtk module.
There is a code to get selected text from anywhere:
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
class GetSelectionExample:
# Signal handler invoked when user clicks on the
# "Get String Target" button
def get_stringtarget(self, widget):
# And request the "STRING" target for the primary selection
ret = widget.selection_convert("PRIMARY", "STRING")
return
# Signal handler called when the selections owner returns the data
def selection_received(self, widget, selection_data, data):
# Make sure we got the data in the expected form
if str(selection_data.type) == "STRING":
# Print out the string we received
print "STRING TARGET: %s" % selection_data.get_text()
elif str(selection_data.type) == "ATOM":
# Print out the target list we received
targets = selection_data.get_targets()
for target in targets:
name = str(target)
if name != None:
print "%s" % name
else:
print "(bad target)"
else:
print "Selection was not returned as \"STRING\" or \"ATOM\"!"
return False
def __init__(self):
# Create the toplevel window
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("Get Selection")
window.set_border_width(10)
window.connect("destroy", lambda w: gtk.main_quit())
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
# Create a button the user can click to get the string target
button = gtk.Button("Get String Target")
eventbox = gtk.EventBox()
eventbox.add(button)
button.connect_object("clicked", self.get_stringtarget, eventbox)
eventbox.connect("selection_received", self.selection_received)
vbox.pack_start(eventbox)
eventbox.show()
button.show()
window.show()
def main():
gtk.main()
return 0
if __name__ == "__main__":
GetSelectionExample()
main()
But i don't want to this exactly.
i dont want to click a button. I want to see the selected text only, not after a button clicking. When i start the program ; it must show me the selected text automatically (without clicking any button!).
I want to this exactly :
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
class MyApp (object):
def __init__(self):
self.window=gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect("delete_event", gtk.main_quit )
self.entry = gtk.Entry()
try:
self.s_text=gtk.SelectionData.get_text
# i expect that : the selected text (from anywhere)
# but it returns me :
#<method 'get_text' of 'gtk.SelectionData' objects>
except:
self.s_text="it must be selected text"
self.entry.set_text("Selected Text is : %s" % self.s_text )
self.window.add(self.entry)
self.window.show_all()
def main(self):
gtk.main()
app=MyApp()
app.main()
This program must show me the selected text in the entry box automatically.
Only this. But i can't do!
i expect " gtk.SelectionData.get_text " will show me the selected text but it returns "<method 'get_text' of 'gtk.SelectionData' objects>" .
And also i tried self.s_text=gtk.SelectionData.get_text()
But it returns me :
self.s_text=gtk.SelectionData.get_text()
TypeError: descriptor 'get_text' of 'gtk.SelectionData' object needs an argument
How can i do this? And also i am a beginner python programmer; if u can write the code ; it will be very good for me :)
thanks a lot !!

self.s_text=gtk.SelectionData.get_text
Method get_text is not called yet! You are assigning self.s_text to the method(function) object itself. Which is converted to string in "Selected Text is : %s" % self.s_text
You should changed it to:
self.s_text=gtk.SelectionData.get_text()
EDIT: But since you need a SelectionData object to pass to this method, the whole idea is wrong. I combined you two codes as something working:
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
class MyApp (object):
def __init__(self):
self.window=gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect("delete_event", gtk.main_quit )
self.entry = gtk.Entry()
self.window.selection_convert("PRIMARY", "STRING")
self.window.connect("selection_received", self.selection_received)
self.window.add(self.entry)
self.window.show_all()
# Signal handler called when the selections owner returns the data
def selection_received(self, widget, selection_data, data):
print 'selection_data.type=%r'%selection_data.type
# Make sure we got the data in the expected form
if str(selection_data.type) == "STRING":
self.entry.set_text("Selected Text is : %s" % selection_data.get_text())
elif str(selection_data.type) == "ATOM":
# Print out the target list we received
targets = selection_data.get_targets()
for target in targets:
name = str(target)
if name != None:
self.entry.set_text("%s" % name)
else:
self.entry.set_text("(bad target)")
else:
self.entry.set_text("Selection was not returned as \"STRING\" or \"ATOM\"!")
return False
def main(self):
gtk.main()
app=MyApp()
app.main()

Related

blender python increment an integer

I'm pretty sure this has been answered, but I can't seem to locate it.
What I want is a python script for Blender that creates a custom tab that contains a button. When that button is pressed, it prints the value of an integer and increments it, so that when you press the button again, it shows an incremented value. Everything seems to work, except for the incremental part.
Here is the code I am using at the moment:
===
import bpy
from bpy.props import (IntProperty,)
from bpy.types import (Panel, Operator, AddonPreferences, PropertyGroup,)
def main(context):
my_number += 1
print(str(my_number))
class MySettings(PropertyGroup):
my_number = IntProperty(
name="Int property",
description="This is an integer.",
default = 1
)
class AddOne(bpy.types.Operator):
"""This is an operator"""
bl_idname = "op.add_one"
bl_label = "Increment by 1"
def execute(self, context):
main(context)
return {'FINISHED'}
class CreatePanel(bpy.types.Panel):
bl_label = "Render Setup Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'TOOLS'
bl_category = "Increment by 1 Tab"
def draw(self, context):
layout = self.layout
obj = context.object
row = layout.row()
row.operator("op.add_one")
def register():
bpy.utils.register_class(AddOne)
bpy.utils.register_class(MySettings)
bpy.utils.register_class(CreatePanel)
def unregister():
bpy.utils.unregister_class(AddOne)
bpy.utils.unregister_class(MySettings)
bpy.utils.unregister_class(CreatePanel)
if __name__ == "__main__":
register()
===
However, when I press the button 'Increment by 1', I get the following error:
"local variable 'my_number' referenced before assignment"
The point of this exercise is just to create an integer variable, store it, then increment it's value and print it out.
EDIT: I added the actual code, rather than an image of it.
The variable my_number is defined in the class MySettings - it can only be accessed through that class, whether that is inside a method that is also part of the class (self.my_number) or directly as a property that is part of an instance of the class (settings_instance.my_number).
You need to find a place outside of the operator and panel to store persistent variables. Adding a custom property to the object or scene types are common options. As you are showing your panel in the node editor, maybe you will want to add it to the material to keep it specific to a material, instead of global to the scene. You define these properties in the addons register() and remove them in unregister().
def register():
bpy.types.Scene.my_settings = bpy.props.PointerProperty(type=MySettings)
def unregister():
del bpy.types.Scene.my_settings
Then in your operator (or main() function) and your panel you can access the variable through the context paramater.
context.scene.my_settings.my_number += 1
Putting that together into your example, with a label to show the value -
import bpy
from bpy.props import (IntProperty,)
from bpy.types import (Panel, Operator, AddonPreferences, PropertyGroup,)
def main(context):
context.scene.my_settings.my_number += 1
print(str(context.scene.my_settings.my_number))
class MySettings(PropertyGroup):
my_number: IntProperty(
name="Int property",
description="This is an integer.",
default = 1
)
class AddOne(Operator):
"""This is an operator"""
bl_idname = "op.add_one"
bl_label = "Increment by 1"
def execute(self, context):
main(context)
return {'FINISHED'}
class CreatePanel(Panel):
bl_label = "Render Setup Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
bl_category = "Increment by 1 Tab"
def draw(self, context):
layout = self.layout
obj = context.object
row = layout.row()
row.operator("op.add_one")
row = layout.row()
row.label(text='Value is: '+str(context.scene.my_settings.my_number))
def register():
bpy.utils.register_class(AddOne)
bpy.utils.register_class(MySettings)
bpy.utils.register_class(CreatePanel)
bpy.types.Scene.my_settings = bpy.props.PointerProperty(type=MySettings)
def unregister():
bpy.utils.unregister_class(AddOne)
bpy.utils.unregister_class(MySettings)
bpy.utils.unregister_class(CreatePanel)
del bpy.types.Scene.my_settings
if __name__ == "__main__":
register()
You will find blender.stackexchange a better place to ask for blender specific python help.
Generally this problem "local variable 'my_number' referenced before assignment" comes when you have 'my_number' variable in code and you had not initialized that variable at top of your code or before using that variable do one thing .
Declare my_number=0 and then do your calculation on my_number variable .

PYQT: QTableView. Filter Between Dates

I've created a GUI that allows users to modify, filter update and delete from a sqlite database. Everything is working great except the date range filter. When I run the code, I don't get an error, I only get a blank filtered screen with no data. Does anyone see what's wrong with my code? [Section 1a, subgroup{v} is what I am seeking help on]. Thanks!
from PyQt4 import QtCore, QtGui, QtSql
import sys
import sqlite3
import time
import Search #imported ui.py MainWindow file
import os
try:
from PyQt4.QtCore import QString
except ImportError:
QString = str
class TableEditor(QtGui.QMainWindow, Search.Search_MainWindow):
def __init__(self, tableName, parent=None):
super(self.__class__, self).__init__()
self.setupUi(self)
self.model = QtSql.QSqlTableModel(self)
self.model.setTable('CAUTI')
self.model.setEditStrategy(QtSql.QSqlTableModel.OnManualSubmit)
self.model.select()
self.model.setHeaderData(0, QtCore.Qt.Horizontal, "MRN")
self.model.setHeaderData(1, QtCore.Qt.Horizontal, "Last Name")
self.model.setHeaderData(2, QtCore.Qt.Horizontal, "First Name")
self.model.setHeaderData(3, QtCore.Qt.Horizontal, "Date of Event")
self.model.setHeaderData(4, QtCore.Qt.Horizontal, "Facility")
self.model.setHeaderData(5, QtCore.Qt.Horizontal, "Unit")
self.model.setHeaderData(6, QtCore.Qt.Horizontal, "User")
self.tableView.setModel(self.model)
self.setWindowTitle("HAI Table")
self.tableView.setColumnWidth(0,100)
self.tableView.setColumnWidth(1,100)
self.tableView.setColumnWidth(2,100)
self.tableView.setColumnWidth(3,100)
self.tableView.setColumnWidth(4,100)
self.tableView.setColumnWidth(5,100)
self.tableView.setColumnWidth(6,83)
self.submitButton.clicked.connect(self.submit)
self.revertButton.clicked.connect(self.model.revertAll)
self.quitButton.clicked.connect(self.close)
current = QtCore.QDateTime.currentDateTime()
self.startDate.setDate(current.date())
self.endDate.setDate(current.date())
self.startDate.setDisplayFormat("M/dd/yyyy")
self.endDate.setDisplayFormat("M/dd/yyyy")
# Section 1: Signals
# {i} Search Fields Button Emitted:
# [1]
self.search_MRN_Button.clicked.connect(self.search_MRN_FilterRecord)
# [2]
self.search_Lname_Button.clicked.connect(self.search_Lname_FilterRecord)
# [3]
self.search_Unit_Button.clicked.connect(self.search_Unit_FilterRecord)
# {ii} Search Clear Buttons Emitted:
# [1]
self.search_MRN_CancelButton.clicked.connect(self.search_MRN_CancelButton_Clicked)
# [2]
self.search_Lname_CancelButton.clicked.connect(self.search_Lname_CancelButton_Clicked)
# [3]
self.search_Unit_CancelButton.clicked.connect(self.search_Unit_CancelButton_Clicked)
# {iii} Search Fields Button Emitted:
# [1]
self.search_MRN.selectionChanged.connect(self.search_MRN_Edit)
# [2]
self.search_Lname.selectionChanged.connect(self.search_Lname_Edit)
# [3]
self.search_Unit.selectionChanged.connect(self.search_Unit_Edit)
# {iv} Search Fields Button Emitted:
# [1]
self.search_MRN.returnPressed.connect(self.search_MRN_Enter)
# [2]
self.search_Lname.returnPressed.connect(self.search_Lname_Enter)
# [3]
self.search_Unit.returnPressed.connect(self.search_Unit_Enter)
#{v} Search Between 2 Dates
self.btnSubmit.clicked.connect(self.FilterBetweenDates)
# Section 1a: Slots from Section 1.
#{i} Search Field Button Slots:
#[1]
def search_MRN_FilterRecord(self):
text = self.search_MRN.text()
if len(text) == 0:
self.model.setFilter("")
else:
self.model.setFilter("MRN like'" +self.search_MRN.text()+ "%%'")
#self.model.setFilter("MRN = '%s'" % text)
#[2]
def search_Lname_FilterRecord(self):
text = self.search_Lname.text()
if len(text) == 0:
self.model.setFilter("")
else:
self.model.setFilter("Surname like'" +self.search_Lname.text()+ "%'")
#self.model.setFilter("Surname = '%s'" % text) #This line of code will only pull exact matches.
#[3]
def search_Unit_FilterRecord(self):
text = self.search_Unit.text()
if len(text) == 0:
self.model.setFilter("")
else:
self.model.setFilter("Unit like'" +self.search_Unit.text()+ "%'")
#self.model.setFilter("Unit = '%s'" % text) #This line of code will only pull exact matches.
#{ii} Search Field Cancel Button Slots:
#[1]
def search_MRN_CancelButton_Clicked(self):
self.model.setFilter("")
self.search_MRN.setText("MRN Search")
#[2]
def search_Lname_CancelButton_Clicked(self):
self.model.setFilter("")
self.search_Lname.setText("Last Name Search")
#[3]
def search_Unit_CancelButton_Clicked(self):
self.model.setFilter("")
self.search_Unit.setText("Unit Search")
#{iii} Search Text Edited Slots:
#[1]
def search_MRN_Edit(self):
self.search_MRN.setText("")
#[2]
def search_Lname_Edit(self):
self.search_Lname.setText("")
#[3]
def search_Unit_Edit(self):
self.search_Unit.setText("")
#{iv} Search Text Return Pressed (Enter) Slots:
#[1]
def search_MRN_Enter(self):
self.search_MRN_FilterRecord()
#[2]
def search_Lname_Enter(self):
self.search_Lname_FilterRecord()
#[3]
def search_Unit_Enter(self):
self.search_Unit_FilterRecord()
#{v} Filter Between Dates, Slot:
def FilterBetweenDates(self):
start = str(self.startDate.text())
finish = str(self.endDate.text())
self.model.setFilter("EventDate BETWEEN'" + start and finish)
def submit(self):
self.model.database().transaction()
if self.model.submitAll():
self.model.database().commit()
else:
self.model.database().rollback()
QtGui.QMessageBox.warning(self, "HAI Table",
"The database reported an error: %s" % self.model.lastError().text())
def main():
app = QtGui.QApplication(sys.argv)
#app.setStyle( "Plastique" )
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('HAI.db')
editor = TableEditor('CAUTI')
editor.show()
app.exec_()
if __name__ == '__main__':
The and in your filter text should part of the filter string. Now you are taking the logical-and of two strings (which will be the last string unless the first is empty) and append that to the filter string.
So change
self.model.setFilter("EventDate BETWEEN'" + start and finish)
to
filter = "EventDate BETWEEN '{}' AND '{}'".format(start, finish)
print(filter) # for debugging
self.model.setFilter(filter)
During debugging, it's probably a good idea to print the filter string and try it out in an SQL query (directly in the sqlite3 tool) so that you can see it works.

PyQt4 How to get the "text" of a checkbox

So I'm trying to add the "text" associated with a checked checkbox to a list as soon as they're checked, and I'm doing this:
class Interface(QtGui.QMainWindow):
def __init__(self):
super(Interface, self).__init__()
self.initUI()
self.shops=[]
def initUI(self):
widthPx = 500
heightPx = 500
self.setGeometry(100,100,widthPx,heightPx)
#menus
fileMenu = menuBar.addMenu("&File")
helpMenu = menuBar.addMenu("&Help")
#labels
shopList = _getShops()
for i, shop in enumerate(shopList):
cb = QtGui.QCheckBox(shop, self)
cb.move(20, 15*(i)+50)
cb.toggle()
cb.stateChanged.connect(self.addShop)
self.setWindowTitle("Absolute")
self.show()
def addShop(self, state):
if state == QtCore.Qt.Checked:
#I want to add the checkbox's text
self.shops.append('IT WORKS')
else:
self.shops.remove('IT WORKS')
But instead of adding "IT WORKS" I want to add the text associated with the checkbox that was just selected.
I usually pass additionnal parameters in my signals/slots using partial
Functools doc
You can use it to pass your checkbox text.
First, import partial:
from functools import partial
Then, change your connect() method and pass your checkbox text:
cb.stateChanged.connect( partial( self.addShop, shop) )
To finish, update your addShop() method:
def addShop(self, shop, state):
if state == Qt.Checked:
self.shops.append(shop)
else:
try:
self.shops.remove(shop)
except:
print ""
Notes:
I've added a try/except at the end because your checkboxes are checked by default. When you uncheck them, it tries to remove an unknow item from your self.shops list.
With this method, this is not the current checkbox text which is send to your method. It it the first text that was used to initialize your checkboxes. If, during the execution of your script, you modify the checkbox text, it will not be updated in your addShop method.
Update:
In fact, you can pass your checkbox in the partial:
cb.stateChanged.connect( partial( self.addShop, cb) )
and retrieve it this way:
def addShop(self, shop, state):
if state == Qt.Checked:
self.shops.append(shop.text())
else:
try:
self.shops.remove(shop.text())
except:
print ""

PyGI emulating set_attribute / appropriate signal to emit?

I have an existing project that I'm trying to build a GUI around (using PyGI + Gtk3). There are some native objects that I need to extend slightly to make them renderable. I've boiled the problem down to the simplified code here:
# Simplified Equivalent Code
from gi.repository import GObject
from gi.repository import Gtk
from gi.repository import GdkPixbuf
# Pre-existing, complex object
class Move(object):
def __init__(self, color):
self.color = color
# Pre-existing, complex object
class Block(object):
def __init__(self,move=None,**kwds):
self.move = move
# New object created to help render a Block
class BlockGui(Block):
pixbufs = {
'empty' : GdkPixbuf.Pixbuf.new_from_file('block_empty.png'),
'red' : GdkPixbuf.Pixbuf.new_from_file('block_red.png'),
'blue' : GdkPixbuf.Pixbuf.new_from_file('block_blue.png'),
}
def __setattr__(self, name, value):
super(BlockGui, self).__setattr__(name, value)
if name == 'move':
print "Need to emit a signal here"
def get_pixbuf(self):
try:
return BlockGui.pixbufs[self.move.color]
except AttributeError:
return BlockGui.pixbufs['empty']
class BlockRenderer(Gtk.CellRendererPixbuf):
__gproperties__ = {
'block' : (GObject.TYPE_PYOBJECT,
'block to render',
'the block object to be rendered',
GObject.PARAM_READWRITE)
}
def __init__(self):
GObject.GObject.__init__(self)
self.block = None
def do_set_property(self, prop, value):
# What is a GParamBoxed? Should I be checking if prop == 'block' from it somehow?
if isinstance(value, BlockGui):
self.block = value
self.set_property('pixbuf', self.block.get_pixbuf())
GObject.type_register(BlockRenderer)
def destroy(widget, data=None):
Gtk.main_quit()
# Normally do not have access to this assignment
def on_clicked(widget, liststore, treeview):
treeiter = liststore.get_iter(2)
block = liststore.get_value(treeiter, 1)
block.move = Move('red')
def main():
# 3x5 so this demo window has some size
fmt = [GObject.TYPE_PYOBJECT] * 3
liststore = Gtk.ListStore(*fmt)
for r in xrange(5):
liststore.append([BlockGui() for x in xrange(3)])
treeview = Gtk.TreeView(liststore)
for c in xrange(3):
col = Gtk.TreeViewColumn(str(c))
treeview.append_column(col)
cell = BlockRenderer()
col.pack_start(cell, True)
col.add_attribute(cell, 'block', c)
button = Gtk.Button("Change Color!")
button.connect('clicked', on_clicked, liststore, treeview)
vbox = Gtk.VBox()
vbox.add(treeview)
vbox.add(button)
window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
window.connect('destroy', destroy)
window.add(vbox)
window.show_all()
Gtk.main()
if __name__ == '__main__':
main()
When the current code is run, clicking the button yields no immediate result, but running the mouse over the changed row will cause the center square to turn red (as the hover over the row triggers a refresh). Normally, when a 'proper' GObject has a set_attribute called, it will emit some signals to notify the widgets containing it to re-render.
I need to know which signal that emits, to whom it's emitted, and how to emulate that behavior.
If you know the widget that must be redrawn, then you can just call queue_draw(), queue_draw_region() or queue_draw_area() for that widget. That will invalidate that window area and it will be redrawn. If you want more fine grained control, you might want to use Gtk.DrawingArea.
You might want to check the documentation for The GTK+ Drawing Model.

Python clist widget not returning expected list, returns only the first character of each item

I wrote a simple program to print out all non-hidden files and subdirectories in a given directory.
I am now trying to migrate my code into a clist widget example I found on Google. Other than ripping out some unneeded buttons, all I changed was the top portion to integrate my code, and it partially works except that it only returns the first character of each file and subdirectory. So I expected this:
Desktop
Downloads
Scripts
textfile.txt
pron.avi
But instead got this:
D
D
S
t
p
Here is the example with the code I changed (really just the first def)
import gtk, os
class CListExample:
# this is the part Thraspic changed (other than safe deletions)
# User clicked the "Add List" button.
def button_add_clicked(self, data):
dirList=os.listdir("/usr/bin")
for item in dirList:
if item[0] != '.':
data.append(item)
data.sort()
return
def __init__(self):
self.flag = 0
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(250,150)
window.set_title("GtkCList Example")
window.connect("destroy", gtk.mainquit)
vbox = gtk.VBox(gtk.FALSE, 5)
vbox.set_border_width(0)
window.add(vbox)
vbox.show()
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
vbox.pack_start(scrolled_window, gtk.TRUE, gtk.TRUE, 0)
scrolled_window.show()
clist = gtk.CList(1)
# What however is important, is that we set the column widths as
# they will never be right otherwise. Note that the columns are
# numbered from 0 and up (to an anynumber of columns).
clist.set_column_width(0, 150)
# Add the CList widget to the vertical box and show it.
scrolled_window.add(clist)
clist.show()
hbox = gtk.HBox(gtk.FALSE, 0)
vbox.pack_start(hbox, gtk.FALSE, gtk.TRUE, 0)
hbox.show()
button_add = gtk.Button("Add List")
hbox.pack_start(button_add, gtk.TRUE, gtk.TRUE, 0)
# Connect our callbacks to the three buttons
button_add.connect_object("clicked", self.button_add_clicked,
clist)
button_add.show()
# The interface is completely set up so we show the window and
# enter the gtk_main loop.
window.show()
def main():
gtk.mainloop()
return 0
if __name__ == "__main__":
CListExample()
main()
When you adding data to CList through append method, you must pass a sequence. Rewrite your code:
def button_add_clicked(self, data):
dirList = os.listdir("/usr/bin")
for item in dirList:
if not item.startswith('.'):
data.append([item])
data.sort()
When you creating CList instance you passes to the constructor number of collumns. In your example you created CList with one collumn, that's why you can see only first element (first character) of passed sequence in the append method.

Categories