How to refer to the text entry widget`s input in a subprocess.call() in Python GTK? - pygtk

How to refer to the text entry widget`s input in a subprocess.call() in Python GTK? App for calling bioinformatics tool from PyGTK:
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
import subprocess
class EntryExample:
def enter_callback(self, widget, entry):
entry_text = entry.get_text()
print "Entry contents: %s\n" % entry_text
def entry_toggle_editable(self, checkbutton, entry):
entry.set_editable(checkbutton.get_active())
def entry_toggle_visibility(self, checkbutton, entry):
entry.set_visibility(checkbutton.get_active())
def __init__(self):
# create a new window
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(200, 100)
window.set_title("GTK Entry")
window.connect("delete_event", lambda w,e: gtk.main_quit())
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
entry = gtk.Entry()
entry.set_max_length(50)
entry.connect("activate", self.enter_callback, entry)
entry.set_text("Insert")
entry.insert_text(" SRA accession number", len(entry.get_text()))
entry.select_region(0, len(entry.get_text()))
vbox.pack_start(entry, True, True, 0)
entry.show()
hbox = gtk.HBox(False, 0)
vbox.add(hbox)
hbox.show()
# Create a new button for running Linux Shell script
buttonscript = gtk.Button(label="Download", stock=None)
# Connect the "clicked" signal of the button to the function
buttonscript.connect("clicked", runlinuxshell )
vbox.pack_start(buttonscript, True, True, 0)
buttonscript.set_flags(gtk.CAN_DEFAULT)
buttonscript.grab_default()
buttonscript.show()
button = gtk.Button(stock=gtk.STOCK_CLOSE)
button.connect("clicked", lambda w: gtk.main_quit())
vbox.pack_start(button, True, True, 0)
button.set_flags(gtk.CAN_DEFAULT)
button.grab_default()
button.show()
window.show()
def runlinuxshell ():
subprocess.call('$i=len(entry.get_text()) # Error is here
echo $i
./fastq-dump --split-files $i -v')
def main():
gtk.main()
return 0
if __name__ == "__main__":
EntryExample()
main()
How to pass text input from a widget into the suprocess.call()?
Is there any good example on how to call bioinformatics linux tools in PyGTK?

disclaimer: the sample uses pygobject with introspection and not pygtk which is deprecated for years and should not be used in new code.
disclaimer 2: the sample can be greatly improved to say the least, it's just an adaption of your original script.
You probably would do some like the following:
import gi
from gi.repository import Gtk
import subprocess
class EntryExample:
def __init__(self):
window = Gtk.Window()
window.set_size_request(200, 100)
window.set_title("GTK Entry")
window.connect("delete_event", Gtk.main_quit)
vbox = Gtk.VBox(False, 0)
window.add(vbox)
self.entry = Gtk.Entry()
self.entry.set_max_length(50)
self.entry.set_text("SRA accession number")
vbox.pack_start(self.entry, True, True, 0)
buttonscript = Gtk.Button(label="Download", stock=None)
buttonscript.connect("clicked", self.runlinuxshell)
vbox.pack_start(buttonscript, True, True, 0)
button = Gtk.Button(stock=Gtk.STOCK_CLOSE)
button.connect("clicked", Gtk.main_quit)
vbox.pack_start(button, True, True, 0)
window.show_all()
def runlinuxshell (self, widget):
mylen = len(self.entry.get_text())
# Here you will execute your subprocess with mylen
def main(self):
Gtk.main()
if __name__ == "__main__":
sub = EntryExample()
sub.main()

Related

PyQt5 QTimer in not working after moving it to a thread

I am currently trying to separate my PyQT5-GUI from my serial communication to prevent a freezing GUI.
Therefore, I tried to implement threading. So when I am pressing a button "Open Port", a new thread starts which handles this incoming and outgoing data of the Port.
Now, this works fine, but I am having problems with a timer not fulfilling its function. Essentially, I want to close the port after a 'no valid' message has been received for x seconds.
I tried to create a minimum example:
Upon starting, the GUI and the thread are created. When pressing "Open", the port is opened and the timer in the thread should start. After 3000 milliseconds, the port should be closed by the timer overflow.
from PyQt5 import QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import QtSerialPort
import sys
class AECRobotControl(QMainWindow):
signal_open_port = pyqtSignal(str)
signal_close_port = pyqtSignal(int)
def __init__(self):
super().__init__()
# main-window setup
self.ui = Ui_RobotControls_Main()
self.ui.setupUi(self)
# Port
self.port_gcode_timer_sending = QTimer() # Timer for sending Gcode to prevent robot queue overflow
# END Port
# Threads
self.thread_port = QThread()
self.thread_port_worker = None
# END Threads
# END Variables
# Functions
# Init the ui with standard values
# self.init_ui()
# Init COM-worker
self.init_worker()
# Init signal callbacks
self.init_signals()
# show GUI
self.show()
# END Functions
def init_ui(self):
self.layout.addWidget(self.button_open)
self.layout.addWidget(self.button_close)
self.setLayout(self.layout)
def init_signals(self):
# Button Open Port
self.ui.pushButton_open_port.clicked.connect(self.button_open_comport)
# END Button Open Port
# Button Close Port
self.ui.pushButton_close_port.clicked.connect(self.button_close_comport)
# END Button Close Port
def init_worker(self):
self.thread_port_worker = RobotMessageThread()
self.thread_port_worker.moveToThread(self.thread_port)
self.thread_port.started.connect(self.thread_port_worker.start_thread)
self.thread_port.finished.connect(self.thread_port.deleteLater)
self.thread_port_worker.finished.connect(self.thread_port.quit)
self.thread_port_worker.finished.connect(self.thread_port_worker.deleteLater)
self.signal_open_port.connect(self.thread_port_worker.open_port_slot)
self.signal_close_port.connect(self.thread_port_worker.close_comport)
self.thread_port.start()
def button_open_comport(self):
self.signal_open_port.emit("COM4")
def button_close_comport(self):
if (self.thread_port.isRunning() == True):
self.signal_close_port.emit(0)
def parse_com_message(self, message):
try:
print(message)
except Exception as e:
print(e)
class RobotMessageThread(QObject):
finished = pyqtSignal()
progress = pyqtSignal(int)
com_message_parsed = pyqtSignal(QByteArray)
com_ascii_message_parsed = pyqtSignal(str)
def __init__(self):
super().__init__()
self.port_com_port = QtSerialPort.QSerialPort()
self.port_name = None
self.port_is_alive_timer = QTimer() # Interprets valid received messages as alive-sign from robot.
""" Functions to be called upon start of thread"""
def start_thread(self):
print("Thread started")
self.port_is_alive_timer.timeout.connect(lambda: self.close_comport(1))
""" Inits the port"""
def _init_port(self):
self.port_com_port.setPortName(self.port_name)
self.port_com_port.setBaudRate(QtSerialPort.QSerialPort.BaudRate.Baud115200)
self.port_com_port.setParity(QtSerialPort.QSerialPort.Parity.NoParity)
self.port_com_port.setDataBits(QtSerialPort.QSerialPort.DataBits.Data8)
self.port_com_port.setStopBits(QtSerialPort.QSerialPort.StopBits.OneStop)
#pyqtSlot(bytearray)
def message_slot(self, message: bytearray):
self._write_to_port(message)
#pyqtSlot(str)
def open_port_slot(self, com_name: str):
self.port_name = com_name
self._init_port()
self._open_comport()
#pyqtSlot()
def close_port_slot(self, message: bytearray):
self.close_comport(0)
""" Tries to open the selected comport"""
def _open_comport(self):
# Check whether port is already open
if self.port_com_port.open(QIODevice.ReadWrite) == True:
self.port_com_port.setDataTerminalReady(True)
print("COM Opened")
# Reset message-buffer
self.port_is_alive_timer.start(3000)
else:
print("opening failed")
""" Closes the selected comport"""
def close_comport(self, source):
if self.port_com_port.isOpen() == True:
# Close port and delete queue
self.port_com_port.clear()
self.port_com_port.close()
# Stop timers
self.port_is_alive_timer.stop()
print("Closed by " + str(source))
else:
print("Closing failed")
# GUI
class Ui_RobotControls_Main(object):
def setupUi(self, RobotControls_Main):
RobotControls_Main.setObjectName("RobotControls_Main")
RobotControls_Main.resize(1024, 900)
RobotControls_Main.setMinimumSize(QSize(1024, 900))
RobotControls_Main.setMaximumSize(QSize(1600, 1200))
self.centralwidget = QtWidgets.QWidget(RobotControls_Main)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_12 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_12.setObjectName("gridLayout_12")
self.QGroupBox_port_settings = QtWidgets.QGroupBox(self.centralwidget)
self.QGroupBox_port_settings.setObjectName("QGroupBox_port_settings")
self.gridLayout_15 = QtWidgets.QGridLayout(self.QGroupBox_port_settings)
self.gridLayout_15.setObjectName("gridLayout_15")
self.horizontalLayout_21 = QtWidgets.QHBoxLayout()
self.horizontalLayout_21.setObjectName("horizontalLayout_21")
self.pushButton_open_port = QtWidgets.QPushButton(self.QGroupBox_port_settings)
self.pushButton_open_port.setMaximumSize(QSize(100, 50))
self.pushButton_open_port.setObjectName("pushButton_open_port")
self.horizontalLayout_21.addWidget(self.pushButton_open_port)
self.gridLayout_15.addLayout(self.horizontalLayout_21, 0, 0, 1, 1)
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.pushButton_close_port = QtWidgets.QPushButton(self.QGroupBox_port_settings)
self.pushButton_close_port.setObjectName("pushButton_close_port")
self.horizontalLayout_4.addWidget(self.pushButton_close_port)
self.gridLayout_15.addLayout(self.horizontalLayout_4, 0, 1, 1, 1)
self.gridLayout_12.addWidget(self.QGroupBox_port_settings, 0, 0, 1, 1)
RobotControls_Main.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(RobotControls_Main)
self.statusbar.setObjectName("statusbar")
RobotControls_Main.setStatusBar(self.statusbar)
self.retranslateUi(RobotControls_Main)
QMetaObject.connectSlotsByName(RobotControls_Main)
def retranslateUi(self, RobotControls_Main):
_translate = QCoreApplication.translate
RobotControls_Main.setWindowTitle(_translate("RobotControls_Main", "RobotControls"))
self.QGroupBox_port_settings.setTitle(_translate("RobotControls_Main", "Port settings"))
self.pushButton_open_port.setText(_translate("RobotControls_Main", "Open Port"))
self.pushButton_close_port.setText(_translate("RobotControls_Main", "Close Port"))
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = AECRobotControl()
app.exec() # QT main-threadtimer.start(TIME)
I found a solution. In the above code, just one line needs to be added: after moving the worker to the separate thread, the QTimer also has to be moved to the same thread. So, after self.thread_port_worker.moveToThread(self.thread_port), the line self.thread_port_worker.port_is_alive_timer.moveToThread(self.thread_port) needs to be added

Set different background color in specific rows in QTableview

Hello, how i can change the background color in specific rows in QTableview?
I would like to know which method to use to make.
I have the method seleckRow but click another the color is not maintained in the selected row.
__author__ = 'jordiponsisala'
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtSql import *
from PyQt5 import QtWidgets
from Llistats import modificarLineal
def crearConeccio():
db = QSqlDatabase.addDatabase("QMYSQL")
db.setHostName("localhost")
db.setDatabaseName("ProvaDB")
db.setUserName("root")
db.setPassword("password")
db.open()
print (db.lastError().text())
return True
class clasArticles(QDialog, modificarLineal.Ui_Dialog):
def __init__(self, parent=None):
super(clasArticles, self).__init__(parent)
self.setupUi(self)
self.setWindowTitle('Posu el nom que vulgui')
self.model= QSqlRelationalTableModel(self)
self.model.setTable('preu')
#self.model.setEditStrategy(QSqlRelationalTableModel.OnFieldChange)
self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
self.model.setRelation(2,QSqlRelation("probeedors", "id", "nomProbeedor"))
self.model.select()
self.tableView.setModel(self.model)
self.tableView.setItemDelegate(QSqlRelationalDelegate(self.model))
self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableView.selectRow(1)
self.filtrarLineal.clicked.connect(self.filtrarRecords)
self.cancelarLineal.clicked.connect(self.cancelRecords)
self.afegirLineal.clicked.connect(self.insertRecords)
self.eliminarLineal.clicked.connect(self.deleteRecords)
self.seleccionar.clicked.connect(self.seleccionarCodi)
self.tableView.doubleClicked.connect(self.probes_index)
self.tableView.activated.connect(self.actualitzarRecords)# Pres intro method
def probes_index(self):# metod for print index in row
indexes = self.tableView.selectionModel().selectedRows()
for index in sorted(indexes):
self.lblnomSeleccionat.setText(str(index.row()))
def seleccionarCodi(self):
index = self.tableView.selectedIndexes()[0]
id_seleccionat = str(self.tableView.model().data(index))
print ("index : " + str(id_seleccionat))
self.lblnomSeleccionat.setText(str(id_seleccionat))
def actualitzarRecords(self):
index_0 = self.tableView.selectedIndexes()[0]
index_id = str(self.tableView.model().data(index_0))
index_2 = self.tableView.selectedIndexes()[1]
index_probeedor_id = str(self.tableView.model().data(index_2))
index_3 = self.tableView.selectedIndexes()[3]
index_preuTarifa = str(self.tableView.model().data(index_3))
self.model = QSqlQueryModel(self)
self.model.setQuery("UPDATE `ProvaDB`.`preu` SET `preuTarifa`="+index_preuTarifa+" WHERE `id`="+index_id+" and`probeedors_id`="+index_probeedor_id+"")
def cancelRecords(self):
self.model.revertAll()
def insertRecords(self):
self.model.insertRow(self.tableView.currentIndex().row())
def deleteRecords(self):
self.model.removeRow(self.tableView.currentIndex().row())
self.model.submitAll()
def filtrarRecords(self):
self.model.setFilter("preu.id = '"+self.txtEditFiltre.text()+"%'")
if __name__ == '__main__':
app = QApplication(sys.argv)
if not crearConeccio():
sys.exit(1)
formMod = clasArticles()
formMod.show()
sys.exit(app.exec_())

How to create a dropdown from a gtk.Entry's icon?

I have a gtk.Entry with an icon after the text, intending to be a text search field:
What I'm trying to do is to display a dropdown (i.e. a gtk.ComboBox) when the user clicks on the icon, to choose the type of search. A mock of that feature would be:
I have tried several things without any success. For example, trying to pack an empty gtk.ComboBox only showing an arrow right after the Entry, and stuffing it only on icon-press, which creates the illusion, but it has two drawbacks: a) when I stuff the ComboBox, the toolbar grows, and b) when I clear() the ListStore, the ComboBox retains its width and leaves an ugly grey box.
At this point I guess that I need to create a CellRenderer on icon-press that pops down the icon of the Entry, and I tried without a lot of success to understand the code of gtk.ComboBoxEntry (in gtkcomboboxentry.c), but as far as I understood it uses a vertical Container on the whole piece together with a CellRenderer.
Also GTK+3 doesn't have any ideas on this respect.
Any ideas, or some guidance in how to create this in PyGTK?
I was looking for something similar, so I came up with the code below. I haven't really worried about the aesthetics. I did pass a list of tuples to the MyPopup class, with the idea of passing handlers for each of the menu items in the dropdown. Note that the item.show() is necessary, even though there is a show_all():
from gi.repository import Gtk
class MyPopup(Gtk.MenuButton):
def __init__(self, btndefs):
super(MyPopup, self).__init__()
self.menu = Gtk.Menu()
self.set_popup(self.menu)
#self.set_label(">")
self.set_direction(Gtk.ArrowType.RIGHT)
for btndef in btndefs:
item = Gtk.MenuItem()
item.set_label(btndef[0])
item.show()
self.menu.append(item)
class MainWindow(Gtk.Window):
def __init__(self):
super(MainWindow, self).__init__()
self.set_size_request(100, -1)
self.connect("destroy", lambda x: Gtk.main_quit())
self.hbox = Gtk.Box(orientation = Gtk.Orientation.HORIZONTAL)
self.entry = Gtk.Entry()
self.popup = MyPopup( (("String",),
("String no case",),
("Hexadecimal",),
("Regexp",)) )
self.hbox.pack_start(self.entry, True, True, 0)
self.hbox.pack_start(self.popup, False, True, 0)
self.add(self.hbox)
self.show_all()
def run(self):
Gtk.main()
def main():
mw = MainWindow()
mw.run()
return 0
if __name__ == '__main__':
main()
yup its year late, but lets not make next person stumbled here to be sad like me.
this is the example using Gtk.Menu() popup, you can also similar feat. with Gtk.Popover()
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
opts = {
'hex' : "system-run-symbolic",
'regex' : "font-select-symbolic",
'string' : "font-x-generic-symbolic",
'no-case' : "tools-check-spelling-symbolic",
}
def make_menu(entry, opts):
menu = Gtk.Menu()
for label, icon in opts.items():
item = Gtk.MenuItem()
item.set_label(label)
item.connect(
"activate",
lambda w: entry.set_icon_from_icon_name(0, opts[w.get_label()])
)
menu.append(item)
# NOTE you can use Gtk.ImageMenuItem to add image but its
# Deprecated since version 3.10
menu.show_all()
return menu
def on_icon_release(widget, pos, event):
menu = make_menu(widget, opts)
menu.popup(
parent_menu_shell = None,
parent_menu_item = None,
func = None,
data = None,
button = Gdk.BUTTON_PRIMARY,
activate_time = event.get_time()
)
def make_entry():
entry = Gtk.Entry()
entry.set_icon_from_icon_name(0, 'action-unavailable-symbolic')
entry.set_icon_from_icon_name(1, 'fonts')
entry.set_icon_sensitive(1, True)
entry.set_icon_activatable(1, True)
entry.connect("icon-release", on_icon_release)
return entry
root = Gtk.Window()
root.add(make_entry())
root.show_all()
Gtk.main()

Double buffering in Jython

recently I started learning Jython and now I have rather simply problem. I would like to improve quality of my animation. Unfortunately I don't know how to add double buffering to my applet . Could you help me?
Best regards!
from javax.swing import JToolBar
from javax.swing import JButton
from javax.swing import JFrame
import time
from java import awt
from java.awt import BorderLayout
class Canvas(awt.Canvas):
u"Canvas - drawing area"
def __init__(self,winSize = 400):
self.play = False
self.background=awt.Color.black
self.winSize = winSize
self.l = 0
def playSim(self, play):
if play == True:
self.play = True
self.repaint()
else: self.play = False
def paint(self, g):
g.fillRect(50, int(self.winSize/4), self.l, int(self.winSize/2))
if self.l < self.winSize: self.l += 1
else: self.l = 0
time.sleep(0.02)
if self.play == True: self.repaint()
class Example(JFrame):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
winSize = 600
toolbar = JToolBar()
self.playButton = JButton("Start", actionPerformed=self.playButtonPress )
toolbar.add(self.playButton)
self.add(toolbar, BorderLayout.NORTH)
self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
self.setSize(winSize, winSize)
self.setResizable(False)
self.setLocationRelativeTo(None)
self.setVisible(True)
self.canvas = Canvas(winSize)
self.getContentPane().add(self.canvas)
self.setTitle("TEST")
self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
def playButtonPress(self, e):
if self.playButton.getLabel() == "Start":
self.canvas.playSim(True)
self.playButton.setLabel("Stop")
else:
self.playButton.setLabel("Start")
self.canvas.playSim(False)
if __name__ == '__main__':
Example()
I solved my recent problem:
from javax.swing import JToolBar
from javax.swing import JButton
from javax.swing import JFrame
import time
from java import awt
from java.awt import BorderLayout
class Canvas(awt.Canvas):
u"Canvas - drawing area"
def __init__(self,winSize = 400):
self.play = False
self.background=awt.Color.black
self.winSize = winSize
self.l = 0
self.bi = BufferedImage(winSize, winSize, BufferedImage.TYPE_INT_RGB)
self.offScreenGraphics = self.bi.getGraphics()
def playSim(self, play):
if play == True:
self.play = True
self.repaint()
else: self.play = False
def paint(self, g):
self.offScreenGraphics.fillRect(50, int(self.winSize/4), self.l, int(self.winSize/2))
if self.l < self.winSize: self.l += 1
else: self.l = 0
g.drawImage(self.bi, 0, 0, None)
time.sleep(0.02)
if self.play == True: self.repaint()
class Example(JFrame):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
winSize = 600
toolbar = JToolBar()
self.playButton = JButton("Start", actionPerformed=self.playButtonPress )
toolbar.add(self.playButton)
self.add(toolbar, BorderLayout.NORTH)
self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
self.setSize(winSize, winSize)
self.setResizable(False)
self.setLocationRelativeTo(None)
self.setVisible(True)
self.canvas = Canvas(winSize)
self.getContentPane().add(self.canvas)
self.setTitle("TEST")
self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
def playButtonPress(self, e):
if self.playButton.getLabel() == "Start":
self.canvas.playSim(True)
self.playButton.setLabel("Stop")
else:
self.playButton.setLabel("Start")
self.canvas.playSim(False)
if __name__ == '__main__':
Example()
Now I've another(rather trivial) problem:
How can I make from this python file *the class file* which would be ready to publish it on website as an applet?

how to extract pdf index/table-of-contents with poppler?

I see that pdf-viewers like okular and evince are able to display the index of a pdf document (book) very well, with link to every paragraph.
How can they do so? They use poppler library, how could I do extract that index with poppler, or in general?
it just stops at first level (recursion needed to go more deeply)
toc=document->toc();
QDomElement docElem = toc->documentElement();
QDomNode n = docElem.firstChild();
while(!n.isNull()) {
QDomElement e = n.toElement(); // try to convert the node to an element.
if(!e.isNull()) {
qDebug("elem %s\n",qPrintable(e.tagName())); // the node really is an element.
}
n = n.nextSibling();
}
Here is a demo how to do this with poppler in Python:
import poppler
def walk_index(iterp, doc):
while iterp.next():
link=iterp.get_action()
s = doc.find_dest(link.dest.named_dest)
print link.title,' ', doc.get_page(s.page_num).get_label()
child = iterp.get_child()
if child:
walk_index(child, doc)
def main():
uri = ("file:///"+path_to_pdf)
doc = poppler.document_new_from_file(uri, None)
iterp = poppler.IndexIter(doc)
link = iterp.get_action()
s = doc.find_dest(link.dest.named_dest)
print link.title,' ', doc.get_page(s.page_num).get_label()
walk_index(iterp, doc)
return 0
if __name__ == '__main__':
main()
python poppler library is obsolete, here is how to do it with Gobject:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# walk to table of contents and print titles and pages
import sys
from gi.repository import Poppler
def walk_index(iterp, doc):
while iterp.next():
link=iterp.get_action()
dest=doc.find_dest(link.goto_dest.dest.named_dest)
s = doc.get_page(dest.page_num-1)
print link.goto_dest.title, dest.page_num, s.get_label()
child = iterp.get_child()
if child:
walk_index(child, doc)
def main():
uri = ("file:///"+sys.argv[1])
doc = Poppler.Document.new_from_file(uri, None)
iterp = Poppler.IndexIter.new(doc)
link = iterp.get_action()
dest=doc.find_dest(link.goto_dest.dest.named_dest)
s = doc.get_page(dest.page_num-1)
print link.goto_dest.title, dest.page_num, s.get_label()
walk_index(iterp, doc)
return 0
if __name__ == '__main__':
main()