Пример #1
0
 def _add_completer_list_item(self, url):
     self._completer_word_list.append(self.url_lineedit.text())
     self._completer_word_list = list(set(self._completer_word_list))
     self._completer = QCompleter(self._completer_word_list)
     self._completer.setCaseSensitivity(Qt.CaseInsensitive)
     self._completer.setCompletionMode(QCompleter.PopupCompletion)
     self.url_lineedit.setCompleter(self._completer)
Пример #2
0
 def _add_completer_list_item(self, url):
     self._completer_word_list.append(self.url_lineedit.text())
     self._completer_word_list = list(set(self._completer_word_list))
     self._completer = QCompleter(self._completer_word_list)
     self._completer.setCaseSensitivity(Qt.CaseInsensitive)
     self._completer.setCompletionMode(QCompleter.PopupCompletion)
     self.url_lineedit.setCompleter(self._completer)
Пример #3
0
    def __init__(self, parent=None):
        super(ExtendedComboBox, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        # add a filter model to filter matching items
        self.filter_model = QSortFilterProxyModel(self)
        self.filter_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.filter_model.setSourceModel(self.model())

        # add a completer, which uses the filter model
        self.completer = QCompleter(self.filter_model, self)
        # always show all (filtered) completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.setCompleter(self.completer)

        # connect signals
        self.lineEdit().textEdited[unicode].connect(self.filter_model.setFilterFixedString)
        self.completer.activated.connect(self.on_completer_activated)
        self.setItems.connect(self.onSetItems)
Пример #4
0
class ExtendedComboBox(QComboBox):
    setItems = Signal(list)

    def __init__(self, parent=None):
        super(ExtendedComboBox, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        # add a filter model to filter matching items
        self.filter_model = QSortFilterProxyModel(self)
        self.filter_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.filter_model.setSourceModel(self.model())

        # add a completer, which uses the filter model
        self.completer = QCompleter(self.filter_model, self)
        # always show all (filtered) completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.setCompleter(self.completer)

        # connect signals
        self.lineEdit().textEdited[str].connect(
            self.filter_model.setFilterFixedString)
        self.completer.activated.connect(self.on_completer_activated)
        self.setItems.connect(self.onSetItems)

    # on selection of an item from the completer, select the corresponding item from combobox
    def on_completer_activated(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)

    # on model change, update the models of the filter and completer as well
    def setModel(self, model):
        super(ExtendedComboBox, self).setModel(model)
        self.filter_model.setSourceModel(model)
        self.completer.setModel(self.filter_model)

    # on model column change, update the model column of the filter and completer as well
    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.filter_model.setFilterKeyColumn(column)
        super(ExtendedComboBox, self).setModelColumn(column)

    @Slot(list)
    def onSetItems(self, items):
        self.clear()
        self.addItems(items)
    def __init__(self, parent=None):
        super(ExtendedComboBox, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        # add a filter model to filter matching items
        self.filter_model = QSortFilterProxyModel(self)
        self.filter_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.filter_model.setSourceModel(self.model())

        # add a completer, which uses the filter model
        self.completer = QCompleter(self.filter_model, self)
        # always show all (filtered) completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.setCompleter(self.completer)

        # connect signals
        self.lineEdit().textEdited[str].connect(self.filter_model.setFilterFixedString)
        self.completer.activated.connect(self.on_completer_activated)
        self.setItems.connect(self.onSetItems)
class ExtendedComboBox(QComboBox):
    setItems = Signal(list)

    def __init__(self, parent=None):
        super(ExtendedComboBox, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        # add a filter model to filter matching items
        self.filter_model = QSortFilterProxyModel(self)
        self.filter_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.filter_model.setSourceModel(self.model())

        # add a completer, which uses the filter model
        self.completer = QCompleter(self.filter_model, self)
        # always show all (filtered) completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.setCompleter(self.completer)

        # connect signals
        self.lineEdit().textEdited[str].connect(self.filter_model.setFilterFixedString)
        self.completer.activated.connect(self.on_completer_activated)
        self.setItems.connect(self.onSetItems)

    # on selection of an item from the completer, select the corresponding item from combobox
    def on_completer_activated(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)

    # on model change, update the models of the filter and completer as well
    def setModel(self, model):
        super(ExtendedComboBox, self).setModel(model)
        self.filter_model.setSourceModel(model)
        self.completer.setModel(self.filter_model)

    # on model column change, update the model column of the filter and completer as well
    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.filter_model.setFilterKeyColumn(column)
        super(ExtendedComboBox, self).setModelColumn(column)

    @Slot(list)
    def onSetItems(self, items):
        self.clear()
        self.addItems(items)
Пример #7
0
 def __init__(self, parent=None):
     super(LineEditDialog, self).__init__()
     self.value = None
     vbox = QVBoxLayout(self)
     # combo box
     model = QtGui.QStandardItemModel(self)
     for elm in rospy.get_param_names():
         model.setItem(model.rowCount(), 0, QtGui.QStandardItem(elm))
     self.combo_box = QComboBox(self)
     self.line_edit = QLineEdit()
     self.combo_box.setLineEdit(self.line_edit)
     self.combo_box.setCompleter(QCompleter())
     self.combo_box.setModel(model)
     self.combo_box.completer().setModel(model)
     self.combo_box.lineEdit().setText('')
     vbox.addWidget(self.combo_box)
     # button
     button = QPushButton()
     button.setText("Done")
     button.clicked.connect(self.buttonCallback)
     vbox.addWidget(button)
     self.setLayout(vbox)
Пример #8
0
class WebWidget(QWidget):
    def __init__(self, url=None):
        """
        Class to load a webpage in a widget.

        :param url: If url is empty then a navigation bar is shown otherwise the url is loaded and the navigation bar is hidden, ''str''
        """
        super(WebWidget, self).__init__()
        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_web'), 'resource', 'web_widget.ui')
        loadUi(ui_file, self)
        self.setObjectName('WebWidget')

        self._loading = False
        self._stop_icon = QIcon.fromTheme('process-stop')
        self._reload_icon = QIcon.fromTheme('view-refresh')
        self._working_icon = QIcon.fromTheme('process-working')

        self._completer_word_list = ['']
        self._view = QWebView()
        self.verticalLayout.addWidget(self._view)
        if url is None:
            self.set_url("http://ros.org", True)
        else:
            self.set_url(url, False)

        self.url_lineedit.returnPressed.connect(self._handle_url_change)
        self._view.loadFinished[bool].connect(self._handle_load_finished)
        self.reload_button.clicked.connect(self._handle_reload_clicked)
        self._view.linkClicked.connect(self._handle_link_clicked)
        self._view.urlChanged[QUrl].connect(self._handle_url_changed)

    def set_url(self, url, showinput=False):
        """
        Sets the url and begins loading that page
        :param url: url to load in the webview, ''str or QUrl''
        :param showinput: if true the input bar will be shown, else hidden, ''bool''
        """
        if url is not None:
            self._url = QUrl(url)
            self.set_show_url_input(showinput)
            self._view.setUrl(self._url)

    def set_show_url_input(self, showinput):
        """
        Sets the value of the show_url_input flag and hides/shows the widgets as required
        :param showinput: true - show inputbar false - hide , ''bool''
        """
        self._show_url_input = showinput
        self.url_lineedit.setVisible(self._show_url_input)
        self.reload_button.setVisible(self._show_url_input)
        if self._show_url_input:
            self._view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        else:
            self._view.page().setLinkDelegationPolicy(QWebPage.DontDelegateLinks)

    def save_settings(self, settings):
        settings.set_value('url_completion', self._pack(self._completer_word_list))
        settings.set_value('url_current', self._url.toString())

    def restore_settings(self, settings):
        self._completer_word_list += self._unpack(settings.value('url_completion'))
        self._completer_word_list = list(set(self._completer_word_list))
        url = settings.value('url_current')
        if url:
            self.set_url(url, self._show_url_input)

    def _handle_url_change(self):
        self.set_url(self.url_lineedit.text(), True)

    def _handle_link_clicked(self, url):
        self.set_url(url, True)

    def _handle_reload_clicked(self):
        if self._loading:
            self._view.stop()
            self._loading = False
            self.reload_button.setIcon(self._reload_icon)
        else:
            self._view.reload()
            self._loading = True
            self.reload_button.setIcon(self._stop_icon)

    def _handle_url_changed(self, url):
        # set text to the current loading item
        self.url_lineedit.setText(url.toString())
        self.reload_button.setIcon(self._stop_icon)
        self._loading = True

    def _handle_load_finished(self, ok):
        self._loading = False
        self.reload_button.setIcon(self._reload_icon)
        if ok:
            self._add_completer_list_item(self._url.toString())
        else:
            # need to disconnect or we will resend the signal once the error page loads
            self._view.loadFinished[bool].disconnect(self._handle_load_finished)
            self._view.page().currentFrame().setHtml('<html><h2>The url you entered seems to be faulty.</h2></html>')
            self._view.loadFinished[bool].connect(self._handle_load_finished)

    def _add_completer_list_item(self, url):
        self._completer_word_list.append(self.url_lineedit.text())
        self._completer_word_list = list(set(self._completer_word_list))
        self._completer = QCompleter(self._completer_word_list)
        self._completer.setCaseSensitivity(Qt.CaseInsensitive)
        self._completer.setCompletionMode(QCompleter.PopupCompletion)
        self.url_lineedit.setCompleter(self._completer)

    @staticmethod
    def _pack(data):
        """
        Packs 'data' into a form that can be easily and readably written to an ini file
        :param data: A list of strings to be flattened into a string ''list''
        :return: A string suitable for output to ini files ''str''
        """
        if len(data) == 0:
            return ''
        if len(data) == 1:
            return data[0]
        return data

    @staticmethod
    def _unpack(data):
        """
        Unpacks the values read from an ini file
        :param data: An entry taken from an ini file ''list or string''
        :return: A list of strings ''list''
        """
        if data is None or data == '':
            data = []
        elif is_string(data):
            data = [data]
        return data
Пример #9
0
 def pathFromIndex(self, index):
     path = QCompleter.pathFromIndex(self, index)
     lst = str(self.widget().text()).split(',')
     if len(lst) > 1:
         path = '%s, %s' % (','.join(lst[:-1]), path)
     return path
Пример #10
0
 def init(self, parent=None):
     QCompleter.init(self, parent)
Пример #11
0
 def pathFromIndex(self, index):
     path = QCompleter.pathFromIndex(self, index)
     lst = str(self.widget().text()).split(',')
     if len(lst) > 1:
         path = '%s, %s' % (','.join(lst[:-1]), path)
     return path
Пример #12
0
 def init(self, parent=None):
     QCompleter.init(self, parent)
Пример #13
0
class WebWidget(QWidget):
    def __init__(self, url=None):
        """
        Class to load a webpage in a widget.

        :param url: If url is empty then a navigation bar is shown otherwise the url is loaded and the navigation bar is hidden, ''str''
        """
        super(WebWidget, self).__init__()
        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_web'), 'resource', 'web_widget.ui')
        loadUi(ui_file, self)
        self.setObjectName('WebWidget')

        self._loading = False
        self._stop_icon = QIcon.fromTheme('process-stop')
        self._reload_icon = QIcon.fromTheme('view-refresh')
        self._working_icon = QIcon.fromTheme('process-working')

        self._completer_word_list = ['']
        self._view = QWebView()
        self.verticalLayout.addWidget(self._view)
        if url is None:
            self.set_url("http://ros.org", True)
        else:
            self.set_url(url, False)

        self.url_lineedit.returnPressed.connect(self._handle_url_change)
        self._view.loadFinished[bool].connect(self._handle_load_finished)
        self.reload_button.clicked.connect(self._handle_reload_clicked)
        self._view.linkClicked.connect(self._handle_link_clicked)
        self._view.urlChanged[QUrl].connect(self._handle_url_changed)

    def set_url(self, url, showinput=False):
        """
        Sets the url and begins loading that page
        :param url: url to load in the webview, ''str or QUrl''
        :param showinput: if true the input bar will be shown, else hidden, ''bool''
        """
        if url is not None:
            self._url = QUrl(url)
            self.set_show_url_input(showinput)
            self._view.setUrl(self._url)

    def set_show_url_input(self, showinput):
        """
        Sets the value of the show_url_input flag and hides/shows the widgets as required
        :param showinput: true - show inputbar false - hide , ''bool''
        """
        self._show_url_input = showinput
        self.url_lineedit.setVisible(self._show_url_input)
        self.reload_button.setVisible(self._show_url_input)
        if self._show_url_input:
            self._view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        else:
            self._view.page().setLinkDelegationPolicy(QWebPage.DontDelegateLinks)

    def save_settings(self, settings):
        settings.set_value('url_completion', self._pack(self._completer_word_list))
        settings.set_value('url_current', self._url.toString())

    def restore_settings(self, settings):
        self._completer_word_list += self._unpack(settings.value('url_completion'))
        self._completer_word_list = list(set(self._completer_word_list))
        url = settings.value('url_current')
        if url:
            self.set_url(url, self._show_url_input)

    def _handle_url_change(self):
        self.set_url(self.url_lineedit.text(), True)

    def _handle_link_clicked(self, url):
        self.set_url(url, True)

    def _handle_reload_clicked(self):
        if self._loading:
            self._view.stop()
            self._loading = False
            self.reload_button.setIcon(self._reload_icon)
        else:
            self._view.reload()
            self._loading = True
            self.reload_button.setIcon(self._stop_icon)

    def _handle_url_changed(self, url):
        # set text to the current loading item
        self.url_lineedit.setText(url.toString())
        self.reload_button.setIcon(self._stop_icon)
        self._loading = True

    def _handle_load_finished(self, ok):
        self._loading = False
        self.reload_button.setIcon(self._reload_icon)
        if ok:
            self._add_completer_list_item(self._url.toString())
        else:
            # need to disconnect or we will resend the signal once the error page loads
            self._view.loadFinished[bool].disconnect(self._handle_load_finished)
            self._view.page().currentFrame().setHtml('<html><h2>The url you entered seems to be faulty.</h2></html>')
            self._view.loadFinished[bool].connect(self._handle_load_finished)

    def _add_completer_list_item(self, url):
        self._completer_word_list.append(self.url_lineedit.text())
        self._completer_word_list = list(set(self._completer_word_list))
        self._completer = QCompleter(self._completer_word_list)
        self._completer.setCaseSensitivity(Qt.CaseInsensitive)
        self._completer.setCompletionMode(QCompleter.PopupCompletion)
        self.url_lineedit.setCompleter(self._completer)

    @staticmethod
    def _pack(data):
        """
        Packs 'data' into a form that can be easily and readably written to an ini file
        :param data: A list of strings to be flattened into a string ''list''
        :return: A string suitable for output to ini files ''str''
        """
        if len(data) == 0:
            return ''
        if len(data) == 1:
            return data[0]
        return data

    @staticmethod
    def _unpack(data):
        """
        Unpacks the values read from an ini file
        :param data: An entry taken from an ini file ''list or string''
        :return: A list of strings ''list''
        """
        if data is None or data == '':
            data = []
        elif isinstance(data, basestring):
            data = [data]
        return data
Пример #14
0
	def __init__(self, plugin=None, selected_topics=None, select_topic_type=SELECT_BY_NAME):
		"""
		@type selected_topics: list of tuples.
		@param selected_topics: [($NAME_TOPIC$, $TYPE_TOPIC$), ...]
		@type select_topic_type: int
		@param select_topic_type: Can specify either the name of topics or by
								  the type of topic, to filter the topics to
								  show. If 'select_topic_type' argument is
								  None, this arg shouldn't be meaningful.
		"""
		super(FuncWidget, self).__init__()

		rp = rospkg.RosPack()
		ui_file = os.path.join(rp.get_path('rqt_dyn_tune'), 'resource', 'FuncWidget.ui')
		loadUi(ui_file, self)
		
		self._plugin = plugin
		self.list_available_functions = rospy.ServiceProxy('/list_available_functions', ListAvailableFunctions)
		self.functions = function.load_functions()
		self._select_topic_type = select_topic_type
		self.topics_tree_widget = self.widget_topic.topics_tree_widget

		self.execs = {}
		self.values = {}
		self.items = {}

		


		self.hLayout_0.setStretchFactor(self.vLayout_0, 5)
		self.hLayout_0.setStretchFactor(self.gridLayout, 2)


		@Slot(dict)
		def selection_changed(data):
			self.func_list.clear()
			funcs = self.list_available_functions(self.widget_topic.get_selected_types()).functions			

			for func in funcs:
				item = QListWidgetItem()				
				item.setData(Qt.UserRole, func)
				item.setText(func + "(...)")
				item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
				self.func_list.addItem(item)

			self.block_label.setText("")


		self.add_button.clicked.connect(self.add_button_clicked)
		self.add_script.clicked.connect(self.add_script_clicked)

		self.widget_topic.topicsRefreshed.connect(self.topics_refreshed)        
		self.widget_topic.selectionChanged.connect(selection_changed)
		
		self.widget_topic.selectionChanged.emit([])


		delegate = FuncEditorDelegate(self.block_list)
		font = QFont("Monospace")

		self.block_list.setFont(font)
		self.block_list.setItemDelegate(delegate)
		self.block_list.setContentsMargins(100,10,10,100)
		self.block_list.setWordWrap(True)
		self.block_list.setTextElideMode(Qt.ElideNone)		
		self.block_list.setSelectionMode(QAbstractItemView.SingleSelection)
		self.block_list.setDragEnabled(True)
		self.block_list.viewport().setAcceptDrops(True)
		self.block_list.setDropIndicatorShown(True)
		self.block_list.setDragDropMode(QAbstractItemView.InternalMove)
		self.block_list.setMouseTracking(True)
		self.block_list.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
		self.block_list.setSpacing(3)

		self.block_list.addItem( ListBlockItem("\"\"\"\n" \
												+ "# Add your own python script here! You could \n" \
												+ "# access the variables defined by the previous \n" \
												+ "# blocks. To access observable values use \n" \
												+ "# vars()['value_name'] or locals()['value_name'] \n" \
												+ "\"\"\"") )


		self.func_list.setAlternatingRowColors(True)
		self.func_list.itemSelectionChanged.connect(self.func_list_changed)
		self.func_ret.setAutoFillBackground(True)

		completer = QCompleter(self.block_list.model())
		completer = QCompleter(["bob", "bobby", "bud", "charles", "charlie"], self.func_ret)
		self.func_ret.setCompleter(completer)
		self.func_ret.setEditable(True)

		# add a filter model to filter matching items
		self.pFilterModel = QSortFilterProxyModel(self.func_ret)
		self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
		self.pFilterModel.setSourceModel(self.widget_topic.topics_tree_widget.model())

		# add a completer, which uses the filter model
		self.completer = QCompleter(self.pFilterModel, self)
		# always show all (filtered) completions
		self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)

		self.func_ret.setCompleter(self.completer)

		# connect signals
		def filter(text):
			print "Edited: ", text, "type: ", type(text)
			self.pFilterModel.setFilterFixedString(str(text))

		def on_completer_activated(text):
			if text:
				index = self.func_ret.findText(str(text))
				self.func_ret.setCurrentIndex(index)

		self.func_ret.lineEdit().textEdited[unicode].connect(filter)
		self.completer.activated.connect(on_completer_activated)


		def block_label_clicked(*arg):
			# print "BLOCK LABEL CLICKED"
			self.assign_var.setFocus()
			self.assign_var.selectAll()

		self.block_label.clicked.connect(block_label_clicked)
		# self.block_label.setLineWrapMode(QTextEdit.WidgetWidth)


		def assign_var_text_changed(text = None):
			if text == None:
				text = self.assign_var.text()
			font = self.assign_var.font()
			fm = QFontMetrics(font);
			pixelsWide = fm.width(text);
			# pixelsHigh = fm.height();
			self.assign_var.setFixedSize(pixelsWide + 10, self.assign_var.height())

			text = self.assign_var.text()
			text = text.replace(" ", "")
			self.assign_var.setText(text)

		self.assign_var.textChanged.connect(assign_var_text_changed)
		self.assign_var.returnPressed.connect(self.add_button_clicked)
Пример #15
0
class FuncWidget(QWidget):
	"""
	main class inherits from the ui window class.

	You can specify the topics that the topic pane.

	FuncWidget.start must be called in order to update topic pane.
	"""

	SELECT_BY_NAME = 0
	SELECT_BY_MSGTYPE = 1

	_column_names = ['topic', 'type', 'value', 'checkbox']

	def __init__(self, plugin=None, selected_topics=None, select_topic_type=SELECT_BY_NAME):
		"""
		@type selected_topics: list of tuples.
		@param selected_topics: [($NAME_TOPIC$, $TYPE_TOPIC$), ...]
		@type select_topic_type: int
		@param select_topic_type: Can specify either the name of topics or by
								  the type of topic, to filter the topics to
								  show. If 'select_topic_type' argument is
								  None, this arg shouldn't be meaningful.
		"""
		super(FuncWidget, self).__init__()

		rp = rospkg.RosPack()
		ui_file = os.path.join(rp.get_path('rqt_dyn_tune'), 'resource', 'FuncWidget.ui')
		loadUi(ui_file, self)
		
		self._plugin = plugin
		self.list_available_functions = rospy.ServiceProxy('/list_available_functions', ListAvailableFunctions)
		self.functions = function.load_functions()
		self._select_topic_type = select_topic_type
		self.topics_tree_widget = self.widget_topic.topics_tree_widget

		self.execs = {}
		self.values = {}
		self.items = {}

		


		self.hLayout_0.setStretchFactor(self.vLayout_0, 5)
		self.hLayout_0.setStretchFactor(self.gridLayout, 2)


		@Slot(dict)
		def selection_changed(data):
			self.func_list.clear()
			funcs = self.list_available_functions(self.widget_topic.get_selected_types()).functions			

			for func in funcs:
				item = QListWidgetItem()				
				item.setData(Qt.UserRole, func)
				item.setText(func + "(...)")
				item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
				self.func_list.addItem(item)

			self.block_label.setText("")


		self.add_button.clicked.connect(self.add_button_clicked)
		self.add_script.clicked.connect(self.add_script_clicked)

		self.widget_topic.topicsRefreshed.connect(self.topics_refreshed)        
		self.widget_topic.selectionChanged.connect(selection_changed)
		
		self.widget_topic.selectionChanged.emit([])


		delegate = FuncEditorDelegate(self.block_list)
		font = QFont("Monospace")

		self.block_list.setFont(font)
		self.block_list.setItemDelegate(delegate)
		self.block_list.setContentsMargins(100,10,10,100)
		self.block_list.setWordWrap(True)
		self.block_list.setTextElideMode(Qt.ElideNone)		
		self.block_list.setSelectionMode(QAbstractItemView.SingleSelection)
		self.block_list.setDragEnabled(True)
		self.block_list.viewport().setAcceptDrops(True)
		self.block_list.setDropIndicatorShown(True)
		self.block_list.setDragDropMode(QAbstractItemView.InternalMove)
		self.block_list.setMouseTracking(True)
		self.block_list.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
		self.block_list.setSpacing(3)

		self.block_list.addItem( ListBlockItem("\"\"\"\n" \
												+ "# Add your own python script here! You could \n" \
												+ "# access the variables defined by the previous \n" \
												+ "# blocks. To access observable values use \n" \
												+ "# vars()['value_name'] or locals()['value_name'] \n" \
												+ "\"\"\"") )


		self.func_list.setAlternatingRowColors(True)
		self.func_list.itemSelectionChanged.connect(self.func_list_changed)
		self.func_ret.setAutoFillBackground(True)

		completer = QCompleter(self.block_list.model())
		completer = QCompleter(["bob", "bobby", "bud", "charles", "charlie"], self.func_ret)
		self.func_ret.setCompleter(completer)
		self.func_ret.setEditable(True)

		# add a filter model to filter matching items
		self.pFilterModel = QSortFilterProxyModel(self.func_ret)
		self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
		self.pFilterModel.setSourceModel(self.widget_topic.topics_tree_widget.model())

		# add a completer, which uses the filter model
		self.completer = QCompleter(self.pFilterModel, self)
		# always show all (filtered) completions
		self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)

		self.func_ret.setCompleter(self.completer)

		# connect signals
		def filter(text):
			print "Edited: ", text, "type: ", type(text)
			self.pFilterModel.setFilterFixedString(str(text))

		def on_completer_activated(text):
			if text:
				index = self.func_ret.findText(str(text))
				self.func_ret.setCurrentIndex(index)

		self.func_ret.lineEdit().textEdited[unicode].connect(filter)
		self.completer.activated.connect(on_completer_activated)


		def block_label_clicked(*arg):
			# print "BLOCK LABEL CLICKED"
			self.assign_var.setFocus()
			self.assign_var.selectAll()

		self.block_label.clicked.connect(block_label_clicked)
		# self.block_label.setLineWrapMode(QTextEdit.WidgetWidth)


		def assign_var_text_changed(text = None):
			if text == None:
				text = self.assign_var.text()
			font = self.assign_var.font()
			fm = QFontMetrics(font);
			pixelsWide = fm.width(text);
			# pixelsHigh = fm.height();
			self.assign_var.setFixedSize(pixelsWide + 10, self.assign_var.height())

			text = self.assign_var.text()
			text = text.replace(" ", "")
			self.assign_var.setText(text)

		self.assign_var.textChanged.connect(assign_var_text_changed)
		self.assign_var.returnPressed.connect(self.add_button_clicked)



	def func_list_changed(self, *_):


		args = self.widget_topic.get_selected()
		func = self.func_list.selectedItems()

		if func and args:
			func = func[0].data(Qt.UserRole)		
			first = " = {0}( ".format(func)
			joint = ', '
			second = "{0} )".format(joint.join(args))

			self.block_label.setText(first + second)
			self.assign_var.setFocus()
			self.assign_var.selectAll()

		else:
			self.block_label.setText("")




	def add_script_clicked(self, checked = False):	
		self.block_list.insertItem(self.block_list.currentRow() + 1, ListBlockItem())

	def add_button_clicked(self, checked = False):

		args = self.widget_topic.get_selected()
		func = self.func_list.selectedItems()
		retvar = self.assign_var.text()

		if args and func and retvar != '' and retvar != None:
			func = func[0].data(Qt.UserRole)
			print "there is items: ", args, func
			

			first = "{0} = {1}( ".format(retvar, func)
			spcs = len(first)
			joint = ',\n' + ''.join([' '] * spcs)
			second = "{0} )".format(joint.join(args))

			item = ListBlockItem((first + second), 
									func = self.functions[func], 
									args = args, 
									retvar = retvar, 
									has_script = False ) 

			font = QFont("Courier")
			font.setFamily("Courier");
			font.setStyleHint(QFont.Monospace);
			font.setFixedPitch(True);
			font.setPointSize(10);
			item.setFont(font)

			self.widget_topic.clear_selection()
			self.block_label.setText("")
			self.block_list.addItem(item)
			self.func_ret.setCurrentText(retvar)
	

	def resolve_type(self, msg):
		if hasattr(msg, '_type') and type(msg) != type:
			return msg._type

		if hasattr(msg, 'dtype') and type(msg.dtype.name) == str:
			return str(msg.dtype.name) + '[]'

		return type(msg).__name__


	def create_function_msg(self, name = "objective", desc = 'A new objective function'):
		func = Function()
		func.name = name

		blocks = [ self.block_list.item(index) for index in xrange(self.block_list.count()) ]

		for block in blocks:
			
			task = Task()
			task.has_script = block.has_script
			task.script = block.data(Qt.EditRole)
			
			if block.func != None:
				task.function = block.func.__name__
				task.args = block.args
				task.return_var = block.retvar

			func.tasks.append(task)

		func.return_var = self.func_ret.currentText()
		func.return_type = "*"
		func.arg_types = "[\"*\", []]"
		func.description = desc

		return func


	def topics_refreshed(self, values = {}):

		DUPLICATE_FACTOR = 10

		values =  { key:np.array([value] * DUPLICATE_FACTOR) for key, value in values.items() }

		items = [ self.block_list.item(index) for index in xrange(self.block_list.count()) ]

		print self.block_list.count()
		print "=========== EXECUTING ==========="
		count = 0
		for item in items:
			print ">> block #%d" % count 
			count += 1
			values.update( item.execute(values) )
			print "_________________________________"
		print "================================="

		_values = values.copy()

		for key in _values:
			if re.match("__.*__",key):
				del values[key]

		self.values = values

		# print values

		topic_widget = self.widget_topic

		for key, value in self.values.items():
			if key not in topic_widget._tree_items:
				topic_widget._tree_items[key] = TreeWidgetItem(topic_widget._toggle_monitoring, key, self.topics_tree_widget, is_topic = False)
			
			_item = topic_widget._tree_items[key]
			_item.setText(topic_widget._column_index['topic'], key)
			_item.setText(topic_widget._column_index['type'], self.resolve_type(value))
			_item.setText(topic_widget._column_index['value'], repr(value))
			_item.setData(topic_widget._column_index['value'], Qt.UserRole, value)


		for key, item in topic_widget._tree_items.items():
			if key not in self.values:				
				
				topic_widget.unselect(key)
				topic_widget.remove(key)

				print self.values
				print "deleting", key

	def start(self):
		# self.widget_topic.start()
		pass

	def shutdown_plugin(self):
		self.widget_topic.shutdown_plugin()

	# TODO(Enhancement) Save/Restore tree expansion state
	def save_settings(self, plugin_settings, instance_settings):
		print "do no saving"
		pass
		# header_state = self.topics_tree_widget.header().saveState()
		# instance_settings.set_value('tree_widget_header_state', header_state)

	def restore_settings(self, pluggin_settings, instance_settings):
		print "do no restoring"
		pass