33 from __future__
import division
37 from python_qt_binding
import loadUi
38 from python_qt_binding.QtCore
import Qt, QTimer, Signal, Slot, QSize, QRectF, QSizeF, Property, QSortFilterProxyModel
39 from python_qt_binding.QtGui
import QIcon, QFont, QFontMetrics, QTextDocument, QTextOption, QPen, QPainter, QColor, QTextCursor
40 from python_qt_binding.QtWidgets
import QHBoxLayout, QVBoxLayout, QGridLayout, QLabel, QPlainTextEdit, QListWidget, QCompleter
41 from python_qt_binding.QtWidgets
import QStyledItemDelegate, QItemDelegate, QPushButton, QLineEdit, QTextEdit
42 from python_qt_binding.QtWidgets
import QSlider, QAbstractItemView, QListWidgetItem, QStyleOptionViewItem
43 from python_qt_binding.QtWidgets
import QHeaderView, QMenu, QTreeWidgetItem, QWidget, QAbstractItemView
49 from rospy.exceptions
import ROSException
51 from .topic_info
import TopicInfo
54 from dyn_tune.msg
import Function, Task
58 import topic_widget
as topic_widget
59 from .topic_widget
import TreeWidgetItem
61 from dyn_tune
import function
63 import dyn_tune.function
72 super(QStyledItemDelegate, self).
__init__(parent)
78 editor = QTextEdit(parent)
81 font = QFont(
"Courier")
82 font.setFamily(
"Courier");
83 font.setStyleHint(QFont.Monospace);
84 font.setFixedPitch(
True);
85 font.setPointSize(10);
89 metrics = QFontMetrics(font)
90 editor.setTabStopWidth(tab_stop * metrics.width(
' '));
95 index.model().setData(index, editor.toPlainText(), Qt.EditRole)
104 editor.setPlainText(index.data(Qt.EditRole))
107 editor.blockSignals(
True)
108 index.model().setData(index, editor.toPlainText(), Qt.EditRole)
110 print editor.toHtml()
112 editor.blockSignals(
False)
114 editor.textChanged.connect(text_changed)
119 doc = editor.document()
120 cursor = QTextCursor(doc);
121 cursor.movePosition(QTextCursor.End);
122 editor.setTextCursor(cursor);
126 item = self.parent().item(index.row())
127 doc = QTextDocument()
129 font = QFont(
"Courier")
130 font.setFamily(
"Courier");
131 font.setStyleHint(QFont.Monospace);
132 font.setFixedPitch(
True);
133 font.setPointSize(self.parent().font().pointSize());
134 doc.setDefaultFont(font)
136 text = index.data(Qt.EditRole)
137 text = text.replace(
"\t",
''.join([
' '] * 4))
139 doc.setPlainText(text)
140 doc.setDefaultStyleSheet(
"background-color: red;")
142 return QSize(doc.size().width(), doc.size().height())
145 def paint(self, painter, option, index):
149 item = self.parent().item(index.row())
152 pen = QPen(QColor(255, 117, 117), 3)
154 painter.drawRect(option.rect)
155 elif item == self.parent().currentItem():
156 pen = QPen(Qt.white, 3)
158 painter.drawRect(option.rect)
161 if not item.has_script:
162 painter.fillRect(option.rect, QColor(153, 153, 153))
164 painter.fillRect(option.rect, Qt.white)
167 doc = QTextDocument()
170 font = QFont(
"Courier")
171 font.setFamily(
"Courier");
172 font.setStyleHint(QFont.Monospace);
173 font.setFixedPitch(
True);
174 font.setPointSize(self.parent().font().pointSize())
175 doc.setDefaultFont(font)
178 text = index.data(Qt.EditRole)
179 text = text.replace(
"\t",
''.join([
' '] * 4))
181 doc.setPlainText(text)
182 doc.setDefaultStyleSheet(
"background-color: red;")
184 painter.translate(option.rect.topLeft())
185 doc.drawContents(painter)
186 painter.resetTransform()
192 main class inherits from the ui window class. 194 You can specify the topics that the topic pane. 196 FuncWidget.start must be called in order to update topic pane. 200 SELECT_BY_MSGTYPE = 1
202 _column_names = [
'topic',
'type',
'value',
'checkbox']
204 def __init__(self, plugin=None, selected_topics=None, select_topic_type=SELECT_BY_NAME):
206 @type selected_topics: list of tuples. 207 @param selected_topics: [($NAME_TOPIC$, $TYPE_TOPIC$), ...] 208 @type select_topic_type: int 209 @param select_topic_type: Can specify either the name of topics or by 210 the type of topic, to filter the topics to 211 show. If 'select_topic_type' argument is 212 None, this arg shouldn't be meaningful. 216 rp = rospkg.RosPack()
217 ui_file = os.path.join(rp.get_path(
'rqt_dyn_tune'),
'resource',
'FuncWidget.ui')
218 loadUi(ui_file, self)
233 self.hLayout_0.setStretchFactor(self.vLayout_0, 5)
234 self.hLayout_0.setStretchFactor(self.gridLayout, 2)
238 def selection_changed(data):
239 self.func_list.clear()
243 item = QListWidgetItem()
244 item.setData(Qt.UserRole, func)
245 item.setText(func +
"(...)")
246 item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
247 self.func_list.addItem(item)
249 self.block_label.setText(
"")
256 self.widget_topic.selectionChanged.connect(selection_changed)
258 self.widget_topic.selectionChanged.emit([])
262 font = QFont(
"Monospace")
264 self.block_list.setFont(font)
265 self.block_list.setItemDelegate(delegate)
266 self.block_list.setContentsMargins(100,10,10,100)
267 self.block_list.setWordWrap(
True)
268 self.block_list.setTextElideMode(Qt.ElideNone)
269 self.block_list.setSelectionMode(QAbstractItemView.SingleSelection)
270 self.block_list.setDragEnabled(
True)
271 self.block_list.viewport().setAcceptDrops(
True)
272 self.block_list.setDropIndicatorShown(
True)
273 self.block_list.setDragDropMode(QAbstractItemView.InternalMove)
274 self.block_list.setMouseTracking(
True)
275 self.block_list.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
276 self.block_list.setSpacing(3)
279 +
"# Add your own python script here! You could \n" \
280 +
"# access the variables defined by the previous \n" \
281 +
"# blocks. To access observable values use \n" \
282 +
"# vars()['value_name'] or locals()['value_name'] \n" \
286 self.func_list.setAlternatingRowColors(
True)
288 self.func_ret.setAutoFillBackground(
True)
290 completer = QCompleter(self.block_list.model())
291 completer = QCompleter([
"bob",
"bobby",
"bud",
"charles",
"charlie"], self.func_ret)
292 self.func_ret.setCompleter(completer)
293 self.func_ret.setEditable(
True)
297 self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
298 self.pFilterModel.setSourceModel(self.widget_topic.topics_tree_widget.model())
303 self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
305 self.func_ret.setCompleter(self.
completer)
309 print "Edited: ", text,
"type: ", type(text)
310 self.pFilterModel.setFilterFixedString(str(text))
312 def on_completer_activated(text):
314 index = self.func_ret.findText(str(text))
315 self.func_ret.setCurrentIndex(index)
317 self.func_ret.lineEdit().textEdited[unicode].connect(filter)
318 self.completer.activated.connect(on_completer_activated)
321 def block_label_clicked(*arg):
323 self.assign_var.setFocus()
324 self.assign_var.selectAll()
326 self.block_label.clicked.connect(block_label_clicked)
330 def assign_var_text_changed(text = None):
332 text = self.assign_var.text()
333 font = self.assign_var.font()
334 fm = QFontMetrics(font);
335 pixelsWide = fm.width(text);
337 self.assign_var.setFixedSize(pixelsWide + 10, self.assign_var.height())
339 text = self.assign_var.text()
340 text = text.replace(
" ",
"")
341 self.assign_var.setText(text)
343 self.assign_var.textChanged.connect(assign_var_text_changed)
351 args = self.widget_topic.get_selected()
352 func = self.func_list.selectedItems()
355 func = func[0].data(Qt.UserRole)
356 first =
" = {0}( ".
format(func)
358 second =
"{0} )".
format(joint.join(args))
360 self.block_label.setText(first + second)
361 self.assign_var.setFocus()
362 self.assign_var.selectAll()
365 self.block_label.setText(
"")
371 self.block_list.insertItem(self.block_list.currentRow() + 1,
ListBlockItem())
375 args = self.widget_topic.get_selected()
376 func = self.func_list.selectedItems()
377 retvar = self.assign_var.text()
379 if args
and func
and retvar !=
'' and retvar !=
None:
380 func = func[0].data(Qt.UserRole)
381 print "there is items: ", args, func
384 first =
"{0} = {1}( ".
format(retvar, func)
386 joint =
',\n' +
''.join([
' '] * spcs)
387 second =
"{0} )".
format(joint.join(args))
395 font = QFont(
"Courier")
396 font.setFamily(
"Courier");
397 font.setStyleHint(QFont.Monospace);
398 font.setFixedPitch(
True);
399 font.setPointSize(10);
402 self.widget_topic.clear_selection()
403 self.block_label.setText(
"")
404 self.block_list.addItem(item)
405 self.func_ret.setCurrentText(retvar)
409 if hasattr(msg,
'_type')
and type(msg) != type:
412 if hasattr(msg,
'dtype')
and type(msg.dtype.name) == str:
413 return str(msg.dtype.name) +
'[]' 415 return type(msg).__name__
422 blocks = [ self.block_list.item(index)
for index
in xrange(self.block_list.count()) ]
427 task.has_script = block.has_script
428 task.script = block.data(Qt.EditRole)
430 if block.func !=
None:
431 task.function = block.func.__name__
432 task.args = block.args
433 task.return_var = block.retvar
435 func.tasks.append(task)
437 func.return_var = self.func_ret.currentText()
438 func.return_type =
"*" 439 func.arg_types =
"[\"*\", []]" 440 func.description = desc
447 DUPLICATE_FACTOR = 10
449 values = { key:np.array([value] * DUPLICATE_FACTOR)
for key, value
in values.items() }
451 items = [ self.block_list.item(index)
for index
in xrange(self.block_list.count()) ]
453 print self.block_list.count()
454 print "=========== EXECUTING ===========" 457 print ">> block #%d" % count
459 values.update( item.execute(values) )
460 print "_________________________________" 461 print "=================================" 463 _values = values.copy()
466 if re.match(
"__.*__",key):
473 topic_widget = self.widget_topic
475 for key, value
in self.values.items():
476 if key
not in topic_widget._tree_items:
477 topic_widget._tree_items[key] = TreeWidgetItem(topic_widget._toggle_monitoring, key, self.
topics_tree_widget, is_topic =
False)
479 _item = topic_widget._tree_items[key]
480 _item.setText(topic_widget._column_index[
'topic'], key)
481 _item.setText(topic_widget._column_index[
'type'], self.
resolve_type(value))
482 _item.setText(topic_widget._column_index[
'value'], repr(value))
483 _item.setData(topic_widget._column_index[
'value'], Qt.UserRole, value)
486 for key, item
in topic_widget._tree_items.items():
487 if key
not in self.
values:
489 topic_widget.unselect(key)
490 topic_widget.remove(key)
493 print "deleting", key
500 self.widget_topic.shutdown_plugin()
510 print "do no restoring" 519 DEFAULT_TEXT =
"\"\"\" Write your own python script here !!! \"\"\"\n" 522 parent =
None, func =
None, args = [],
523 retvar =
'', has_script =
True):
525 self.
darkness = Property(bool, ListBlockItem.isDark, ListBlockItem.setDark)
528 text = ListBlockItem.DEFAULT_TEXT
530 super(QListWidgetItem, self).
__init__(text, parent)
538 Qt.ItemIsDragEnabled |
540 Qt.ItemIsSelectable |
542 (Qt.ItemIsEditable
if has_script
else Qt.ItemIsEnabled) )
546 self.
setData(Qt.UserRole,
False)
559 if self.
func !=
None:
563 script = self.data(Qt.EditRole)
564 exec(script, values, values)
567 print "block executed successfullly" 569 self.
setData(Qt.UserRole,
False)
571 print "block is faulty" 574 traceback.print_exc()
576 self.
setData(Qt.UserRole,
True)
584 super(ListBlockItem, self).
setData(role, value)
589 clicked = Signal(name=
'clicked')
592 super(QLabel, self).
__init__(parent=parent)
601 return super(QLabel, self).
sizeHint()
603 doc = QTextDocument()
606 font.setStyleHint(QFont.Monospace);
607 font.setFixedPitch(
True);
608 doc.setDefaultFont(font)
611 doc.setPlainText(text)
613 size = QSize(doc.size().
width(), doc.size().height())
618 return super(QLabel, self).
sizeHint()
621 painter = QPainter(self)
623 doc = QTextDocument()
627 font.setStyleHint(QFont.Monospace);
628 font.setFixedPitch(
True);
629 doc.setDefaultFont(font)
633 doc.setPlainText(text)
635 painter.translate(0., event.rect().center().y() - doc.size().height()/2.)
636 doc.drawContents(painter, QRectF(event.rect()))
637 painter.resetTransform()
639 self.
size = doc.size()
def format(color, style='')