def __init__(self): QMainWindow.__init__(self) self.resize(800, 600) self.setWindowTitle('PDF Merger') about = QAction('About', self) self.connect(about, SIGNAL('triggered()'), self.show_about) exit = QAction('Exit', self) exit.setShortcut('Ctrl+Q') self.connect(exit, SIGNAL('triggered()'), SLOT('close()')) self.statusBar() menubar = self.menuBar() file = menubar.addMenu('File') file.addAction(about) file.addAction(exit) self.main_widget = QWidget(self) self.setCentralWidget(self.main_widget) self.up_down_widget = QWidget(self) self.options_widget = QWidget(self) input_files_label = QLabel( "Input PDFs\nThis is the order in which the files will be merged too" ) self.files_list = QListWidget() self.files_list.setSelectionMode(QAbstractItemView.ExtendedSelection) add_button = QPushButton("Add PDF(s) to merge...") add_button.clicked.connect(self.clicked_add) up_button = QPushButton("Up") up_button.clicked.connect(self.move_file_up) down_button = QPushButton("Down") down_button.clicked.connect(self.move_file_down) remove_button = QPushButton("Remove PDF") remove_button.clicked.connect(self.remove_file) select_path_label = QLabel("Output PDF") self.dest_path_edit = QLineEdit() self.dest_path_edit.setReadOnly(True) select_path = QPushButton("Select...") select_path.clicked.connect(self.select_save_path) start = QPushButton("Start") start.clicked.connect(self.merge_pdf) up_down_vbox = QVBoxLayout(self.up_down_widget) up_down_vbox.addWidget(up_button) up_down_vbox.addWidget(down_button) up_down_vbox.addWidget(remove_button) self.up_down_widget.setLayout(up_down_vbox) group_input = QGroupBox() grid_input = QGridLayout() grid_input.addWidget(add_button, 0, 0) grid_input.addWidget(input_files_label, 1, 0) grid_input.addWidget(self.files_list, 2, 0) grid_input.addWidget(self.up_down_widget, 2, 1) group_input.setLayout(grid_input) group_output = QGroupBox() grid_output = QGridLayout() grid_output.addWidget(select_path_label, 0, 0) grid_output.addWidget(self.dest_path_edit, 1, 0) grid_output.addWidget(select_path, 1, 1) group_output.setLayout(grid_output) vbox_options = QVBoxLayout(self.options_widget) vbox_options.addWidget(group_input) vbox_options.addWidget(group_output) vbox_options.addWidget(start) self.options_widget.setLayout(vbox_options) splitter_filelist = QSplitter() splitter_filelist.setOrientation(Qt.Vertical) splitter_filelist.addWidget(self.options_widget) vbox_main = QVBoxLayout(self.main_widget) vbox_main.addWidget(splitter_filelist) vbox_main.setContentsMargins(0, 0, 0, 0)
class ClassyWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) layout = QVBoxLayout(self) horiz_layout = QHBoxLayout() self.conditional_legend_widget = EdgeWidget(self, True) self.conditional_legend_widget.setMinimumHeight(15) horiz_layout.addWidget(self.conditional_legend_widget) self.conditional_legend_label = QLabel("Conditional transition", self) horiz_layout.addWidget(self.conditional_legend_label) self.unconditional_legend_widget = EdgeWidget(self, False) self.unconditional_legend_widget.setMinimumHeight(15) horiz_layout.addWidget(self.unconditional_legend_widget) self.unconditional_legend_label = QLabel("Non-conditional transition", self) horiz_layout.addWidget(self.unconditional_legend_label) layout.addLayout(horiz_layout) self.splitter = QSplitter(self) layout.addWidget(self.splitter) self.view = ClassyView(self.splitter) # layout.addWidget(self.view) self.scene = ClassyScene(self) self.view.setScene(self.scene) self._menu_bar = QMenuBar(self) self._menu = QMenu("&File") self._menu_bar.addMenu(self._menu) layout.setMenuBar(self._menu_bar) self.open_action = QAction("O&pen", self) self.exit_action = QAction("E&xit", self) self._menu.addAction(self.open_action) self._menu.addAction(self.exit_action) self.connect(self.open_action, SIGNAL("triggered()"), self.open_file) self.connect(self.exit_action, SIGNAL("triggered()"), self.close) self.settings = QSettings("CD Projekt RED", "TweakDB") self.log_window = QPlainTextEdit(self.splitter) self.splitter.setOrientation(Qt.Vertical) self.setWindowTitle("Classy nodes") @Slot() def open_file(self): last_dir = self.settings.value("last_dir") if last_dir is None: last_dir = '' # noinspection PyCallByClass file_path = QFileDialog.getOpenFileName(self, "Select tweakdb file", last_dir, "*.tweak") if file_path[0]: tweak_file = file_path[0] self.settings.setValue("last_dir", os.path.dirname(tweak_file)) else: return try: self._process_db_file(file_path[0]) except Exception as e: # noinspection PyCallByClass QMessageBox.critical( self, "Error", "Error while loading {0}: {1}".format(file_path, str(e))) self.setWindowTitle("Classy nodes - {0}".format(file_path[0])) @Slot(str) def log(self, value): self.log_window.appendPlainText(str(value)) self.log_window.verticalScrollBar().scroll( 0, self.log_window.verticalScrollBar().maximum()) def _process_db_file(self, file_path): class TweakClass(object): def __init__(self, name, base=""): self.name = name self.base = base self.transitions_to = [] self.transitions_conditions = [] def has_transition(self, name): return name in self.transitions_to def transition_conditional(self, name): if len(self.transitions_to) != len( self.transitions_conditions): raise ValueError( "Transitions length does not match conditions length in {0}" .format(self.name)) if name not in name: raise ValueError( "Class {0} has no transition to {1}".format( self.name, name)) return self.transitions_conditions[self.transitions_to.index( name)] with open(file_path, "r") as f: contents = f.read() lines = contents.split("\n") is_in_class = False is_class_declared = False current_class = None classes = {} parsed_line = 0 for line in lines: parsed_line += 1 if line.startswith("package"): continue if line.startswith("using"): continue if not line.strip(): continue if line.startswith("//"): continue if not is_in_class and not is_class_declared: if line.find("=") > 0: # static variable continue spl = [x.strip() for x in line.strip().split(":")] if len(spl) == 1: c = TweakClass(spl[0]) else: c = TweakClass(spl[0], spl[1]) is_class_declared = True current_class = c classes[c.name] = c continue if not is_in_class and not line.find("{") >= 0: raise ValueError( "Failed to parse the file {0} in line: {1}".format( file_path, parsed_line)) else: is_in_class = True if line.find("}") >= 0: is_in_class = False is_class_declared = False continue if re.match(".+transitionTo( +||\t+)+=( +||\t+)+\[.+\]$", line.strip()): spl = line.split("=")[1].strip()[1:-1] transitions = [x.strip().strip("\"") for x in spl.split(",")] current_class.transitions_to = transitions continue if re.match(".+transitionCondition( +||\t+)+=( +||\t+)+\[.+\]$", line.strip()): spl = "=".join(line.split("=")[1:]).strip()[1:-1] transitions = [x.strip().strip("\"") for x in spl.split(",")] current_class.transitions_conditions = [ True if x.strip() == '=' else False for x in transitions ] continue self.scene.clear() # --- Create nodes for node_key in classes: # g.add_node(str(node_key), # shape_fill="#aaaa33", # shape="roundrectangle", # font_style="bolditalic", # label=classes.get(node_key).name) self.scene.add_node(node_key) edges_created = [] # --- Create edges for node_key in classes: # --- Get each node current_node = classes.get(node_key) # --- Iterate it's "transition_to" list for t in current_node.transitions_to: # --- Find node to create transition edge to transition_to_node = classes.get(t) if transition_to_node is None: self.log("Invalid transition in class {0} -> {1}".format( node_key, t)) continue # --- Check if it's a two way transition two_way = False if transition_to_node.has_transition(node_key): two_way = True # --- make sure that these edges were not created yet edges_to_create = ["{0}!@#{1}".format(node_key, t)] if two_way: edges_to_create = ["{0}!@#{1}".format(t, node_key)] edge_already_created = False for e in edges_to_create: if e in edges_created: edge_already_created = True break if edge_already_created: continue # --- Check if the transitions are conditional or not try: conditional_to = current_node.transition_conditional(t) except ValueError as e: self.log(str(e)) continue conditional_from = False if two_way: conditional_from = transition_to_node.transition_conditional( node_key) self.scene.add_edge(current_node.name, transition_to_node.name, conditional_to=conditional_to, two_way=two_way, conditional_from=conditional_from) edges_created += edges_to_create self.scene.layout_nodes()
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!")
def __init__(self): QMainWindow.__init__(self) self.resize(800,600) self.setWindowTitle('PDF Merger') about = QAction('About', self) self.connect(about, SIGNAL('triggered()'), self.show_about) exit = QAction('Exit', self) exit.setShortcut('Ctrl+Q') self.connect(exit, SIGNAL('triggered()'), SLOT('close()')) self.statusBar() menubar = self.menuBar() file = menubar.addMenu('File') file.addAction(about) file.addAction(exit) self.main_widget = QWidget(self) self.setCentralWidget(self.main_widget) self.up_down_widget = QWidget(self) self.options_widget = QWidget(self) input_files_label = QLabel("Input PDFs\nThis is the order in which the files will be merged too") self.files_list = QListWidget() self.files_list.setSelectionMode(QAbstractItemView.ExtendedSelection) add_button = QPushButton("Add PDF(s) to merge...") add_button.clicked.connect(self.clicked_add) up_button = QPushButton("Up") up_button.clicked.connect(self.move_file_up) down_button = QPushButton("Down") down_button.clicked.connect(self.move_file_down) remove_button = QPushButton("Remove PDF") remove_button.clicked.connect(self.remove_file) select_path_label = QLabel("Output PDF") self.dest_path_edit = QLineEdit() self.dest_path_edit.setReadOnly(True) select_path = QPushButton("Select...") select_path.clicked.connect(self.select_save_path) start = QPushButton("Start") start.clicked.connect(self.merge_pdf) up_down_vbox = QVBoxLayout(self.up_down_widget) up_down_vbox.addWidget(up_button) up_down_vbox.addWidget(down_button) up_down_vbox.addWidget(remove_button) self.up_down_widget.setLayout(up_down_vbox) group_input = QGroupBox() grid_input = QGridLayout() grid_input.addWidget(add_button, 0, 0) grid_input.addWidget(input_files_label, 1, 0) grid_input.addWidget(self.files_list, 2, 0) grid_input.addWidget(self.up_down_widget, 2, 1) group_input.setLayout(grid_input) group_output = QGroupBox() grid_output = QGridLayout() grid_output.addWidget(select_path_label, 0, 0) grid_output.addWidget(self.dest_path_edit, 1, 0) grid_output.addWidget(select_path, 1, 1) group_output.setLayout(grid_output) vbox_options = QVBoxLayout(self.options_widget) vbox_options.addWidget(group_input) vbox_options.addWidget(group_output) vbox_options.addWidget(start) self.options_widget.setLayout(vbox_options) splitter_filelist = QSplitter() splitter_filelist.setOrientation(Qt.Vertical) splitter_filelist.addWidget(self.options_widget) vbox_main = QVBoxLayout(self.main_widget) vbox_main.addWidget(splitter_filelist) vbox_main.setContentsMargins(0,0,0,0)
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)