class SelectDialog(QDialog):
    '''
    This dialog creates an input mask for a string list and return selected entries.
    '''
    def __init__(self,
                 items=list(),
                 buttons=QDialogButtonBox.Cancel | QDialogButtonBox.Ok,
                 exclusive=False,
                 preselect_all=False,
                 title='',
                 description='',
                 icon='',
                 parent=None,
                 select_if_single=True,
                 checkitem1='',
                 checkitem2='',
                 closein=0):
        '''
        Creates an input dialog.
        @param items: a list with strings
        @type items: C{list()}
        '''
        QDialog.__init__(self, parent=parent)
        self.setObjectName(' - '.join(['SelectDialog', utf8(items)]))

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(1, 1, 1, 1)

        # add filter row
        self.filter_frame = QFrame(self)
        filterLayout = QHBoxLayout(self.filter_frame)
        filterLayout.setContentsMargins(1, 1, 1, 1)
        label = QLabel("Filter:", self.filter_frame)
        self.filter_field = EnchancedLineEdit(self.filter_frame)
        filterLayout.addWidget(label)
        filterLayout.addWidget(self.filter_field)
        self.filter_field.textChanged.connect(self._on_filter_changed)
        self.verticalLayout.addWidget(self.filter_frame)

        if description:
            self.description_frame = QFrame(self)
            descriptionLayout = QHBoxLayout(self.description_frame)
            #      descriptionLayout.setContentsMargins(1, 1, 1, 1)
            if icon:
                self.icon_label = QLabel(self.description_frame)
                self.icon_label.setSizePolicy(QSizePolicy.Fixed,
                                              QSizePolicy.Fixed)
                self.icon_label.setPixmap(
                    QPixmap(icon).scaled(30, 30, Qt.KeepAspectRatio))
                descriptionLayout.addWidget(self.icon_label)
            self.description_label = QLabel(self.description_frame)
            self.description_label.setWordWrap(True)
            self.description_label.setText(description)
            descriptionLayout.addWidget(self.description_label)
            self.verticalLayout.addWidget(self.description_frame)

        # create area for the parameter
        self.content = MainBox(self)
        if items:
            self.scroll_area = QScrollArea(self)
            self.scroll_area.setFocusPolicy(Qt.NoFocus)
            self.scroll_area.setObjectName("scroll_area")
            self.scroll_area.setWidgetResizable(True)
            self.scroll_area.setWidget(self.content)
            self.verticalLayout.addWidget(self.scroll_area)

        self.checkitem1 = checkitem1
        self.checkitem1_result = False
        self.checkitem2 = checkitem2
        self.checkitem2_result = False

        # add select all option
        if not exclusive and items:
            self._ignore_next_toggle = False
            self.select_all_checkbox = QCheckBox('all entries')
            self.select_all_checkbox.setTristate(True)
            self.select_all_checkbox.stateChanged.connect(
                self._on_select_all_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.select_all_checkbox)
            self.content.toggled.connect(self._on_main_toggle)
        if self.checkitem1:
            self.checkitem1_checkbox = QCheckBox(self.checkitem1)
            self.checkitem1_checkbox.stateChanged.connect(
                self._on_select_checkitem1_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.checkitem1_checkbox)
        if self.checkitem2:
            self.checkitem2_checkbox = QCheckBox(self.checkitem2)
            self.checkitem2_checkbox.stateChanged.connect(
                self._on_select_checkitem2_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.checkitem2_checkbox)
        if not items:
            spacerItem = QSpacerItem(1, 1, QSizePolicy.Expanding,
                                     QSizePolicy.Expanding)
            self.verticalLayout.addItem(spacerItem)

        self._close_timer = None
        self._closein = closein - 1
        if closein > 0:
            self.closein_label = QLabel("OK in %d sec..." % closein)
            self.closein_label.setAlignment(Qt.AlignRight)
            self.verticalLayout.addWidget(self.closein_label)
            self._close_timer = threading.Timer(1.0, self._on_close_timer)
            self._close_timer.start()

        # create buttons
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setObjectName("buttonBox")
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(buttons)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.verticalLayout.addWidget(self.buttonBox)

        # set the input fields
        if items:
            self.content.createFieldsFromValues(items, exclusive)
            if (select_if_single and len(items) == 1) or preselect_all:
                self.select_all_checkbox.setCheckState(Qt.Checked)

        if not items or len(items) < 7:
            self.filter_frame.setVisible(False)
#    print '=============== create', self.objectName()
#
#  def __del__(self):
#    print "************ destroy", self.objectName()

    def _on_main_toggle(self, state):
        self.cancel_autoclose()
        self._ignore_next_toggle = state != self.select_all_checkbox.checkState(
        )
        self.select_all_checkbox.setCheckState(state)

    def _on_select_all_checkbox_stateChanged(self, state):
        self.cancel_autoclose()
        if not self._ignore_next_toggle:
            self.content.setState(state)
        self._ignore_next_toggle = False

    def _on_select_checkitem1_checkbox_stateChanged(self, state):
        self.cancel_autoclose()
        if state == Qt.Checked:
            self.checkitem1_result = True
        elif state == Qt.Unchecked:
            self.checkitem1_result = False

    def _on_select_checkitem2_checkbox_stateChanged(self, state):
        self.cancel_autoclose()
        if state == Qt.Checked:
            self.checkitem2_result = True
        elif state == Qt.Unchecked:
            self.checkitem2_result = False

    def _on_filter_changed(self):
        self.content.filter(self.filter_field.text())

    def _on_close_timer(self):
        self.closein_label.setText("OK in %d sec..." % self._closein)
        if self._closein == 0:
            self.buttonBox.accepted.emit()
            return
        self._closein -= 1
        self._close_timer = threading.Timer(1.0, self._on_close_timer)
        self._close_timer.start()

    def cancel_autoclose(self):
        if self._close_timer is not None:
            self._close_timer.cancel()
            self.closein_label.setVisible(False)

    def getSelected(self):
        return self.content.getSelected()

    @staticmethod
    def getValue(title,
                 description='',
                 items=list(),
                 exclusive=False,
                 preselect_all=False,
                 icon='',
                 parent=None,
                 select_if_single=True,
                 checkitem1='',
                 checkitem2='',
                 closein=0):
        selectDia = SelectDialog(items,
                                 exclusive=exclusive,
                                 preselect_all=preselect_all,
                                 description=description,
                                 icon=icon,
                                 parent=parent,
                                 select_if_single=select_if_single,
                                 checkitem1=checkitem1,
                                 checkitem2=checkitem2,
                                 closein=closein)
        selectDia.setWindowTitle(title)
        selectDia.resize(480, 256)
        if selectDia.exec_():
            if selectDia.checkitem2:
                return selectDia.getSelected(
                ), True, selectDia.checkitem1_result, selectDia.checkitem2_result
            if selectDia.checkitem1:
                return selectDia.getSelected(
                ), True, selectDia.checkitem1_result
            return selectDia.getSelected(), True
        if selectDia.checkitem2:
            return list(), False, False, False
        if selectDia.checkitem1:
            return list(), False, False
        return list(), False


# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# %%%%%%%%%%%%%%%%%% close handling                        %%%%%%%%%%%%%%%%%%%%%
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    def accept(self):
        self.cancel_autoclose()
        self.setResult(QDialog.Accepted)
        self.hide()

    def reject(self):
        self.cancel_autoclose()
        self.setResult(QDialog.Rejected)
        self.hide()

    def hideEvent(self, event):
        self.close()

    def closeEvent(self, event):
        '''
        Test the open files for changes and save this if needed.
        '''
        self.cancel_autoclose()
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        QDialog.closeEvent(self, event)
class SyncDialog(QDialog):
    '''
    A dialog to set the sync options.
    '''

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
#    self.host = host
        self.setWindowIcon(QIcon(":/icons/irondevil_sync.png"))
        self.setWindowTitle('Sync')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.resize(350, 190)

        self.toolButton_SyncAll = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(2)
        sizePolicy.setHeightForWidth(self.toolButton_SyncAll.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncAll.setSizePolicy(sizePolicy)
        self.toolButton_SyncAll.setObjectName("toolButton_SyncAll")
        self.verticalLayout.addWidget(self.toolButton_SyncAll)
        self.toolButton_SyncAll.setText(self._translate("Sync All"))
        self.toolButton_SyncAll.clicked.connect(self._on_sync_all_clicked)

#     self.toolButton_SyncAllAnyMsg = QToolButton(self)
#     sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
#     sizePolicy.setHorizontalStretch(0)
#     sizePolicy.setVerticalStretch(1)
#     sizePolicy.setHeightForWidth(self.toolButton_SyncAllAnyMsg.sizePolicy().hasHeightForWidth())
#     self.toolButton_SyncAllAnyMsg.setSizePolicy(sizePolicy)
#     self.toolButton_SyncAllAnyMsg.setObjectName("toolButton_SyncAllAnyMsg")
#     self.verticalLayout.addWidget(self.toolButton_SyncAllAnyMsg)
#     self.toolButton_SyncAllAnyMsg.setText(self._translate("Sync all (+AnyMsg)"))
#     self.toolButton_SyncAllAnyMsg.clicked.connect(self._on_sync_all_anymsg_clicked)

        self.toolButton_SyncTopicOnDemand = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_SyncTopicOnDemand.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncTopicOnDemand.setSizePolicy(sizePolicy)
        self.toolButton_SyncTopicOnDemand.setObjectName("toolButton_SyncTopicOnDemand")
        self.verticalLayout.addWidget(self.toolButton_SyncTopicOnDemand)
        self.toolButton_SyncTopicOnDemand.setText(self._translate("Sync only topics on demand"))
        self.toolButton_SyncTopicOnDemand.clicked.connect(self._on_sync_topics_on_demand_clicked)

        self.toolButton_SelectInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_SelectInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_SelectInterface.setSizePolicy(sizePolicy)
        self.toolButton_SelectInterface.setObjectName("toolButton_SelectInterface")
        self.verticalLayout.addWidget(self.toolButton_SelectInterface)
        self.toolButton_SelectInterface.setText(self._translate("Select an interface"))
        self.toolButton_SelectInterface.clicked.connect(self._on_select_interface_clicked)

        self.interface_field = QComboBox(self)
        self.interface_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.interface_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.interface_field.setEditable(True)
        self.interface_field.setVisible(False)
        self.interface_field.setObjectName("interface_field")
        self.verticalLayout.addWidget(self.interface_field)
        self.interface_field.currentIndexChanged[str].connect(self._on_interface_selected)

        self.toolButton_EditInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_EditInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_EditInterface.setSizePolicy(sizePolicy)
        self.toolButton_EditInterface.setObjectName("toolButton_EditInterface")
        self.verticalLayout.addWidget(self.toolButton_EditInterface)
        self.toolButton_EditInterface.setText(self._translate("Edit selected interface"))
        self.toolButton_EditInterface.clicked.connect(self._on_edit_interface_clicked)
        self.toolButton_EditInterface.setVisible(False)

        self.toolButton_CreateInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_CreateInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_CreateInterface.setSizePolicy(sizePolicy)
        self.toolButton_CreateInterface.setObjectName("toolButton_CreateInterface")
        self.verticalLayout.addWidget(self.toolButton_CreateInterface)
        self.toolButton_CreateInterface.setText(self._translate("Create an interface"))
        self.toolButton_CreateInterface.clicked.connect(self._on_create_interface_clicked)
        self.toolButton_CreateInterface.setVisible(False)

        self.textedit = TextEdit('', self)
        self.hl = SyncHighlighter(self.textedit.document())
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.textedit.setSizePolicy(sizePolicy)
        self.textedit.setObjectName("syncedit")
        self.verticalLayout.addWidget(self.textedit)
        self.textedit.setVisible(False)

        self._fill_interface_thread = None
        self._interfaces_files = None
        self._sync_args = []
        self._interface_filename = None

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self._new_iface = True

    def _translate(self, text):
        if hasattr(QApplication, "UnicodeUTF8"):
            return QApplication.translate("Form", text, None, QApplication.UnicodeUTF8)
        else:
            return QApplication.translate("Form", text, None)

    @property
    def sync_args(self):
        return self._sync_args

    @property
    def interface_filename(self):
        return self._interface_filename

    def _on_sync_all_clicked(self):
        self.setResult(QDialog.Accepted)
        self._sync_args = []
        self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
        self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'False']))
        self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
        self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
        self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
        self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
        self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_publishers:=', '[]']))
        self._sync_args.append(''.join(['_ignore_subscribers:=', '[]']))
        self._sync_args.append(''.join(['_sync_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
        self._interface_filename = None
        self.accept()

#   def _on_sync_all_anymsg_clicked(self):
#     self._sync_args = []
#     self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
#     self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'True']))
#     self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
#     self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
#     self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
#     self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
#     self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
#     self._sync_args.append(''.join(['_sync_topics:=', '[/*]']))
#     self._sync_args.append(''.join(['_ignore_services:=', '[]']))
#     self._sync_args.append(''.join(['_sync_services:=', '[]']))
#     self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
#     self._interface_filename = None
#     self.accept()

    def _on_sync_topics_on_demand_clicked(self):
        self._sync_args = []
        self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
        self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'True']))
        self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
        self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
        self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
        self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
        self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_publishers:=', '[]']))
        self._sync_args.append(''.join(['_ignore_subscribers:=', '[]']))
        self._sync_args.append(''.join(['_sync_topics:=', '[/only_on_demand]']))
        self._sync_args.append(''.join(['_ignore_services:=', '[/*]']))
        self._sync_args.append(''.join(['_sync_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
        self._interface_filename = None
        self.accept()

    def _on_select_interface_clicked(self):
        self.toolButton_SyncAll.setVisible(False)
#    self.toolButton_SyncAllAnyMsg.setVisible(False)
        self.toolButton_SyncTopicOnDemand.setVisible(False)
        self.toolButton_SelectInterface.setVisible(False)
        self.interface_field.setVisible(True)
        self.toolButton_CreateInterface.setVisible(True)
        self.toolButton_EditInterface.setVisible(True)
        self.toolButton_EditInterface.setEnabled(False)
        self.textedit.setVisible(False)
#    # fill the interfaces
        if self._interfaces_files is None:
            self.interface_field.addItems(['interface searching...'])
            self.interface_field.setCurrentIndex(0)
            self._fill_interface_thread = InterfacesThread()
            self._fill_interface_thread.interfaces.connect(self._fill_interfaces)
            self._fill_interface_thread.start()
        else:
            self.toolButton_EditInterface.setEnabled(self.interface_field.currentText() in self._interfaces_files)
        self.buttonBox.clear()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.interface_field.setFocus(Qt.TabFocusReason)
        self.resize(350, 80)

    def _fill_interfaces(self, interfaces_files):
        self._interfaces_files = interfaces_files
        self.interface_field.clear()
        self.interface_field.clearEditText()
        self.interface_field.addItems(self._interfaces_files.keys())

    def _on_interface_selected(self, interface):
        if self._interfaces_files and interface in self._interfaces_files:
            self._sync_args = []
            self._sync_args.append(''.join(['_interface_url:=', interface]))
            self.toolButton_EditInterface.setEnabled(True)
        else:
            self.toolButton_EditInterface.setEnabled(False)

    def accept(self):
        if self.textedit.isVisible():
            try:
                tmp_file = os.path.join(nm.screen().LOG_PATH, 'tmp_sync_interface.sync')
                with open(tmp_file, 'w+') as f:
                    f.write(self.textedit.toPlainText())
                from master_discovery_fkie.common import read_interface
                read_interface(tmp_file)
                if not self._new_iface and self.interface_field.currentText() in self._interfaces_files:
                    fileName = self._interfaces_files[self.interface_field.currentText()]
                else:
                    fileName, _ = QFileDialog.getSaveFileName(self, 'Save sync interface', '/home', "Sync Files (*.sync)")
                if fileName:
                    with open(fileName, 'w+') as f:
                        self._interface_filename = fileName
                        f.write(self.textedit.toPlainText())
                        if self._new_iface:
                            self.interface_field.clear()
                            self._interfaces_files = None
                        self._on_select_interface_clicked()
#        QDialog.accept(self)
#        self.resetView()
            except Exception as e:
                MessageBox.warning(self, "Create sync interface",
                                   "Error while create interface",
                                   utf8(e))
        elif self.interface_field.isVisible():
            interface = self.interface_field.currentText()
            if self._interfaces_files and interface in self._interfaces_files:
                self._interface_filename = self._interfaces_files[interface]
                self._sync_args = []
                self._sync_args.append(''.join(['_interface_url:=', interface]))
                QDialog.accept(self)
                self.resetView()
        else:
            QDialog.accept(self)
            self.resetView()

    def reject(self):
        if self.textedit.isVisible():
            self._on_select_interface_clicked()
        else:
            QDialog.reject(self)
            self.resetView()

    def _on_create_interface_clicked(self):
        self._new_iface = True
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(True)
        self.textedit.setText("# The ignore_* lists will be processed first.\n"
                              "# For ignore/sync nodes, topics or services\n"
                              "# use follow declaration:\n"
                              "#{param name}: \n"
                              "#   - {ros name}\n"
                              "# or for selected hosts:\n"
                              "#   - {host name}:\n"
                              "#     - {ros name}\n\n"
                              "# you can use follow wildcard: '*', but not as a first character\n"
                              "ignore_hosts:\n"
                              "sync_hosts:\n\n"
                              "ignore_nodes:\n"
                              "sync_nodes:\n\n"
                              "ignore_topics:\n"
                              "ignore_publishers:\n"
                              "ignore_subscribers:\n"
                              "sync_topics:\n\n"
                              "ignore_services:\n"
                              "  - /*get_loggers\n"
                              "  - /*set_logger_level\n"
                              "sync_services:\n\n"
                              "# If sync_topics_on_demand is True the local subscribed and published topics\n"
                              "# are synchronized with remote even if they are not in the sync_* list.\n"
                              "sync_topics_on_demand: False\n\n"
                              "# The nodes which are running not at the same host as the ROS master are not\n"
                              "# synchronized by default. Use sync_remote_nodes to sync these nodes also.\n"
                              "sync_remote_nodes: False\n\n"
                              )
        self.resize(350, 300)

    def _on_edit_interface_clicked(self):
        self._new_iface = False
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(True)
        if self.interface_field.currentText() in self._interfaces_files:
            try:
                with open(self._interfaces_files[self.interface_field.currentText()], 'rw') as f:
                    iface = f.read()
                    self.textedit.setText(iface)
            except Exception as e:
                MessageBox.warning(self, "Edit sync interface",
                                   "Error while open interface",
                                   utf8(e))
        self.resize(350, 300)

    def resetView(self):
        self.toolButton_SyncAll.setVisible(True)
#     self.toolButton_SyncAllAnyMsg.setVisible(True)
        self.toolButton_SyncTopicOnDemand.setVisible(True)
        self.toolButton_SelectInterface.setVisible(True)
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(False)
        self.buttonBox.clear()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.resize(350, 160)
示例#3
0
class PackageDialog(QDialog):
    def __init__(self, masteruri, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Select Binary')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")

        self.content = QWidget()
        self.contentLayout = QFormLayout(self.content)
        self.contentLayout.setVerticalSpacing(0)
        self.verticalLayout.addWidget(self.content)

        self.packages = None
        self.masteruri = "ROS_MASTER_URI" if masteruri is None else masteruri
        package_label = QLabel("Package:", self.content)
        self.package_field = QComboBox(self.content)
        self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.package_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.package_field.setEditable(True)
        self.contentLayout.addRow(package_label, self.package_field)
        binary_label = QLabel("Binary:", self.content)
        self.binary_field = QComboBox(self.content)
        self.binary_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.binary_field.setEditable(True)
        self.contentLayout.addRow(binary_label, self.binary_field)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.package_field.setFocus(Qt.TabFocusReason)
        self.package = ''
        self.binary = ''
        self._request_bin_thread = None

        if self.packages is None:
            self.package_field.addItems(['packages searching...'])
            self.package_field.setCurrentIndex(0)
        # fill the input fields
        self.packages = {
            name: path
            for path, name in nm.nmd().file.get_packages(
                nmdurl.nmduri(masteruri)).items()
        }
        packages = self.packages.keys()
        packages.sort()
        self.package_field.clear()
        self.package_field.clearEditText()
        self.package_field.addItems(packages)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        QMetaObject.connectSlotsByName(self)
        self.package_field.activated[str].connect(self.on_package_selected)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
            self.binary_field.textChanged.connect(self.on_binary_selected)
        else:
            self.package_field.editTextChanged.connect(
                self.on_package_selected)
            self.binary_field.editTextChanged.connect(self.on_binary_selected)

    def on_package_selected(self, package):
        getnew = False
        if self._request_bin_thread is None:
            getnew = True
        else:
            if self._request_bin_thread.pkgname != package:
                self._request_bin_thread.cancel()
                getnew = True
        if self._request_bin_thread is not None and self._request_bin_thread.pkgname == package:
            # use already got data
            self._request_bin_thread.reemit()
        elif getnew:
            self.binary_field.clear()
            if self.packages and package in self.packages:
                self.binary_field.setEnabled(True)
                self._request_bin_thread = RequestBinariesThread(
                    package, nmdurl.nmduri(self.masteruri))
                self._request_bin_thread.binaries_signal.connect(
                    self._on_new_binaries)
                self._request_bin_thread.start()

    def _on_new_binaries(self, pkgname, binaries):
        # update the binaries
        binaries = [os.path.basename(item) for item in binaries.keys()]
        binaries = list(set(binaries))
        binaries.sort()
        self.binary_field.addItems(binaries)
        self.package = pkgname
        self.binary = self.binary_field.currentText()

    def on_binary_selected(self, binary):
        self.binary = binary
示例#4
0
class SelectDialog(QDialog):
    '''
    This dialog creates an input mask for a string list and return selected entries.
    '''

    def __init__(self, items=list(), buttons=QDialogButtonBox.Cancel | QDialogButtonBox.Ok, exclusive=False,
                 preselect_all=False, title='', description='', icon='', parent=None, select_if_single=True,
                 checkitem1='', checkitem2=''):
        '''
        Creates an input dialog.
        @param items: a list with strings
        @type items: C{list()}
        '''
        QDialog.__init__(self, parent=parent)
        self.setObjectName(' - '.join(['SelectDialog', str(items)]))

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(1, 1, 1, 1)

        # add filter row
        self.filter_frame = QFrame(self)
        filterLayout = QHBoxLayout(self.filter_frame)
        filterLayout.setContentsMargins(1, 1, 1, 1)
        label = QLabel("Filter:", self.filter_frame)
        self.filter_field = EnchancedLineEdit(self.filter_frame)
        filterLayout.addWidget(label)
        filterLayout.addWidget(self.filter_field)
        self.filter_field.textChanged.connect(self._on_filter_changed)
        self.verticalLayout.addWidget(self.filter_frame)

        if description:
            self.description_frame = QFrame(self)
            descriptionLayout = QHBoxLayout(self.description_frame)
#      descriptionLayout.setContentsMargins(1, 1, 1, 1)
            if icon:
                self.icon_label = QLabel(self.description_frame)
                self.icon_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
                self.icon_label.setPixmap(QPixmap(icon).scaled(30, 30, Qt.KeepAspectRatio))
                descriptionLayout.addWidget(self.icon_label)
            self.description_label = QLabel(self.description_frame)
            self.description_label.setWordWrap(True)
            self.description_label.setText(description)
            descriptionLayout.addWidget(self.description_label)
            self.verticalLayout.addWidget(self.description_frame)

        # create area for the parameter
        self.content = MainBox(self)
        if items:
            self.scroll_area = QScrollArea(self)
            self.scroll_area.setFocusPolicy(Qt.NoFocus)
            self.scroll_area.setObjectName("scroll_area")
            self.scroll_area.setWidgetResizable(True)
            self.scroll_area.setWidget(self.content)
            self.verticalLayout.addWidget(self.scroll_area)

        self.checkitem1 = checkitem1
        self.checkitem1_result = False
        self.checkitem2 = checkitem2
        self.checkitem2_result = False

        # add select all option
        if not exclusive and items:
            self._ignore_next_toggle = False
            self.select_all_checkbox = QCheckBox('all entries')
            self.select_all_checkbox.setTristate(True)
            self.select_all_checkbox.stateChanged.connect(self._on_select_all_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.select_all_checkbox)
            self.content.toggled.connect(self._on_main_toggle)
        if self.checkitem1:
            self.checkitem1_checkbox = QCheckBox(self.checkitem1)
            self.checkitem1_checkbox.stateChanged.connect(self._on_select_checkitem1_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.checkitem1_checkbox)
        if self.checkitem2:
            self.checkitem2_checkbox = QCheckBox(self.checkitem2)
            self.checkitem2_checkbox.stateChanged.connect(self._on_select_checkitem2_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.checkitem2_checkbox)
        if not items:
            spacerItem = QSpacerItem(1, 1, QSizePolicy.Expanding, QSizePolicy.Expanding)
            self.verticalLayout.addItem(spacerItem)

        # create buttons
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setObjectName("buttonBox")
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(buttons)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.verticalLayout.addWidget(self.buttonBox)

        # set the input fields
        if items:
            self.content.createFieldsFromValues(items, exclusive)
            if (select_if_single and len(items) == 1) or preselect_all:
                self.select_all_checkbox.setCheckState(Qt.Checked)

        if not items or len(items) < 7:
            self.filter_frame.setVisible(False)
#    print '=============== create', self.objectName()
#
#  def __del__(self):
#    print "************ destroy", self.objectName()

    def _on_main_toggle(self, state):
        self._ignore_next_toggle = state != self.select_all_checkbox.checkState()
        self.select_all_checkbox.setCheckState(state)

    def _on_select_all_checkbox_stateChanged(self, state):
        if not self._ignore_next_toggle:
            self.content.setState(state)
        self._ignore_next_toggle = False

    def _on_select_checkitem1_checkbox_stateChanged(self, state):
        if state == Qt.Checked:
            self.checkitem1_result = True
        elif state == Qt.Unchecked:
            self.checkitem1_result = False

    def _on_select_checkitem2_checkbox_stateChanged(self, state):
        if state == Qt.Checked:
            self.checkitem2_result = True
        elif state == Qt.Unchecked:
            self.checkitem2_result = False

    def _on_filter_changed(self):
        self.content.filter(self.filter_field.text())

    def getSelected(self):
        return self.content.getSelected()

    @staticmethod
    def getValue(title, description='', items=list(), exclusive=False, preselect_all=False, icon='', parent=None, select_if_single=True, checkitem1='', checkitem2=''):
        selectDia = SelectDialog(items, exclusive=exclusive, preselect_all=preselect_all, description=description, icon=icon, parent=parent, select_if_single=select_if_single, checkitem1=checkitem1, checkitem2=checkitem2)
        selectDia.setWindowTitle(title)
        selectDia.resize(480, 256)
        if selectDia.exec_():
            if selectDia.checkitem2:
                return selectDia.getSelected(), True, selectDia.checkitem1_result, selectDia.checkitem2_result
            if selectDia.checkitem1:
                return selectDia.getSelected(), True, selectDia.checkitem1_result
            return selectDia.getSelected(), True
        if selectDia.checkitem2:
            return list(), False, False, False
        if selectDia.checkitem1:
            return list(), False, False
        return list(), False


# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# %%%%%%%%%%%%%%%%%% close handling                        %%%%%%%%%%%%%%%%%%%%%
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    def accept(self):
        self.setResult(QDialog.Accepted)
        self.hide()

    def reject(self):
        self.setResult(QDialog.Rejected)
        self.hide()

    def hideEvent(self, event):
        self.close()

    def closeEvent(self, event):
        '''
        Test the open files for changes and save this if needed.
        '''
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        QDialog.closeEvent(self, event)
示例#5
0
class SyncDialog(QDialog):
    '''
    A dialog to set the sync options.
    '''
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        #    self.host = host
        self.setWindowIcon(QIcon(":/icons/irondevil_sync.png"))
        self.setWindowTitle('Sync')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.resize(350, 190)

        self.toolButton_SyncAll = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(2)
        sizePolicy.setHeightForWidth(
            self.toolButton_SyncAll.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncAll.setSizePolicy(sizePolicy)
        self.toolButton_SyncAll.setObjectName("toolButton_SyncAll")
        self.verticalLayout.addWidget(self.toolButton_SyncAll)
        self.toolButton_SyncAll.setText(self._translate("Sync All"))
        self.toolButton_SyncAll.clicked.connect(self._on_sync_all_clicked)

        #     self.toolButton_SyncAllAnyMsg = QToolButton(self)
        #     sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        #     sizePolicy.setHorizontalStretch(0)
        #     sizePolicy.setVerticalStretch(1)
        #     sizePolicy.setHeightForWidth(self.toolButton_SyncAllAnyMsg.sizePolicy().hasHeightForWidth())
        #     self.toolButton_SyncAllAnyMsg.setSizePolicy(sizePolicy)
        #     self.toolButton_SyncAllAnyMsg.setObjectName("toolButton_SyncAllAnyMsg")
        #     self.verticalLayout.addWidget(self.toolButton_SyncAllAnyMsg)
        #     self.toolButton_SyncAllAnyMsg.setText(self._translate("Sync all (+AnyMsg)"))
        #     self.toolButton_SyncAllAnyMsg.clicked.connect(self._on_sync_all_anymsg_clicked)

        self.toolButton_SyncTopicOnDemand = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_SyncTopicOnDemand.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncTopicOnDemand.setSizePolicy(sizePolicy)
        self.toolButton_SyncTopicOnDemand.setObjectName(
            "toolButton_SyncTopicOnDemand")
        self.verticalLayout.addWidget(self.toolButton_SyncTopicOnDemand)
        self.toolButton_SyncTopicOnDemand.setText(
            self._translate("Sync only topics on demand"))
        self.toolButton_SyncTopicOnDemand.clicked.connect(
            self._on_sync_topics_on_demand_clicked)

        self.toolButton_SelectInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_SelectInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_SelectInterface.setSizePolicy(sizePolicy)
        self.toolButton_SelectInterface.setObjectName(
            "toolButton_SelectInterface")
        self.verticalLayout.addWidget(self.toolButton_SelectInterface)
        self.toolButton_SelectInterface.setText(
            self._translate("Select an interface"))
        self.toolButton_SelectInterface.clicked.connect(
            self._on_select_interface_clicked)

        self.interface_field = QComboBox(self)
        self.interface_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.interface_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.interface_field.setEditable(True)
        self.interface_field.setVisible(False)
        self.interface_field.setObjectName("interface_field")
        self.verticalLayout.addWidget(self.interface_field)
        self.interface_field.currentIndexChanged[str].connect(
            self._on_interface_selected)

        self.toolButton_EditInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_EditInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_EditInterface.setSizePolicy(sizePolicy)
        self.toolButton_EditInterface.setObjectName("toolButton_EditInterface")
        self.verticalLayout.addWidget(self.toolButton_EditInterface)
        self.toolButton_EditInterface.setText(
            self._translate("Edit selected interface"))
        self.toolButton_EditInterface.clicked.connect(
            self._on_edit_interface_clicked)
        self.toolButton_EditInterface.setVisible(False)

        self.toolButton_CreateInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_CreateInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_CreateInterface.setSizePolicy(sizePolicy)
        self.toolButton_CreateInterface.setObjectName(
            "toolButton_CreateInterface")
        self.verticalLayout.addWidget(self.toolButton_CreateInterface)
        self.toolButton_CreateInterface.setText(
            self._translate("Create an interface"))
        self.toolButton_CreateInterface.clicked.connect(
            self._on_create_interface_clicked)
        self.toolButton_CreateInterface.setVisible(False)

        self.textedit = TextEdit('', self)
        self.hl = SyncHighlighter(self.textedit.document())
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.textedit.setSizePolicy(sizePolicy)
        self.textedit.setObjectName("syncedit")
        self.verticalLayout.addWidget(self.textedit)
        self.textedit.setVisible(False)

        self._fill_interface_thread = None
        self._interfaces_files = None
        self._sync_args = []
        self._interface_filename = None

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self._new_iface = True

    def _translate(self, text):
        if hasattr(QApplication, "UnicodeUTF8"):
            return QApplication.translate("Form", text, None,
                                          QApplication.UnicodeUTF8)
        else:
            return QApplication.translate("Form", text, None)

    @property
    def sync_args(self):
        return self._sync_args

    @property
    def interface_filename(self):
        return self._interface_filename

    def _on_sync_all_clicked(self):
        self.setResult(QDialog.Accepted)
        self._sync_args = []
        self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
        self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'False']))
        self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
        self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
        self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
        self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
        self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_publishers:=', '[]']))
        self._sync_args.append(''.join(['_ignore_subscribers:=', '[]']))
        self._sync_args.append(''.join(['_sync_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
        self._interface_filename = None
        self.accept()

#   def _on_sync_all_anymsg_clicked(self):
#     self._sync_args = []
#     self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
#     self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'True']))
#     self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
#     self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
#     self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
#     self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
#     self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
#     self._sync_args.append(''.join(['_sync_topics:=', '[/*]']))
#     self._sync_args.append(''.join(['_ignore_services:=', '[]']))
#     self._sync_args.append(''.join(['_sync_services:=', '[]']))
#     self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
#     self._interface_filename = None
#     self.accept()

    def _on_sync_topics_on_demand_clicked(self):
        self._sync_args = []
        self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
        self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'True']))
        self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
        self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
        self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
        self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
        self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_publishers:=', '[]']))
        self._sync_args.append(''.join(['_ignore_subscribers:=', '[]']))
        self._sync_args.append(''.join(['_sync_topics:=',
                                        '[/only_on_demand]']))
        self._sync_args.append(''.join(['_ignore_services:=', '[/*]']))
        self._sync_args.append(''.join(['_sync_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
        self._interface_filename = None
        self.accept()

    def _on_select_interface_clicked(self):
        self.toolButton_SyncAll.setVisible(False)
        #    self.toolButton_SyncAllAnyMsg.setVisible(False)
        self.toolButton_SyncTopicOnDemand.setVisible(False)
        self.toolButton_SelectInterface.setVisible(False)
        self.interface_field.setVisible(True)
        self.toolButton_CreateInterface.setVisible(True)
        self.toolButton_EditInterface.setVisible(True)
        self.toolButton_EditInterface.setEnabled(False)
        self.textedit.setVisible(False)
        #    # fill the interfaces
        if self._interfaces_files is None:
            self.interface_field.addItems(['interface searching...'])
            self.interface_field.setCurrentIndex(0)
            self._fill_interface_thread = InterfacesThread()
            self._fill_interface_thread.interfaces.connect(
                self._fill_interfaces)
            self._fill_interface_thread.start()
        else:
            self.toolButton_EditInterface.setEnabled(
                self.interface_field.currentText() in self._interfaces_files)
        self.buttonBox.clear()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.interface_field.setFocus(Qt.TabFocusReason)
        self.resize(350, 80)

    def _fill_interfaces(self, interfaces_files):
        self._interfaces_files = interfaces_files
        self.interface_field.clear()
        self.interface_field.clearEditText()
        self.interface_field.addItems(self._interfaces_files.keys())

    def _on_interface_selected(self, interface):
        if self._interfaces_files and interface in self._interfaces_files:
            self._sync_args = []
            self._sync_args.append(''.join(['_interface_url:=', interface]))
            self.toolButton_EditInterface.setEnabled(True)
        else:
            self.toolButton_EditInterface.setEnabled(False)

    def accept(self):
        if self.textedit.isVisible():
            try:
                tmp_file = os.path.join(screen.LOG_PATH,
                                        'tmp_sync_interface.sync')
                with open(tmp_file, 'w+') as f:
                    f.write(self.textedit.toPlainText())
                from fkie_master_discovery.common import read_interface
                read_interface(tmp_file)
                if not self._new_iface and self.interface_field.currentText(
                ) in self._interfaces_files:
                    fileName = self._interfaces_files[
                        self.interface_field.currentText()]
                else:
                    fileName, _ = QFileDialog.getSaveFileName(
                        self, 'Save sync interface', '/home',
                        "Sync Files (*.sync)")
                if fileName:
                    with open(fileName, 'w+') as f:
                        self._interface_filename = fileName
                        f.write(self.textedit.toPlainText())
                        if self._new_iface:
                            self.interface_field.clear()
                            self._interfaces_files = None
                        self._on_select_interface_clicked()


#        QDialog.accept(self)
#        self.resetView()
            except Exception as e:
                MessageBox.warning(self, "Create sync interface",
                                   "Error while create interface", utf8(e))
        elif self.interface_field.isVisible():
            interface = self.interface_field.currentText()
            if self._interfaces_files and interface in self._interfaces_files:
                self._interface_filename = self._interfaces_files[interface]
                self._sync_args = []
                self._sync_args.append(''.join(['_interface_url:=',
                                                interface]))
                QDialog.accept(self)
                self.resetView()
        else:
            QDialog.accept(self)
            self.resetView()

    def reject(self):
        if self.textedit.isVisible():
            self._on_select_interface_clicked()
        else:
            QDialog.reject(self)
            self.resetView()

    def _on_create_interface_clicked(self):
        self._new_iface = True
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(True)
        self.textedit.setText(
            "# The ignore_* lists will be processed first.\n"
            "# For ignore/sync nodes, topics or services\n"
            "# use follow declaration:\n"
            "#{param name}: \n"
            "#   - {ros name}\n"
            "# or for selected hosts:\n"
            "#   - {host name}:\n"
            "#     - {ros name}\n\n"
            "# you can use follow wildcard: '*', but not as a first character\n"
            "ignore_hosts:\n"
            "sync_hosts:\n\n"
            "ignore_nodes:\n"
            "sync_nodes:\n\n"
            "ignore_topics:\n"
            "ignore_publishers:\n"
            "ignore_subscribers:\n"
            "sync_topics:\n\n"
            "ignore_services:\n"
            "  - /*get_loggers\n"
            "  - /*set_logger_level\n"
            "sync_services:\n\n"
            "# If sync_topics_on_demand is True the local subscribed and published topics\n"
            "# are synchronized with remote even if they are not in the sync_* list.\n"
            "sync_topics_on_demand: False\n\n"
            "# The nodes which are running not at the same host as the ROS master are not\n"
            "# synchronized by default. Use sync_remote_nodes to sync these nodes also.\n"
            "sync_remote_nodes: False\n\n")
        self.resize(350, 300)

    def _on_edit_interface_clicked(self):
        self._new_iface = False
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(True)
        if self.interface_field.currentText() in self._interfaces_files:
            try:
                with open(
                        self._interfaces_files[
                            self.interface_field.currentText()], 'rw') as f:
                    iface = f.read()
                    self.textedit.setText(iface)
            except Exception as e:
                MessageBox.warning(self, "Edit sync interface",
                                   "Error while open interface", utf8(e))
        self.resize(350, 300)

    def resetView(self):
        self.toolButton_SyncAll.setVisible(True)
        #     self.toolButton_SyncAllAnyMsg.setVisible(True)
        self.toolButton_SyncTopicOnDemand.setVisible(True)
        self.toolButton_SelectInterface.setVisible(True)
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(False)
        self.buttonBox.clear()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.resize(350, 160)
class PackageDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Select Binary')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")

        self.content = QWidget()
        self.contentLayout = QFormLayout(self.content)
        self.contentLayout.setVerticalSpacing(0)
        self.verticalLayout.addWidget(self.content)

        self.packages = None

        package_label = QLabel("Package:", self.content)
        self.package_field = QComboBox(self.content)
        self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.package_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.package_field.setEditable(True)
        self.contentLayout.addRow(package_label, self.package_field)
        binary_label = QLabel("Binary:", self.content)
        self.binary_field = QComboBox(self.content)
#    self.binary_field.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.binary_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.binary_field.setEditable(True)
        self.contentLayout.addRow(binary_label, self.binary_field)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.package_field.setFocus(Qt.TabFocusReason)
        self.package = ''
        self.binary = ''

        if self.packages is None:
            self.package_field.addItems(['packages searching...'])
            self.package_field.setCurrentIndex(0)
            self._fill_packages_thread = PackagesThread()
            self._fill_packages_thread.packages.connect(self._fill_packages)
            self._fill_packages_thread.start()

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        QMetaObject.connectSlotsByName(self)
        self.package_field.activated[str].connect(self.on_package_selected)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
            self.binary_field.textChanged.connect(self.on_binary_selected)
        else:
            self.package_field.editTextChanged.connect(self.on_package_selected)
            self.binary_field.editTextChanged.connect(self.on_binary_selected)

    def _fill_packages(self, packages):
        # fill the input fields
        self.packages = packages
        packages = packages.keys()
        packages.sort()
        self.package_field.clear()
        self.package_field.clearEditText()
        self.package_field.addItems(packages)

    def _getBinaries(self, path):
        result = {}
        if os.path.isdir(path):
            fileList = os.listdir(path)
            for f in fileList:
                if f and f[0] != '.' and f not in ['build'] and not f.endswith('.cfg') and not f.endswith('.so'):
                    ret = self._getBinaries(os.path.join(path, f))
                    result = dict(ret.items() + result.items())
        elif os.path.isfile(path) and os.access(path, os.X_OK):
            # create a selection for binaries
            return {os.path.basename(path): path}
        return result

    def on_package_selected(self, package):
        self.binary_field.clear()
        if self.packages and package in self.packages:
            self.binary_field.setEnabled(True)
            path = self.packages[package]
            binaries = self._getBinaries(path).keys()
            try:
                # find binaries in catkin workspace
                from catkin.find_in_workspaces import find_in_workspaces as catkin_find
                search_paths = catkin_find(search_dirs=['libexec', 'share'], project=package, first_matching_workspace_only=True)
                for p in search_paths:
                    binaries += self._getBinaries(p).keys()
            except:
                pass
            binaries = list(set(binaries))
            binaries.sort()
            self.binary_field.addItems(binaries)
            self.package = package
            self.binary = self.binary_field.currentText()

    def on_binary_selected(self, binary):
        self.binary = binary