Esempio n. 1
0
class Preferences(object):
    """docstring for Preferences"""
    def __init__(self):
        self.qs = QSettings()
        self.ui_prefs = Ui_Preferences()
        self.widget = QWidget()
        self.ui_prefs.setupUi(self.widget)
        self.readPreferences()
        self.widget.addAction(self.ui_prefs.actionClose)
        self.ui_prefs.actionClose.triggered.connect(self.hideDialog)
        self.ui_prefs.honeycomb_rows_spin_box.valueChanged.connect(
            self.setHoneycombRows)
        self.ui_prefs.honeycomb_cols_spin_box.valueChanged.connect(
            self.setHoneycombCols)
        self.ui_prefs.honeycomb_steps_spin_box.valueChanged.connect(
            self.setHoneycombSteps)
        self.ui_prefs.square_rows_spin_box.valueChanged.connect(
            self.setSquareRows)
        self.ui_prefs.square_cols_spin_box.valueChanged.connect(
            self.setSquareCols)
        self.ui_prefs.square_steps_spin_box.valueChanged.connect(
            self.setSquareSteps)
        self.ui_prefs.auto_scaf_combo_box.currentIndexChanged.connect(
            self.setAutoScaf)
        self.ui_prefs.default_tool_combo_box.currentIndexChanged.connect(
            self.setStartupTool)
        self.ui_prefs.zoom_speed_slider.valueChanged.connect(self.setZoomSpeed)
        # self.ui_prefs.helixAddCheckBox.toggled.connect(self.setZoomToFitOnHelixAddition)
        self.ui_prefs.button_box.clicked.connect(self.handleButtonClick)
        self.ui_prefs.add_plugin_button.clicked.connect(self.addPlugin)

    def showDialog(self):
        # self.exec_()
        self.readPreferences()
        self.widget.show()  # launch prefs in mode-less dialog

    def hideDialog(self):
        self.widget.hide()

    # @pyqtSlot(object)
    def handleButtonClick(self, button):
        """
        Restores defaults. Other buttons are ignored because connections
        are already set up in qt designer.
        """
        if self.ui_prefs.button_box.buttonRole(
                button) == QDialogButtonBox.ResetRole:
            self.restoreDefaults()

    def readPreferences(self):
        self.qs.beginGroup("Preferences")
        self.honeycomb_rows = self.qs.value("honeycomb_rows",
                                            styles.HONEYCOMB_PART_MAXROWS)
        self.honeycomb_cols = self.qs.value("honeycomb_cols",
                                            styles.HONEYCOMB_PART_MAXCOLS)
        self.honeycomb_steps = self.qs.value("honeycomb_steps",
                                             styles.HONEYCOMB_PART_MAXSTEPS)
        self.square_rows = self.qs.value("square_rows",
                                         styles.SQUARE_PART_MAXROWS)
        self.square_cols = self.qs.value("square_cols",
                                         styles.SQUARE_PART_MAXCOLS)
        self.square_steps = self.qs.value("square_steps",
                                          styles.SQUARE_PART_MAXSTEPS)
        self.auto_scaf_index = self.qs.value("autoScaf",
                                             styles.PREF_AUTOSCAF_INDEX)
        self.startup_tool_index = self.qs.value("startup_tool",
                                                styles.PREF_STARTUP_TOOL_INDEX)
        self.zoom_speed = self.qs.value("zoom_speed", styles.PREF_ZOOM_SPEED)
        self.zoom_on_helix_add = self.qs.value(
            "zoom_on_helix_add", styles.PREF_ZOOM_AFTER_HELIX_ADD)
        self.qs.endGroup()
        self.ui_prefs.honeycomb_rows_spin_box.setProperty(
            "value", self.honeycomb_rows)
        self.ui_prefs.honeycomb_cols_spin_box.setProperty(
            "value", self.honeycomb_cols)
        self.ui_prefs.honeycomb_steps_spin_box.setProperty(
            "value", self.honeycomb_steps)
        self.ui_prefs.square_rows_spin_box.setProperty("value",
                                                       self.square_rows)
        self.ui_prefs.square_cols_spin_box.setProperty("value",
                                                       self.square_cols)
        self.ui_prefs.square_steps_spin_box.setProperty(
            "value", self.square_steps)
        self.ui_prefs.auto_scaf_combo_box.setCurrentIndex(self.auto_scaf_index)
        self.ui_prefs.default_tool_combo_box.setCurrentIndex(
            self.startup_tool_index)
        self.ui_prefs.zoom_speed_slider.setProperty("value", self.zoom_speed)
        ptw = self.ui_prefs.plugin_table_widget
        loaded_plugin_paths = util.loadedPlugins.keys()
        ptw.setRowCount(len(loaded_plugin_paths))
        for i in range(len(loaded_plugin_paths)):
            row = QTableWidgetItem(loaded_plugin_paths[i])
            row.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            ptw.setItem(i, 0, row)
        # self.ui_prefs.helixAddCheckBox.setChecked(self.zoom_on_helix_add)

    def restoreDefaults(self):
        self.ui_prefs.honeycomb_rows_spin_box.setProperty(
            "value", styles.HONEYCOMB_PART_MAXROWS)
        self.ui_prefs.honeycomb_cols_spin_box.setProperty(
            "value", styles.HONEYCOMB_PART_MAXCOLS)
        self.ui_prefs.honeycomb_steps_spin_box.setProperty(
            "value", styles.HONEYCOMB_PART_MAXSTEPS)
        self.ui_prefs.square_rows_spin_box.setProperty(
            "value", styles.SQUARE_PART_MAXROWS)
        self.ui_prefs.square_cols_spin_box.setProperty(
            "value", styles.SQUARE_PART_MAXCOLS)
        self.ui_prefs.square_steps_spin_box.setProperty(
            "value", styles.SQUARE_PART_MAXSTEPS)
        self.ui_prefs.auto_scaf_combo_box.setCurrentIndex(
            styles.PREF_AUTOSCAF_INDEX)
        self.ui_prefs.default_tool_combo_box.setCurrentIndex(
            styles.PREF_STARTUP_TOOL_INDEX)
        self.ui_prefs.zoom_speed_slider.setProperty("value",
                                                    styles.PREF_ZOOM_SPEED)
        # self.ui_prefs.helixAddCheckBox.setChecked(styles.PREF_ZOOM_AFTER_HELIX_ADD)

    def setHoneycombRows(self, rows):
        self.honeycomb_rows = rows
        self.qs.beginGroup("Preferences")
        self.qs.setValue("honeycomb_rows", self.honeycomb_rows)
        self.qs.endGroup()

    def setHoneycombCols(self, cols):
        self.honeycomb_cols = cols
        self.qs.beginGroup("Preferences")
        self.qs.setValue("honeycomb_cols", self.honeycomb_cols)
        self.qs.endGroup()

    def setHoneycombSteps(self, steps):
        self.honeycomb_steps = steps
        self.qs.beginGroup("Preferences")
        self.qs.setValue("honeycomb_steps", self.honeycomb_steps)
        self.qs.endGroup()

    def setSquareRows(self, rows):
        self.square_rows = rows
        self.qs.beginGroup("Preferences")
        self.qs.setValue("square_rows", self.square_rows)
        self.qs.endGroup()

    def setSquareCols(self, cols):
        self.square_cols = cols
        self.qs.beginGroup("Preferences")
        self.qs.setValue("square_cols", self.square_cols)
        self.qs.endGroup()

    def setSquareSteps(self, steps):
        self.square_steps = steps
        self.qs.beginGroup("Preferences")
        self.qs.setValue("square_steps", self.square_steps)
        self.qs.endGroup()

    def setAutoScaf(self, index):
        self.auto_scaf_index = index
        self.qs.beginGroup("Preferences")
        self.qs.setValue("autoScaf", self.auto_scaf_index)
        self.qs.endGroup()

    def setStartupTool(self, index):
        self.startup_tool_index = index
        self.qs.beginGroup("Preferences")
        self.qs.setValue("startup_tool", self.startup_tool_index)
        self.qs.endGroup()

    def setZoomSpeed(self, speed):
        self.zoom_speed = speed
        self.qs.beginGroup("Preferences")
        self.qs.setValue("zoom_speed", self.zoom_speed)
        self.qs.endGroup()

    # def setZoomToFitOnHelixAddition(self, checked):
    #     self.zoom_on_helix_add = checked
    #     self.qs.beginGroup("Preferences")
    #     self.qs.setValue("zoom_on_helix_add", self.zoom_on_helix_add)
    #     self.qs.endGroup()

    def getAutoScafType(self):
        return ['Mid-seam', 'Raster'][self.auto_scaf_index]

    def getStartupToolName(self):
        return ['Select', 'Pencil', 'Paint', 'AddSeq'][self.startup_tool_index]

    def addPlugin(self):
        fdialog = QFileDialog(self.widget, "Install Plugin", util.this_path(),
                              "Cadnano Plugins (*.cnp)")
        fdialog.setAcceptMode(QFileDialog.AcceptOpen)
        fdialog.setWindowFlags(Qt.Sheet)
        fdialog.setWindowModality(Qt.WindowModal)
        fdialog.filesSelected.connect(self.addPluginAtPath)
        self.fileopendialog = fdialog
        fdialog.open()

    def addPluginAtPath(self, fname):
        self.fileopendialog.close()
        fname = str(fname[0])
        print("Attempting to open plugin %s" % fname)
        try:
            zf = zipfile.ZipFile(fname, 'r')
        except Exception as e:
            self.failWithMsg("Plugin file seems corrupt: %s." % e)
            return
        tdir = tempfile.mkdtemp()
        try:
            for f in zf.namelist():
                if f.endswith('/'):
                    os.makedirs(os.path.join(tdir, f))
            for f in zf.namelist():
                if not f.endswith('/'):
                    zf.extract(f, tdir)
        except Exception as e:
            self.failWithMsg("Extraction of plugin archive failed: %s." % e)
            return
        files_in_zip = [(f, os.path.join(tdir, f)) for f in os.listdir(tdir)]
        try:
            self.confirmDestructiveIfNecessary(files_in_zip)
            self.removePluginsToBeOverwritten(files_in_zip)
            self.movePluginsIntoPluginsFolder(files_in_zip)
        except OSError:
            print("Couldn't copy files into plugin directory, attempting\
                   again after boosting privileges.")
            if platform.system() == 'Darwin':
                self.darwinAuthedMvPluginsIntoPluginsFolder(files_in_zip)
            elif platform.system() == 'Linux':
                self.linuxAuthedMvPluginsIntoPluginsFolder(files_in_zip)
            else:
                print("Can't boost privelages on platform %s" %
                      platform.system())
        loadedAPlugin = util.loadAllPlugins()
        if not loadedAPlugin:
            print("Unable to load anythng from plugin %s" % fname)
        self.readPreferences()
        shutil.rmtree(tdir)

    def darwinAuthedMvPluginsIntoPluginsFolder(self, files_in_zip):
        envirn = {"DST": util.this_path() + '/plugins'}
        srcstr = ''
        for i in range(len(files_in_zip)):
            file_name, file_path = files_in_zip[i]
            srcstr += ' \\"$SRC' + str(i) + '\\"'
            envirn['SRC' + str(i)] = file_path
        proc = subprocess.Popen(['osascript','-e',\
                          'do shell script "cp -fR ' + srcstr +\
                          ' \\"$DST\\"" with administrator privileges'],\
                          env=envirn)
        retval = self.waitForProcExit(proc)
        if retval != 0:
            self.failWithMsg('cp failed with code %i' % retval)

    def linuxAuthedMvPluginsIntoPluginsFolder(self, files_in_zip):
        args = ['gksudo', 'cp', '-fR']
        args.extend(file_path for file_name, file_path in files_in_zip)
        args.append(util.this_path() + '/plugins')
        proc = subprocess.Popen(args)
        retval = self.waitForProcExit(proc)
        if retval != 0:
            self.failWithMsg('cp failed with code %i' % retval)

    def confirmDestructiveIfNecessary(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            if os.path.isfile(target):
                return self.confirmDestructive()
            elif os.path.isdir(target):
                return self.confirmDestructive()

    def confirmDestructive(self):
        mb = QMessageBox(self.widget)
        mb.setIcon(QMessageBox.Warning)
        mb.setInformativeText("The plugin you are trying to install\
has already been installed. Replace the currently installed one?")
        mb.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
        mb.exec_()
        return mb.clickedButton() == mb.button(QMessageBox.Yes)

    def removePluginsToBeOverwritten(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            if os.path.isfile(target):
                os.unlink(target)
            elif os.path.isdir(target):
                shutil.rmtree(target)

    def movePluginsIntoPluginsFolder(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            shutil.move(file_path, target)

    def waitForProcExit(self, proc):
        procexit = False
        while not procexit:
            try:
                retval = proc.wait()
                procexit = True
            except OSError as e:
                if e.errno != errno.EINTR:
                    raise ose
        return retval

    def failWithMsg(self, str):
        mb = QMessageBox(self.widget)
        mb.setIcon(QMessageBox.Warning)
        mb.setInformativeText(str)
        mb.buttonClicked.connect(self.closeFailDialog)
        self.fail_message_box = mb
        mb.open()

    def closeFailDialog(self, button):
        self.fail_message_box.close()
        del self.fail_message_box
        self.fail_message_box = None
Esempio n. 2
0
class Preferences(object):
    """docstring for Preferences"""
    def __init__(self):
        self.qs = QSettings()
        self.ui_prefs = Ui_Preferences()
        self.widget = QWidget()
        self.ui_prefs.setupUi(self.widget)
        self.readPreferences()
        self.widget.addAction(self.ui_prefs.actionClose)
        self.ui_prefs.actionClose.triggered.connect(self.hideDialog)
        self.ui_prefs.grid_appearance_type_combo_box.currentIndexChanged.connect(
            self.setGridAppearanceType)
        self.ui_prefs.zoom_speed_slider.valueChanged.connect(self.setZoomSpeed)
        self.ui_prefs.button_box.clicked.connect(self.handleButtonClick)
        self.ui_prefs.add_plugin_button.clicked.connect(self.addPlugin)
        self.ui_prefs.show_icon_labels.clicked.connect(self.setShowIconLabels)

        self.ui_prefs.grid_appearance_type_combo_box.activated.connect(
            self.updateGrid)
        self.document = None

    # end def

    def showDialog(self):
        self.readPreferences()
        self.widget.show()  # launch prefs in mode-less dialog

    # end def

    def updateGrid(self, index):
        self.setGridAppearanceType(index)
        value = self.getGridAppearanceType()
        for part in self.document.getParts():
            part.partDocumentSettingChangedSignal.emit(part, 'grid', value)

    # end def

    def hideDialog(self):
        self.widget.hide()

    # end def

    def handleButtonClick(self, button):
        """
        Restores defaults. Other buttons are ignored because connections
        are already set up in qt designer.
        """
        if self.ui_prefs.button_box.buttonRole(
                button) == QDialogButtonBox.ResetRole:
            self.restoreDefaults()

    # end def

    def readPreferences(self):
        self.qs.beginGroup("Preferences")
        self.grid_appearance_type_index = self.qs.value(
            "grid_appearance_type_index",
            styles.PREF_GRID_APPEARANCE_TYPE_INDEX)
        self.zoom_speed = self.qs.value("zoom_speed", styles.PREF_ZOOM_SPEED)
        self.show_icon_labels = self.qs.value("ui_icons_labels",
                                              styles.PREF_SHOW_ICON_LABELS)
        self.qs.endGroup()
        self.ui_prefs.grid_appearance_type_combo_box.setCurrentIndex(
            self.grid_appearance_type_index)
        self.ui_prefs.zoom_speed_slider.setProperty("value", self.zoom_speed)
        self.ui_prefs.show_icon_labels.setChecked(self.show_icon_labels)
        ptw = self.ui_prefs.plugin_table_widget
        loaded_plugin_paths = util.loadedPlugins.keys()
        ptw.setRowCount(len(loaded_plugin_paths))
        for i in range(len(loaded_plugin_paths)):
            row = QTableWidgetItem(loaded_plugin_paths[i])
            row.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            ptw.setItem(i, 0, row)

    # end def

    def restoreDefaults(self):
        self.ui_prefs.grid_appearance_type_combo_box.setCurrentIndex(
            styles.PREF_GRID_APPEARANCE_TYPE_INDEX)
        self.ui_prefs.zoom_speed_slider.setProperty("value",
                                                    styles.PREF_ZOOM_SPEED)
        self.ui_prefs.show_icon_labels.setChecked(styles.PREF_SHOW_ICON_LABELS)

    # end def

    def setGridAppearanceType(self, grid_appearance_type_index):
        self.grid_appearance_type_index = grid_appearance_type_index
        self.qs.beginGroup("Preferences")
        self.qs.setValue("grid_appearance_type_index",
                         grid_appearance_type_index)
        self.qs.endGroup()

    # end def

    def getGridAppearanceType(self):
        return ['circles', 'lines and points',
                'points'][self.grid_appearance_type_index]

    # end def

    def setZoomSpeed(self, speed):
        self.zoom_speed = speed
        self.qs.beginGroup("Preferences")
        self.qs.setValue("zoom_speed", self.zoom_speed)
        self.qs.endGroup()

    # end def

    def setShowIconLabels(self, checked):
        self.show_icon_labels = checked
        self.qs.beginGroup("Preferences")
        self.qs.setValue("ui_icons_labels", self.show_icon_labels)
        self.qs.endGroup()

    # end def

    def addPlugin(self):
        fdialog = QFileDialog(self.widget, "Install Plugin", util.this_path(),
                              "Cadnano Plugins (*.cnp)")
        fdialog.setAcceptMode(QFileDialog.AcceptOpen)
        fdialog.setWindowFlags(Qt.Sheet)
        fdialog.setWindowModality(Qt.WindowModal)
        fdialog.filesSelected.connect(self.addPluginAtPath)
        self.fileopendialog = fdialog
        fdialog.open()

    # end def

    def addPluginAtPath(self, fname):
        self.fileopendialog.close()
        fname = str(fname[0])
        print("Attempting to open plugin %s" % fname)
        try:
            zf = zipfile.ZipFile(fname, 'r')
        except Exception as e:
            self.failWithMsg("Plugin file seems corrupt: %s." % e)
            return
        tdir = tempfile.mkdtemp()
        try:
            for f in zf.namelist():
                if f.endswith('/'):
                    os.makedirs(os.path.join(tdir, f))
            for f in zf.namelist():
                if not f.endswith('/'):
                    zf.extract(f, tdir)
        except Exception as e:
            self.failWithMsg("Extraction of plugin archive failed: %s." % e)
            return
        files_in_zip = [(f, os.path.join(tdir, f)) for f in os.listdir(tdir)]
        try:
            self.confirmDestructiveIfNecessary(files_in_zip)
            self.removePluginsToBeOverwritten(files_in_zip)
            self.movePluginsIntoPluginsFolder(files_in_zip)
        except OSError:
            print("Couldn't copy files into plugin directory, attempting\
                   again after boosting privileges.")
            if platform.system() == 'Darwin':
                self.darwinAuthedMvPluginsIntoPluginsFolder(files_in_zip)
            elif platform.system() == 'Linux':
                self.linuxAuthedMvPluginsIntoPluginsFolder(files_in_zip)
            else:
                print("Can't boost privelages on platform %s" %
                      platform.system())
        loadedAPlugin = util.loadAllPlugins()
        if not loadedAPlugin:
            print("Unable to load anythng from plugin %s" % fname)
        self.readPreferences()
        shutil.rmtree(tdir)

    # end def

    def darwinAuthedMvPluginsIntoPluginsFolder(self, files_in_zip):
        envirn = {"DST": util.this_path() + '/plugins'}
        srcstr = ''
        for i in range(len(files_in_zip)):
            file_name, file_path = files_in_zip[i]
            srcstr += ' \\"$SRC' + str(i) + '\\"'
            envirn['SRC' + str(i)] = file_path
        proc = subprocess.Popen(['osascript','-e',\
                          'do shell script "cp -fR ' + srcstr +\
                          ' \\"$DST\\"" with administrator privileges'],\
                          env=envirn)
        retval = self.waitForProcExit(proc)
        if retval != 0:
            self.failWithMsg('cp failed with code %i' % retval)

    # end def

    def linuxAuthedMvPluginsIntoPluginsFolder(self, files_in_zip):
        args = ['gksudo', 'cp', '-fR']
        args.extend(file_path for file_name, file_path in files_in_zip)
        args.append(util.this_path() + '/plugins')
        proc = subprocess.Popen(args)
        retval = self.waitForProcExit(proc)
        if retval != 0:
            self.failWithMsg('cp failed with code %i' % retval)

    # end def

    def confirmDestructiveIfNecessary(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            if os.path.isfile(target):
                return self.confirmDestructive()
            elif os.path.isdir(target):
                return self.confirmDestructive()

    # end def

    def confirmDestructive(self):
        mb = QMessageBox(self.widget)
        mb.setIcon(QMessageBox.Warning)
        mb.setInformativeText("The plugin you are trying to install\
has already been installed. Replace the currently installed one?")
        mb.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
        mb.exec_()
        return mb.clickedButton() == mb.button(QMessageBox.Yes)

    # end def

    def removePluginsToBeOverwritten(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            if os.path.isfile(target):
                os.unlink(target)
            elif os.path.isdir(target):
                shutil.rmtree(target)

    # end def

    def movePluginsIntoPluginsFolder(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            shutil.move(file_path, target)

    # end def

    def waitForProcExit(self, proc):
        procexit = False
        while not procexit:
            try:
                retval = proc.wait()
                procexit = True
            except OSError as e:
                if e.errno != errno.EINTR:
                    raise ose
        return retval

    # end def

    def failWithMsg(self, str):
        mb = QMessageBox(self.widget)
        mb.setIcon(QMessageBox.Warning)
        mb.setInformativeText(str)
        mb.buttonClicked.connect(self.closeFailDialog)
        self.fail_message_box = mb
        mb.open()

    # end def

    def closeFailDialog(self, button):
        self.fail_message_box.close()
        del self.fail_message_box
        self.fail_message_box = None
Esempio n. 3
0
class Preferences(object):
    """docstring for Preferences"""
    def __init__(self):
        self.qs = QSettings()
        self.ui_prefs = Ui_Preferences()
        self.widget = QWidget()
        self.ui_prefs.setupUi(self.widget)
        self.readPreferences()
        self.widget.addAction(self.ui_prefs.actionClose)
        self.ui_prefs.actionClose.triggered.connect(self.hideDialog)
        self.ui_prefs.honeycomb_rows_spin_box.valueChanged.connect(self.setHoneycombRows)
        self.ui_prefs.honeycomb_cols_spin_box.valueChanged.connect(self.setHoneycombCols)
        self.ui_prefs.honeycomb_steps_spin_box.valueChanged.connect(self.setHoneycombSteps)
        self.ui_prefs.square_rows_spin_box.valueChanged.connect(self.setSquareRows)
        self.ui_prefs.square_cols_spin_box.valueChanged.connect(self.setSquareCols)
        self.ui_prefs.square_steps_spin_box.valueChanged.connect(self.setSquareSteps)
        self.ui_prefs.auto_scaf_combo_box.currentIndexChanged.connect(self.setAutoScaf)
        self.ui_prefs.default_tool_combo_box.currentIndexChanged.connect(self.setStartupTool)
        self.ui_prefs.zoom_speed_slider.valueChanged.connect(self.setZoomSpeed)
        # self.ui_prefs.helixAddCheckBox.toggled.connect(self.setZoomToFitOnHelixAddition)
        self.ui_prefs.button_box.clicked.connect(self.handleButtonClick)
        self.ui_prefs.add_plugin_button.clicked.connect(self.addPlugin)

    def showDialog(self):
        # self.exec_()
        self.readPreferences()
        self.widget.show()  # launch prefs in mode-less dialog

    def hideDialog(self):
        self.widget.hide()

    # @pyqtSlot(object)
    def handleButtonClick(self, button):
        """
        Restores defaults. Other buttons are ignored because connections
        are already set up in qt designer.
        """
        if self.ui_prefs.button_box.buttonRole(button) == QDialogButtonBox.ResetRole:
            self.restoreDefaults()

    def readPreferences(self):
        self.qs.beginGroup("Preferences")
        self.honeycomb_rows = self.qs.value("honeycomb_rows", slicestyles.HONEYCOMB_PART_MAXROWS)
        self.honeycomb_cols = self.qs.value("honeycomb_cols", slicestyles.HONEYCOMB_PART_MAXCOLS)
        self.honeycomb_steps = self.qs.value("honeycomb_steps", slicestyles.HONEYCOMB_PART_MAXSTEPS)
        self.square_rows = self.qs.value("square_rows", slicestyles.SQUARE_PART_MAXROWS)
        self.square_cols = self.qs.value("square_cols", slicestyles.SQUARE_PART_MAXCOLS)
        self.square_steps = self.qs.value("square_steps", slicestyles.SQUARE_PART_MAXSTEPS)
        self.auto_scaf_index = self.qs.value("autoScaf", styles.PREF_AUTOSCAF_INDEX)
        self.startup_tool_index = self.qs.value("startup_tool", styles.PREF_STARTUP_TOOL_INDEX)
        self.zoom_speed = self.qs.value("zoom_speed", styles.PREF_ZOOM_SPEED)
        self.zoom_on_helix_add = self.qs.value("zoom_on_helix_add", styles.PREF_ZOOM_AFTER_HELIX_ADD)
        self.qs.endGroup()
        self.ui_prefs.honeycomb_rows_spin_box.setProperty("value", self.honeycomb_rows)
        self.ui_prefs.honeycomb_cols_spin_box.setProperty("value", self.honeycomb_cols)
        self.ui_prefs.honeycomb_steps_spin_box.setProperty("value", self.honeycomb_steps)
        self.ui_prefs.square_rows_spin_box.setProperty("value", self.square_rows)
        self.ui_prefs.square_cols_spin_box.setProperty("value", self.square_cols)
        self.ui_prefs.square_steps_spin_box.setProperty("value", self.square_steps)
        self.ui_prefs.auto_scaf_combo_box.setCurrentIndex(self.auto_scaf_index)
        self.ui_prefs.default_tool_combo_box.setCurrentIndex(self.startup_tool_index)
        self.ui_prefs.zoom_speed_slider.setProperty("value", self.zoom_speed)
        ptw = self.ui_prefs.plugin_table_widget
        loaded_plugin_paths = util.loadedPlugins.keys()
        ptw.setRowCount(len(loaded_plugin_paths))
        for i in range(len(loaded_plugin_paths)):
            row = QTableWidgetItem(loaded_plugin_paths[i])
            row.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            ptw.setItem(i, 0, row)
        # self.ui_prefs.helixAddCheckBox.setChecked(self.zoom_on_helix_add)
        

    def restoreDefaults(self):
        self.ui_prefs.honeycomb_rows_spin_box.setProperty("value", slicestyles.HONEYCOMB_PART_MAXROWS)
        self.ui_prefs.honeycomb_cols_spin_box.setProperty("value", slicestyles.HONEYCOMB_PART_MAXCOLS)
        self.ui_prefs.honeycomb_steps_spin_box.setProperty("value", slicestyles.HONEYCOMB_PART_MAXSTEPS)
        self.ui_prefs.square_rows_spin_box.setProperty("value", slicestyles.SQUARE_PART_MAXROWS)
        self.ui_prefs.square_cols_spin_box.setProperty("value", slicestyles.SQUARE_PART_MAXCOLS)
        self.ui_prefs.square_steps_spin_box.setProperty("value", slicestyles.SQUARE_PART_MAXSTEPS)
        self.ui_prefs.auto_scaf_combo_box.setCurrentIndex(styles.PREF_AUTOSCAF_INDEX)
        self.ui_prefs.default_tool_combo_box.setCurrentIndex(styles.PREF_STARTUP_TOOL_INDEX)
        self.ui_prefs.zoom_speed_slider.setProperty("value", styles.PREF_ZOOM_SPEED)
        # self.ui_prefs.helixAddCheckBox.setChecked(styles.PREF_ZOOM_AFTER_HELIX_ADD)

    def setHoneycombRows(self, rows):
        self.honeycomb_rows = rows
        self.qs.beginGroup("Preferences")
        self.qs.setValue("honeycomb_rows", self.honeycomb_rows)
        self.qs.endGroup()

    def setHoneycombCols(self, cols):
        self.honeycomb_cols = cols
        self.qs.beginGroup("Preferences")
        self.qs.setValue("honeycomb_cols", self.honeycomb_cols)
        self.qs.endGroup()

    def setHoneycombSteps(self, steps):
        self.honeycomb_steps = steps
        self.qs.beginGroup("Preferences")
        self.qs.setValue("honeycomb_steps", self.honeycomb_steps)
        self.qs.endGroup()

    def setSquareRows(self, rows):
        self.square_rows = rows
        self.qs.beginGroup("Preferences")
        self.qs.setValue("square_rows", self.square_rows)
        self.qs.endGroup()

    def setSquareCols(self, cols):
        self.square_cols = cols
        self.qs.beginGroup("Preferences")
        self.qs.setValue("square_cols", self.square_cols)
        self.qs.endGroup()

    def setSquareSteps(self, steps):
        self.square_steps = steps
        self.qs.beginGroup("Preferences")
        self.qs.setValue("square_steps", self.square_steps)
        self.qs.endGroup()

    def setAutoScaf(self, index):
        self.auto_scaf_index = index
        self.qs.beginGroup("Preferences")
        self.qs.setValue("autoScaf", self.auto_scaf_index)
        self.qs.endGroup()

    def setStartupTool(self, index):
        self.startup_tool_index = index
        self.qs.beginGroup("Preferences")
        self.qs.setValue("startup_tool", self.startup_tool_index)
        self.qs.endGroup()

    def setZoomSpeed(self, speed):
        self.zoom_speed = speed
        self.qs.beginGroup("Preferences")
        self.qs.setValue("zoom_speed", self.zoom_speed)
        self.qs.endGroup()

    # def setZoomToFitOnHelixAddition(self, checked):
    #     self.zoom_on_helix_add = checked
    #     self.qs.beginGroup("Preferences")
    #     self.qs.setValue("zoom_on_helix_add", self.zoom_on_helix_add)
    #     self.qs.endGroup()

    def getAutoScafType(self):
        return ['Mid-seam', 'Raster'][self.auto_scaf_index]

    def getStartupToolName(self):
        return ['Select', 'Pencil', 'Paint', 'AddSeq'][self.startup_tool_index]

    def addPlugin(self):
        fdialog = QFileDialog(
                    self.widget,
                    "Install Plugin",
                    util.this_path(),
                    "Cadnano Plugins (*.cnp)")
        fdialog.setAcceptMode(QFileDialog.AcceptOpen)
        fdialog.setWindowFlags(Qt.Sheet)
        fdialog.setWindowModality(Qt.WindowModal)
        fdialog.filesSelected.connect(self.addPluginAtPath)
        self.fileopendialog = fdialog
        fdialog.open()

    def addPluginAtPath(self, fname):
        self.fileopendialog.close()
        fname = str(fname[0])
        print("Attempting to open plugin %s" % fname)
        try:
            zf = zipfile.ZipFile(fname, 'r')
        except Exception as e:
            self.failWithMsg("Plugin file seems corrupt: %s."%e)
            return
        tdir = tempfile.mkdtemp()
        try:
            for f in zf.namelist():
                if f.endswith('/'):
                    os.makedirs(os.path.join(tdir,f))
            for f in zf.namelist():
                if not f.endswith('/'):
                    zf.extract(f, tdir)
        except Exception as e:
            self.failWithMsg("Extraction of plugin archive failed: %s."%e)
            return
        files_in_zip = [(f, os.path.join(tdir, f)) for f in os.listdir(tdir)]
        try:
            self.confirmDestructiveIfNecessary(files_in_zip)
            self.removePluginsToBeOverwritten(files_in_zip)
            self.movePluginsIntoPluginsFolder(files_in_zip)
        except OSError:
            print("Couldn't copy files into plugin directory, attempting\
                   again after boosting privileges.")
            if platform.system() == 'Darwin':
                self.darwinAuthedMvPluginsIntoPluginsFolder(files_in_zip)
            elif platform.system() == 'Linux':
                self.linuxAuthedMvPluginsIntoPluginsFolder(files_in_zip)
            else:
                print("Can't boost privelages on platform %s" % platform.system())
        loadedAPlugin = util.loadAllPlugins()
        if not loadedAPlugin:
            print("Unable to load anythng from plugin %s" % fname)
        self.readPreferences()
        shutil.rmtree(tdir)

    def darwinAuthedMvPluginsIntoPluginsFolder(self, files_in_zip):
        envirn={"DST":util.this_path()+'/plugins'}
        srcstr = ''
        for i in range(len(files_in_zip)):
            file_name, file_path = files_in_zip[i]
            srcstr += ' \\"$SRC' + str(i) + '\\"'
            envirn['SRC'+str(i)] = file_path
        proc = subprocess.Popen(['osascript','-e',\
                          'do shell script "cp -fR ' + srcstr +\
                          ' \\"$DST\\"" with administrator privileges'],\
                          env=envirn)
        retval = self.waitForProcExit(proc)
        if retval != 0:
            self.failWithMsg('cp failed with code %i'%retval)

    def linuxAuthedMvPluginsIntoPluginsFolder(self, files_in_zip):
        args = ['gksudo', 'cp', '-fR']
        args.extend(file_path for file_name, file_path in files_in_zip)
        args.append(util.this_path()+'/plugins')
        proc = subprocess.Popen(args)
        retval = self.waitForProcExit(proc)
        if retval != 0:
            self.failWithMsg('cp failed with code %i'%retval)

    def confirmDestructiveIfNecessary(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            if os.path.isfile(target):
                return self.confirmDestructive()
            elif os.path.isdir(target):
                return self.confirmDestructive()

    def confirmDestructive(self):
        mb = QMessageBox(self.widget)
        mb.setIcon(QMessageBox.Warning)
        mb.setInformativeText("The plugin you are trying to install\
has already been installed. Replace the currently installed one?")
        mb.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
        mb.exec_()
        return mb.clickedButton() == mb.button(QMessageBox.Yes)
        
    def removePluginsToBeOverwritten(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            if os.path.isfile(target):
                os.unlink(target)
            elif os.path.isdir(target):
                shutil.rmtree(target)

    def movePluginsIntoPluginsFolder(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            shutil.move(file_path, target)

    def waitForProcExit(self, proc):
        procexit = False
        while not procexit:
            try:
                retval = proc.wait()
                procexit = True
            except OSError as e:
                if e.errno != errno.EINTR:
                    raise ose
        return retval

    def failWithMsg(self, str):
        mb = QMessageBox(self.widget)
        mb.setIcon(QMessageBox.Warning)
        mb.setInformativeText(str)
        mb.buttonClicked.connect(self.closeFailDialog)
        self.fail_message_box = mb
        mb.open()

    def closeFailDialog(self, button):
        self.fail_message_box.close()
        del self.fail_message_box
        self.fail_message_box = None
Esempio n. 4
0
class Preferences(object):
    """docstring for Preferences"""
    def __init__(self):
        self.qs = QSettings()
        self.ui_prefs = Ui_Preferences()
        self.widget = QWidget()
        self.ui_prefs.setupUi(self.widget)
        self.readPreferences()
        self.widget.addAction(self.ui_prefs.actionClose)
        self.ui_prefs.actionClose.triggered.connect(self.hideDialog)
        self.ui_prefs.grid_appearance_type_combo_box.currentIndexChanged.connect(self.setGridAppearanceType)
        self.ui_prefs.zoom_speed_slider.valueChanged.connect(self.setZoomSpeed)
        self.ui_prefs.button_box.clicked.connect(self.handleButtonClick)
        self.ui_prefs.add_plugin_button.clicked.connect(self.addPlugin)
        self.ui_prefs.show_icon_labels.clicked.connect(self.setShowIconLabels)

        self.ui_prefs.grid_appearance_type_combo_box.activated.connect(self.updateGrid)
        self.document = None
    # end def

    def showDialog(self):
        self.readPreferences()
        self.widget.show()  # launch prefs in mode-less dialog
    # end def

    def updateGrid(self, index):
        self.setGridAppearanceType(index)
        value = self.getGridAppearanceType()
        for part in self.document.getParts():
            part.partDocumentSettingChangedSignal.emit(part, 'grid', value)
    # end def

    def hideDialog(self):
        self.widget.hide()
    # end def

    def handleButtonClick(self, button):
        """
        Restores defaults. Other buttons are ignored because connections
        are already set up in qt designer.
        """
        if self.ui_prefs.button_box.buttonRole(button) == QDialogButtonBox.ResetRole:
            self.restoreDefaults()
    # end def

    def readPreferences(self):
        self.qs.beginGroup("Preferences")
        self.grid_appearance_type_index = self.qs.value("grid_appearance_type_index", styles.PREF_GRID_APPEARANCE_TYPE_INDEX)
        self.zoom_speed = self.qs.value("zoom_speed", styles.PREF_ZOOM_SPEED)
        self.show_icon_labels = self.qs.value("ui_icons_labels", styles.PREF_SHOW_ICON_LABELS)
        self.qs.endGroup()
        self.ui_prefs.grid_appearance_type_combo_box.setCurrentIndex(self.grid_appearance_type_index)
        self.ui_prefs.zoom_speed_slider.setProperty("value", self.zoom_speed)
        self.ui_prefs.show_icon_labels.setChecked(self.show_icon_labels)
        ptw = self.ui_prefs.plugin_table_widget
        loaded_plugin_paths = util.loadedPlugins.keys()
        ptw.setRowCount(len(loaded_plugin_paths))
        for i in range(len(loaded_plugin_paths)):
            row = QTableWidgetItem(loaded_plugin_paths[i])
            row.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            ptw.setItem(i, 0, row)
    # end def

    def restoreDefaults(self):
        self.ui_prefs.grid_appearance_type_combo_box.setCurrentIndex(styles.PREF_GRID_APPEARANCE_TYPE_INDEX)
        self.ui_prefs.zoom_speed_slider.setProperty("value", styles.PREF_ZOOM_SPEED)
        self.ui_prefs.show_icon_labels.setChecked(styles.PREF_SHOW_ICON_LABELS)
    # end def

    def setGridAppearanceType(self, grid_appearance_type_index):
        self.grid_appearance_type_index = grid_appearance_type_index
        self.qs.beginGroup("Preferences")
        self.qs.setValue("grid_appearance_type_index", grid_appearance_type_index)
        self.qs.endGroup()
    # end def

    def getGridAppearanceType(self):
        return ['circles', 'lines and points', 'points'][self.grid_appearance_type_index]
    # end def

    def setZoomSpeed(self, speed):
        self.zoom_speed = speed
        self.qs.beginGroup("Preferences")
        self.qs.setValue("zoom_speed", self.zoom_speed)
        self.qs.endGroup()
    # end def

    def setShowIconLabels(self, checked):
        self.show_icon_labels = checked
        self.qs.beginGroup("Preferences")
        self.qs.setValue("ui_icons_labels", self.show_icon_labels)
        self.qs.endGroup()
    # end def

    def addPlugin(self):
        fdialog = QFileDialog(
                    self.widget,
                    "Install Plugin",
                    util.this_path(),
                    "Cadnano Plugins (*.cnp)")
        fdialog.setAcceptMode(QFileDialog.AcceptOpen)
        fdialog.setWindowFlags(Qt.Sheet)
        fdialog.setWindowModality(Qt.WindowModal)
        fdialog.filesSelected.connect(self.addPluginAtPath)
        self.fileopendialog = fdialog
        fdialog.open()
    # end def

    def addPluginAtPath(self, fname):
        self.fileopendialog.close()
        fname = str(fname[0])
        print("Attempting to open plugin %s" % fname)
        try:
            zf = zipfile.ZipFile(fname, 'r')
        except Exception as e:
            self.failWithMsg("Plugin file seems corrupt: %s."%e)
            return
        tdir = tempfile.mkdtemp()
        try:
            for f in zf.namelist():
                if f.endswith('/'):
                    os.makedirs(os.path.join(tdir,f))
            for f in zf.namelist():
                if not f.endswith('/'):
                    zf.extract(f, tdir)
        except Exception as e:
            self.failWithMsg("Extraction of plugin archive failed: %s."%e)
            return
        files_in_zip = [(f, os.path.join(tdir, f)) for f in os.listdir(tdir)]
        try:
            self.confirmDestructiveIfNecessary(files_in_zip)
            self.removePluginsToBeOverwritten(files_in_zip)
            self.movePluginsIntoPluginsFolder(files_in_zip)
        except OSError:
            print("Couldn't copy files into plugin directory, attempting\
                   again after boosting privileges.")
            if platform.system() == 'Darwin':
                self.darwinAuthedMvPluginsIntoPluginsFolder(files_in_zip)
            elif platform.system() == 'Linux':
                self.linuxAuthedMvPluginsIntoPluginsFolder(files_in_zip)
            else:
                print("Can't boost privelages on platform %s" % platform.system())
        loadedAPlugin = util.loadAllPlugins()
        if not loadedAPlugin:
            print("Unable to load anythng from plugin %s" % fname)
        self.readPreferences()
        shutil.rmtree(tdir)
    # end def

    def darwinAuthedMvPluginsIntoPluginsFolder(self, files_in_zip):
        envirn={"DST":util.this_path()+'/plugins'}
        srcstr = ''
        for i in range(len(files_in_zip)):
            file_name, file_path = files_in_zip[i]
            srcstr += ' \\"$SRC' + str(i) + '\\"'
            envirn['SRC'+str(i)] = file_path
        proc = subprocess.Popen(['osascript','-e',\
                          'do shell script "cp -fR ' + srcstr +\
                          ' \\"$DST\\"" with administrator privileges'],\
                          env=envirn)
        retval = self.waitForProcExit(proc)
        if retval != 0:
            self.failWithMsg('cp failed with code %i'%retval)
    # end def

    def linuxAuthedMvPluginsIntoPluginsFolder(self, files_in_zip):
        args = ['gksudo', 'cp', '-fR']
        args.extend(file_path for file_name, file_path in files_in_zip)
        args.append(util.this_path()+'/plugins')
        proc = subprocess.Popen(args)
        retval = self.waitForProcExit(proc)
        if retval != 0:
            self.failWithMsg('cp failed with code %i'%retval)
    # end def

    def confirmDestructiveIfNecessary(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            if os.path.isfile(target):
                return self.confirmDestructive()
            elif os.path.isdir(target):
                return self.confirmDestructive()
    # end def

    def confirmDestructive(self):
        mb = QMessageBox(self.widget)
        mb.setIcon(QMessageBox.Warning)
        mb.setInformativeText("The plugin you are trying to install\
has already been installed. Replace the currently installed one?")
        mb.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
        mb.exec_()
        return mb.clickedButton() == mb.button(QMessageBox.Yes)
    # end def

    def removePluginsToBeOverwritten(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            if os.path.isfile(target):
                os.unlink(target)
            elif os.path.isdir(target):
                shutil.rmtree(target)
    # end def

    def movePluginsIntoPluginsFolder(self, files_in_zip):
        for file_name, file_path in files_in_zip:
            target = os.path.join(util.this_path(), 'plugins', file_name)
            shutil.move(file_path, target)
    # end def

    def waitForProcExit(self, proc):
        procexit = False
        while not procexit:
            try:
                retval = proc.wait()
                procexit = True
            except OSError as e:
                if e.errno != errno.EINTR:
                    raise ose
        return retval
    # end def

    def failWithMsg(self, str):
        mb = QMessageBox(self.widget)
        mb.setIcon(QMessageBox.Warning)
        mb.setInformativeText(str)
        mb.buttonClicked.connect(self.closeFailDialog)
        self.fail_message_box = mb
        mb.open()
    # end def

    def closeFailDialog(self, button):
        self.fail_message_box.close()
        del self.fail_message_box
        self.fail_message_box = None