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)
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)
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)
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()
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)
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
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!")
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)