예제 #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", 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
예제 #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.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
예제 #3
0
class ConnectionWindow:
    """
    Fenetre de connexion en local. Impossible pour le moment de se connecter à un réseau
    et de s'enregistrer dedans 
    """
    current_user = None

    def __init__(self):
        ## Variables autres -----------------------
        global version

        self.colorText = ""
        if sys.platform == "win32":
            self.colorText = "color: #334d9b"

        if choicedBackgroundColor() == 1:
            self.colorText = "color: white;"

        self.version = version
        self.files_enregistrement = None
        self.connected_one = None

        self.ftp = Online()
        # self.ftp.downloadftp("comptes.spi")

        self.ftp.downloadftp("admin.spi")

        try:
            with open("./bin/comptes.spi", "rb") as file:
                depickle = pickle.Unpickler(file)
                self.files_enregistrement = depickle.load()
                Donnees.comptes = self.files_enregistrement

        except:
            with open("./bin/comptes.spi", "wb") as file:
                pickler = pickle.Pickler(file)
                pickler.dump({"uadmin": "padmin"})
                Donnees.comptes, self.files_enregistrement = {
                    "uadmin": "padmin"
                }

        ## APPLICATION ----------------------------

        self.app = QApplication(sys.argv)
        self.win = QWidget()
        x, y = 650, 320
        self.posx, self.posy = center(x, y)
        self.win.setGeometry(self.posx, self.posy, x, y)
        self.win.setWindowTitle("Page de Connexion")
        self.win.setWindowFlag(Qt.FramelessWindowHint)
        self.win.setWindowIcon(QIcon("./bin/icon1.png"))

        self.win.show()

        self.label0 = QLabel(self.win)
        self.label0.move(0, 0)
        self.label0.resize(x, y)
        self.label0.setStyleSheet(getBackgroundColor())
        self.label0.show()

        self.label1 = QLabel(self.win)
        self.label1.setText("Choix")
        self.label1.move(20, 10)
        self.label1.setFont(QFont('Mangal', 80))
        self.label1.setStyleSheet(self.colorText)
        self.label1.adjustSize()
        self.label1.show()

        self.label2 = QLabel(self.win)
        self.label2.setText("Mauvais identifiants, réessayez.")
        self.label2.move(260, 150)
        self.label2.setFont(QFont('Mangal', 11))
        self.label2.adjustSize()
        # self.label2.show()

        self.label3 = QLabel(self.win)
        self.label3.setText("Vérification de version en cours...")
        self.label3.move(20, 190)
        self.label3.setFont(QFont('Mangal', 11))
        self.label3.setStyleSheet(self.colorText)
        self.label3.adjustSize()
        self.label3.show()
        self.threadLabel3 = Thread(None, self.version_search)
        self.threadLabel3.start()

        self.champ1 = QLineEdit(self.win)
        self.champ1.move(20, 140)
        self.champ1.resize(220, 30)
        self.champ1.setFont(QFont('Mangal', 15))
        # self.champ1.show()

        self.champ2 = QLineEdit(self.win)
        self.champ2.setEchoMode(QLineEdit.Password)
        self.champ2.move(20, 180)
        self.champ2.setFont(QFont('Mangal', 15))
        self.champ2.resize(220, 30)
        # self.champ2.show()

        self.bouton1 = QPushButton(self.win)
        self.bouton1.setText(" Se connecter ")
        self.bouton1.move(20, 220)
        self.bouton1.setFont(QFont('Mangal', 20))
        self.bouton1.clicked.connect(self.connection)

        self.openAction = QAction("&ouvrir", self.win)
        self.openAction.setShortcut("Return")
        self.openAction.triggered.connect(self.connection)
        self.win.addAction(self.openAction)
        # self.bouton1.show()

        self.bouton2 = QPushButton(self.win)
        self.bouton2.setText(" S'enregistrer ")
        self.bouton2.move(220, 220)
        self.bouton2.setFont(QFont('Mangal', 20))
        self.bouton2.clicked.connect(self.register_window)
        # self.bouton2.show()

        self.bouton3 = QPushButton(self.win)
        self.bouton3.setText("Fermer")
        self.bouton3.move(20, 270)
        self.bouton3.setFont(QFont('Mangal', 11))
        self.bouton3.clicked.connect(self.quitterNet)
        self.bouton3.show()

        self.bouton4 = QPushButton(self.win)
        self.bouton4.setText("Télécharger ?")
        self.bouton4.move(400, 220)
        self.bouton4.setFont(QFont('Mangal', 20))
        self.bouton4.setStyleSheet(self.colorText)
        self.bouton4.clicked.connect(self.updateDownload)

        self.radio1 = QRadioButton(self.win)
        self.radio1.setText("En Ligne")
        self.radio1.move(120, 275)
        self.radio1.setStyleSheet(self.colorText)
        self.radio1.adjustSize()
        self.radio1.toggled.connect(self.onlineOrNot)
        self.radio1.show()

        self.radio2 = QRadioButton(self.win)
        self.radio2.setText("Hors Ligne")
        self.radio2.move(200, 275)
        self.radio2.setStyleSheet(self.colorText)
        self.radio2.adjustSize()
        self.radio2.toggled.connect(self.onlineOrNot)
        self.radio2.show()

        # --------------- Page d'enregistrement --------------

        self.win2 = QWidget()
        x2, y2 = 270, 400
        self.posx2, self.posy2 = center(x2, y2)
        self.win2.setGeometry(self.posx2, self.posy2, x2, y2)
        self.win2.setWindowTitle("S'enregistrer")
        self.win2.setWindowIcon(QIcon("./bin/icon1.png"))

        self.labelWin21 = QLabel(self.win2)
        self.labelWin21.setText("S'enregistrer")
        self.labelWin21.move(20, 10)
        self.labelWin21.setFont(QFont('Mangal', 30))
        self.labelWin21.adjustSize()
        self.labelWin21.show()

        self.labelWin22 = QLabel(self.win2)
        self.labelWin22.setText("Nouveau nom d'utilisateur")
        self.labelWin22.move(20, 70)
        self.labelWin22.setFont(QFont('Mangal', 12))
        self.labelWin22.adjustSize()
        self.labelWin22.show()

        self.champWin21 = QLineEdit(self.win2)
        self.champWin21.setText("username")
        self.champWin21.move(20, 90)
        self.champWin21.resize(220, 30)
        self.champWin21.show()

        self.labelWin23 = QLabel(self.win2)
        self.labelWin23.setText("Mot de passe")
        self.labelWin23.move(20, 130)
        self.labelWin23.setFont(QFont('Mangal', 12))
        self.labelWin23.adjustSize()
        self.labelWin23.show()

        self.champWin22 = QLineEdit(self.win2)
        self.champWin22.setEchoMode(QLineEdit.Password)
        self.champWin22.move(20, 150)
        self.champWin22.resize(220, 30)
        self.champWin22.show()

        self.labelWin24 = QLabel(self.win2)
        self.labelWin24.setText("Retapez le mot de passe")
        self.labelWin24.move(20, 190)
        self.labelWin24.setFont(QFont('Mangal', 12))
        self.labelWin24.adjustSize()
        self.labelWin24.show()

        self.champWin23 = QLineEdit(self.win2)
        self.champWin23.setEchoMode(QLineEdit.Password)
        self.champWin23.move(20, 210)
        self.champWin23.resize(220, 30)
        self.champWin23.show()

        self.labelWin25 = QLabel(self.win2)
        self.labelWin25.setText("Retapez le mot de passe")
        self.labelWin25.move(20, 250)
        self.labelWin25.setFont(QFont('Mangal', 12))
        self.labelWin25.adjustSize()

        self.boutonWin21 = QPushButton(self.win2)
        self.boutonWin21.setText("S'enregistrer")
        self.boutonWin21.move(20, 300)
        self.boutonWin21.setFont(QFont('Mangal', 13))
        self.boutonWin21.clicked.connect(self.register)
        self.boutonWin21.show()

        self.app.exec_()

    def onlineOrNot(self) -> None:
        if Donnees.online_final == False:
            self.radio1.setCheckable(False)
            self.radio1.setStyleSheet("color : red;")

        if self.radio1.isChecked():

            self.bouton2.show()
            self.bouton1.show()
            self.label1.setText("Connexion")
            self.label1.adjustSize()
            self.bouton1.setText(" Se connecter ")
            self.bouton1.adjustSize()
            self.bouton2.setVisible(True)
            self.champ1.setVisible(True)
            self.champ2.setVisible(True)
            self.label3.setVisible(True)
            self.label3.move(250, 170)
            self.label3.show()
            Donnees.online = True
            self.ftp.downloadftp("comptes.spi")

        elif self.radio2.isChecked():

            self.label1.setText("Offline")
            self.label1.adjustSize()
            self.bouton1.setText(" Se connecter Hors Ligne ")
            self.bouton1.show()
            self.bouton1.adjustSize()
            self.bouton2.setVisible(False)
            self.champ1.setVisible(False)
            self.champ2.setVisible(False)
            self.label3.setVisible(False)

            Donnees.online = False

    def connection(self) -> None:
        """
        Module connexion
        """
        admin = False
        admin_list = None
        if self.radio1.isChecked():
            try:
                with open("./bin/admin.spi", "rb") as adm:
                    pic = pickle.Unpickler(adm)
                    admin_list = pic.load()
                    Donnees.admin = admin_list
            except:
                with open("./bin/admin.spi", "wb") as adm:
                    pic = pickle.Pickler(adm)
                    pic.dump(["uadmin", "Shayajs"])
                    Donnees.admin = ["uadmin", "Shayajs"]

            tha = Thread(None, self._timer_labe2)
            try:
                if self.files_enregistrement[
                        self.champ1.text()] and self.files_enregistrement[
                            self.champ1.text()] == self.champ2.text():

                    self.label2.setText("Connecté !")
                    self.label2.setStyleSheet("color : green;")
                    self.label2.adjustSize()
                    self.label2.show()
                    self.connected_one = (self.champ1.text(), True)

                    if self.champ1.text() in admin_list:
                        admin = True

                    Donnees.current_user = {
                        "user": self.champ1.text(),
                        "admin": admin
                    }

                    self.quitter()
                    self.win.setVisible(False)

                else:

                    self.label2.setStyleSheet("color : red;")
                    self.label2.show()
                    tha.start()

            except:
                self.label2.show()
                self.label2.setStyleSheet("color : red;")
                tha.start()
        elif self.radio2.isChecked():
            self.quitter()
            self.win.setVisible(False)
            Donnees.current_user = {"user": "******", "admin": False}

    def version_search(self) -> None:
        """
        Vérifie si le logiciel est à jour
        """
        a = 0
        b = 0

        try:
            verif = verif_ver()

            splited1 = verif.split(".")
            splited2 = self.version.split(".")

            for i in range(0, 3):
                if int(splited1[i]) == int(splited2[i]):
                    pass
                elif int(splited1[i]) > int(splited2[i]):
                    a = 1
                    break
                elif int(splited1[i]) < int(splited2[i]):
                    b = 1
                    break

            if b == a:
                self.label3.setText("Vous êtes à jour")
                self.label3.adjustSize()
                self.label3.setStyleSheet("color: green;")

            elif b < a:
                self.label3.setText(f"La version {verif} est disponible !")
                self.label3.adjustSize()
                self.label3.setStyleSheet("color: steelblue;")
                self.bouton4.show()

            elif b > a:
                # self.label3.move(250, 170)
                self.label3.setText(
                    f"Votre version ({self.version}) est une version beta !\n(Version en ligne : {verif})"
                )
                self.label3.setStyleSheet("color: goldenrod;")
                self.label3.adjustSize()

            else:
                self.label3.setText(
                    "Impossible de vérifier les mises à jours.")
        except:
            self.label3.setText("Impossible de vérifier les mises à jours.")
            self.label3.adjustSize()

    def _timer_labe2(self) -> None:
        """
        Permettre un affichage limité de l'étiquette de connexion
        """
        sleep(2.5)
        self.label2.setVisible(False)
        self.win2.setVisible(False)

    def quitter(self) -> None:
        """
        Quitter l'application
        """
        self.win.setVisible(False)
        # self.app.quit()
        qApp.quit()

    def quitterNet(self):
        """
        Quitter l'application
        """
        Donnees.current_user = {"user": None, "admin": False}
        self.win.setVisible(False)
        # self.app.quit()
        qApp.quit()
        del self

    def register_window(self) -> None:
        """
        Ouvrir la page d'enregistrement
        """
        try:
            self.win2.show()
            self.champWin21.setText("")
            self.champWin22.setText("")
            self.champWin23.setText("")
            self.labelWin25.setVisible(False)
        except:
            self.label2.setText("Une erreur est survenue")
            threadExceptLabel2 = Thread(None, self._timer_labe2)
            threadExceptLabel2.start()
            exceptionRaised()

    def register(self):
        """
        Page d'enregistrement
        """
        a = 0
        try:
            self.files_enregistrement[self.champWin21.text()]
            a = 1
        except:
            a = 2

        if a == 1:
            self.labelWin25.setText("Ce compte est déjà enregistré !")
            self.labelWin25.setStyleSheet("color: red;")
            self.labelWin25.adjustSize()
            self.labelWin25.show()

        elif a == 2:
            if self.champWin22.text() == self.champWin23.text() and (
                    self.champWin22.text() != ""
                    and self.champWin23.text() != ""):

                self.files_enregistrement[
                    self.champWin21.text()] = self.champWin22.text()

                self.labelWin25.setText("Enregistrement en cours ...")

                with open("./bin/comptes.spi", "wb") as file:
                    pickler = pickle.Pickler(file)
                    pickler.dump(self.files_enregistrement)

                sleep(1)

                Donnees.comptes = self.files_enregistrement
                self.ftp.uploadftp("comptes.spi")

                self.labelWin25.setText("Enregistré")
                self.labelWin25.setStyleSheet("color: green;")
                self.labelWin25.adjustSize()
                self.labelWin25.show()

            elif self.champWin22.text() != self.champWin23.text():
                self.labelWin25.setText(
                    "Vous n'avez pas renseigné deux\nfois le même mot de passe !"
                )
                self.labelWin25.setStyleSheet("color: red;")
                self.labelWin25.adjustSize()
                self.labelWin25.show()

            elif self.champWin22.text() == "" and self.champWin23.text() == "":
                self.labelWin25.setText("Renseignez un mot de passe")
                self.labelWin25.setStyleSheet("color: red;")
                self.labelWin25.adjustSize()
                self.labelWin25.show()

            else:
                self.labelWin25.setText("Une erreur s'est déroulée")
                self.labelWin25.setStyleSheet("color: steelblue;")
                self.labelWin25.adjustSize()
                self.labelWin25.show()

    def updateThread(self):

        self.champ1.setVisible(False)
        self.champ2.setVisible(False)
        self.bouton4.setVisible(False)
        self.label3.setText("Téléchargement en cours...")
        self.label3.setFont(QFont('Mangal', 30))
        self.label3.move(30, 140)
        self.label3.adjustSize()
        self.bouton1.setVisible(False)
        self.bouton2.setVisible(False)
        self.radio1.setVisible(False)
        self.radio2.setVisible(False)
        self.bouton3.setText("Annuler")

    def updateStateTwo(self):
        self.label3.setText("Installation en cours")

    def updateDownload(self):

        sender = Recver()
        tha = Thread(None, self.updateThread)
        tha.start()
        thb = Thread(None, sender.recvtd2, None, (self.label3, ))

        try:
            thb.start()
        except:
            self.label3.setStyleSheet("color: red;")
            self.label3.setText("Le serveur est down")

    def __del__(self):
        print("Sortie sans connexion")
예제 #4
0
class Preferences(object):
    """Connect UI elements to the backend."""
    def __init__(self):
        self.qs = QSettings("cadnano.org", "cadnano2.5")
        #        print('Settings are stored at %s' % self.qs.fileName())
        self.ui_prefs = Ui_Preferences()
        self.widget = QWidget()
        self.ui_prefs.setupUi(self.widget)
        self.readPreferences()
        self.widget.addAction(self.ui_prefs.actionClose)
        self.connectSignals()

        self.document = None

    # end def

    ### SUPPORT METHODS ###
    def connectSignals(self):
        ui_prefs = self.ui_prefs
        ui_prefs.actionClose.triggered.connect(self.hideDialog)
        ui_prefs.button_box.clicked.connect(self.handleButtonClick)
        ui_prefs.enabled_orthoview_combo_box.currentIndexChanged.connect(
            self.orthoviewChangedSlot)
        ui_prefs.gridview_style_combo_box.currentIndexChanged.connect(
            self.gridviewStyleChangedSlot)
        ui_prefs.show_icon_labels.clicked.connect(self.setShowIconLabels)
        ui_prefs.zoom_speed_slider.valueChanged.connect(self.setZoomSpeed)

    # end def

    def readPreferences(self):
        """Read the preferences from self.qs (a QSettings object) and set the
        preferences accordingly in the UI popup.
        """
        qs = self.qs
        qs.beginGroup(PREFS_GROUP_NAME)
        self.gridview_style_idx = int(
            qs.value(GRIDVIEW_STYLE_KEY, GRIDVIEW_STYLE_DEFAULT))
        self.orthoview_style_idx = int(
            qs.value(ORTHOVIEW_KEY, ORTHOVIEW_DEFAULT))
        self.zoom_speed = int(qs.value(ZOOM_SPEED_KEY, ZOOM_SPEED_DEFAULT))
        self.show_icon_labels = qs.value(SHOW_ICON_LABELS_KEY,
                                         SHOW_ICON_LABELS_DEFAULT)
        qs.endGroup()
        ui_prefs = self.ui_prefs
        ui_prefs.gridview_style_combo_box.setCurrentIndex(
            self.gridview_style_idx)
        # print(self.orthoview_style_idx, ORTHOVIEW_DEFAULT, ORTHOVIEW_DEFAULT)
        ui_prefs.enabled_orthoview_combo_box.setCurrentIndex(
            self.orthoview_style_idx)
        ui_prefs.show_icon_labels.setChecked(self.show_icon_labels)
        ui_prefs.zoom_speed_slider.setProperty("value", self.zoom_speed)

    # end def

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

    # end def

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

    # end def

    def gridviewStyleChangedSlot(self, index):
        """Update the grid when the type of grid is changed.

        Calls setGridviewStyleIdx and updates each part of the document
        accordingly.
        """
        gridview_style = GRIDVIEW_STYLES[self.gridview_style_idx]
        for part in self.document.getParts():
            part.partDocumentSettingChangedSignal.emit(part, 'grid',
                                                       gridview_style)

    # end def

    def handleButtonClick(self, button):
        """Used only to restore 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 restoreDefaults(self):
        """Restore the default settings."""
        gridview_style_idx = GRIDVIEW_STYLE_DEFAULT
        orthoview_idx = ORTHOVIEW_DEFAULT
        ui_prefs = self.ui_prefs
        ui_prefs.gridview_style_combo_box.setCurrentIndex(gridview_style_idx)
        ui_prefs.enabled_orthoview_combo_box.setCurrentIndex(orthoview_idx)
        ui_prefs.zoom_speed_slider.setProperty("value", ZOOM_SPEED_DEFAULT)
        ui_prefs.show_icon_labels.setChecked(SHOW_ICON_LABELS_DEFAULT)

    # end def

    def setGridviewStyleIdx(self, value):
        """Select the type of grid that should be displayed."""
        self.gridview_style_idx = value
        self.qs.beginGroup(PREFS_GROUP_NAME)
        self.qs.setValue(GRIDVIEW_STYLE_KEY, value)
        self.qs.endGroup()

    # end def

    def orthoviewChangedSlot(self, view_idx: EnumType):
        """Handles index changes to enabled_orthoview_combo_box.
        Saves the setting and notifies the doc controller to toggle
        visibilty of appropriate 2D orthographic view (sliceview or gridview).
        """
        assert isinstance(view_idx, EnumType)
        new_orthoview_style_idx = view_idx
        assert new_orthoview_style_idx in (OrthoViewEnum.GRID,
                                           OrthoViewEnum.SLICE)

        self.orthoview_style_idx = new_orthoview_style_idx
        self.qs.beginGroup(PREFS_GROUP_NAME)
        self.qs.setValue(ORTHOVIEW_KEY, new_orthoview_style_idx)
        self.qs.endGroup()

        the_app = app()
        if len(the_app.cnmain_windows) > 0:
            app_window = the_app.cnmain_windows[0]
            app_window.setSliceOrGridViewVisible(self.orthoview_style_idx)

    # end def

    def setShowIconLabels(self, value):
        self.show_icon_labels = value
        self.qs.beginGroup(PREFS_GROUP_NAME)
        self.qs.setValue(SHOW_ICON_LABELS_KEY, value)
        self.qs.endGroup()

    # end def

    def setZoomSpeed(self, value):
        self.zoom_speed = value
        self.qs.beginGroup(PREFS_GROUP_NAME)
        self.qs.setValue(ZOOM_SPEED_KEY, value)
        self.qs.endGroup()
예제 #5
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
예제 #6
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
예제 #7
0
    def __init__(self, parent=None, wflags=Qt.WindowFlags(), **kw):
        # the current button
        self._ActiveButton = Qt.NoButton

        # private attributes
        self.__saveX = 0
        self.__saveY = 0
        self.__saveModifiers = Qt.NoModifier
        self.__saveButtons = Qt.NoButton
        self.__fullScreenAction = QAction(parent)

        # do special handling of some keywords:
        # stereo, rw

        stereo = 0

        if "stereo" in kw:
            if kw["stereo"]:
                stereo = 1

        rw = None

        if "rw" in kw:
            rw = kw["rw"]

        # create qt-level widget
        QWidget.__init__(self, parent, wflags | Qt.MSWindowsOwnDC)

        # Add full screen shortcut
        self.__fullScreenAction.setShortcut(QKeySequence.FullScreen)
        self.__fullScreenAction.setCheckable(True)
        self.__fullScreenAction.setChecked(False)
        self.__fullScreenAction.triggered.connect(self.toggleFullScreen)
        QWidget.addAction(self, self.__fullScreenAction)

        if rw:  # user-supplied render window
            self._RenderWindow = rw
        else:
            self._RenderWindow = vtk.vtkRenderWindow()

        WId = self.winId()

        if type(WId).__name__ == "PyCObject":
            from ctypes import pythonapi, c_void_p, py_object

            pythonapi.PyCObject_AsVoidPtr.restype = c_void_p
            pythonapi.PyCObject_AsVoidPtr.argtypes = [py_object]

            WId = pythonapi.PyCObject_AsVoidPtr(WId)

        self._RenderWindow.SetWindowInfo(str(int(WId)))

        if stereo:  # stereo mode
            self._RenderWindow.StereoCapableWindowOn()
            self._RenderWindow.SetStereoTypeToCrystalEyes()

        if "iren" in kw:
            self._Iren = kw["iren"]
        else:
            self._Iren = vtk.vtkGenericRenderWindowInteractor()
            self._Iren.SetRenderWindow(self._RenderWindow)

        # do all the necessary qt setup
        self.setAttribute(Qt.WA_OpaquePaintEvent)
        self.setAttribute(Qt.WA_PaintOnScreen)
        self.setMouseTracking(True)  # get all mouse events
        self.setFocusPolicy(Qt.WheelFocus)
        self.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))

        self._Timer = QTimer(self)
        self._Timer.timeout.connect(self.TimerEvent)

        self._Iren.AddObserver("CreateTimerEvent", self.CreateTimer)
        self._Iren.AddObserver("DestroyTimerEvent", self.DestroyTimer)
        self._Iren.GetRenderWindow().AddObserver("CursorChangedEvent",
                                                 self.CursorChangedEvent)

        # Create a hidden child widget and connect its destroyed signal to its
        # parent ``Finalize`` slot. The hidden children will be destroyed before
        # its parent thus allowing cleanup of VTK elements.
        # self._hidden = QtGui.QWidget(self)
        self._hidden = QWidget(self)
        self._hidden.hide()
        self._hidden.destroyed.connect(self.Finalize)
예제 #8
0
 def build_placeholder(self, parent: QtWidgets.QWidget,
                       item: MenuItem) -> None:
     action = QtWidgets.QAction(parent)
     action.setText(item.label)
     action.setEnabled(False)
     parent.addAction(action)
예제 #9
0
 def build_themes(self, parent: QtWidgets.QWidget, item: MenuItem) -> None:
     if item.label:
         parent = parent.addMenu(item.label)
     for theme in BaseTheme.__subclasses__():
         action = LoadThemeAction(self.api, theme, parent)
         parent.addAction(action)