def create_search_internet_menu(callback, author=None): m = QMenu( (_('Search the internet for the author {}').format(author) if author is not None else _('Search the internet for this book')) + '…') m.menuAction().setIcon(QIcon(I('search.png'))) items = all_book_searches() if author is None else all_author_searches() for k in sorted(items, key=lambda k: name_for(k).lower()): m.addAction(QIcon(I('search.png')), name_for(k), partial(callback, InternetSearch(author, k))) return m
class ImageController(QFrame): """An ImageController is a widget for controlling the display of one image. It can emit the following signals from the image: raise raise button was clicked center center-on-image option was selected unload unload option was selected slice image slice has changed, need to redraw (emitted by SkyImage automatically) repaint image display range or colormap has changed, need to redraw (emitted by SkyImage automatically) """ # image signals imageSignalRepaint = pyqtSignal() imageSignalSlice = pyqtSignal(tuple) imageSignalRaise = pyqtSignal([FITSImagePlotItem]) imageSignalUnload = pyqtSignal(object) imageSignalCenter = pyqtSignal(object) def __init__(self, image, parent, imgman, name=None, save=False): QFrame.__init__(self, parent) self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) # init state self._border_pen = None self._image_label_text = None self._subset = None self.image = image self._imgman = imgman self._currier = PersistentCurrier() self._control_dialog = None # create widgets self._lo = lo = QHBoxLayout(self) lo.setContentsMargins(0, 0, 0, 0) lo.setSpacing(2) # raise button self._wraise = QToolButton(self) lo.addWidget(self._wraise) self._wraise.setIcon(pixmaps.raise_up.icon()) self._wraise.setAutoRaise(True) self._can_raise = False self._wraise.clicked.connect(self._raiseButtonPressed) self._wraise.setToolTip( """<P>Click here to raise this image above other images. Hold the button down briefly to show a menu of image operations.</P>""") # center label self._wcenter = QLabel(self) self._wcenter.setPixmap(pixmaps.center_image.pm()) self._wcenter.setToolTip( "<P>The plot is currently centered on (the reference pixel %d,%d) of this image.</P>" % self.image.referencePixel()) lo.addWidget(self._wcenter) # name/filename label self.name = image.name self._wlabel = QLabel(self.name, self) self._number = 0 self.setName(self.name) self._wlabel.setToolTip( "%s %s" % (image.filename, "\u00D7".join(map(str, image.data().shape)))) lo.addWidget(self._wlabel, 1) # if 'save' is specified, create a "save" button if save: self._wsave = QToolButton(self) lo.addWidget(self._wsave) self._wsave.setText("save") self._wsave.setAutoRaise(True) self._save_dir = save if isinstance(save, str) else "." self._wsave.clicked.connect(self._saveImage) self._wsave.setToolTip( """<P>Click here to write this image to a FITS file.</P>""") # render control self.image.connectRepaint(self.imageSignalRepaint) self.image.connectSlice(self.imageSignalSlice) self.image.connectRaise(self.imageSignalRaise) self.image.connectUnload(self.imageSignalUnload) self.image.connectCenter(self.imageSignalCenter) dprint(2, "creating RenderControl") self._rc = RenderControl(image, self) dprint(2, "done") # selectors for extra axes self._wslicers = [] curslice = self._rc.currentSlice( ) # this may be loaded from config, so not necessarily 0 for iextra, axisname, labels in self._rc.slicedAxes(): if axisname.upper() not in ["STOKES", "COMPLEX"]: lbl = QLabel("%s:" % axisname, self) lo.addWidget(lbl) else: lbl = None slicer = QComboBox(self) self._wslicers.append(slicer) lo.addWidget(slicer) slicer.addItems(labels) slicer.setToolTip( """<P>Selects current slice along the %s axis.</P>""" % axisname) slicer.setCurrentIndex(curslice[iextra]) slicer.activated[int].connect( self._currier.curry(self._rc.changeSlice, iextra)) # min/max display ranges lo.addSpacing(5) self._wrangelbl = QLabel(self) lo.addWidget(self._wrangelbl) self._minmaxvalidator = FloatValidator(self) self._wmin = QLineEdit(self) self._wmax = QLineEdit(self) width = self._wmin.fontMetrics().width("1.234567e-05") for w in self._wmin, self._wmax: lo.addWidget(w, 0) w.setValidator(self._minmaxvalidator) w.setMaximumWidth(width) w.setMinimumWidth(width) w.editingFinished.connect(self._changeDisplayRange) # full-range button self._wfullrange = QToolButton(self) lo.addWidget(self._wfullrange, 0) self._wfullrange.setIcon(pixmaps.zoom_range.icon()) self._wfullrange.setAutoRaise(True) self._wfullrange.clicked.connect( self.renderControl().resetSubsetDisplayRange) rangemenu = QMenu(self) rangemenu.addAction(pixmaps.full_range.icon(), "Full subset", self.renderControl().resetSubsetDisplayRange) for percent in (99.99, 99.9, 99.5, 99, 98, 95): rangemenu.addAction( "%g%%" % percent, self._currier.curry(self._changeDisplayRangeToPercent, percent)) self._wfullrange.setPopupMode(QToolButton.DelayedPopup) self._wfullrange.setMenu(rangemenu) # update widgets from current display range self._updateDisplayRange(*self._rc.displayRange()) # lock button self._wlock = QToolButton(self) self._wlock.setIcon(pixmaps.unlocked.icon()) self._wlock.setAutoRaise(True) self._wlock.setToolTip( """<P>Click to lock or unlock the intensity range. When the intensity range is locked across multiple images, any changes in the intensity range of one are propagated to the others. Hold the button down briefly for additional options.</P>""" ) lo.addWidget(self._wlock) self._wlock.clicked.connect(self._toggleDisplayRangeLock) self.renderControl().displayRangeLocked.connect( self._setDisplayRangeLock) self.renderControl().dataSubsetChanged.connect(self._dataSubsetChanged) lockmenu = QMenu(self) lockmenu.addAction( pixmaps.locked.icon(), "Lock all to this", self._currier.curry(imgman.lockAllDisplayRanges, self.renderControl())) lockmenu.addAction(pixmaps.unlocked.icon(), "Unlock all", imgman.unlockAllDisplayRanges) self._wlock.setPopupMode(QToolButton.DelayedPopup) self._wlock.setMenu(lockmenu) self._setDisplayRangeLock(self.renderControl().isDisplayRangeLocked()) # dialog button self._wshowdialog = QToolButton(self) lo.addWidget(self._wshowdialog) self._wshowdialog.setIcon(pixmaps.colours.icon()) self._wshowdialog.setAutoRaise(True) self._wshowdialog.setToolTip( """<P>Click for colourmap and intensity policy options.</P>""") self._wshowdialog.clicked.connect(self.showRenderControls) tooltip = """<P>You can change the currently displayed intensity range by entering low and high limits here.</P> <TABLE> <TR><TD><NOBR>Image min:</NOBR></TD><TD>%g</TD><TD>max:</TD><TD>%g</TD></TR> </TABLE>""" % self.image.imageMinMax() for w in self._wmin, self._wmax, self._wrangelbl: w.setToolTip(tooltip) # create image operations menu self._menu = QMenu(self.name, self) self._qa_raise = self._menu.addAction( pixmaps.raise_up.icon(), "Raise image", self._currier.curry(self.image.signalRaise.emit, None)) self._qa_center = self._menu.addAction( pixmaps.center_image.icon(), "Center plot on image", self._currier.curry(self.image.signalCenter.emit, True)) self._qa_show_rc = self._menu.addAction(pixmaps.colours.icon(), "Colours && Intensities...", self.showRenderControls) if save: self._qa_save = self._menu.addAction("Save image...", self._saveImage) self._menu.addAction("Export image to PNG file...", self._exportImageToPNG) self._export_png_dialog = None self._menu.addAction( "Unload image", self._currier.curry(self.image.signalUnload.emit, None)) self._wraise.setMenu(self._menu) self._wraise.setPopupMode(QToolButton.DelayedPopup) # connect updates from renderControl and image self.image.signalSlice.connect(self._updateImageSlice) self._rc.displayRangeChanged.connect(self._updateDisplayRange) # default plot depth of image markers self._z_markers = None # and the markers themselves self._image_border = QwtPlotCurve() self._image_border.setRenderHint(QwtPlotItem.RenderAntialiased) self._image_label = QwtPlotMarker() self._image_label.setRenderHint(QwtPlotItem.RenderAntialiased) # subset markers self._subset_pen = QPen(QColor("Light Blue")) self._subset_border = QwtPlotCurve() self._subset_border.setRenderHint(QwtPlotItem.RenderAntialiased) self._subset_border.setPen(self._subset_pen) self._subset_border.setVisible(False) self._subset_label = QwtPlotMarker() self._subset_label.setRenderHint(QwtPlotItem.RenderAntialiased) text = QwtText("subset") text.setColor(self._subset_pen.color()) self._subset_label.setLabel(text) self._subset_label.setLabelAlignment(Qt.AlignRight | Qt.AlignBottom) self._subset_label.setVisible(False) self._setting_lmrect = False self._all_markers = [ self._image_border, self._image_label, self._subset_border, self._subset_label ] self._exportMaxRes = False self._dockable_colour_ctrl = None def close(self): if self._control_dialog: self._control_dialog.close() self._control_dialog = None def __del__(self): self.close() def __eq__(self, other): return self is other def renderControl(self): return self._rc def getMenu(self): return self._menu def getFilename(self): return self.image.filename def setName(self, name): self.name = name self._wlabel.setText("%s: %s" % (chr(ord('a') + self._number), self.name)) def setNumber(self, num): self._number = num self._menu.menuAction().setText( "%s: %s" % (chr(ord('a') + self._number), self.name)) self._qa_raise.setShortcut(QKeySequence("Alt+" + chr(ord('A') + num))) self.setName(self.name) def getNumber(self): return self._number def setPlotProjection(self, proj): self.image.setPlotProjection(proj) sameproj = proj == self.image.projection self._wcenter.setVisible(sameproj) self._qa_center.setVisible(not sameproj) if self._image_border: (l0, l1), (m0, m1) = self.image.getExtents() path = numpy.array([l0, l0, l1, l1, l0]), numpy.array([m0, m1, m1, m0, m0]) self._image_border.setSamples(*path) if self._image_label: self._image_label.setValue(path[0][2], path[1][2]) def addPlotBorder(self, border_pen, label, label_color=None, bg_brush=None): # make plot items for image frame # make curve for image borders (l0, l1), (m0, m1) = self.image.getExtents() self._border_pen = QPen(border_pen) self._image_border.show() self._image_border.setSamples([l0, l0, l1, l1, l0], [m0, m1, m1, m0, m0]) self._image_border.setPen(self._border_pen) self._image_border.setZ( self.image.z() + 1 if self._z_markers is None else self._z_markers) if label: self._image_label.show() self._image_label_text = text = QwtText(" %s " % label) text.setColor(label_color) text.setBackgroundBrush(bg_brush) self._image_label.setValue(l1, m1) self._image_label.setLabel(text) self._image_label.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter) self._image_label.setZ( self.image.z() + 2 if self._z_markers is None else self._z_markers) def setPlotBorderStyle(self, border_color=None, label_color=None): if border_color: self._border_pen.setColor(border_color) self._image_border.setPen(self._border_pen) if label_color: self._image_label_text.setColor(label_color) self._image_label.setLabel(self._image_label_text) def showPlotBorder(self, show=True): self._image_border.setVisible(show) self._image_label.setVisible(show) def attachToPlot(self, plot, z_markers=None): for item in [self.image] + self._all_markers: if item.plot() != plot: item.attach(plot) def setImageVisible(self, visible): self.image.setVisible(visible) def showRenderControls(self): if not self._control_dialog: dprint(1, "creating control dialog") self._control_dialog = ImageControlDialog(self, self._rc, self._imgman) # line below allows window to be resized by the user self._control_dialog.setSizeGripEnabled(True) # get and set sizing self._control_dialog.setMinimumWidth(396) # create size policy for control dialog colour_ctrl_policy = QSizePolicy() colour_ctrl_policy.setHorizontalPolicy(QSizePolicy.Minimum) self._control_dialog.setSizePolicy(colour_ctrl_policy) # setup dockable colour control dialog self._dockable_colour_ctrl = TDockWidget( title=f"{self._rc.image.name}", parent=self.parent().mainwin, bind_widget=self._control_dialog, close_slot=self.colourctrl_dockwidget_closed, toggle_slot=self.colourctrl_dockwidget_toggled) self.addDockWidgetToTab() dprint(1, "done") # set dockable widget visibility in sync with control dialog if not self._control_dialog.isVisible(): dprint(1, "showing control dialog") self._control_dialog.show() self._dockable_colour_ctrl.setVisible(True) self.addDockWidgetToTab() self._dockable_colour_ctrl.show() self._dockable_colour_ctrl.raise_() else: self._control_dialog.hide() self._dockable_colour_ctrl.setVisible(False) self.parent().mainwin.setMaximumWidth( self.parent().mainwin.width() + self._dockable_colour_ctrl.width()) def addDockWidgetToTab(self): # Add dockable widget to main window. # This needs to itterate through the widgets to find DockWidgets already in the right side area, # then tabifydockwidget when adding, or add to the right area if empty widget_list = self.parent().mainwin.findChildren(QDockWidget) for widget in widget_list: if self.parent().mainwin.dockWidgetArea( widget) == 2: # if in right dock area if widget.isVisible() and not widget.isFloating( ): # if widget active and not a window if self._dockable_colour_ctrl is not widget: # check not itself # add dock widget in tab on top of current widget in right area self.parent().mainwin.tabifyDockWidget( widget, self._dockable_colour_ctrl) self.parent().mainwin.resizeDocks( [widget], [widget.bind_widget.width()], Qt.Horizontal) elif self.parent().mainwin.dockWidgetArea( widget ) == 0: # if not in any dock area assume we have new dock widget # no previous widget in this area then add self.parent().mainwin.addDockWidget(Qt.RightDockWidgetArea, self._dockable_colour_ctrl) self.parent().mainwin.resizeDocks([widget], [widget.bind_widget.width()], Qt.Horizontal) def removeDockWidget(self): # remove image control dock widget self.parent().mainwin.removeDockWidget(self._dockable_colour_ctrl) # get widgets to resize widget_list = self.parent().mainwin.findChildren(QDockWidget) size_list = [] result = [] for widget in widget_list: if not isinstance(widget.bind_widget, ImageControlDialog): size_list.append(widget.bind_widget.width()) result.append(widget) dprint(2, f"{widget} width {widget.width()}") dprint( 2, f"{widget} bind_widget width {widget.bind_widget.width()}") if isinstance(widget.bind_widget, LiveImageZoom): widget.bind_widget.setMinimumWidth(widget.width()) widget_list = result # resize dock areas self.parent().mainwin.resizeDocks(widget_list, size_list, Qt.Horizontal) def colourctrl_dockwidget_closed(self): self._dockable_colour_ctrl.setVisible(False) self.parent().mainwin.setMaximumWidth( self.parent().mainwin.width() - self._dockable_colour_ctrl.width()) def colourctrl_dockwidget_toggled(self): if self._dockable_colour_ctrl.isVisible(): if self._dockable_colour_ctrl.isWindow(): self._dockable_colour_ctrl.setFloating(False) else: self._dockable_colour_ctrl.setFloating(True) self.parent().mainwin.setMaximumWidth( self.parent().mainwin.width() + self._dockable_colour_ctrl.width()) def _changeDisplayRangeToPercent(self, percent): if not self._control_dialog: self._control_dialog = ImageControlDialog(self, self._rc, self._imgman) self._control_dialog._changeDisplayRangeToPercent(percent) def _updateDisplayRange(self, dmin, dmax): """Updates display range widgets.""" self._wmin.setText("%.4g" % dmin) self._wmax.setText("%.4g" % dmax) self._updateFullRangeIcon() def _changeDisplayRange(self): """Gets display range from widgets and updates the image with it.""" try: newrange = float(str(self._wmin.text())), float( str(self._wmax.text())) except ValueError: return self._rc.setDisplayRange(*newrange) def _dataSubsetChanged(self, subset, minmax, desc, subset_type): """Called when the data subset changes (or is reset)""" # hide the subset indicator -- unless we're invoked while we're actually setting the subset itself if not self._setting_lmrect: self._subset = None self._subset_border.setVisible(False) self._subset_label.setVisible(False) def setLMRectSubset(self, rect): self._subset = rect l0, m0, l1, m1 = rect.getCoords() self._subset_border.setSamples([l0, l0, l1, l1, l0], [m0, m1, m1, m0, m0]) self._subset_border.setVisible(True) self._subset_label.setValue(max(l0, l1), max(m0, m1)) self._subset_label.setVisible(True) self._setting_lmrect = True self.renderControl().setLMRectSubset(rect) self._setting_lmrect = False def currentSlice(self): return self._rc.currentSlice() def _updateImageSlice(self, _slice): dprint(2, _slice) for i, (iextra, name, labels) in enumerate(self._rc.slicedAxes()): slicer = self._wslicers[i] if slicer.currentIndex() != _slice[iextra]: dprint(3, "setting widget", i, "to", _slice[iextra]) slicer.setCurrentIndex(_slice[iextra]) def setMarkersZ(self, z): self._z_markers = z for i, elem in enumerate(self._all_markers): elem.setZ(z + i) def setZ(self, z, top=False, depthlabel=None, can_raise=True): self.image.setZ(z) if self._z_markers is None: for i, elem in enumerate(self._all_markers): elem.setZ(z + i + i) # set the depth label, if any label = "%s: %s" % (chr(ord('a') + self._number), self.name) # label = "%s %s"%(depthlabel,self.name) if depthlabel else self.name if top: label = "%s: <B>%s</B>" % (chr(ord('a') + self._number), self.name) self._wlabel.setText(label) # set hotkey self._qa_show_rc.setShortcut(Qt.Key_F9 if top else QKeySequence()) # set raise control self._can_raise = can_raise self._qa_raise.setVisible(can_raise) self._wlock.setVisible(can_raise) if can_raise: self._wraise.setToolTip( "<P>Click here to raise this image to the top. Click on the down-arrow to access the image menu.</P>" ) else: self._wraise.setToolTip("<P>Click to access the image menu.</P>") def _raiseButtonPressed(self): if self._can_raise: self.image.signalRaise.emit(self.image) else: self._wraise.showMenu() def _saveImage(self): filename = QFileDialog.getSaveFileName( self, "Save FITS file", self._save_dir, "FITS files(*.fits *.FITS *fts *FTS)", options=QFileDialog.DontUseNativeDialog) filename = str(filename[0]) if not filename: return busy = BusyIndicator() self._imgman.signalShowMessage.emit( """Writing FITS image %s""" % filename, 3000) QApplication.flush() try: self.image.save(filename) except Exception as exc: busy.reset_cursor() traceback.print_exc() self._imgman.signalShowErrorMessage.emit( """Error writing FITS image %s: %s""" % (filename, str(sys.exc_info()[1]))) return None self.renderControl().startSavingConfig(filename) self.setName(self.image.name) self._qa_save.setVisible(False) self._wsave.hide() busy.reset_cursor() def _exportImageResolution(self): sender = self.sender() if isinstance(sender, QCheckBox): if sender.isChecked(): self._exportMaxRes = True else: self._exportMaxRes = False def _exportImageToPNG(self, filename=None): if not filename: if not self._export_png_dialog: dialog = self._export_png_dialog = QFileDialog( self, "Export image to PNG", ".", "*.png") dialog.setDefaultSuffix("png") dialog.setFileMode(QFileDialog.AnyFile) dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setModal(True) dialog.filesSelected['QStringList'].connect( self._exportImageToPNG) # attempt to add limit 4K option - not available on Ubuntu Unity layout = dialog.layout() if layout is not None: checkbox = QCheckBox("Limit to 4K image") checkbox.setChecked(False) checkbox.setToolTip("Limits the image output to 4K") checkbox.toggled.connect(self._exportImageResolution) layout.addWidget(checkbox) dialog.setLayout(layout) return self._export_png_dialog.exec_() == QDialog.Accepted busy = BusyIndicator() if isinstance(filename, QStringList): filename = filename[0] filename = str(filename) # get image dimensions nx, ny = self.image.imageDims() # export either max resolution possible or default to 4K. If image is small then no scaling occurs. if not self._exportMaxRes: # get free memory. Note: Linux only! import os total_memory, used_memory, free_memory = map( int, os.popen('free -t -m').readlines()[-1].split()[1:]) # use 90% of free memory available free_memory = free_memory * 0.9 # use an approximation to find the max image size that can be generated if nx >= ny and nx > free_memory: scale_factor = round(free_memory / nx, 1) elif ny > nx and ny > free_memory: scale_factor = round(free_memory / ny, 1) else: scale_factor = 1 else: # default to 4K if nx > 4000: scale_factor = 4000 / nx elif ny > nx and ny > 4000: scale_factor = 4000 / ny else: scale_factor = 1 # make QPixmap nx = nx * scale_factor ny = ny * scale_factor (l0, l1), (m0, m1) = self.image.getExtents() pixmap = QPixmap(nx, ny) painter = QPainter(pixmap) # use QwtPlot implementation of draw canvas, since we want to avoid caching xmap = QwtScaleMap() xmap.setPaintInterval(0, nx) xmap.setScaleInterval(l1, l0) ymap = QwtScaleMap() ymap.setPaintInterval(ny, 0) ymap.setScaleInterval(m0, m1) # call painter with clear cache option for consistent file size output. self.image.draw(painter, xmap, ymap, pixmap.rect(), use_cache=False) painter.end() # save to file try: pixmap.save(filename, "PNG") # clean up export items pixmap.detach() del xmap del ymap del pixmap del painter except Exception as exc: self._imgman.signalShowErrorMessage[str, int].emit( "Error writing %s: %s" % (filename, str(exc)), 3000) busy.reset_cursor() else: busy.reset_cursor() self._imgman.signalShowMessage[str, int].emit( "Exported image to file %s" % filename, 3000) def _toggleDisplayRangeLock(self): self.renderControl().lockDisplayRange( not self.renderControl().isDisplayRangeLocked()) def _setDisplayRangeLock(self, locked): self._wlock.setIcon( pixmaps.locked.icon() if locked else pixmaps.unlocked.icon()) def _updateFullRangeIcon(self): if self._rc.isSubsetDisplayRange(): self._wfullrange.setIcon(pixmaps.zoom_range.icon()) self._wfullrange.setToolTip( """<P>The current intensity range is the full range. Hold this button down briefly for additional options.</P>""" ) else: self._wfullrange.setIcon(pixmaps.full_range.icon()) self._wfullrange.setToolTip( """<P>Click to reset to a full intensity range. Hold the button down briefly for additional options.</P>""" )
class Ui(QApplication): def __init__(self): super().__init__(argv) self.w = QMainWindow() self.w.setMinimumWidth(300) self.w.setMinimumHeight(300) # self.w.setWindowTitle(tr("Отправка запросов на ВС АУГО")) self.cw = QScrollArea() # self.__create_ui() self.__showed = False self.__wgts = {} self.cb = QComboBox() self.individuals = [] self.entities = [] self.documents = [] self.doc_files = [] self.__setupUi(self.w) self.w.showMaximized() def report_error(self, msg=None): if not msg: etype, value, tb = exc_info() trace = ''.join(format_exception(etype, value, tb)) delim_len = 40 msg = ("*" * delim_len + "\n%s\n" + "*" * delim_len) % trace error(msg) mb = QMessageBox(QMessageBox.Critical, tr('Ошибка'), str(exc_info()[1])) mb.setDetailedText(msg) mb.exec() def __create_ui(self): self.l = QGridLayout() self.t = QTableWidget(0, 3) self.t.setHorizontalHeaderLabels( ('№ дела (обращения)', 'Дата приёма', 'Дата отправки в СМЭВ')) self.t.resizeColumnsToContents() self.l.addWidget(self.t, 0, 0, 1, 2) w = QWidget() hl = QHBoxLayout(w) hl.setDirection(QHBoxLayout.LeftToRight) hl.addWidget(QWidget()) ok_b = QPushButton(tr('Добавить запрос')) ok_b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum) ok_b.clicked.connect(self.__show_form) hl.addWidget(ok_b) w.setLayout(hl) self.l.addWidget(w, 1, 0, 1, 2) w = QWidget() w.setLayout(self.l) self.cw.setWidget(w) # self.cw.setLayout(self.l) # self.w.setCentralWidget(self.cw) w = QWidget() l = QVBoxLayout() l.addWidget(self.cw) w.setLayout(l) self.w.setCentralWidget(w) def __setupUi(self, mainWindow): mainWindow.setObjectName("MainWindow") self.centralwidget = QWidget(mainWindow) self.centralwidget.setObjectName("centralwidget") self.horizontalLayout = QHBoxLayout(self.centralwidget) self.horizontalLayout.setObjectName("horizontalLayout") self.scrollArea = QScrollArea(self.centralwidget) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") self.gridLayout = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout.setObjectName("gridLayout") self.__show_form() self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.horizontalLayout.addWidget(self.scrollArea) mainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(mainWindow) self.menubar.setObjectName("menubar") self.menu = QMenu(self.menubar) self.menu.setObjectName("menu") mainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(mainWindow) self.statusbar.setObjectName("statusbar") mainWindow.setStatusBar(self.statusbar) self.action_1 = QAction(mainWindow) self.action_1.setObjectName("action") self.action_1.triggered.connect(self.send) self.action = QAction(mainWindow) self.action.setObjectName("action") self.action.triggered.connect(self.on_action_triggered) self.action_2 = QAction(mainWindow) self.action_2.setObjectName("action_2") self.action_3 = QAction(mainWindow) self.action_3.setObjectName("action_3") self.action_3.triggered.connect(self.get_response) self.menu.addAction(self.action) self.menubar.addAction(self.action_1) self.menubar.addAction(self.action_2) self.menubar.addAction(self.action_3) self.menubar.addAction(self.menu.menuAction()) self.__retranslateUi(mainWindow) QMetaObject.connectSlotsByName(mainWindow) @pyqtSlot(bool) def get_response(self): try: from dmsic import Integration i = Integration(self) res = i.get_response()[0] if res: QMessageBox.information(self.w, tr("Получен ответ"), str(res)) except: self.report_error() @pyqtSlot(bool) def send(self): try: from dmsic import Integration i = Integration(self) declar = {} for k, v in self.__wgts.items(): if k in ('object_address', 'AppliedDocument', 'legal_entity', 'person'): a = {} for key, val in v.items(): if val.metaObject().className() == 'QDateEdit': a[key] = datetime.strptime(val.text(), '%d.%m.%Y') else: a[key] = val.text() declar[k] = a else: if v.metaObject().className() == 'QDateEdit': declar[k] = datetime.strptime(v.text(), '%d.%m.%Y') else: declar[k] = v.text() a = declar[ 'AppliedDocument'] if 'AppliedDocument' in declar else [] for v in self.documents: d = {} for key, val in v.items(): if val.metaObject().className() == 'QDateEdit': d[key] = datetime.strptime(val.text(), '%d.%m.%Y') else: d[key] = val.text() if not self.doc_files: raise Exception('Добавте файл документа') d['file_name'] = self.doc_files[self.documents.index(v)] a.append(d) declar['AppliedDocument'] = a a = declar['person'] if 'person' in declar else [] for v in self.individuals: ind = {} for key, val in v.items(): if key in ('address', 'fact_address'): adr = {} for k, vl in val.items(): adr[k] = vl.text() ind[key] = adr else: if val.metaObject().className() == 'QDateEdit': ind[key] = datetime.strptime( val.text(), '%d.%m.%Y') else: ind[key] = val.text() a.append(ind) declar['person'] = a a = declar['legal_entity'] if 'legal_entity' in declar else [] for v in self.entities: ent = {} for key, val in v.items(): if key == 'address': adr = {} for k, vl in val.items(): adr[k] = vl.text() ent[key] = adr else: if val.metaObject().className() == 'QDateEdit': ent[key] = datetime.strptime( val.text(), '%d.%m.%Y') else: ent[key] = val.text() a.append(ent) declar['legal_entity'] = a i.send(declar) mb = QMessageBox(self.w) mb.information(self.w, tr('Готово'), tr('Запрос отправлен')) except: self.report_error() @pyqtSlot(bool) def on_action_triggered(self): a = Ui_Dialog() d = QDialog() a.setupUi(d) d.exec() def __retranslateUi(self, MainWindow): _translate = QCoreApplication.translate MainWindow.setWindowTitle( _translate("MainWindow", "Отправка запросов на ВС АУГО")) # self.pushButton.setText(_translate("MainWindow", "Добавить")) self.menu.setTitle(_translate("MainWindow", "Справка")) self.action_1.setText(_translate("MainWindow", "Отправить")) self.action_2.setText(_translate("MainWindow", "Настройка")) self.action.setText(_translate("MainWindow", "О программе")) self.action_3.setText(_translate("MainWindow", "Получить ответ")) @pyqtSlot(bool) def __show_form(self): if self.__showed: return self.gridLayout.addWidget( QLabel(tr('№ дела (обращения) <em style="color: red">*</em>'))) w = QLineEdit() self.gridLayout.addWidget(w) w.setFocus() self.__wgts['declar_number'] = w self.gridLayout.addWidget( QLabel( tr('Услуга (код или номер, или наименование)<em style="color: red">*</em>' ))) w = QLineEdit() self.gridLayout.addWidget(w) self.__wgts['service'] = w self.gridLayout.addWidget( QLabel( tr('Дата регистрации запроса <em style="color: red">*</em>'))) de = QDateEdit(QDate().currentDate()) de.setCalendarPopup(True) self.gridLayout.addWidget(de) self.__wgts['register_date'] = de self.gridLayout.addWidget( QLabel( tr('Плановый срок предоставления услуги <em style="color: red">*</em>' ))) de = QDateEdit() self.__wgts['register_date'].dateChanged.connect(de.setMinimumDate) de.setCalendarPopup(True) de.setMinimumDate(self.__wgts['register_date'].date()) self.gridLayout.addWidget(de) self.__wgts['end_date'] = de gb = QGroupBox(tr('Место нахождения объекта услуги')) gb_l = QGridLayout() self.__wgts['object_address'] = self.__add_address(gb_l) gb.setLayout(gb_l) self.gridLayout.addWidget(gb, self.gridLayout.rowCount() + 1, 0, 1, 2) doc = {} gb = QGroupBox(tr('Приложенный документ *')) gb_l = QGridLayout() gb_l.addWidget( QLabel(tr('Наименование документа <em style="color: red">*</em>'))) w = QLineEdit() w.setMaxLength(1024) gb_l.addWidget(w, 0, 1, 1, 1) doc['title'] = w gb_l.addWidget( QLabel(tr('Номер документа <em style="color: red">*</em>'))) w = QLineEdit() w.setMaxLength(50) gb_l.addWidget(w) doc['number'] = w gb_l.addWidget( QLabel(tr('Дата документа <em style="color: red">*</em>'))) w = QDateEdit() w.setCalendarPopup(True) gb_l.addWidget(w) doc['date'] = w gb_l.addWidget( QLabel( tr('Прямая ссылка на файл. Поддерживаются только пртоколы ' 'HTTP, FTP <em style="color: red">*</em>'))) w = QLineEdit() gb_l.addWidget(w) doc['url'] = w gb.setLayout(gb_l) self.gridLayout.addWidget(gb, self.gridLayout.rowCount() + 1, 0, 1, 2) self.documents.append(doc) gb = QGroupBox(tr('Заявители *')) self.dec_layout = QGridLayout() self.cb = QComboBox() self.cb.addItems(('Физическое лицо', 'Юридическое лицо/Индивидуальный предприниматель')) self.dec_layout.addWidget(self.cb) b = QPushButton(tr('Добавить')) b.clicked.connect(self.add_declarant) self.dec_layout.addWidget(b, 0, 1, 1, 1) gb.setLayout(self.dec_layout) self.gridLayout.addWidget(gb, self.gridLayout.rowCount() + 1, 0, 1, 2) b = QPushButton(tr('Добавить файл документа')) b.clicked.connect(self.__add_doc_file) self.gridLayout.addWidget(b) self.file_label = QLabel() self.gridLayout.addWidget(self.file_label) self.warn_label = QLabel(tr("Не удаляйте файл до отправки запроса")) self.warn_label.setStyleSheet('color: red') self.warn_label.setVisible(False) self.gridLayout.addWidget(self.warn_label, self.gridLayout.rowCount() + 1, 0, 1, 2) self.__showed = True @pyqtSlot(bool) def __add_doc_file(self): file_name = QFileDialog.getOpenFileName( caption=tr('Выбурите файл'), filter=tr('Файлы pdf (*.pdf);;Все файлы (*.*)'))[0] self.file_label.setText(file_name) if self.doc_files: self.doc_files = [] self.doc_files.append(file_name) self.warn_label.setVisible(True) def __add_address(self, gb_l): wgts = {} gb_l.addWidget(QLabel(tr('Почтовый индекс'))) w = QLineEdit() gb_l.addWidget(w, 0, 1, 1, 1) wgts['Postal_Code'] = w gb_l.addWidget(QLabel(tr('Регион'))) w = QLineEdit() gb_l.addWidget(w) wgts['Region'] = w gb_l.addWidget(QLabel(tr('Район'))) w = QLineEdit() gb_l.addWidget(w) wgts['District'] = w gb_l.addWidget(QLabel(tr('Муниципальное образование'))) w = QLineEdit() gb_l.addWidget(w) wgts['City'] = w gb_l.addWidget(QLabel(tr('Городской район'))) w = QLineEdit() gb_l.addWidget(w) wgts['Urban_District'] = w gb_l.addWidget(QLabel(tr('Сельсовет'))) w = QLineEdit() gb_l.addWidget(w) wgts['Soviet_Village'] = w gb_l.addWidget( QLabel(tr('Населенный пункт <em style="color: red">*</em>'))) w = QLineEdit() gb_l.addWidget(w) wgts['Locality'] = w cb = QComboBox() cb.addItems(('Вариант 1', 'Вариант 2')) gb_l.addWidget(cb) st = QStackedWidget() p1 = QWidget() l = QGridLayout() l.setSpacing(3) l.addWidget(QLabel(tr('Улица <em style="color: red">*</em>'))) w = QLineEdit() l.addWidget(w, 0, 1, 1, 1) wgts["Street"] = w l.addWidget(QLabel(tr('Дом <em style="color: red">*</em>'))) w = QLineEdit() l.addWidget(w) wgts["House"] = w p1.setLayout(l) st.addWidget(p1) p2 = QWidget() l = QGridLayout() l.setSpacing(3) l.addWidget(QLabel(tr('Ориентир'))) w = QLineEdit() l.addWidget(w, 0, 1, 1, 1) wgts["Reference_point"] = w p2.setLayout(l) st.addWidget(p2) gb_l.addWidget(st, 9, 0, 1, 2) cb.activated.connect(st.setCurrentIndex) gb_l.addWidget(QLabel(tr('Корпус'))) w = QLineEdit() gb_l.addWidget(w) wgts['Housing'] = w gb_l.addWidget(QLabel(tr('Строение'))) w = QLineEdit() gb_l.addWidget(w) wgts['Building'] = w gb_l.addWidget(QLabel(tr('Квартира'))) w = QLineEdit() gb_l.addWidget(w) wgts['Apartment'] = w return wgts @pyqtSlot(bool) def add_declarant(self, var=True, gl=None): if not gl: gl = self.dec_layout dc = {} gb_l = QGridLayout() if self.cb.currentIndex() == 0 or gl != self.dec_layout: # Add Individual gb = QGroupBox(tr('Физическое лицо *')) gb_l.addWidget(QLabel(tr('Фамилия <em style="color: red">*</em>'))) w = QLineEdit() gb_l.addWidget(w, 0, 1, 1, 1) dc['surname'] = w gb_l.addWidget(QLabel(tr('Имя <em style="color: red">*</em>'))) w = QLineEdit() gb_l.addWidget(w) dc['first_name'] = w gb_l.addWidget(QLabel(tr('Отчество'))) w = QLineEdit() gb_l.addWidget(w) dc['patronymic'] = w adr = QGroupBox(tr('Адрес регистрации *')) adr_l = QGridLayout() dc['address'] = self.__add_address(adr_l) adr.setLayout(adr_l) gb_l.addWidget(adr, gb_l.rowCount() + 1, 0, 1, 2) gb.setLayout(gb_l) gl.addWidget(gb, gl.rowCount() + 1, 0, 1, 2) self.individuals.append(dc) else: # Add LegalEntity gb = QGroupBox( tr('Юридическое лицо/Индивидуальный предприниматель *')) gb_l.addWidget( QLabel( tr('Краткое наименование ЮЛ <em style="color: red">*</em>') )) w = QLineEdit() gb_l.addWidget(w, 0, 1, 1, 1) dc['name'] = w adr = QGroupBox(tr('Юридический адрес *')) adr_l = QGridLayout() dc['address'] = self.__add_address(adr_l) adr.setLayout(adr_l) gb_l.addWidget(adr, gb_l.rowCount() + 1, 0, 1, 2) gb.setLayout(gb_l) gl.addWidget(gb, gl.rowCount() + 1, 0, 1, 2) self.entities.append(dc)