Example #1
0
    def __init__(self, parent=None):
        super(SplitterWidget, self).__init__(parent)
        self.setWindowTitle("Splitter")

        font = QFont(self.tr("黑体"), 12)
        QApplication.setFont(font)

        mainSplitter = QSplitter(Qt.Horizontal, self)

        leftText = QTextEdit(self.tr("左窗口"), mainSplitter)
        leftText.setAlignment(Qt.AlignCenter)

        rightSplitter = QSplitter(Qt.Vertical, mainSplitter)
        rightSplitter.setOpaqueResize(False)

        upText = QTextEdit(self.tr("上窗口"), rightSplitter)
        upText.setAlignment(Qt.AlignCenter)

        bottomText = QTextEdit(self.tr("下窗口"), rightSplitter)
        bottomText.setAlignment(Qt.AlignCenter)

        mainSplitter.setStretchFactor(1, 1)
        mainSplitter.setWindowTitle(self.tr("分割窗口"))

        self.setCentralWidget(mainSplitter)
Example #2
0
 def __init__(self):
     super(HelpDockWidget, self).__init__(self.str_helpDockTitle)
     helpEngine = QHelpEngine(filePath('help/collection.qhc'))
     helpEngine.setupData()
     helpPanel = QSplitter(Qt.Vertical)
     helpBrowser = HelpTextBrowser(helpEngine)
     helpEngine.contentWidget().linkActivated.connect(helpBrowser.setSource)
     helpPanel.insertWidget(0, helpEngine.contentWidget())
     helpPanel.insertWidget(1, helpBrowser)
     helpPanel.setStretchFactor(1, 1)
     self.setWidget(helpPanel)
Example #3
0
    def __init__(self, *args, **kwargs):

        super(Widget_textEdit_splitter, self).__init__(*args, **kwargs)
        self.installEventFilter(self)
        mainLayout = QVBoxLayout(self)

        w_convertButton = QWidget()
        lay_convertButton = QHBoxLayout(w_convertButton)
        label_orig = QLabel("Original")
        label_orig.setAlignment(QtCore.Qt.AlignCenter)
        label_convert = QLabel("Converted")
        label_convert.setAlignment(QtCore.Qt.AlignCenter)
        button = QPushButton(" >> ")
        lay_convertButton.addWidget(label_orig)
        lay_convertButton.addWidget(button)
        lay_convertButton.addWidget(label_convert)
        w_convertButton.setStyleSheet("font-size:13px")
        sizePolicy = QSizePolicy()
        sizePolicy.setVerticalPolicy(QSizePolicy.Fixed)
        sizePolicy.setHorizontalPolicy(QSizePolicy.Expanding)
        w_convertButton.setSizePolicy(sizePolicy)

        splitter = QSplitter()
        splitter.setStretchFactor(1, 1)

        textEdit_left = QTextEdit()
        textEdit_right = QTextEdit()
        splitter.addWidget(textEdit_left)
        splitter.addWidget(textEdit_right)

        textEdit_left.setLineWrapMode(QTextEdit.NoWrap)
        textEdit_right.setLineWrapMode(QTextEdit.NoWrap)

        mainLayout.addWidget(w_convertButton)
        mainLayout.addWidget(splitter)

        self.textEdit_left = textEdit_left
        self.textEdit_right = textEdit_right

        button.clicked.connect(self.load_convertedText)
Example #4
0
class BrowserWindow(QMainWindow):

    MO_ROLE = Qt.UserRole+1

    def __init__(self, conn):
        super(BrowserWindow, self).__init__()
        self._conn = conn
        self._resolver = AsyncResolver()
        self._resolver.object_resolved.connect(self._data_resolved)
        self._resolver.start()
        self._init_models()
        self._init_gui()
        self._init_data()
        self._init_connections()

    def __del__(self):
        self._resolver.stop_work()
        self._resolver.terminate()

    def _init_models(self):
        self._hierarchy_model = QStandardItemModel()
        self._hierarchy_model.setColumnCount(2)
        self._hierarchy_model.setHorizontalHeaderLabels(['class', 'dn'])
        self._details_model = QStandardItemModel()
        self._details_model.setColumnCount(2)
        self._details_model.setHorizontalHeaderLabels(['Property', 'Value'])

    def _init_gui(self):
        self._widget = QSplitter(self, Qt.Horizontal)
        self._hierarchy_view = QTreeView(self._widget)
        self._details_view = QTableView(self._widget)

        self._widget.addWidget(self._hierarchy_view)
        self._widget.addWidget(self._details_view)
        self._widget.setStretchFactor(0, 2)
        self._widget.setStretchFactor(1, 1)
        self.setCentralWidget(self._widget)

        self._hierarchy_view.setModel(self._hierarchy_model)
        self._details_view.setModel(self._details_model)

        self._hierarchy_view.expanded.connect(self._mo_item_expand)

    def _init_data(self):
        item = self._row_for_mo(self._conn.resolve_dn(''))
        self._hierarchy_model.insertRow(0, item)

    def _init_connections(self):
        self.connect(self._resolver,
                        SIGNAL('object_resolved(QVariant)'),
                     self,
                        SLOT('_data_resolved(QVariant)'))
        self._hierarchy_view.activated.connect(self._item_activated)
        #self.connect(self._hierarchy_view.selectionModel(),
        #                SIGNAL('currentChanged(QModelIndex,QModelIndex)'),
        #             self,
        #                SLOT('_current_changed(QModelIndex, QModelIndex)'))
        self.connect(self._hierarchy_view.selectionModel(),
                        SIGNAL('activated(QModelIndex)'),
                     self,
                        SLOT('_item_activated(QModelIndex)'))


    def _row_for_mo(self, mo):
        row = [QStandardItem(mo.ucs_class), QStandardItem(mo.dn)]
        for item in row:
            item.setEditable(False)
        row[0].appendColumn([QStandardItem('Loading...')])
        row[0].setData(mo, self.MO_ROLE)
        return row

    def _add_mo_in_tree(self, mo, index=QtCore.QModelIndex()):
        item = None
        if index.isValid():
            item = self._hierarchy_model.itemFromIndex(index)
        else:
            item = self._get_item_for_dn(self._parent_dn(mo.dn))
        if item:
            item.appendColumn([self._row_for_mo(mo)[0]])
        self.auto_width()

    def _add_mos_in_tree(self, mos, index=QtCore.QModelIndex()):
        item = None
        if index.isValid():
            item = self._hierarchy_model.itemFromIndex(index)
        else:
            if not mos:
                return
            item = self._get_item_for_dn(self._parent_dn(mos[0].dn))
        while item.columnCount():
            item.removeColumn(0)
        items = map(self._row_for_mo, mos)
        if items:
            for x in xrange(len(items[0])):
                item.appendColumn([row[x] for row in items])
        self.auto_width()

    @staticmethod
    def _parent_dn(dn):
        parent_dn, _, rn = dn.rpartition('/')
        return parent_dn

    def _get_item_for_dn(self, dn):
        parent_dn = dn
        items = self._hierarchy_model.findItems(parent_dn, column=1)
        if items:
            return self._hierarchy_model.item(items[0].row())
        return None

    @QtCore.Slot('_data_resolved(QVariant)')
    def _data_resolved(self, datav):
        print 'Data resolved: ', datav
        index, data = datav
        if isinstance(data, UcsmObject):
            self._add_mo_in_tree(data, index=index)
        else:
            self._add_mos_in_tree(data, index=index)

    @QtCore.Slot('_current_changed(QModelIndex,QModelIndex)')
    def _current_changed(self, curr, prev):
        self._item_activated(curr)

    @QtCore.Slot('_item_activated(QModelIndex)')
    def _item_activated(self, index):
        print 'Activated: %s data %s' % (index, index.data(self.MO_ROLE))
        if index.sibling(0, 0).isValid():
            index = index.sibling(0, 0)
            data = index.data(self.MO_ROLE)
            self.set_detail_object(data)

    def _mo_item_expand(self, index):
        obj = index.data(self.MO_ROLE)
        print 'Expanded object: %s' % obj
        try:
            self._resolver.add_task(lambda: (index,
                                        self._conn.resolve_children(obj.dn)))
        except (KeyError, AttributeError):
            QtGui.QMessageBox.critical(0, 'Error', 'Object does not have dn')

    def auto_width(self):
        for view in [self._hierarchy_view, self._details_view]:
            for col in xrange(view.model().columnCount()):
                view.resizeColumnToContents(col)

    def set_detail_object(self, object):
        self._details_model.removeRows(0, self._details_model.rowCount())
        for k, v in object.attributes.iteritems():
            row = [QStandardItem(k), QStandardItem(v)]
            for item in row:
                item.setEditable(False)
            self._details_model.appendRow(row)
        self.auto_width()
Example #5
0
class FilterTab(QWidget):
    """This class is the GUI for creating filters for the FilterBox
       module. This GUI will be added as a tab to the ModuleFrame
       tab dialog.
    """

    applySignal = Signal(Clause)

    def __init__(self, parent, mframe, existing_filters):
        """Create a FilterTab with the given parent TabDialog, logical
           parent ModuleFrame mframe, and existing_filters list of Clause
           objects.
        """
        super(FilterTab, self).__init__(parent)

        self.mframe = mframe
        self.parent = parent
        self.attributes = self.mframe.agent.datatree.generateAttributeList()

        self.clause_list = list()
        self.clause_dict = dict()
        # Right now we only look at the first passed in filter.
        # TODO: At GUI to switch between existing filters
        if existing_filters is not None and len(existing_filters) > 0:
            for clause in existing_filters[0].conditions.clauses:
                self.clause_list.append(str(clause))
                self.clause_dict[str(clause)] = clause

        self.clause_model = QStringListModel(self.clause_list)

        layout = QVBoxLayout(self)
        self.sidesplitter = QSplitter(Qt.Horizontal)

        # You can only select one attribute at a time to build the 
        # filter clauses
        self.data_view = QTreeView(self)
        self.data_view.setModel(self.mframe.agent.datatree)
        self.data_view.setDragEnabled(True)
        self.data_view.setDropIndicatorShown(True)
        self.data_view.expandAll()
        self.sidesplitter.addWidget(self.data_view)
        self.sidesplitter.setStretchFactor(1,1)

        self.filter_widget = self.buildFilterWidget()
        self.sidesplitter.addWidget(self.filter_widget)
        self.sidesplitter.setStretchFactor(1,0)

        layout.addWidget(self.sidesplitter)

        # Apply buttons
        buttonWidget = QWidget()
        buttonLayout = QHBoxLayout(buttonWidget)
        self.applyButton = QPushButton("Apply")
        self.applyButton.clicked.connect(self.applyFilter)
        self.closeButton = QPushButton("Apply & Close")
        self.closeButton.clicked.connect(self.applyCloseFilter)
        buttonLayout.addWidget(self.applyButton)
        buttonLayout.addWidget(self.closeButton)
        buttonWidget.setLayout(buttonLayout)

        layout.addWidget(buttonWidget)
        self.setLayout(layout)

    def applyFilter(self):
        """Emits the applySignal with the Clause object currently
           represented by this FilterTab.
        """
        num_clauses = len(self.clause_list)
        if num_clauses == 0:
            self.applySignal.emit(None)
        else:
            self.applySignal.emit(Clause("and", *self.clause_dict.values()))

    def applyCloseFilter(self):
        """Calls applyFilter and then closes the containing TabDialog."""
        self.applyFilter()
        self.parent.close()

    def buildFilterWidget(self):
        """Creates the filter portion of the widget by laying out
           the subwidgets for relations, workspace and existing
           clauses.
        """
        filter_widget = QWidget()
        filter_layout = QVBoxLayout(filter_widget)

        filter_layout.addWidget(self.buildRelationsWidget())
        filter_layout.addItem(QSpacerItem(5,5))
        filter_layout.addWidget(self.buildWorkFrame())
        filter_layout.addItem(QSpacerItem(5,5))
        filter_layout.addWidget(self.buildFilterListView())

        filter_widget.setLayout(filter_layout)
        return filter_widget

    def buildFilterListView(self):
        """Creates the QListView that contains all of the basic Clause
           objects.
        """
        groupBox = QGroupBox("Clauses")
        layout = QVBoxLayout(groupBox)

        self.list_view = QListView(groupBox)
        self.list_view.setModel(self.clause_model)
        layout.addWidget(self.list_view)

        layout.addItem(QSpacerItem(5,5))
        self.delButton = QPushButton("Remove Selected Clause")
        self.delButton.clicked.connect(self.deleteClause)
        layout.addWidget(self.delButton)

        groupBox.setLayout(layout)
        return groupBox

    def buildWorkFrame(self):
        """Creates the grouped set of widgets that allow users to build
           basic Clause objects.
        """
        groupBox = QGroupBox("Clause Workspace")
        layout = QHBoxLayout(groupBox)

        attributeCompleter = QCompleter(self.attributes)
        attributeCompleter.setCompletionMode(QCompleter.InlineCompletion)
        self.dropAttribute = DropLineEdit(self, self.mframe.agent.datatree, "",
            attributeCompleter)
        self.dropRelation = DropTextLabel("__")
        self.dropValue = FilterValueLineEdit(groupBox,
            self.mframe.agent.datatree, self.dropAttribute)

        # Clear dropValue when dropAttribute changes
        self.dropAttribute.textChanged.connect(self.dropValue.clear)

        # Enter in dropValue works like addButton
        self.dropValue.returnPressed.connect(self.addClause)

        self.addButton = QPushButton("Add", groupBox)
        self.addButton.clicked.connect(self.addClause)
        layout.addWidget(self.dropAttribute)
        layout.addItem(QSpacerItem(5,5))
        layout.addWidget(self.dropRelation)
        layout.addItem(QSpacerItem(5,5))
        layout.addWidget(self.dropValue)
        layout.addItem(QSpacerItem(5,5))
        layout.addWidget(self.addButton)

        groupBox.setLayout(layout)
        return groupBox

    def buildRelationsWidget(self):
        """Creates the set of draggable relations. These relations are
           whatever is available in the relations dict of Table.
        """
        relations_widget = QWidget()
        layout = QHBoxLayout(relations_widget)

        for relation in Table.relations:
            layout.addWidget(DragTextLabel(relation))

        relations_widget.setLayout(layout)
        return relations_widget

    def addClause(self):
        """Adds a basic Clause to the current filter."""
        if self.dropRelation.text() in Table.relations \
            and len(self.dropValue.text()) > 0 \
            and len(self.dropAttribute.text()) > 0:

            clause = Clause(self.dropRelation.text(),
                TableAttribute(self.dropAttribute.text()),
                self.dropValue.text())

            # Guard double add
            if str(clause) not in self.clause_dict:
                self.clause_list.append(str(clause))
                self.clause_dict[str(clause)] = clause
                self.clause_model.setStringList(self.clause_list)

    def deleteClause(self):
        """Removes the selected basic Clause objects from the current
           filter.
        """
        clause = self.clause_model.data(
            self.list_view.selectedIndexes()[0], Qt.DisplayRole)
        if clause is not None and clause in self.clause_list:
            self.clause_list.remove(clause)
            del self.clause_dict[clause]
            self.clause_model.setStringList(self.clause_list)
Example #6
0
class RobocompDslGui(QMainWindow):
    def __init__(self, parent=None):
        super(RobocompDslGui, self).__init__(parent)
        self.setWindowTitle("Create new component")
        # self._idsl_paths = []
        self._communications = {
            "implements": [],
            "requires": [],
            "subscribesTo": [],
            "publishes": []
        }
        self._interfaces = {}
        self._cdsl_doc = CDSLDocument()
        self._command_process = QProcess()

        self._main_widget = QWidget()
        self._main_layout = QVBoxLayout()
        self.setCentralWidget(self._main_widget)

        self._name_layout = QHBoxLayout()
        self._name_line_edit = QLineEdit()
        self._name_line_edit.textEdited.connect(self.update_component_name)
        self._name_line_edit.setPlaceholderText("New component name")
        self._name_layout.addWidget(self._name_line_edit)
        self._name_layout.addStretch()

        # DIRECTORY SELECTION
        self._dir_line_edit = QLineEdit()
        # self._dir_line_edit.textEdited.connect(self.update_completer)
        self._dir_completer = QCompleter()
        self._dir_completer_model = QFileSystemModel()
        if os.path.isdir(ROBOCOMP_COMP_DIR):
            self._dir_line_edit.setText(ROBOCOMP_COMP_DIR)
            self._dir_completer_model.setRootPath(ROBOCOMP_COMP_DIR)
        self._dir_completer.setModel(self._dir_completer_model)
        self._dir_line_edit.setCompleter(self._dir_completer)

        self._dir_button = QPushButton("Select directory")
        self._dir_button.clicked.connect(self.set_output_directory)
        self._dir_layout = QHBoxLayout()
        self._dir_layout.addWidget(self._dir_line_edit)
        self._dir_layout.addWidget(self._dir_button)

        # LIST OF ROBOCOMP INTERFACES
        self._interface_list = QListWidget()
        self._interface_list.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self._interface_list.itemSelectionChanged.connect(
            self.set_comunication)

        # LIST OF CONNECTION TyPES
        self._type_combo_box = QComboBox()
        self._type_combo_box.addItems(
            ["publishes", "implements", "subscribesTo", "requires"])
        self._type_combo_box.currentIndexChanged.connect(
            self.reselect_existing)

        # BUTTON TO ADD A NEW CONNECTION
        # self._add_connection_button = QPushButton("Add")
        # self._add_connection_button.clicked.connect(self.add_new_comunication)
        self._add_connection_layout = QHBoxLayout()
        # self._add_connection_layout.addWidget(self._add_connection_button)
        self._language_combo_box = QComboBox()
        self._language_combo_box.addItems(["Python", "Cpp", "Cpp11"])
        self._language_combo_box.currentIndexChanged.connect(
            self.update_language)
        self._add_connection_layout.addWidget(self._language_combo_box)
        self._add_connection_layout.addStretch()
        self._gui_check_box = QCheckBox()
        self._gui_check_box.stateChanged.connect(self.update_gui_selection)
        self._gui_label = QLabel("Use Qt GUI")
        self._add_connection_layout.addWidget(self._gui_label)
        self._add_connection_layout.addWidget(self._gui_check_box)

        # WIDGET CONTAINING INTERFACES AND TYPES
        self._selection_layout = QVBoxLayout()
        self._selection_layout.addWidget(self._type_combo_box)
        self._selection_layout.addWidget(self._interface_list)
        self._selection_layout.addLayout(self._add_connection_layout)
        self._selection_widget = QWidget()
        self._selection_widget.setLayout(self._selection_layout)

        # TEXT EDITOR WITH THE RESULTING CDSL CODE
        self._editor = QTextEdit(self)
        self._editor.setHtml("")

        self._document = self._editor.document()
        self._component_directory = None

        # SPLITTER WITH THE SELECTION AND THE CODE
        self._body_splitter = QSplitter(Qt.Horizontal)
        self._body_splitter.addWidget(self._selection_widget)
        self._body_splitter.addWidget(self._editor)
        self._body_splitter.setStretchFactor(0, 2)
        self._body_splitter.setStretchFactor(1, 9)

        # CREATION BUTTONS
        self._create_button = QPushButton("Create .cdsl")
        self._create_button.clicked.connect(self.write_cdsl_file)
        self._creation_layout = QHBoxLayout()
        self._creation_layout.addStretch()
        self._creation_layout.addWidget(self._create_button)

        self._console = QConsole()
        self._command_process.readyReadStandardOutput.connect(
            self._console.standard_output)
        self._command_process.readyReadStandardError.connect(
            self._console.error_output)

        # ADDING WIDGETS TO MAIN LAYOUT
        self._main_widget.setLayout(self._main_layout)
        self._main_layout.addLayout(self._name_layout)
        self._main_layout.addLayout(self._dir_layout)
        self._main_layout.addWidget(self._body_splitter)
        self._main_layout.addLayout(self._creation_layout)
        self._main_layout.addWidget(self._console)
        self.setMinimumSize(800, 500)
        self._editor.setText(self._cdsl_doc.generate_doc())

    # self.editor->show();

    # def update_completer(self, path):
    # 	print "update_completer %s"%path
    # 	info = QFileInfo(path)
    # 	if info.exists() and info.isDir():
    # 			if not path.endswith(os.path.pathsep):
    # 				new_path = os.path.join(path, os.sep)
    # 				# self._dir_line_edit.setText(new_path)
    # 			all_dirs_output = [dI for dI in os.listdir(path) if os.path.isdir(os.path.join(path, dI))]
    # 			print all_dirs_output
    # 			self._dir_completer.complete()

    def load_idsl_files(self, fullpath=None):
        if fullpath is None:
            fullpath = ROBOCOMP_INTERFACES
        idsls_dir = os.path.join(ROBOCOMP_INTERFACES, "IDSLs")
        if os.path.isdir(idsls_dir):
            for full_filename in os.listdir(idsls_dir):
                file_name, file_extension = os.path.splitext(full_filename)
                if "idsl" in file_extension.lower():
                    full_idsl_path = os.path.join(idsls_dir, full_filename)
                    # self._idsl_paths.append(os.path.join(idsls_dir,full_filename))
                    self.parse_idsl_file(full_idsl_path)
        self._interface_list.addItems(self._interfaces.keys())

    def parse_idsl_file(self, fullpath):

        with open(fullpath, 'r') as fin:
            interface_name = None
            for line in fin:
                result = re.findall(r'^\s*interface\s+(\w+)\s*\{?\s*$',
                                    line,
                                    flags=re.MULTILINE)
                if len(result) > 0:
                    interface_name = result[0]
            print("%s for idsl %s" % (interface_name, fullpath))
            if interface_name is not None:
                self._interfaces[interface_name] = fullpath

    def add_new_comunication(self):
        interface_names = self._interface_list.selectedItems()
        com_type = str(self._type_combo_box.currentText())
        for iface_name_item in interface_names:
            iface_name = str(iface_name_item.text())
            self._communications[com_type].append(iface_name)
            idsl_full_path = self._interfaces[iface_name]
            idsl_full_filename = os.path.basename(idsl_full_path)
            self._cdsl_doc.add_comunication(com_type, iface_name)
            self._cdsl_doc.add_import(idsl_full_filename)
        self.update_editor()

    def set_comunication(self):
        interface_names = self._interface_list.selectedItems()
        com_type = str(self._type_combo_box.currentText())
        self._communications[com_type] = []
        self._cdsl_doc.clear_comunication(com_type)
        for iface_name_item in interface_names:
            iface_name = str(iface_name_item.text())
            self._communications[com_type].append(iface_name)
            self._cdsl_doc.add_comunication(com_type, iface_name)
        self.update_imports()
        self.update_editor()

    def update_imports(self):
        self._cdsl_doc.clear_imports()
        for com_type in self._communications:
            for iface_name in self._communications[com_type]:
                idsl_full_path = self._interfaces[iface_name]
                idsl_full_filename = os.path.basename(idsl_full_path)
                self._cdsl_doc.add_import(idsl_full_filename)

    def update_language(self):
        language = self._language_combo_box.currentText()
        self._cdsl_doc.set_language(str(language))
        self.update_editor()

    def update_gui_selection(self):
        checked = self._gui_check_box.isChecked()
        if checked:
            self._cdsl_doc.set_qui(True)
        else:
            self._cdsl_doc.set_qui(False)
        self.update_editor()

    def update_component_name(self, name):
        self._cdsl_doc.set_name(name)
        self.update_editor()

    def update_editor(self):
        self._editor.setText(self._cdsl_doc.generate_doc())

    def set_output_directory(self):
        dir_set = False
        while not dir_set:
            dir = QFileDialog.getExistingDirectory(
                self, "Select Directory", ROBOCOMP_COMP_DIR,
                QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)
            if self.check_dir_is_empty(str(dir)):
                self._dir_line_edit.setText(dir)
                dir_set = True

    def write_cdsl_file(self):
        component_dir = str(self._dir_line_edit.text())
        text = self._cdsl_doc.generate_doc()
        if not self._name_line_edit.text():
            component_name, ok = QInputDialog.getText(self,
                                                      'No component name set',
                                                      'Enter component name:')
            if ok:
                self.update_component_name(component_name)
                self._name_line_edit.setText(component_name)
            else:
                return False

        if not os.path.exists(component_dir):
            if QMessageBox.Yes == QMessageBox.question(
                    self, "Directory doesn't exist.",
                    "Do you want create the directory %s?" % component_dir,
                    QMessageBox.Yes | QMessageBox.No):
                os.makedirs(component_dir)
            else:
                QMessageBox.question(
                    self, "Directory not exist",
                    "Can't create a component witout a valid directory")
                return False

        file_path = os.path.join(component_dir,
                                 str(self._name_line_edit.text()) + ".cdsl")
        if os.path.exists(file_path):
            if QMessageBox.No == QMessageBox.question(
                    self, "File already exists", "Do you want to overwrite?",
                    QMessageBox.Yes | QMessageBox.No):
                return False

        with open(file_path, 'w') as the_file:
            the_file.write(text)
        self.execute_robocomp_cdsl()
        return True

    def execute_robocomp_cdsl(self):
        cdsl_file_path = os.path.join(
            str(self._dir_line_edit.text()),
            str(self._name_line_edit.text()) + ".cdsl")
        command = "python -u %s/robocompdsl.py %s %s" % (
            ROBOCOMPDSL_DIR, cdsl_file_path,
            os.path.join(str(self._dir_line_edit.text())))
        self._console.append_custom_text("%s\n" % command)
        self._command_process.start(command,
                                    QProcess.Unbuffered | QProcess.ReadWrite)

    def reselect_existing(self):
        com_type = self._type_combo_box.currentText()
        selected = self._communications[com_type]
        self._interface_list.clearSelection()
        for iface in selected:
            items = self._interface_list.findItems(iface,
                                                   Qt.MatchFlag.MatchExactly)
            if len(items) > 0:
                item = items[0]
                item.setSelected(True)

    def check_dir_is_empty(self, dir_path):
        if len(os.listdir(dir_path)) > 0:
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Directory not empty")
            msgBox.setText(
                "The selected directory is not empty.\n"
                "For a new Component you usually want a new directory.\n"
                "Do you want to use this directory anyway?")
            msgBox.setStandardButtons(QMessageBox.Yes)
            msgBox.addButton(QMessageBox.No)
            msgBox.setDefaultButton(QMessageBox.No)
            if msgBox.exec_() == QMessageBox.Yes:
                return True
            else:
                return False
        else:
            return True
Example #7
0
class PostViewWidget(HorsePanel):
    def __init__(self, parent, order_overview_widget, find_order_slot):
        global configuration

        super(PostViewWidget, self).__init__(parent)

        self.set_panel_title(_("Post overview"))
        self.bold_font = QFont(self.font())
        self.bold_font.setBold(True)
        self.nb_cols = 8  # Number of columns in the operation definition table

        self.order_overview_widget = order_overview_widget

        self.button = QPushButton(_("Refresh"), self)
        self.button.clicked.connect(self.refresh_action)
        self.sort_by_deadline_button = QRadioButton(_("By deadline"), self)
        self.sort_by_deadline_button.toggled.connect(self.sort_by_deadline)
        self.sort_by_size_button = QRadioButton(_("By hours left to do"), self)
        self.sort_by_size_button.toggled.connect(self.sort_by_size)

        # hlayout = QHBoxLayout()
        # hlayout.setObjectName("halyout")
        # hlayout.setContentsMargins(0,0,0,0)
        # hlayout.addWidget(self.sort_by_deadline_button)
        # hlayout.addWidget(self.sort_by_size_button)
        # hlayout.addWidget(self.button)
        # hlayout.addStretch()

        self.navbar = NavBar(self, [(self.sort_by_deadline_button, None),
                                    (self.sort_by_size_button, None),
                                    (self.button, None),
                                    (_("Find"), find_order_slot)])
        self.navbar.buttons[3].setObjectName("specialMenuButton")

        self.vlayout = QVBoxLayout(self)
        self.vlayout.setObjectName("Vlayout")
        self.vlayout.addWidget(
            TitleWidget(_("Posts Overview"), self, self.navbar))

        self._table_model = QStandardItemModel(1, self.nb_cols, self)
        self.table_view = QTableView(None)
        self.table_view.setModel(self._table_model)
        self.table_view.selectionModel().currentChanged.connect(
            self.operation_selected)

        self.table_view.verticalHeader().hide()
        self.table_view.horizontalHeader().hide()
        self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows)

        # This forces Qt to expand layout once I fill data in
        # FIXME dirty but I really don't get why setting
        # the mini width to something smaller (that happens at
        # startup, on first refresh) doesn't work
        self.table_view.setMinimumWidth(1)
        self.table_view.setMaximumWidth(1)

        self.post_view_scene = PostViewScene(self, order_overview_widget)
        self.post_view_scene_view = QGraphicsView(self)
        self.post_view_scene_view.setScene(self.post_view_scene)
        self.post_view_scene_view.setSizePolicy(QSizePolicy.Expanding,
                                                QSizePolicy.Expanding)

        self.splitter = QSplitter(Qt.Horizontal)
        self.splitter.addWidget(
            SubFrame(_("Posts"), self.table_view, self.splitter))
        self.splitter.addWidget(
            SubFrame(_("Workload"), self.post_view_scene_view, self.splitter))
        # self.splitter.setStretchFactor(0,1)
        self.splitter.setStretchFactor(1, 1)
        self.vlayout.addWidget(self.splitter)

        # hlayout = QHBoxLayout()
        # hlayout.addWidget(SubFrame(_("Posts"),self.table_view,self))
        # hlayout.addWidget(SubFrame(_("Workload"),self.post_view_scene_view,self))
        # hlayout.setStretch(1,1)
        # self.vlayout.addLayout(hlayout)

        self.vlayout.setStretch(0, 0)
        self.vlayout.setStretch(1, 1)

        self.setLayout(self.vlayout)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.slidePostsScene)

        self.current_view_y = 0

    def _data_load(self):
        global dao

        all_operations = dao.operation_dao.load_all_operations_ready_for_production(
        )
        operation_definitions = dao.operation_definition_dao.all_direct_frozen(
        )

        return operation_definitions, all_operations

    def _reset_operation_definitions(self, operations):
        self._table_model.setColumnCount(1)
        self._table_model.setRowCount(len(operations))

        # BUG This should be refreshed on reload() too

        row = col = 0
        first_active = None

        for opdef in operations:

            if opdef.operation_definition_id in self.post_view_scene.drawn_operations_data:
                # currently total planned time
                t = self.post_view_scene.drawn_operations_data[
                    opdef.operation_definition_id]
                ndx = self._table_model.index(row, col)
                if not first_active:
                    first_active = ndx
                self._table_model.setData(
                    ndx, u"{} {}".format(opdef.description, t), Qt.DisplayRole)
                # self._table_model.setData(ndx,self.bold_font,Qt.FontRole)

                self._table_model.setData(self._table_model.index(row, col),
                                          opdef.operation_definition_id,
                                          Qt.UserRole)
                row += 1

            else:
                pass
                # self._table_model.setData(self._table_model.index(row,col),opdef.description,Qt.DisplayRole)

            # = col + 1
            # if col == self.nb_cols:
            #     col = 0
            #     row += 1

        self._table_model.setRowCount(row)

        # self.table_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        # self.vlayout.setStretch(0,0)
        # self.vlayout.setStretch(1,10)
        # self.vlayout.setStretch(2,10000)

        # height = 0
        # for c in range(self.table_view.model().rowCount()):
        #     height += self.table_view.rowHeight(c) + 1 # +1 for cell border
        # self.table_view.setMinimumHeight(height)
        # self.table_view.setMaximumHeight(height)
        for i in range(self.nb_cols):
            self.table_view.resizeColumnToContents(i)
        self.table_view.setMaximumWidth(self.table_view.columnWidth(0))
        self.table_view.setMinimumWidth(self.table_view.columnWidth(0))
        self.table_view.setSizePolicy(QSizePolicy.Maximum,
                                      QSizePolicy.Preferred)

        self.table_view.update()
        self.splitter.update()

        return first_active

    def slide_to_operation(self, opdef_id):
        if opdef_id in self.post_view_scene.posts_offsets:
            self.slide_target_opdef_id = opdef_id
            # mainlog.debug("Target y = {}".format(self.post_view_scene.posts_offsets[self.slide_target_opdef]))
            self.timer.start(20)

    @Slot()
    def slidePostsScene(self):
        if self.slide_target_opdef_id is None:
            return

        # self.post_view_scene_view
        self.post_view_scene.set_cursor_on(
            self.slide_target_opdef_id
        )  # This done here also aviod some screen trashing

        v = self.post_view_scene_view.verticalScrollBar().value()
        # mainlog.debug( "slidePostsScene : {}".format(v))

        r = self.post_view_scene.posts_offsets[self.slide_target_opdef_id]
        target_y = r.y() + r.height() / 2
        delta = (target_y - self.current_view_y) * 0.4
        self.current_view_y = self.current_view_y + delta
        self.post_view_scene_view.centerOn(0, self.current_view_y)
        # mainlog.debug( "slidePostsScene : {} / {}".format(target_y, self.current_view_y))

        if self.post_view_scene_view.verticalScrollBar().value() == v:
            # Close enough => stop moving
            # FIXME not correct because we must stop when the view stops moving, not when the goal we set for centerOn is reached
            self.timer.stop()

    @Slot(QModelIndex, QModelIndex)
    def operation_selected(self, ndx_cur, ndx_old):
        if ndx_cur.isValid():
            opdef = self._table_model.data(ndx_cur, Qt.UserRole)
            if opdef:
                self.slide_to_operation(
                    self._table_model.data(ndx_cur, Qt.UserRole))

    @Slot()
    def refresh_action(self):
        # FIXME reload operations as well

        operation_definitions, all_operations = self._data_load()

        # mainlog.debug("reload")
        if self.sort_by_deadline_button.isChecked():
            self.post_view_scene.reload(self, operation_definitions,
                                        all_operations, 1)
        elif self.sort_by_size_button.isChecked():
            self.post_view_scene.reload(self, operation_definitions,
                                        all_operations, 2)
        else:
            self.post_view_scene.reload(self, operation_definitions,
                                        all_operations, 0)

        # mainlog.debug("reset")
        first_active = self._reset_operation_definitions(operation_definitions)
        # self.table_view.selectionModel().currentChanged.connect(self.operation_selected)
        if first_active:
            self.table_view.setCurrentIndex(first_active)

        # mainlog.debug("done reset")

    @Slot(bool)
    def sort_by_deadline(self, checked):
        if checked:
            self.refresh_action()

    @Slot(bool)
    def sort_by_size(self, checked):
        if checked:
            self.refresh_action()

    order_part_double_clicked = Signal(int)

    # Callback that will be called by HooverBar
    def set_on_order_part(self, order_part_id):
        self.order_part_double_clicked.emit(order_part_id)
class RegistrationShop(MainWindow, WindowDialog):
    """
	Main class that starts up the application.
	Creates UI and starts project/plugin managers.
	"""
    def __init__(self, args):
        """
		Sets app specific properties.
		Initializes the UI.
		"""
        super(RegistrationShop, self).__init__(args)

        self.setApplicationPath()
        # Instantiate the project controller
        ProjectController.Instance()

        # Initialize the user interface
        self.initUI()

        lastProject = RegistrationShop.settings.value("project/lastProject",
                                                      None)
        if lastProject:
            self.openProject(lastProject)

    def initialize(self):
        # Initialize the render window interactors only after calling show()
        # otherwise OpenGL errors will occur on OS X
        self.fixedDataWidget.rwi.Initialize()
        self.movingDataWidget.rwi.Initialize()
        self.multiDataWidget.rwi.Initialize()

    # UI setup methods

    def initUI(self):
        """
		Initializes the UI. Makes sure previous state of
		application is restored.
		"""
        # Create actions and elements
        self.createElements()
        self.connectElements()
        self.createActions()
        self.createMenus()
        self.createToolbar()
        self.restoreState()

        # Set some window/application properties
        self.setUnifiedTitleAndToolBarOnMac(True)
        self.setWindowTitle(APPNAME)
        self.setWindowState(Qt.WindowActive)

    def createElements(self):
        """
		Creates the widgets and docks of which the
		main window is composed.
		"""
        self.mainWindow = QMainWindow()
        projectController = ProjectController.Instance()
        self.transformTool = None

        # Render widgets
        self.fixedDataWidget = RenderWidget()
        self.movingDataWidget = RenderWidget()
        self.multiDataWidget = MultiRenderWidget()

        self.fixedRenderController = RenderController(self.fixedDataWidget,
                                                      "fixed")
        self.movingRenderController = RenderController(self.movingDataWidget,
                                                       "moving")
        self.multiRenderController = MultiRenderController(
            self.multiDataWidget)

        # Give references of the render controllers to the project controller
        projectController.fixedRenderController = self.fixedRenderController
        projectController.movingRenderController = self.movingRenderController
        projectController.multiRenderController = self.multiRenderController

        # Render properties widgets
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(1)

        self.fixedPropWidget = RenderPropWidget(self.fixedRenderController,
                                                parent=self)
        self.fixedPropWidget.setSizePolicy(sizePolicy)
        self.fixedPropWidget.setFileChangedSignal(
            projectController.fixedFileChanged)
        self.fixedPropWidget.setLoadDataSlot(self.loadFixedDataSetFile)

        self.movingPropWidget = RenderPropWidget(self.movingRenderController,
                                                 parent=self)
        self.movingPropWidget.setSizePolicy(sizePolicy)
        self.movingPropWidget.setFileChangedSignal(
            projectController.movingFileChanged)
        self.movingPropWidget.setLoadDataSlot(self.loadMovingDataSetFile)

        self.multiPropWidget = MultiRenderPropWidget(
            self.multiRenderController, parent=self)
        self.multiPropWidget.setSizePolicy(sizePolicy)

        self.verticalSplitter = QSplitter()
        self.verticalSplitter.setOrientation(Qt.Vertical)

        # Create the layouts

        fixedDataTitleWidget = TitleWidget("Fixed volume")
        multiDataTitleWidget = TitleWidget("Fixed + Moving")
        movingDataTitleWidget = TitleWidget("Moving volume")

        fixedLayout = QGridLayout()
        fixedLayout.setSpacing(0)
        fixedLayout.setContentsMargins(0, 0, 0, 0)
        fixedLayout.addWidget(fixedDataTitleWidget)
        fixedLayout.addWidget(self.fixedDataWidget)
        fixedWidget = QWidget()
        fixedWidget.setLayout(fixedLayout)

        multiLayout = QGridLayout()
        multiLayout.setSpacing(0)
        multiLayout.setContentsMargins(0, 0, 0, 0)
        multiLayout.addWidget(multiDataTitleWidget)
        multiLayout.addWidget(self.multiDataWidget)
        multiWidget = QWidget()
        multiWidget.setLayout(multiLayout)

        movingLayout = QGridLayout()
        movingLayout.setSpacing(0)
        movingLayout.setContentsMargins(0, 0, 0, 0)
        movingLayout.addWidget(movingDataTitleWidget)
        movingLayout.addWidget(self.movingDataWidget)
        movingWidget = QWidget()
        movingWidget.setLayout(movingLayout)

        horizontalSplitter = QSplitter()
        horizontalSplitter.setOrientation(Qt.Horizontal)
        horizontalSplitter.addWidget(fixedWidget)
        horizontalSplitter.addWidget(multiWidget)
        horizontalSplitter.addWidget(movingWidget)

        propsLayout = QHBoxLayout()
        propsLayout.setSpacing(1)
        propsLayout.setContentsMargins(0, 0, 0, 0)
        propsLayout.addWidget(self.fixedPropWidget)
        propsLayout.addWidget(self.multiPropWidget)
        propsLayout.addWidget(self.movingPropWidget)

        propsWidget = QWidget()
        propsWidget.setMinimumHeight(245)
        propsWidget.setMaximumHeight(350)
        propsWidget.setLayout(propsLayout)

        self.verticalSplitter.addWidget(horizontalSplitter)
        self.verticalSplitter.addWidget(propsWidget)
        self.verticalSplitter.setStretchFactor(0, 2)
        self.verticalSplitter.setStretchFactor(1, 1)
        self.setCentralWidget(self.verticalSplitter)

    def connectElements(self):
        """
		All the elements have to be connected because they are dependent
		on each other.
		There is the project controller, two render controllers and a multi render
		controller.
		Also there are two render widgets and a multi render widget. Together with some
		parameter widgets that show settings and with which the user can interact.
		"""
        projectController = ProjectController.Instance()
        projectController.fixedFileChanged.connect(
            self.fixedRenderController.setFile)
        projectController.fixedFileChanged.connect(
            self.multiRenderController.setFixedFile)
        projectController.movingFileChanged.connect(
            self.movingRenderController.setFile)
        projectController.movingFileChanged.connect(
            self.multiRenderController.setMovingFile)
        projectController.fixedSettingsChanged.connect(
            self.fixedRenderController.setRenderSettings)
        projectController.movingSettingsChanged.connect(
            self.movingRenderController.setRenderSettings)
        projectController.multiSettingsChanged.connect(
            self.multiRenderController.setRenderSettings)

        self.fixedRenderController.visualizationChanged.connect(
            self.multiRenderController.setFixedVisualization)
        self.fixedRenderController.visualizationUpdated.connect(
            self.multiRenderController.setFixedVisualization)
        self.movingRenderController.visualizationChanged.connect(
            self.multiRenderController.setMovingVisualization)
        self.movingRenderController.visualizationUpdated.connect(
            self.multiRenderController.setMovingVisualization)

        self.multiDataWidget.transformations.transformationChanged.connect(
            self.movingDataWidget.transformationsUpdated)

    def createActions(self):
        """
		Create actions that can be attached to buttons and menus.
		"""
        userTransformIconName = AppResources.imageNamed(
            'UserTransformButton.png')
        landmarkTransformIconName = AppResources.imageNamed(
            'LandmarkTransformButton.png')
        deformableTransformIconName = AppResources.imageNamed(
            'DeformableTransformButton.png')
        compareIconName = AppResources.imageNamed('CompareButton.png')
        helpIconName = AppResources.imageNamed('HelpButton.png')

        self.actionFreeTransformTool = QAction('Manual transform',
                                               self,
                                               shortcut='Ctrl+1')
        self.actionFreeTransformTool.setIcon(QIcon(userTransformIconName))
        self.actionFreeTransformTool.triggered.connect(self.addManualTransform)

        self.actionLandmarkTransformTool = QAction('Landmark transform',
                                                   self,
                                                   shortcut='Ctrl+2')
        self.actionLandmarkTransformTool.setIcon(
            QIcon(landmarkTransformIconName))
        self.actionLandmarkTransformTool.triggered.connect(
            self.addLandmarkTransform)

        self.actionDeformableTransformTool = QAction('Automatic transform',
                                                     self,
                                                     shortcut='Ctrl+3')
        self.actionDeformableTransformTool.setIcon(
            QIcon(deformableTransformIconName))
        self.actionDeformableTransformTool.triggered.connect(
            self.addDeformableTransform)

        self.actionLoadFixedData = QAction('Load fixed data',
                                           self,
                                           shortcut='Ctrl+Shift+F')
        self.actionLoadFixedData.triggered.connect(self.loadFixedDataSetFile)

        self.actionLoadMovingData = QAction('Load moving data',
                                            self,
                                            shortcut='Ctrl+Shift+M')
        self.actionLoadMovingData.triggered.connect(self.loadMovingDataSetFile)

        self.actionSaveProject = QAction('Save project',
                                         self,
                                         shortcut='Ctrl+S')
        self.actionSaveProject.triggered.connect(self.saveProject)

        self.actionSaveProjectAs = QAction('Save project as...',
                                           self,
                                           shortcut='Ctrl+Shift+S')
        self.actionSaveProjectAs.triggered.connect(self.saveProjectAs)

        self.actionExportDataAs = QAction('Export data...',
                                          self,
                                          shortcut='Ctrl+E')
        self.actionExportDataAs.triggered.connect(self.exportDataAs)

        self.actionOpenProject = QAction('Open project...',
                                         self,
                                         shortcut='Ctrl+O')
        self.actionOpenProject.triggered.connect(self.openProject)

        self.actionNewProject = QAction('New project', self, shortcut='Ctrl+N')
        self.actionNewProject.triggered.connect(self.newProject)

        self.actionCompare = QAction('Compare', self, shortcut='Ctrl+U')
        self.actionCompare.setIcon(QIcon(compareIconName))
        self.actionCompare.triggered.connect(self.startComparison)

        self.actionHelp = QAction('Help', self, shortcut='Ctrl+H')
        self.actionHelp.setIcon(QIcon(helpIconName))
        self.actionHelp.triggered.connect(self.showHelp)

    def createMenus(self):
        """
		Creates menus from actions.
		"""
        self.menuBar = self.menuBar()
        self.menuItemFile = self.menuBar.addMenu('&File')
        self.menuItemFile.addAction(self.actionNewProject)
        self.menuItemFile.addAction(self.actionOpenProject)
        # TODO: Open recent >
        self.menuItemFile.addAction(self.actionSaveProject)
        self.menuItemFile.addAction(self.actionSaveProjectAs)
        self.menuItemFile.addAction(self.actionExportDataAs)

        self.menuItemProject = self.menuBar.addMenu('&Project')
        self.menuItemProject.addAction(self.actionLoadFixedData)
        self.menuItemProject.addAction(self.actionLoadMovingData)
        self.menuItemProject.addSeparator()

    def createToolbar(self):
        """
		Creates the main toolbar and sets the toolbar buttons.
		"""
        # Add toolbar
        self.toolbar = self.addToolBar('Main tools')
        self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setFloatable(False)
        self.toolbar.setMovable(False)

        # Create custom toolbar widget that can align items left, center and right
        self.toolbarWidget = ToolbarWidget()
        self.toolbarWidget.addActionLeft(self.actionFreeTransformTool)
        self.toolbarWidget.addActionLeft(self.actionLandmarkTransformTool)
        self.toolbarWidget.addActionLeft(self.actionDeformableTransformTool)

        statusWidget = StatusWidget.Instance()
        statusWidget.setText(
            "Welcome to RegistrationShop!\nStart your registration by loading two datasets. "
            +
            "After that you can use the transform tools to align your volume data."
        )
        self.toolbarWidget.addCenterItem(statusWidget)

        # Add help button
        self.toolbarWidget.addActionRight(self.actionCompare)
        self.toolbarWidget.addActionRight(self.actionHelp)
        self.toolbar.addWidget(self.toolbarWidget)

    # Private Functions

    def setApplicationPath(self):
        """
		Finds the path to the application. This is done so that it
		can figure out where certain resources are located.
		QCoreApplication::applicationDirPath() on OS X does not return the
		desired path to the actual application but to the python executable
		in /Library/FrameWorks. This is inconvenient because images can't be
		located that way.
		So instead os.path is used to find the location of this __file__.
		"""
        AppVars.setPath(os.path.dirname(os.path.abspath(__file__)))

    # Action callbacks
    @Slot()
    def addManualTransform(self):
        """
		What happens when manual transform is added:
		* Entry is added to the tab history
			* Translation fields
			* Rotation fields
			* Scale field(s)
		* Transform box is added to the render widget
		* Button with apply (will apply the transform to the data)

		Applying the transform to the data means:
		* Create new dataset from transformed data
		* Save this data to the project folder
		* Read in the new data and update this in the multi render widget
		* this would mean a new data model for the multi render widget
		"""
        if not self.movingDataWidget.imageData:
            statusWidget = StatusWidget.Instance()
            statusWidget.setText(
                "Please load a moving dataset before starting a manual transform."
            )
            return

        if self.transformTool is not None:
            self.transformTool.cleanUp()

        self.transformTool = UserTransformationTool()
        self.transformTool.setRenderWidgets(moving=self.movingDataWidget,
                                            multi=self.multiDataWidget)
        self.multiPropWidget.setTransformTool(self.transformTool)
        self.transformTool.toolFinished.connect(self.transformToolFinished)

    @Slot()
    def addLandmarkTransform(self):
        if not self.fixedDataWidget.imageData or not self.movingDataWidget.imageData:
            statusWidget = StatusWidget.Instance()
            statusWidget.setText(
                "Please load a fixed and a moving dataset before starting a landmark transform."
            )
            return

        # Clean up the last transform tool
        if self.transformTool is not None:
            self.transformTool.cleanUp()

        self.transformTool = LandmarkTransformationTool()
        self.transformTool.setRenderWidgets(fixed=self.fixedDataWidget,
                                            moving=self.movingDataWidget,
                                            multi=self.multiDataWidget)

        # Create a tab page under the fixed render widget
        fixedLandmarkWidget = LandmarkWidget()
        self.fixedPropWidget.addTabWidget(fixedLandmarkWidget, "Landmark")

        # Create a tab page under the moving render widget
        movingLandmarkWidget = LandmarkWidget()
        self.movingPropWidget.addTabWidget(movingLandmarkWidget, "Landmark")

        # Make sure the landmark transform tool knows of these tab widgets
        self.transformTool.setLandmarkWidgets(fixedLandmarkWidget,
                                              movingLandmarkWidget)

        # Start the transformation
        self.multiPropWidget.setTransformTool(self.transformTool)
        self.transformTool.toolFinished.connect(self.transformToolFinished)

    @Slot()
    def addDeformableTransform(self):
        if not self.fixedDataWidget.imageData or not self.movingDataWidget.imageData:
            statusWidget = StatusWidget.Instance()
            statusWidget.setText(
                "Please load a fixed and a moving dataset before starting a deformable transform."
            )
            return

        self.multiPropWidget.tabWidget.setCurrentWidget(
            self.multiPropWidget.transformParamWidget)

        if self.transformTool is not None:
            self.transformTool.cleanUp()

        statusWidget = StatusWidget.Instance()
        statusWidget.setText(
            "Choose a template for a deformable transform. After choosing "
            "a template you will be able to review and adjust the parameters.")

        dialog = ElastixMainDialog(self)
        dialog.setModal(True)
        result = dialog.exec_()
        if not result:
            return
        if not dialog.transformation:
            # load custom file
            filename, other = QFileDialog.getOpenFileName(
                self, "Open custom parameter file", "", "(*.c *.txt)")
            if len(filename) == 0:
                return
            transformation = ParameterList()
            if not transformation.loadFromFile(filename):
                transformation = None
                statusWidget = StatusWidget.Instance()
                statusWidget.setText(
                    "Warning: could not load transformation file")
        else:
            transformation = dialog.transformation

        self.transformTool = DeformableTransformationTool()
        self.transformTool.setTransformation(transformation)
        self.transformTool.startedElastix.connect(self.showProgressBar)
        self.transformTool.endedElastix.connect(self.hideProgressBar)
        self.transformTool.setRenderWidgets(fixed=self.fixedDataWidget,
                                            moving=self.movingDataWidget,
                                            multi=self.multiDataWidget)
        self.multiPropWidget.setTransformTool(self.transformTool)
        self.transformTool.toolFinished.connect(self.transformToolFinished)

    @Slot()
    def transformToolFinished(self):
        self.multiPropWidget.transformToolFinished()
        self.fixedPropWidget.removeTabWidget()
        self.movingPropWidget.removeTabWidget()

    @Slot()
    def loadFixedDataSetFile(self):
        """
		Open file dialog to search for data files. If valid data is given, it will
		pass the data file location on to the slicer and the project controller.
		"""
        dataReader = DataReader()
        extensions = dataReader.GetSupportedExtensionsAsString()
        fileName, other = QFileDialog.getOpenFileName(
            self,
            "Open fixed data set",
            "",
            "Images (" + extensions + ")",
            options=QFileDialog.Directory)
        if len(fileName) > 0:
            # If there was another dataset first, ask if the user if the
            # visualizations should be reset
            projectController = ProjectController.Instance()
            if projectController.currentProject.fixedData:
                dialog = ResetVisualizationDialog(self)
                dialog.setWindowModality(Qt.WindowModal)
                dialog.exec_()
                if dialog.result is not None:
                    projectController.loadFixedDataSet(fileName)
                    if dialog.result:
                        self.fixedRenderController.resetVisualizations()
            else:
                projectController.loadFixedDataSet(fileName)

    @Slot()
    def loadMovingDataSetFile(self):
        """
		Open file dialog to search for data files. If valid data is given, it will
		pass the data file location on to the slicer and the project controller.
		"""
        dataReader = DataReader()
        extensions = dataReader.GetSupportedExtensionsAsString()
        fileName, other = QFileDialog.getOpenFileName(
            self,
            "Open moving data set",
            "",
            "Images (" + extensions + ")",
            options=QFileDialog.Directory)
        if len(fileName) > 0:
            # If there was another dataset first, ask if the user if the
            # visualizations should be reset
            projectController = ProjectController.Instance()
            if projectController.currentProject.movingData:
                dialog = ResetVisualizationDialog(self)
                dialog.setWindowModality(Qt.WindowModal)
                dialog.exec_()
                if dialog.result is not None:
                    projectController.loadMovingDataSet(fileName)
                    if dialog.result:
                        self.movingRenderController.resetVisualizations()
            else:
                # Inserting an identity transform
                self.multiDataWidget.transformations.append(
                    Transformation(vtkTransform(), "No transform", fileName))
                projectController.loadMovingDataSet(fileName)

    @Slot()
    def saveProject(self):
        """
		Save the project to the specified name in the current project. If no name
		is specified, then 'save project as' is called.
		"""
        projCont = ProjectController.Instance()

        if projCont.currentProject.folder is not None:
            # Save that project
            saved = projCont.saveProject()
            statusWidget = StatusWidget.Instance()
            if saved:
                # Save it in the settings that this was the last opened project
                RegistrationShop.settings.setValue(
                    "project/lastProject", projCont.currentProject.folder)
                statusWidget.setText(
                    "The project was succesfully saved to disk.")
            else:
                statusWidget.setText(
                    "Something went wrong while saving the project to disk. "
                    "Please try to save the project again.")
        else:
            self.saveProjectAs()

    @Slot()
    def saveProjectAs(self):
        """
		Opens a file dialog so that the user can select a folder
		in which to save the project.
		"""
        # Open file dialog
        fileName = QFileDialog.getExistingDirectory(self,
                                                    "Select project folder",
                                                    "",
                                                    QFileDialog.ShowDirsOnly)
        if len(fileName) > 0:
            # TODO: check for existing project!

            # Set filename of project
            ProjectController.Instance().currentProject.folder = fileName
            # Call save project
            self.saveProject()

    @Slot()
    def openProject(self, folderName=None):
        """
		If no project name is supplied, it will open a file dialog so
		that the user can select a project file
		or project folder.

		:param folderName: Name of a folder with a project
		:type folderName: basestring
		"""
        fileName = ""
        if folderName:
            fileName = folderName
        else:
            fileName = QFileDialog.getExistingDirectory(
                self, "Open project", "", QFileDialog.ShowDirsOnly)

        if len(fileName) > 0:
            fullName = fileName + ProjectController.Instance().ProjectFile
            if os.path.isfile(fullName):
                self.multiDataWidget.transformations.clear()
                loaded = ProjectController.Instance().loadProject(fileName)
                if loaded:
                    RegistrationShop.settings.setValue("project/lastProject",
                                                       fileName)
                else:
                    print "Couldn't load project:", folderName
            else:
                print "Warning: Project file does not exist"
                RegistrationShop.settings.remove("project/lastProject")

    @Slot()
    def newProject(self):
        """
		Create new project by calling the project controller
		"""
        self.multiDataWidget.transformations.clear()
        ProjectController.Instance().newProject()
        # Reset the last loaded project in the settings
        RegistrationShop.settings.setValue("project/lastProject", "")

    @Slot()
    def exportDataAs(self):
        """
		Opens a file dialog so that the user can provide a filename
		for saving the transformed dataset to.
		"""
        fileType = FileTypeDialog.getFileType(self,
                                              "Choose file type for export")
        if len(fileType) == 0:
            return

        extension = "(*." + fileType + ")"
        fileName, other = QFileDialog.getSaveFileName(
            self, "Save registration result to...", "", extension)
        if len(fileName) == 0:
            return

        self.showProgressBar("Exporting data...")

        transform = self.multiDataWidget.transformations.completeTransform()
        dataReader = DataReader()
        imageData = dataReader.GetImageData(
            ProjectController.Instance().currentProject.movingData)
        transformer = DataTransformer()
        outputData = transformer.TransformImageData(imageData, transform)
        writer = DataWriter()
        writer.WriteToFile(outputData, fileName, fileType)

        self.hideProgressBar()

    @Slot()
    def startComparison(self):
        projectController = ProjectController.Instance()
        project = projectController.currentProject
        if not project or not project.fixedData or not project.movingData:
            statusWidget = StatusWidget.Instance()
            statusWidget.setText(
                "Could not start comparison. Please make a project first"
                " and make sure to load two datasets.")
            return

        if hasattr(self, "compareWidget"):
            del self.compareWidget

        transform = self.multiDataWidget.transformations.completeTransform()

        self.controller = ComparisonController()
        self.controller.setInputData(project.fixedData, project.movingData,
                                     transform)
        self.compareWidget = CompareWidget(self.controller.widgets)
        self.compareWidget.show()
        self.controller.initialize()
        self.controller.slicerChanged(self.controller.fixedImageWidget)

    @Slot()
    def showHelp(self):
        statusWidget = StatusWidget.Instance()
        statusWidget.setText("Don't panic!")
Example #9
0
class ConsoleWidget(QMainWindow):
    def __init__(self):
        super(ConsoleWidget, self).__init__()
        self.setWindowTitle('1c query')

        self._connection = None

        self._home = os.path.expanduser('~/%s' % QApplication.applicationName())
        if not os.path.isdir(self._home):
            os.mkdir(self._home)

        self.queryToolBar = self.addToolBar('Query')
        self.queryAction = self.queryToolBar.addAction('Run', self.executeQuery)
        self.queryAction.setDisabled(True)

        uri_history = list()
        path = os.path.join(self._home, 'uri_history.txt')
        if os.path.isfile(path):
            uri_history = open(path, 'r').read().split('\n')

        self.connectionToolBar = self.addToolBar('Connection')
        self.connectionUriCombo = QComboBox(self)
        self.connectionUriCombo.setEditable(True)
        if not uri_history:
            self.connectionUriCombo.addItem('File="";usr="";pwd="";')
            self.connectionUriCombo.addItem('Srvr="{host}";Ref="{ref}";Usr="******";Pwd="{password}";')
        else:
            self.connectionUriCombo.addItems(uri_history)
            self.connectionUriCombo.setCurrentIndex(len(uri_history) - 1)
        self.connectionUriCombo.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Maximum)
        self.connectionToolBar.addWidget(self.connectionUriCombo)

        self.onesVersionCombo = QComboBox(self)
        self.onesVersionCombo.addItems(['8.3', '8.2', '8.1', '8.0'])
        self.onesVersionCombo.setCurrentIndex(0)
        self.connectionToolBar.addWidget(self.onesVersionCombo)
        self.connectAction = self.connectionToolBar.addAction('Connect', self.connectOneS)
        self.disconnectAction = self.connectionToolBar.addAction('Disconnect', self.disconnectOneS)
        self.disconnectAction.setDisabled(True)

        self.logEdit = QPlainTextEdit(self)
        self.logDock = QDockWidget('Log', self)
        self.logDock.setWidget(self.logEdit)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.logDock, Qt.Horizontal)

        self.splitter = QSplitter(Qt.Vertical, self)
        self.setCentralWidget(self.splitter)

        self.sqlEdit = QTextEdit(self)
        self.sqlEdit.setLineWrapMode(QTextEdit.NoWrap)

        path = os.path.join(self._home, 'last-sql.txt')
        if os.path.isfile(path):
            sql = open(path, 'r').read()
            self.sqlEdit.setText(sql)

        self.model = QStandardItemModel(self)
        self.tableView = QTableView(self)
        self.tableView.setModel(self.model)

        self.splitter.addWidget(self.sqlEdit)
        self.splitter.addWidget(self.tableView)
        self.splitter.setStretchFactor(0, 3)
        self.splitter.setStretchFactor(1, 2)

    def query(self, sql):
        if not self._connection:
            self.logEdit.appendPlainText('No connection')
            return None

        try:
            query = self._connection.NewObject('Query', sql)
            result = query.Execute()
        except Exception as e:
            self.logEdit.appendPlainText(str(e))
            return None

        return result

    def refresh(self, result):
        self.model.clear()

        columns = list()
        result_columns = result.Columns
        for index in range(result_columns.Count()):
            name = result_columns.Get(index).Name
            columns.append(name)

        self.model.setColumnCount(len(columns))
        for section, name in enumerate(columns):
            self.model.setHeaderData(section, Qt.Horizontal, name)

        select = result.Choose()
        self.logEdit.appendPlainText('Selected %d records' % select.Count())
        while select.Next():
            items = list()
            for index in range(len(columns)):
                value = select.Get(index)

                item = QStandardItem('')
                if isinstance(value, bool):
                    item.setText(value and 'Yes' or 'No')

                elif isinstance(value, (int, str)):
                    item.setText(str(value))

                elif isinstance(value, datetime.datetime):
                    item.setText(value.strftime('%Y.%m.%d %H:%M:%S'))

                else:
                    item.setText(str(value))
                items.append(item)

            self.model.appendRow(items)

    @Slot()
    def executeQuery(self):
        sql = self.sqlEdit.toPlainText()
        result = self.query(sql)
        if result:
            path = os.path.join(self._home, 'last-sql.txt')
            open(path, 'w').write(sql)
            self.refresh(result)

    @Slot()
    def connectOneS(self):
        uri = self.connectionUriCombo.currentText().strip()
        if not uri:
            self.logEdit.appendPlainText('Need a connection string')
            return

        version = self.onesVersionCombo.currentText()
        comName = "V%s.COMConnector" % str(version).replace('.', '')

        pythoncom.CoInitialize()
        try:
            obj = win32com.client.Dispatch(comName)
            self._connection = obj.Connect(uri)
        except Exception as e:
            self.logEdit.appendPlainText(str(e))
            return

        self.connectAction.setDisabled(True)
        self.disconnectAction.setEnabled(True)
        self.queryAction.setEnabled(True)

        uri_history = list()
        for i in range(self.connectionUriCombo.count()):
            uri_history.append(self.connectionUriCombo.itemText(i))

        if uri not in uri_history:
            self.connectionUriCombo.clearEditText()
            self.connectionUriCombo.addItem(uri)
            self.connectionUriCombo.setCurrentIndex(len(uri_history))
            uri_history.append(uri)
            path = os.path.join(self._home, 'uri_history.txt')
            open(path, 'w').write('\n'.join(uri_history))

    @Slot()
    def disconnectOneS(self):
        pythoncom.CoUninitialize()
        self._connection = None
        self.connectAction.setEnabled(True)
        self.disconnectAction.setDisabled(True)
        self.queryAction.setDisabled(True)