def word_dialog(self, msg): response = QInputDialog.getText(self.top_level_window(), "Ledger Wallet Authentication", msg, QLineEdit.Password) if not response[1]: self.word = None else: self.word = str(response[0]) self.done.set()
def anchor_clicked(self, qurl): url = qurl.toString() if url.startswith('err:'): errnum = int(url[4:]) err = self.errors[errnum] newurl, ok = QInputDialog.getText(self, _('Fix URL'), _('Enter the corrected URL:') + '\xa0'*40, text=err[2]) if not ok: return nmap = defaultdict(set) for name, href in {(l[0], l[1]) for l in err[0]}: nmap[name].add(href) for name, hrefs in nmap.iteritems(): raw = oraw = get_data(name) for href in hrefs: raw = raw.replace(href, newurl) if raw != oraw: set_data(name, raw) self.fixed_errors.add(errnum) self.populate_results() elif url.startswith('loc:'): lnum, name = url[4:].partition(',')[::2] lnum = int(lnum or 1) editor = get_boss().edit_file(name) if lnum and editor is not None and editor.has_line_numbers: editor.current_line = lnum
def create_folder(self, item): text, ok = QInputDialog.getText(self, _('Folder name'), _('Enter a name for the new folder')) if ok and unicode_type(text): c = QTreeWidgetItem(item, (unicode_type(text),)) c.setIcon(0, QIcon(I('mimetypes/dir.png'))) for item in self.folders.selectedItems(): item.setSelected(False) c.setSelected(True) self.folders.setCurrentItem(c)
def change_dictionary_website(self): idx = self.dictionary_list.currentIndex() if idx.isValid(): lc, url = idx.data(Qt.UserRole) url, ok = QInputDialog.getText(self, _("Enter new website"), "URL:", text=url) if ok: wl = self.word_lookups wl[lc] = url self.word_lookups = wl
def request_change_ext(self): names = self.request_rename_common() if names is not None: text, ok = QInputDialog.getText(self, _('Rename files'), _('New file extension:')) if ok and text: ext = text.lstrip('.') def change_name(name): base = posixpath.splitext(name)[0] return base + '.' + ext name_map = {n:change_name(n) for n in names} self.bulk_rename_requested.emit(name_map)
def save_theme(self): themename, ok = QInputDialog.getText(self, _("Theme name"), _("Choose a name for this theme")) if not ok: return themename = unicode(themename).strip() if not themename: return c = config("") c.add_opt("theme_name_xxx", default=themename) self.save_options(c) self.themes["theme_" + themename] = c.src self.init_load_themes() self.theming_message.setText(_("Saved settings as the theme named: %s") % themename)
def save_theme(self): themename, ok = QInputDialog.getText(self, _('Theme name'), _('Choose a name for this theme')) if not ok: return themename = unicode(themename).strip() if not themename: return c = config('') c.add_opt('theme_name_xxx', default=themename) self.save_options(c) self.themes['theme_'+themename] = c.src self.init_load_themes() self.theming_message.setText(_('Saved settings as the theme named: %s')% themename)
def save_settings(self): xpaths = self.xpaths if not xpaths: return error_dialog(self, _('No XPaths'), _('No XPaths have been entered'), show=True) if not self.check(): return name, ok = QInputDialog.getText(self, _('Choose name'), _('Choose a name for these settings')) if ok: name = unicode(name).strip() if name: saved = gprefs.get('xpath_toc_settings', {}) saved[name] = {i:x for i, x in enumerate(xpaths)} gprefs.set('xpath_toc_settings', saved) self.setup_load_button()
def save_settings(self): if not self.something_selected: return error_dialog(self, _('No actions selected'), _('You must select at least one action before saving'), show=True) name, ok = QInputDialog.getText(self, _('Choose name'), _('Choose a name for these settings')) if ok: name = unicode_type(name).strip() if name: settings = {ac:getattr(self, 'opt_'+ac).isChecked() for ac in self.all_actions} saved = gprefs.get('polish_settings', {}) saved[name] = settings gprefs.set('polish_settings', saved) self.setup_load_button()
def add_mapping(self): new_genre_name, ok = QInputDialog.getText(self, 'Add new mapping', 'Enter a Goodreads genre name to create a mapping for:', text='') if not ok: # Operation cancelled return new_genre_name = unicode(new_genre_name).strip() if not new_genre_name: return # Verify it does not clash with any other mappings in the list data = self.edit_table.get_data() for genre_name in data.keys(): if genre_name.lower() == new_genre_name.lower(): return error_dialog(self, 'Add Failed', 'A genre with the same name already exists', show=True) data[new_genre_name] = [] self.edit_table.populate_table(data) self.edit_table.select_genre(new_genre_name)
def bookmark(self, *args): num = 1 bm = None while True: bm = _("Bookmark #%d") % num if bm not in self.existing_bookmarks: break num += 1 title, ok = QInputDialog.getText(self, _("Add bookmark"), _("Enter title for bookmark:"), text=bm) title = unicode(title).strip() if ok and title: bm = self.view.bookmark() bm["spine"] = self.current_index bm["title"] = title self.iterator.add_bookmark(bm) self.set_bookmarks(self.iterator.bookmarks) self.bookmarks.set_current_bookmark(bm)
def rename_requested(self, name, location): LibraryDatabase = db_class() loc = location.replace('/', os.sep) base = os.path.dirname(loc) old_name = name.replace('&&', '&') newname, ok = QInputDialog.getText(self.gui, _('Rename') + ' ' + old_name, '<p>'+_( 'Choose a new name for the library <b>%s</b>. ')%name + '<p>'+_( 'Note that the actual library folder will be renamed.'), text=old_name) newname = sanitize_file_name(unicode_type(newname)) if not ok or not newname or newname == old_name: return newloc = os.path.join(base, newname) if os.path.exists(newloc): return error_dialog(self.gui, _('Already exists'), _('The folder %s already exists. Delete it first.') % newloc, show=True) if (iswindows and len(newloc) > LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT): return error_dialog(self.gui, _('Too long'), _('Path to library too long. Must be less than' ' %d characters.')%LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT, show=True) if not os.path.exists(loc): error_dialog(self.gui, _('Not found'), _('Cannot rename as no library was found at %s. ' 'Try switching to this library first, then switch back ' 'and retry the renaming.')%loc, show=True) return self.gui.library_broker.remove_library(loc) try: os.rename(loc, newloc) except: import traceback det_msg = 'Location: %r New Location: %r\n%s'%(loc, newloc, traceback.format_exc()) error_dialog(self.gui, _('Rename failed'), _('Failed to rename the library at %s. ' 'The most common cause for this is if one of the files' ' in the library is open in another program.') % loc, det_msg=det_msg, show=True) return self.stats.rename(location, newloc) self.build_menus() self.gui.iactions['Copy To Library'].build_menus()
def save_ruleset(self): if not self.rules: error_dialog(self, _('No rules'), _( 'Cannot save as no rules have been created'), show=True) return text, ok = QInputDialog.getText(self, _('Save ruleset as'), _( 'Enter a name for this ruleset:'), text=self.loaded_ruleset or '') if ok and text: if self.loaded_ruleset and text == self.loaded_ruleset: if not question_dialog(self, _('Are you sure?'), _( 'A ruleset with the name "%s" already exists, do you want to replace it?') % text): return self.loaded_ruleset = text rules = self.rules if rules: tag_maps[text] = self.rules elif text in tag_maps: del tag_maps[text] self.build_load_menu()
def save_settings(self): if not self.something_selected: return error_dialog( self, _('No actions selected'), _('You must select at least one action before saving'), show=True) name, ok = QInputDialog.getText(self, _('Choose name'), _('Choose a name for these settings')) if ok: name = unicode_type(name).strip() if name: settings = { ac: getattr(self, 'opt_' + ac).isChecked() for ac in self.all_actions } saved = gprefs.get('polish_settings', {}) saved[name] = settings gprefs.set('polish_settings', saved) self.setup_load_button()
def bookmark(self, *args): num = 1 bm = None while True: bm = _('Bookmark #%d') % num if bm not in self.existing_bookmarks: break num += 1 title, ok = QInputDialog.getText(self, _('Add bookmark'), _('Enter title for bookmark:'), text=bm) title = unicode(title).strip() if ok and title: bm = self.view.bookmark() bm['spine'] = self.current_index bm['title'] = title self.iterator.add_bookmark(bm) self.set_bookmarks(self.iterator.bookmarks) self.bookmarks.set_current_bookmark(bm)
def rename_genre(self): selected_genre = self.edit_table.get_selected_genre() if not selected_genre: return new_genre_name, ok = QInputDialog.getText(self, 'Add new mapping', 'Enter a Goodreads genre name to create a mapping for:', text=selected_genre) if not ok: # Operation cancelled return new_genre_name = unicode(new_genre_name).strip() if not new_genre_name or new_genre_name == selected_genre: return data = self.edit_table.get_data() if new_genre_name.lower() != selected_genre.lower(): # Verify it does not clash with any other mappings in the list for genre_name in data.keys(): if genre_name.lower() == new_genre_name.lower(): return error_dialog(self, 'Rename Failed', 'A genre with the same name already exists', show=True) data[new_genre_name] = data[selected_genre] del data[selected_genre] self.edit_table.populate_table(data) self.edit_table.select_genre(new_genre_name)
def rename_view(self): if not self.view_name != None: return # Display a prompt allowing user to specify a rename view old_view_name = self.view_name new_view_name, ok = QInputDialog.getText( self, 'Rename view', 'Enter a new display name for this view:', text=old_view_name) if not ok: # Operation cancelled return new_view_name = unicode(new_view_name).strip() if new_view_name == old_view_name: return # Verify it does not clash with any other views in the list for view_name in self.views.keys(): if view_name == old_view_name: continue if view_name.lower() == new_view_name.lower(): return error_dialog(self, 'Add Failed', 'A view with the same name already exists', show=True) # Ensure any changes are persisted self.persist_view_config() view_info = self.views[old_view_name] del self.views[old_view_name] self.view_name = new_view_name self.views[new_view_name] = view_info # Now update the views combobox self.select_view_combo.populate_combo(self.views, new_view_name) self.select_view_combo_index_changed(save_previous=False) if unicode(self.auto_view_combo.currentText()) == old_view_name: self.auto_view_combo.populate_combo(self.views, new_view_name) else: self.auto_view_combo.populate_combo(self.views)
def save_settings(self): xpaths = self.xpaths if not xpaths: return error_dialog(self, _('No XPaths'), _('No XPaths have been entered'), show=True) if not self.check(): return name, ok = QInputDialog.getText(self, _('Choose name'), _('Choose a name for these settings')) if ok: name = unicode_type(name).strip() if name: saved = self.prefs.get('xpath_toc_settings', {}) # in JSON all keys have to be strings saved[name] = { unicode_type(i): x for i, x in enumerate(xpaths) } self.prefs.set('xpath_toc_settings', saved) self.setup_load_button()
def impotQQMusic(self): num, ok = QInputDialog.getText(self, '抓取QQ音乐歌词', '输入QQ音乐歌曲链接:') if ok and num: try: data = getQQMLyric(num) if (data['lyric']): ori = base64.b64decode(data['lyric']).decode('utf8') if 'trans' in data and len(data['trans']) > 1: trans = base64.b64decode(data['trans']).decode('utf8') ori, trans = fixlrcs(ori, trans) self.textEdit_2.setText(trans) else: self.textEdit_2.setText("") self.textEdit.setText(ori) except (UnicodeDecodeError, json.decoder.JSONDecodeError, KeyError, TypeError): QMessageBox.warning(self, '提示', '获取QQ音乐歌词失败', QMessageBox.Cancel) pass
def impotNetease(self): num, ok = QInputDialog.getText(self, '抓取网易云音乐歌词', '输入网易云音乐歌曲链接或ID:') if ok and num: try: data = getNCMLyric(num) if (data['lrc']['lyric']): ori = data['lrc']['lyric'] if 'lyric' in data['tlyric'] and data['tlyric']['lyric']: trans = data['tlyric']['lyric'] ori, trans = fixlrcs(ori, trans) self.textEdit_2.setText(trans) else: self.textEdit_2.setText("") self.textEdit.setText(ori) except (UnicodeDecodeError, json.decoder.JSONDecodeError, KeyError, TypeError): QMessageBox.warning(self, '提示', '获取网易云歌词失败', QMessageBox.Cancel) pass
def create_server_configuration(self): name = QInputDialog.getText(self, 'Python Server Gui Dialog', 'Please give this new server configuration a name', QLineEdit.Normal)[0] if name == '': return jar_file = QFileDialog.getOpenFileName(self, 'Select Jar File', '', 'JAR File (*.jar)')[0] if jar_file == '': return file = '\\'.join(jar_file.split('/')) min_ram = 0 max_ram = 0 server = { "min-ram": min_ram, "max-ram": max_ram, "java-version": self.java_version_combo_box.currentText(), "jar-file": file, "custom-arguments": None } self.max_ram_slider.setValue(0) self.min_ram_slider.setValue(0) self.json.create_server(name, server) self.current_config_combo_box.clear self.current_config_combo_box.addItems(self.json.servers().keys()) self.current_config_combo_box.setCurrentIndex(self.current_config_combo_box.findText(name))
def onClickEdit(self): if (self.ui.cBTable.currentIndex() == 0): indMovie = self.ui.tableView.model().index( self.ui.tableView.currentIndex().row(), 0, QModelIndex()) oldMovieName = self.ui.tableView.model().data(indMovie) indDirector = self.ui.tableView.model().index( self.ui.tableView.currentIndex().row(), 1, QModelIndex()) oldDirectorName = self.ui.tableView.model().data(indDirector) indActors = self.ui.tableView.model().index( self.ui.tableView.currentIndex().row(), 2, QModelIndex()) oldActorsName = self.ui.tableView.model().data(indActors) if (self.ui.tableView.currentIndex() == indMovie): movieName, ok = QInputDialog.getText( self, 'Редактирование', 'Введите название фильма') if (not (ok)): return query = QtSql.QSqlQuery() query.prepare("{CALL editMovie(?, ?)}") query.bindValue(0, oldMovieName) query.bindValue(1, movieName) query.exec() if (self.ui.tableView.currentIndex() == indDirector): directorName, ok = QInputDialog.getText( self, 'Редактирование', 'Введите имя режиссера') if (not (ok)): return query = QtSql.QSqlQuery() query.prepare("{CALL editMovieDirector(?, ?)}") query.bindValue(0, directorName) query.bindValue(1, oldMovieName) query.exec() if (self.ui.tableView.currentIndex() == indActors): actorsName, ok = QInputDialog.getText( self, 'Редактирование', 'Введите имя актеров через запятую') if (not (ok)): return query = QtSql.QSqlQuery() actorsNameList = oldActorsName.split(', ') for actorNameStr in actorsNameList: query.prepare("{CALL deleteActorsMovie(?, ?)}") query.bindValue(0, oldMovieName) query.bindValue(1, actorNameStr) query.exec() actorsNameList = actorsName.split(', ') for actorNameStr in actorsNameList: query.prepare("{CALL editMovieActors(?, ?, ?)}") query.bindValue(0, actorNameStr) query.bindValue(1, oldActorsName) query.bindValue(2, oldMovieName) query.exec() if (self.ui.cBTable.currentIndex() == 1): ind = self.ui.tableView.model().index( self.ui.tableView.currentIndex().row(), 0, QModelIndex()) directorName, ok = QInputDialog.getText(self, 'Редактирование', 'Введите имя режиссера') if (not (ok)): return query = QtSql.QSqlQuery() query.prepare("{CALL editDirector(?, ?)}") query.bindValue(0, self.ui.tableView.model().data(ind)) query.bindValue(1, directorName) query.exec() if (self.ui.cBTable.currentIndex() == 2): ind = self.ui.tableView.model().index( self.ui.tableView.currentIndex().row(), 0, QModelIndex()) actorName, ok = QInputDialog.getText(self, 'Редактирование', 'Введите имя актера') if (not (ok)): return query = QtSql.QSqlQuery() query.prepare("{CALL editActor(?, ?)}") query.bindValue(0, self.ui.tableView.model().data(ind)) query.bindValue(1, actorName) query.exec()
def save_view(self, create=False, save_sort=False): if self.current_view is None and not create: return library_config = cfg.get_library_config(self.gui.current_db) views = library_config[cfg.KEY_VIEWS] new_view_name = None if create: new_view_name, ok = QInputDialog.getText( self.gui, 'Add new view', 'Enter a unique display name for this view:', text='Default') if not ok: # Operation cancelled return new_view_name = unicode(new_view_name).strip() # Verify it does not clash with any other views in the list for view_name in views.keys(): if view_name.lower() == new_view_name.lower(): return error_dialog( self.gui, 'Add Failed', 'A view with the same name already exists', show=True) view_info = cfg.get_empty_view() if self.has_pin_view: view_info[ cfg. KEY_APPLY_PIN_COLUMNS] = self.gui.library_view.pin_view.isVisible( ) views[new_view_name] = view_info else: view_info = views[self.current_view] save_sort = save_sort or create save_columns = not save_sort or create # print("pre-view_info:") # pp.pprint(view_info) state = self.gui.library_view.get_state() # print("state:") # pp.pprint(state) if save_sort: new_config_sort = [] already_sorted = {} TF_map = { True: 0, False: 1 } # no idea why VM records asc/desc that way... for col, direct in state['sort_history']: if col not in already_sorted: already_sorted[col] = direct new_config_sort.append([unicode(col), TF_map[direct]]) view_info[cfg.KEY_SORT] = new_config_sort if save_columns: if self.has_pin_view: view_info[ cfg. KEY_APPLY_PIN_COLUMNS] = self.gui.library_view.pin_view.isVisible( ) # only save pin columns if apply *and* currently showing. if view_info.get( cfg.KEY_APPLY_PIN_COLUMNS, False) and self.gui.library_view.pin_view.isVisible(): pin_state = self.gui.library_view.pin_view.get_state() # print("pin_state:") # pp.pprint(pin_state) new_config_cols = self.contruct_config_cols( cfg.KEY_PIN_COLUMNS, view_info, pin_state) # Persist the updated pin view column info view_info[cfg.KEY_PIN_COLUMNS] = new_config_cols # Save splitter location view_info[ cfg. KEY_PIN_SPLITTER_STATE] = self.get_pin_splitter_state( ) new_config_cols = self.contruct_config_cols( cfg.KEY_COLUMNS, view_info, state) # Persist the updated view column info view_info[cfg.KEY_COLUMNS] = new_config_cols library_config[cfg.KEY_VIEWS] = views cfg.set_library_config(self.gui.current_db, library_config) # print("post-view_info:") # pp.pprint(view_info) if create: self.rebuild_menus() self.switch_view(new_view_name)
def delete_sample(self, sample, nr, project, status): """delete a sample from the database & file system """ self.log.debug("Attempting to delete sample '{}' allele {} of project '{}' from database...".format(sample, nr, project)) if self.settings["login"] == "admin": pass else: pwd, ok = QInputDialog.getText(self, "Enter Password", "Please provide password:"******"ichdarfdas": pass else: return else: return self.log.debug("Asking for confirmation before deleting allele...") reply = QMessageBox.question(self, 'Message', "Are you really sure you want to delete sample {} allele #{} from project {}?".format(sample, nr, project), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: # delete from database: delete_q_alleles = "delete from alleles where sample_id_int = '{}' and allele_nr = {} and project_name = '{}'".format(sample, nr, project) success, _ = db_internal.execute_query(delete_q_alleles, 0, self.log, "Deleting sample {} allele #{} from ALLELES table".format(sample, nr), "Sample Deletion Error", self) if success: self.log.debug("\t=> Successfully deleted sample from table ALLELES") more_projects_query = "select project_name from alleles where sample_id_int = '{}'".format(sample) success, data = db_internal.execute_query(more_projects_query, 1, self.log, "Finding more rows with sample {} in ALLELES table".format(sample), "Sample Deletion Error", self) single_allele = False if success: if not data: # sample was only contained in this project and only had one allele single_allele = True delete_q_samples = "delete from SAMPLES where sample_id_int = '{}'".format(sample) success, _ = db_internal.execute_query(delete_q_samples, 0, self.log, "Deleting sample {} from SAMPLES table".format(sample), "Sample Deletion Error", self) if success: self.log.debug("\t=> Successfully deleted sample from table SAMPLES") files_q = "select raw_file, fasta, blast_xml, ena_file, ena_response_file, ipd_submission_file from FILES where sample_id_int = '{}' and allele_nr = {}".format(sample, nr) success, files = db_internal.execute_query(files_q, 6, self.log, "Getting files of sample {} #{} from FILES table".format(sample, nr), "Sample Deletion Error", self) if success: delete_q_files = "delete from FILES where sample_id_int = '{}' and allele_nr = {}".format(sample, nr) success, _ = db_internal.execute_query(delete_q_files, 0, self.log, "Deleting sample {} from FILES table".format(sample), "Sample Deletion Error", self) if success: self.log.debug("\t=> Successfully deleted sample from table FILES") # delete from disk space: self.log.debug("Attempting to delete sample {} allele #{} of project '{}' from file system...".format(sample, nr, project)) sample_dir = os.path.join(self.settings["projects_dir"], project, sample) if files: for myfile in files[0]: if myfile: self.log.debug("\tDeleting {}...".format(myfile)) try: os.remove(os.path.join(sample_dir, myfile)) except Exception: self.log.debug("\t\t=> Could not delete") if single_allele: self.log.debug("\tDeleting sample dir {}...".format(sample_dir)) os.removedirs(sample_dir) self.log.debug("=> Sample {} #{} of project {} successfully deleted from database and file system".format(sample, nr, project)) self.refresh.emit(project) self.changed_projects.emit(project, status)
def rename_requested(self, name, location): LibraryDatabase = db_class() loc = location.replace("/", os.sep) base = os.path.dirname(loc) newname, ok = QInputDialog.getText( self.gui, _("Rename") + " " + name, "<p>" + _("Choose a new name for the library <b>%s</b>. ") % name + "<p>" + _("Note that the actual library folder will be renamed."), text=name, ) newname = sanitize_file_name_unicode(unicode(newname)) if not ok or not newname or newname == name: return newloc = os.path.join(base, newname) if os.path.exists(newloc): return error_dialog( self.gui, _("Already exists"), _("The folder %s already exists. Delete it first.") % newloc, show=True ) if iswindows and len(newloc) > LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT: return error_dialog( self.gui, _("Too long"), _("Path to library too long. Must be less than" " %d characters.") % LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT, show=True, ) if not os.path.exists(loc): error_dialog( self.gui, _("Not found"), _( "Cannot rename as no library was found at %s. " "Try switching to this library first, then switch back " "and retry the renaming." ) % loc, show=True, ) return try: os.rename(loc, newloc) except: import traceback det_msg = "Location: %r New Location: %r\n%s" % (loc, newloc, traceback.format_exc()) error_dialog( self.gui, _("Rename failed"), _( "Failed to rename the library at %s. " "The most common cause for this is if one of the files" " in the library is open in another program." ) % loc, det_msg=det_msg, show=True, ) return self.stats.rename(location, newloc) self.build_menus() self.gui.iactions["Copy To Library"].build_menus()
def computeImage(self, expression=None): """Computes image from expression (if expression is None, pops up dialog)""" if expression is None: (expression, ok) = QInputDialog.getText( self, "Compute image", """Enter an image expression to compute. Any valid numpy expression is supported, and all functions from the numpy module are available (including sub-modules such as fft). Use 'a', 'b', 'c' to refer to images. Examples: "(a+b)/2", "cos(a)+sin(b)", "a-a.mean()", "fft.fft2(a)", etc.""" ) # (expression,ok) = QInputDialog.getText(self,"Compute image","""<P>Enter an expression to compute. # Use 'a', 'b', etc. to refer to loaded images. Any valid numpy expression is supported, and all the # functions from the numpy module are available. Examples of valid expressions include "(a+b)/2", # "cos(a)+sin(b)", "a-a.mean()", etc. # </P> # """) expression = str(expression) if not ok or not expression: return # try to parse expression arglist = [(chr(ord('a') + ic.getNumber()), ic.image) for ic in self._imagecons] try: exprfunc = eval( "lambda " + (",".join([x[0] for x in arglist])) + ":" + expression, numpy.__dict__, {}) except Exception as exc: self.signalShowErrorMessage.emit( """Error parsing expression "%s": %s.""" % (expression, str(exc))) return None # try to evaluate expression self.signalShowMessage.emit("Computing expression \"%s\"" % expression, 10000) busy = BusyIndicator() QApplication.flush() # trim trivial trailing dimensions. This avoids the problem of when an NxMx1 and an NxMx1x1 arrays are added, # the result is promoted to NxMxMx1 following the numpy rules. def trimshape(shape): out = shape while out and out[-1] == 1: out = out[:-1] return out def trimarray(array): return array.reshape(trimshape(array.shape)) try: result = exprfunc(*[trimarray(x[1].data()) for x in arglist]) except Exception as exc: busy.reset_cursor() traceback.print_exc() self.signalShowErrorMessage.emit("""Error evaluating "%s": %s.""" % (expression, str(exc))) return None busy.reset_cursor() if type(result) != numpy.ma.masked_array and type( result) != numpy.ndarray: self.signalShowErrorMessage.emit( """Result of "%s" is of invalid type "%s" (array expected).""" % (expression, type(result).__name__)) return None # convert coomplex results to real if numpy.iscomplexobj(result): self.signalShowErrorMessage.emit( """Result of "%s" is complex. Complex images are currently not fully supported, so we'll implicitly use the absolute value instead.""" % (expression)) expression = "abs(%s)" % expression result = abs(result) # determine which image this expression can be associated with res_shape = trimshape(result.shape) arglist = [ x for x in arglist if hasattr(x[1], 'fits_header') and trimshape(x[1].data().shape) == res_shape ] if not arglist: self.signalShowErrorMessage.emit( """Result of "%s" has shape %s, which does not match any loaded FITS image.""" % (expression, "x".join(map(str, result.shape)))) return None # look for an image in the arglist with the same projection, and with a valid dirname # (for the where-to-save hint) template = arglist[0][1] # if all images in arglist have the same projection, then it doesn't matter what we use # else ask if len( [x for x in arglist[1:] if x[1].projection == template.projection ]) != len(arglist) - 1: options = [x[0] for x in arglist] (which, ok) = QInputDialog.getItem( self, "Compute image", "Coordinate system to use for the result of \"%s\":" % expression, options, 0, False) if not ok: return None try: template = arglist[options.index(which)][1] except: pass # create a FITS image busy = BusyIndicator() dprint(2, "creating FITS image", expression) self.signalShowMessage.emit("""Creating image for %s""" % expression, 3000) QApplication.flush() try: hdu = pyfits.PrimaryHDU(result.transpose(), template.fits_header) skyimage = SkyImage.FITSImagePlotItem(name=expression, filename=None, hdu=hdu) except: busy.reset_cursor() traceback.print_exc() self.signalShowErrorMessage.emit( """Error creating FITS image %s: %s""" % (expression, str(sys.exc_info()[1]))) return None # get directory name for save-to hint dirname = getattr(template, 'filename', None) if not dirname: dirnames = [ getattr(img, 'filename') for x, img in arglist if hasattr(img, 'filename') ] dirname = dirnames[0] if dirnames else None # create control bar, add to widget stack self._createImageController( skyimage, expression, expression, save=((dirname and os.path.dirname(dirname)) or ".")) self.signalShowMessage.emit("Created new image for %s" % expression, 3000) dprint(2, "image created") busy.reset_cursor()